Sven Steudte 2018-07-09 14:48:08 +02:00
commit 644d466197
35 zmienionych plików z 3070 dodań i 2836 usunięć

Wyświetl plik

@ -16,22 +16,34 @@ __Powering:__ The Pecan Pico 10 can be powered either by USB or by a single LiPO
__Storage:__ There can be stored up to 14,560 data points (GPS & telemetry) without any external memory devices. For additional storage and picture logging, a Micro SD card can be inserted into the device.
__Transceiver:__ Though the software is mainly optimized for APRS operation, it can be also used for 2/4FSK (RTTY) and OOK (CW) operation. The maximum transmission power is 100mW. The fastest tested FSK speed is 115k2.
__Transceiver:__ Though the software is mainly optimized for APRS operation, it can be also used for 2/4FSK (RTTY) and OOK (CW) operation. The maximum transmission power is 100mW. While the transceiver has ony a signle LPF, it is only able to operate on one frequency band (either 2m or 70cm). The inductors/capacitors in the schematic are adjusted to the 2m amateur radio band, but with different components it can be used on the 70cm band too. The fastest tested 2FSK transmission speed is 115k2. While the Pecan can transmit AFSK and 2FSK, it is only able to receive AFSK APRS. It is possible to receive 2FSK APRS too, although the software hasn't been implemented yet.
__Image transmission:__ The software makes use of the JPEG compression of the Omnivision OV5640. Although the connector is suitable for some other cameras too, the OV5640 is the only camera which can be used due to the missing HREF pin. The protocol being used for the images transmission is APRS/SSDV. This protocol is fully APRS compatible but needs extra software to be decoded again. Though the camera can do pictures up to 5MP, there is only enough memory available to take XGA pictures (1024x768px).
__Image transmission:__ The software makes use of the JPEG compression of the Omnivision OV5640. Although the connector is suitable for some other cameras too, the OV5640 is the only camera which can be used due to the missing HREF pin. The protocol being used for the images transmission is APRS/SSDV. This protocol is fully APRS compatible but needs extra software to be decoded again which is included in this project. Though the camera can do pictures up to 5MP, there is only enough memory available to take XGA pictures (1024x768px).
TODO: Precise description about APRS/SSDV
__Telemetry transmission:__ Since APRS does only allow a ceirtain amount of telemetry fields being transmitted, the complete telemetry is sent as a binary format along with the position transmissions in the comment field. The APRS packet stays completly compatible with the existing network. The additional telemetry can be decoded with an additional software.
__Telemetry transmission:__ Since APRS does only allow a ceirtain amount of telemetry fields being transmitted, the complete telemetry is sent as a binary format along with the position transmissions in the comment field. The APRS packet stays completly compatible with the existing network. The additional telemetry can be decoded with an additional decoder which is included in this project. It is the same decoder which decodes APRS/SSDV too. The software is currently running on [this website](http://www.wlankabel.com).
__Sensors:__ The Pecan uses a single chip (BME280) to measure the temperature, airpressure and humidity. There can be attached up to two additional BME280's for various purposes.
__Sensors:__ The Pecan uses a single chip (BME280) to measure the temperature, airpressure and humidity. There can be attached up to two additional BME280's for various purposes like internal and external temperatures. You may want to have an external sensor while the internal sensor on the PCB is influenced by the heat generated by the components. The difference can vary between 2 and 10°C.
__Additional sensors:__ The Pecan provides an external I2C bus from where addional sensors can be accessed. There is also a signle GPIO pin, which can be used for varios stuff.
__Additional sensors:__ The Pecan provides an external busses (I2C and UART) from where addional sensors can be accessed. On the 10a variant is a signle GPIO pin, which can be used for varios stuff. There can either be I2C or UART be used on the 10a variant while I2C shared the same pins as UART does. In the 10b variant the additional GPIO pin has been removed, therefore I2C and UART are now separate. If you have no need for UART/I2C, those pins can be also used as normal GPIO's.
__GNSS (GPS):__ The ublox EVA-7M chip can receive GPS which is used to determine the region specific APRS frequency. Since the GPS draws a lot of power, it can be switched on and off as needed. The device is also compatible with the ublox EVA-M8.
__GNSS (GPS):__ The ublox EVA-7M chip can receive GPS which is used to determine it's location and the region specific APRS frequency. Since the GPS draws a lot of power, it can be switched on and off as needed. The device is also compatible with the ublox EVA-M8 which can receive GLONASS, Beido and Galileo too.
__Debugging/Configuration:__ The device can be accessed over USB in order to configure it or get debug messages out of the device. The log memory can also be accessed over USB.
__Debugging/Configuration:__ The device can be accessed over USB (serial terminal) in order to configure it or get debug messages out of the device. The log memory can also be accessed over USB.
__Schematic:__ Here we go! [Download](https://raw.githubusercontent.com/DL7AD/pecanpico10/master/tracker/hardware/pico/output/pecanpico10.pdf)
__Operation variants__
- Car/Balloon Tracker
- Digipeater
- Weather station (software not implemented yet)
- Image transmitting device
All variants can be combined with each other
__Software Manual__
TODO: How to access it through USB
TODO: How to configure the device
__More:__ *Flashing the chip (link missing)*
# Transmitted test pictures

Wyświetl plik

@ -2,18 +2,22 @@
The Pecan can be either powered by following power sources. The power consumption is around 50mW in sleep mode and around 200mW at normal operation. If the transmitter is constantly transmitting, the tracker consumes around 500mW.
There are two power inputs which can be accessed from the 100mil-pinheader and one by USB. Solar cells are connected to pin 1 and 2. The battery is connected on the backside to the BATT_CONN and GND pad. While the battery is physically connected to the curcuit board, it's not directly connected to the circuit itself unless a jumper is connected between pin 3 and 4. Alternatively the battery can be connected to pin 4 and 15.
There are two power inputs which can be accessed from the 100mil-pinheader and one by USB. The solar cells must be connected to pin 1 and 2. The battery is connected on the backside to the BATT_CONN and GND pad. While the battery is physically connected to the circuit board, it's not directly connected to the circuit itself unless a jumper is connected between pin 3 and 4. Alternatively the battery can be connected to pin 4 and 15.
The circuit can also be powered externally by USB.
## Battery disconnect by USB
Note: Due to an error in the design of the Pecan Pico 10a, the battery must not be connected when USB is applied. You may connect USB and battery at the same time, if D1 and Q1 are removed.
The circuit can also be powered externally by USB. In this case, the battery is disconnected from the circuit by Q1 and the circuit is only powered by USB. This means, that the battery can also not be charged by the solar cell. This particular design has been implemented to be used on a rocket. The circuit should be powered by the carrier rocket until the payload is being ejected in order to have full battery capacitance at the ejection event.
Note: Due to an error in the design of the Pecan Pico 10a, the battery must not be connected when USB is applied. You may connect USB and battery at the same time, if D1 and Q1 are removed. This bug has been fixed in the 10b variant and can be used as intended now.
## USB
USB can be used for operation at the computer. You may connect a battery to the battery input. Once USB is connected, the battery gets disconnected and the tracker is only powered over USB. Once USB is disconnected, the tracker is powered from the battery again. This feature is archived by a MOSFET and doesn not need any software cooperation.
## 3x Alkaline or Lithium Batteries
If you have only a time limited operation planned, you might want to use primary batteries. The tracker needs at least 1.8V in order to operate. In order to use the camera it needs at least 3.3V. So the tracker can be powered from three AA or AAA serial connected batteries from the +VBAT input.
If you have only a time-limited operation planned, you might want to use primary batteries. The tracker needs at least 1.8V in order to operate. The camera needs at least 3.3V. So the tracker may be powered by three AA or AAA serial connected batteries from the +VBAT input. Note: You must not attach a solar cell while the tracker would try to charge it.
## A signle LiPO cell and solar cells
If a long operation is required, the tracker can be powered by a LiPO or LiIon battery. The battery can be charged by Solar cells from the +VSOL input. The tracker may also be operated with solar cells only.
If a long operation is required, the tracker can be powered by a LiPO or LiIon battery. The battery can be charged by solar cells from the +VSOL input. The tracker may also be operated with solar cells only.
TODO: Power scheme missing

Wyświetl plik

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.1712694318">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.1712694318" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.cross.base.1712694318" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.1712694318.64830061" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1747856722" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
<option id="cdt.managedbuild.option.gnu.cross.prefix.797583309" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
<option id="cdt.managedbuild.option.gnu.cross.path.457777320" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1829293763" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
<builder id="cdt.managedbuild.builder.gnu.cross.1600801467" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.779862354" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1257116579" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1026108526" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.85562960" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1153182302" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.1246100600" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1112834172" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.1803255837" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.1182444279" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1442015044" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="pecan10master.null.218906227" name="pecan10master"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/pecan10"/>
</configuration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1712694318;cdt.managedbuild.toolchain.gnu.cross.base.1712694318.64830061;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1026108526;cdt.managedbuild.tool.gnu.cpp.compiler.input.85562960">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1712694318;cdt.managedbuild.toolchain.gnu.cross.base.1712694318.64830061;cdt.managedbuild.tool.gnu.cross.c.compiler.779862354;cdt.managedbuild.tool.gnu.c.compiler.input.1257116579">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>

Wyświetl plik

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>pecan10</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<variableList>
<variable>
<name>CHIBIOS</name>
<value>file:/G:/micro_development/other_projects/pecan_pico/pecanpico10/tracker/software/ChibiOS</value>
</variable>
</variableList>
</projectDescription>

Wyświetl plik

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.toolchain.gnu.cross.base.1712694318" name="Default">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-112370262340608666" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
</extension>
</configuration>
</project>

Wyświetl plik

@ -1,2 +0,0 @@
eclipse.preferences.version=1
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false

Wyświetl plik

@ -1,261 +1,219 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "hal.h"
#include "stm32_gpio.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Type of STM32 GPIO port setup.
*/
typedef struct {
uint32_t moder;
uint32_t otyper;
uint32_t ospeedr;
uint32_t pupdr;
uint32_t odr;
uint32_t afrl;
uint32_t afrh;
} gpio_setup_t;
/**
* @brief Type of STM32 GPIO initialization data.
*/
typedef struct {
#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
gpio_setup_t PAData;
#endif
#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
gpio_setup_t PBData;
#endif
#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
gpio_setup_t PCData;
#endif
#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
gpio_setup_t PDData;
#endif
#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
gpio_setup_t PEData;
#endif
#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
gpio_setup_t PFData;
#endif
#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
gpio_setup_t PGData;
#endif
#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
gpio_setup_t PHData;
#endif
#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
gpio_setup_t PIData;
#endif
#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
gpio_setup_t PJData;
#endif
#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
gpio_setup_t PKData;
#endif
} gpio_config_t;
/**
* @brief STM32 GPIO static initialization data.
*/
static const gpio_config_t gpio_default_config = {
#if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
#endif
#if STM32_HAS_GPIOB
{VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
#endif
#if STM32_HAS_GPIOC
{VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
#endif
#if STM32_HAS_GPIOD
{VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
#endif
#if STM32_HAS_GPIOE
{VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
#endif
#if STM32_HAS_GPIOF
{VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
#endif
#if STM32_HAS_GPIOG
{VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
#endif
#if STM32_HAS_GPIOH
{VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
#endif
#if STM32_HAS_GPIOI
{VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
#endif
#if STM32_HAS_GPIOJ
{VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
#endif
#if STM32_HAS_GPIOK
{VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
#endif
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
gpiop->OTYPER = config->otyper;
gpiop->OSPEEDR = config->ospeedr;
gpiop->PUPDR = config->pupdr;
gpiop->ODR = config->odr;
gpiop->AFRL = config->afrl;
gpiop->AFRH = config->afrh;
gpiop->MODER = config->moder;
}
static void stm32_gpio_init(void) {
/* Enabling GPIO-related clocks, the mask comes from the
registry header file.*/
rccResetAHB1(STM32_GPIO_EN_MASK);
rccEnableAHB1(STM32_GPIO_EN_MASK, true);
/* Initializing all the defined GPIO ports.*/
#if STM32_HAS_GPIOA
gpio_init(GPIOA, &gpio_default_config.PAData);
#endif
#if STM32_HAS_GPIOB
gpio_init(GPIOB, &gpio_default_config.PBData);
#endif
#if STM32_HAS_GPIOC
gpio_init(GPIOC, &gpio_default_config.PCData);
#endif
#if STM32_HAS_GPIOD
gpio_init(GPIOD, &gpio_default_config.PDData);
#endif
#if STM32_HAS_GPIOE
gpio_init(GPIOE, &gpio_default_config.PEData);
#endif
#if STM32_HAS_GPIOF
gpio_init(GPIOF, &gpio_default_config.PFData);
#endif
#if STM32_HAS_GPIOG
gpio_init(GPIOG, &gpio_default_config.PGData);
#endif
#if STM32_HAS_GPIOH
gpio_init(GPIOH, &gpio_default_config.PHData);
#endif
#if STM32_HAS_GPIOI
gpio_init(GPIOI, &gpio_default_config.PIData);
#endif
#if STM32_HAS_GPIOJ
gpio_init(GPIOJ, &gpio_default_config.PJData);
#endif
#if STM32_HAS_GPIOK
gpio_init(GPIOK, &gpio_default_config.PKData);
#endif
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Early initialization code.
* @details GPIO ports and system clocks are initialized before everything
* else.
*/
void __early_init(void) {
stm32_gpio_init();
palSetLineMode(LINE_TCXO_EN, PAL_MODE_OUTPUT_PUSHPULL);
palSetLine(LINE_TCXO_EN);
stm32_clock_init();
}
#if HAL_USE_SDC || defined(__DOXYGEN__)
/**
* @brief SDC card detection.
*/
bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
(void)sdcp;
/* TODO: Fill the implementation.*/
return true;
}
/**
* @brief SDC card write protection detection.
*/
bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
(void)sdcp;
/* TODO: Fill the implementation.*/
return false;
}
#endif /* HAL_USE_SDC */
#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
/**
* @brief MMC_SPI card detection.
*/
bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
(void)mmcp;
return palReadLine(LINE_SD_DET);
}
/**
* @brief MMC_SPI card write protection detection.
*/
bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
(void)mmcp;
/* TODO: Fill the implementation.*/
return false;
}
#endif
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
void boardInit(void) {
}
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "hal.h"
#include "stm32_gpio.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Type of STM32 GPIO port setup.
*/
typedef struct {
uint32_t moder;
uint32_t otyper;
uint32_t ospeedr;
uint32_t pupdr;
uint32_t odr;
uint32_t afrl;
uint32_t afrh;
} gpio_setup_t;
/**
* @brief Type of STM32 GPIO initialization data.
*/
typedef struct {
#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
gpio_setup_t PAData;
#endif
#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
gpio_setup_t PBData;
#endif
#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
gpio_setup_t PCData;
#endif
#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
gpio_setup_t PDData;
#endif
#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
gpio_setup_t PEData;
#endif
#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
gpio_setup_t PFData;
#endif
#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
gpio_setup_t PGData;
#endif
#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
gpio_setup_t PHData;
#endif
#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
gpio_setup_t PIData;
#endif
#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
gpio_setup_t PJData;
#endif
#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
gpio_setup_t PKData;
#endif
} gpio_config_t;
/**
* @brief STM32 GPIO static initialization data.
*/
static const gpio_config_t gpio_default_config = {
#if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
#endif
#if STM32_HAS_GPIOB
{VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
#endif
#if STM32_HAS_GPIOC
{VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
#endif
#if STM32_HAS_GPIOD
{VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
#endif
#if STM32_HAS_GPIOE
{VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
#endif
#if STM32_HAS_GPIOF
{VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
#endif
#if STM32_HAS_GPIOG
{VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
#endif
#if STM32_HAS_GPIOH
{VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
#endif
#if STM32_HAS_GPIOI
{VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
#endif
#if STM32_HAS_GPIOJ
{VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
#endif
#if STM32_HAS_GPIOK
{VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
#endif
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
gpiop->OTYPER = config->otyper;
gpiop->OSPEEDR = config->ospeedr;
gpiop->PUPDR = config->pupdr;
gpiop->ODR = config->odr;
gpiop->AFRL = config->afrl;
gpiop->AFRH = config->afrh;
gpiop->MODER = config->moder;
}
static void stm32_gpio_init(void) {
/* Enabling GPIO-related clocks, the mask comes from the
registry header file.*/
rccResetAHB1(STM32_GPIO_EN_MASK);
rccEnableAHB1(STM32_GPIO_EN_MASK, true);
/* Initializing all the defined GPIO ports.*/
#if STM32_HAS_GPIOA
gpio_init(GPIOA, &gpio_default_config.PAData);
#endif
#if STM32_HAS_GPIOB
gpio_init(GPIOB, &gpio_default_config.PBData);
#endif
#if STM32_HAS_GPIOC
gpio_init(GPIOC, &gpio_default_config.PCData);
#endif
#if STM32_HAS_GPIOD
gpio_init(GPIOD, &gpio_default_config.PDData);
#endif
#if STM32_HAS_GPIOE
gpio_init(GPIOE, &gpio_default_config.PEData);
#endif
#if STM32_HAS_GPIOF
gpio_init(GPIOF, &gpio_default_config.PFData);
#endif
#if STM32_HAS_GPIOG
gpio_init(GPIOG, &gpio_default_config.PGData);
#endif
#if STM32_HAS_GPIOH
gpio_init(GPIOH, &gpio_default_config.PHData);
#endif
#if STM32_HAS_GPIOI
gpio_init(GPIOI, &gpio_default_config.PIData);
#endif
#if STM32_HAS_GPIOJ
gpio_init(GPIOJ, &gpio_default_config.PJData);
#endif
#if STM32_HAS_GPIOK
gpio_init(GPIOK, &gpio_default_config.PKData);
#endif
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Early initialization code.
* @details GPIO ports and system clocks are initialized before everything
* else.
*/
void __early_init(void) {
stm32_gpio_init();
palSetLineMode(LINE_TCXO_EN, PAL_MODE_OUTPUT_PUSHPULL);
palSetLine(LINE_TCXO_EN);
stm32_clock_init();
}
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
void boardInit(void) {
}

Wyświetl plik

@ -244,11 +244,14 @@
*/
// IO
/*
#define LINE_GPIO_PIN PAL_LINE(GPIOA, 8U)
#define LINE_IO_TXD PAL_LINE(GPIOB, 10U)
#define LINE_IO_RXD PAL_LINE(GPIOC, 11U)
*/
// APRS IO lines
/*
#define LINE_IO1 LINE_GPIO_PIN
#define LINE_IO2 LINE_IO_TXD
#define LINE_IO3 LINE_IO_RXD
@ -257,29 +260,39 @@
#define LINE_IO6 PAL_NOLINE
#define LINE_IO7 PAL_NOLINE
#define LINE_IO8 PAL_NOLINE
*/
// LED
/*
#define LINE_IO_BLUE PAL_LINE(GPIOC, 1U)
#define LINE_IO_GREEN PAL_LINE(GPIOC, 3U)
*/
// GPS
/*
#define LINE_GPS_EN PAL_LINE(GPIOA, 15U)
#define LINE_GPS_RESET PAL_LINE(GPIOB, 14U)
#define LINE_GPS_TXD PAL_LINE(GPIOB, 13U)
#define LINE_GPS_RXD PAL_LINE(GPIOB, 12U)
#define LINE_GPS_TIMEPULSE PAL_LINE(GPIOB, 15U)
*/
// I2C
/*
#define LINE_I2C_SCL PAL_LINE(GPIOB, 8U)
#define LINE_I2C_SDA PAL_LINE(GPIOB, 9U)
*/
// SPI
/*
#define LINE_SPI_SCK PAL_LINE(GPIOB, 3U)
#define LINE_SPI_MISO PAL_LINE(GPIOB, 4U)
#define LINE_SPI_MOSI PAL_LINE(GPIOB, 5U)
*/
// Camera pins
/*
#define LINE_CAM_XCLK PAL_LINE(GPIOC, 9U)
#define LINE_CAM_PCLK PAL_LINE(GPIOC, 6U)
#define LINE_CAM_VSYNC PAL_LINE(GPIOC, 5U)
@ -293,36 +306,45 @@
#define LINE_CAM_D9 PAL_LINE(GPIOA, 7U)
#define LINE_CAM_EN PAL_LINE(GPIOC, 7U)
#define LINE_CAM_RESET PAL_LINE(GPIOB, 0U)
*/
// Radio pins
/*
#define LINE_RADIO_CS PAL_LINE(GPIOC, 12U)
#define LINE_RADIO_SDN PAL_LINE(GPIOC, 10U)
#define LINE_RADIO_IRQ PAL_LINE(GPIOD, 2U)
#define LINE_RADIO_GPIO0 PAL_LINE(GPIOB, 7U)
#define LINE_RADIO_GPIO1 PAL_LINE(GPIOB, 6U)
*/
// SD Card pins
/*
#define LINE_SD_CS PAL_LINE(GPIOC, 0U)
#define LINE_SD_DET PAL_LINE(GPIOC, 8U)
*/
// ADC
/*
#define LINE_ADC_VSOL PAL_LINE(GPIOC, 2U)
#define LINE_ADC_VBAT PAL_LINE(GPIOB, 1U)
#define LINE_ADC_VUSB PAL_LINE(GPIOC, 4U)
*/
// USB
/*
#define LINE_USB_ID PAL_LINE(GPIOA, 10U)
#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U)
#define LINE_USB_DM PAL_LINE(GPIOA, 11U)
#define LINE_USB_DP PAL_LINE(GPIOA, 12U)
*/
// Misc
#define LINE_TCXO_EN PAL_LINE(GPIOC, 13U)
// Hardware dependent settings
#define Si446x_CLK STM32_HSECLK /* Oscillator frequency in Hz */
#define Si446x_CLK_OFFSET 22 /* Oscillator frequency drift in ppm */
#define Si446x_CLK_TCXO_EN true /* Set this true, if a TCXO is used, false for XTAL */
//#define Si446x_CLK STM32_HSECLK /* Oscillator frequency in Hz */
//#define Si446x_CLK_OFFSET 22 /* Oscillator frequency drift in ppm */
//#define Si446x_CLK_TCXO_EN true /* Set this true, if a TCXO is used, false for XTAL */
/*

Wyświetl plik

@ -63,7 +63,6 @@ const radio_config_t radio_list[] = {
}
};
const SerialConfig debug_config = {
115200,
0,
@ -79,7 +78,6 @@ const SerialConfig debug_config = {
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
@ -88,19 +86,6 @@ const SerialConfig debug_config = {
/* Module exported functions. */
/*===========================================================================*/
void pktConfigSerialDiag(void) {
#if ENABLE_EXTERNAL_I2C == FALSE
/* USART3 TX. */
palSetLineMode(LINE_USART3_TX, PAL_MODE_ALTERNATE(7));
/* USART3 RX. */
palSetLineMode(LINE_USART3_RX, PAL_MODE_ALTERNATE(7));
#endif
}
void pktConfigSerialPkt(void) {
}
/**
* Get number of radios for this board type.
*/
@ -117,6 +102,19 @@ const radio_config_t *pktGetRadioList(void) {
return radio_list;
}
void pktConfigSerialDiag(void) {
#if ENABLE_EXTERNAL_I2C == FALSE
/* USART3 TX. */
palSetLineMode(LINE_USART3_TX, PAL_MODE_ALTERNATE(7));
/* USART3 RX. */
palSetLineMode(LINE_USART3_RX, PAL_MODE_ALTERNATE(7));
#endif
}
void pktConfigSerialPkt(void) {
}
/**
* TODO: Move this into pktconf.h and use general GPIO to setup.
*/
@ -137,7 +135,6 @@ uint8_t pktReadIOlines() {
| palReadLine(LINE_IO_RXD) << 2;
}
void pktSerialStart(void) {
#if ENABLE_EXTERNAL_I2C == FALSE
pktConfigSerialDiag();
@ -180,7 +177,7 @@ void pktWrite(uint8_t *buf, uint32_t len) {
chnWrite((BaseSequentialStream*)SERIAL_CFG_DEBUG_DRIVER, buf, len);
}
void sysConfigureCoreIO(void) {
void pktConfigureCoreIO(void) {
/* Setup SPI3. */
palSetLineMode(LINE_SPI_SCK, PAL_MODE_ALTERNATE(6)
| PAL_STM32_OSPEED_HIGHEST); // SCK
@ -202,16 +199,5 @@ void sysConfigureCoreIO(void) {
#endif
}
/*
* Return a single radio parameter record pointer
* The radio parameter picks a single records.
* The current system does not work if the same radio is listed multiple times.
* TODO: Have an enumeration and check radio array on startup.
*/
radio_config_t *pktGetRadioParameters(radio_unit_t radio) {
(void)radio;
return NULL;
}
/** @} */

Wyświetl plik

@ -33,6 +33,71 @@
*/
#define PKT_RADIO_SPI &SPID3
// Camera pins
#define LINE_CAM_XCLK PAL_LINE(GPIOC, 9U)
#define LINE_CAM_PCLK PAL_LINE(GPIOC, 6U)
#define LINE_CAM_VSYNC PAL_LINE(GPIOC, 5U)
#define LINE_CAM_D2 PAL_LINE(GPIOA, 0U)
#define LINE_CAM_D3 PAL_LINE(GPIOA, 1U)
#define LINE_CAM_D4 PAL_LINE(GPIOA, 2U)
#define LINE_CAM_D5 PAL_LINE(GPIOA, 3U)
#define LINE_CAM_D6 PAL_LINE(GPIOA, 4U)
#define LINE_CAM_D7 PAL_LINE(GPIOA, 5U)
#define LINE_CAM_D8 PAL_LINE(GPIOA, 6U)
#define LINE_CAM_D9 PAL_LINE(GPIOA, 7U)
#define LINE_CAM_EN PAL_LINE(GPIOC, 7U)
#define LINE_CAM_RESET PAL_LINE(GPIOB, 0U)
// SD Card pins
#define LINE_SD_CS PAL_LINE(GPIOC, 0U)
#define LINE_SD_DET PAL_LINE(GPIOC, 8U)
// ADC
#define LINE_ADC_VSOL PAL_LINE(GPIOC, 2U)
#define LINE_ADC_VBAT PAL_LINE(GPIOB, 1U)
#define LINE_ADC_VUSB PAL_LINE(GPIOC, 4U)
// USB
#define LINE_USB_ID PAL_LINE(GPIOA, 10U)
#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U)
#define LINE_USB_DM PAL_LINE(GPIOA, 11U)
#define LINE_USB_DP PAL_LINE(GPIOA, 12U)
// IO
#define LINE_GPIO_PIN PAL_LINE(GPIOA, 8U)
#define LINE_IO_TXD PAL_LINE(GPIOB, 10U)
#define LINE_IO_RXD PAL_LINE(GPIOC, 11U)
// LED
#define LINE_IO_BLUE PAL_LINE(GPIOC, 1U)
#define LINE_IO_GREEN PAL_LINE(GPIOC, 3U)
// I2C
#define LINE_I2C_SCL PAL_LINE(GPIOB, 8U)
#define LINE_I2C_SDA PAL_LINE(GPIOB, 9U)
// GPS
#define LINE_GPS_EN PAL_LINE(GPIOA, 15U)
#define LINE_GPS_RESET PAL_LINE(GPIOB, 14U)
#define LINE_GPS_TXD PAL_LINE(GPIOB, 13U)
#define LINE_GPS_RXD PAL_LINE(GPIOB, 12U)
#define LINE_GPS_TIMEPULSE PAL_LINE(GPIOB, 15U)
// APRS IO lines
#define LINE_IO1 LINE_GPIO_PIN
#define LINE_IO2 LINE_IO_TXD
#define LINE_IO3 LINE_IO_RXD
#define LINE_IO4 PAL_NOLINE
#define LINE_IO5 PAL_NOLINE
#define LINE_IO6 PAL_NOLINE
#define LINE_IO7 PAL_NOLINE
#define LINE_IO8 PAL_NOLINE
// Hardware dependent settings
#define Si446x_CLK STM32_HSECLK /* Oscillator frequency in Hz */
#define Si446x_CLK_OFFSET 22 /* Oscillator frequency drift in ppm */
#define Si446x_CLK_TCXO_EN true /* Set this true, if a TCXO is used, false for XTAL */
/*
* Radio GPIO definitions.
*/
@ -41,6 +106,7 @@
#define LINE_RADIO_IRQ PAL_LINE(GPIOD, 2U)
#define LINE_RADIO_GPIO0 PAL_LINE(GPIOB, 7U)
#define LINE_RADIO_GPIO1 PAL_LINE(GPIOB, 6U)
#define LINE_SPI_SCK PAL_LINE(GPIOB, 3U)
#define LINE_SPI_MISO PAL_LINE(GPIOB, 4U)
#define LINE_SPI_MOSI PAL_LINE(GPIOB, 5U)
@ -56,11 +122,11 @@
#define DEFAULT_OPERATING_FREQ 144800000
/* Si446x clock setup. */
#define Si446x_CLK STM32_HSECLK /* Oscillator frequency in Hz */
#define Si446x_CLK_OFFSET 22 /* Oscillator frequency drift in ppm */
#define Si446x_CLK_TCXO_EN true /* Set this true, if a TCXO is used, false for XTAL */
//#define NUM_PKT_RADIOS 1
#define NUM_BANDS_PER_RADIO 2
/* LED status indicators (set to PAL_NOLINE if not available). */
@ -146,6 +212,7 @@
#define USE_CCM_HEAP_RX_BUFFERS TRUE
#define PKT_RX_RLS_USE_NO_FIFO TRUE
/*
* Number of general AX25/APRS processing & frame send buffers.
* Can configured as being in CCM to save system core memory use.
@ -193,14 +260,12 @@ typedef struct radioConfig {
/* External declarations. */
/*===========================================================================*/
//extern const radio_param_t radio_list[NUM_PKT_RADIOS];
#ifdef __cplusplus
extern "C" {
#endif
void pktConfigSerialDiag(void);
void pktConfigSerialPkt(void);
void sysConfigureCoreIO(void);
void pktConfigureCoreIO(void);
void pktSetLineModeICU(void);
void pktSerialStart(void);
void dbgWrite(uint8_t level, uint8_t *buf, uint32_t len);

Wyświetl plik

@ -1,261 +1,218 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "hal.h"
#include "stm32_gpio.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Type of STM32 GPIO port setup.
*/
typedef struct {
uint32_t moder;
uint32_t otyper;
uint32_t ospeedr;
uint32_t pupdr;
uint32_t odr;
uint32_t afrl;
uint32_t afrh;
} gpio_setup_t;
/**
* @brief Type of STM32 GPIO initialization data.
*/
typedef struct {
#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
gpio_setup_t PAData;
#endif
#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
gpio_setup_t PBData;
#endif
#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
gpio_setup_t PCData;
#endif
#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
gpio_setup_t PDData;
#endif
#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
gpio_setup_t PEData;
#endif
#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
gpio_setup_t PFData;
#endif
#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
gpio_setup_t PGData;
#endif
#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
gpio_setup_t PHData;
#endif
#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
gpio_setup_t PIData;
#endif
#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
gpio_setup_t PJData;
#endif
#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
gpio_setup_t PKData;
#endif
} gpio_config_t;
/**
* @brief STM32 GPIO static initialization data.
*/
static const gpio_config_t gpio_default_config = {
#if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
#endif
#if STM32_HAS_GPIOB
{VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
#endif
#if STM32_HAS_GPIOC
{VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
#endif
#if STM32_HAS_GPIOD
{VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
#endif
#if STM32_HAS_GPIOE
{VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
#endif
#if STM32_HAS_GPIOF
{VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
#endif
#if STM32_HAS_GPIOG
{VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
#endif
#if STM32_HAS_GPIOH
{VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
#endif
#if STM32_HAS_GPIOI
{VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
#endif
#if STM32_HAS_GPIOJ
{VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
#endif
#if STM32_HAS_GPIOK
{VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
#endif
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
gpiop->OTYPER = config->otyper;
gpiop->OSPEEDR = config->ospeedr;
gpiop->PUPDR = config->pupdr;
gpiop->ODR = config->odr;
gpiop->AFRL = config->afrl;
gpiop->AFRH = config->afrh;
gpiop->MODER = config->moder;
}
static void stm32_gpio_init(void) {
/* Enabling GPIO-related clocks, the mask comes from the
registry header file.*/
rccResetAHB1(STM32_GPIO_EN_MASK);
rccEnableAHB1(STM32_GPIO_EN_MASK, true);
/* Initializing all the defined GPIO ports.*/
#if STM32_HAS_GPIOA
gpio_init(GPIOA, &gpio_default_config.PAData);
#endif
#if STM32_HAS_GPIOB
gpio_init(GPIOB, &gpio_default_config.PBData);
#endif
#if STM32_HAS_GPIOC
gpio_init(GPIOC, &gpio_default_config.PCData);
#endif
#if STM32_HAS_GPIOD
gpio_init(GPIOD, &gpio_default_config.PDData);
#endif
#if STM32_HAS_GPIOE
gpio_init(GPIOE, &gpio_default_config.PEData);
#endif
#if STM32_HAS_GPIOF
gpio_init(GPIOF, &gpio_default_config.PFData);
#endif
#if STM32_HAS_GPIOG
gpio_init(GPIOG, &gpio_default_config.PGData);
#endif
#if STM32_HAS_GPIOH
gpio_init(GPIOH, &gpio_default_config.PHData);
#endif
#if STM32_HAS_GPIOI
gpio_init(GPIOI, &gpio_default_config.PIData);
#endif
#if STM32_HAS_GPIOJ
gpio_init(GPIOJ, &gpio_default_config.PJData);
#endif
#if STM32_HAS_GPIOK
gpio_init(GPIOK, &gpio_default_config.PKData);
#endif
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Early initialization code.
* @details GPIO ports and system clocks are initialized before everything
* else.
*/
void __early_init(void) {
stm32_gpio_init();
palSetLineMode(LINE_TCXO_EN, PAL_MODE_OUTPUT_PUSHPULL);
palSetLine(LINE_TCXO_EN);
stm32_clock_init();
}
#if HAL_USE_SDC || defined(__DOXYGEN__)
/**
* @brief SDC card detection.
*/
bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
(void)sdcp;
/* TODO: Fill the implementation.*/
return true;
}
/**
* @brief SDC card write protection detection.
*/
bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
(void)sdcp;
/* TODO: Fill the implementation.*/
return false;
}
#endif /* HAL_USE_SDC */
#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
/**
* @brief MMC_SPI card detection.
*/
bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
(void)mmcp;
return palReadLine(LINE_SD_DET);
}
/**
* @brief MMC_SPI card write protection detection.
*/
bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
(void)mmcp;
/* TODO: Fill the implementation.*/
return false;
}
#endif
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
void boardInit(void) {
}
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "hal.h"
#include "stm32_gpio.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Type of STM32 GPIO port setup.
*/
typedef struct {
uint32_t moder;
uint32_t otyper;
uint32_t ospeedr;
uint32_t pupdr;
uint32_t odr;
uint32_t afrl;
uint32_t afrh;
} gpio_setup_t;
/**
* @brief Type of STM32 GPIO initialization data.
*/
typedef struct {
#if STM32_HAS_GPIOA || defined(__DOXYGEN__)
gpio_setup_t PAData;
#endif
#if STM32_HAS_GPIOB || defined(__DOXYGEN__)
gpio_setup_t PBData;
#endif
#if STM32_HAS_GPIOC || defined(__DOXYGEN__)
gpio_setup_t PCData;
#endif
#if STM32_HAS_GPIOD || defined(__DOXYGEN__)
gpio_setup_t PDData;
#endif
#if STM32_HAS_GPIOE || defined(__DOXYGEN__)
gpio_setup_t PEData;
#endif
#if STM32_HAS_GPIOF || defined(__DOXYGEN__)
gpio_setup_t PFData;
#endif
#if STM32_HAS_GPIOG || defined(__DOXYGEN__)
gpio_setup_t PGData;
#endif
#if STM32_HAS_GPIOH || defined(__DOXYGEN__)
gpio_setup_t PHData;
#endif
#if STM32_HAS_GPIOI || defined(__DOXYGEN__)
gpio_setup_t PIData;
#endif
#if STM32_HAS_GPIOJ || defined(__DOXYGEN__)
gpio_setup_t PJData;
#endif
#if STM32_HAS_GPIOK || defined(__DOXYGEN__)
gpio_setup_t PKData;
#endif
} gpio_config_t;
/**
* @brief STM32 GPIO static initialization data.
*/
static const gpio_config_t gpio_default_config = {
#if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
#endif
#if STM32_HAS_GPIOB
{VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
#endif
#if STM32_HAS_GPIOC
{VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
#endif
#if STM32_HAS_GPIOD
{VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
#endif
#if STM32_HAS_GPIOE
{VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
#endif
#if STM32_HAS_GPIOF
{VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
#endif
#if STM32_HAS_GPIOG
{VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
#endif
#if STM32_HAS_GPIOH
{VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
#endif
#if STM32_HAS_GPIOI
{VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH},
#endif
#if STM32_HAS_GPIOJ
{VAL_GPIOJ_MODER, VAL_GPIOJ_OTYPER, VAL_GPIOJ_OSPEEDR, VAL_GPIOJ_PUPDR,
VAL_GPIOJ_ODR, VAL_GPIOJ_AFRL, VAL_GPIOJ_AFRH},
#endif
#if STM32_HAS_GPIOK
{VAL_GPIOK_MODER, VAL_GPIOK_OTYPER, VAL_GPIOK_OSPEEDR, VAL_GPIOK_PUPDR,
VAL_GPIOK_ODR, VAL_GPIOK_AFRL, VAL_GPIOK_AFRH}
#endif
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void gpio_init(stm32_gpio_t *gpiop, const gpio_setup_t *config) {
gpiop->OTYPER = config->otyper;
gpiop->OSPEEDR = config->ospeedr;
gpiop->PUPDR = config->pupdr;
gpiop->ODR = config->odr;
gpiop->AFRL = config->afrl;
gpiop->AFRH = config->afrh;
gpiop->MODER = config->moder;
}
static void stm32_gpio_init(void) {
/* Enabling GPIO-related clocks, the mask comes from the
registry header file.*/
rccResetAHB1(STM32_GPIO_EN_MASK);
rccEnableAHB1(STM32_GPIO_EN_MASK, true);
/* Initializing all the defined GPIO ports.*/
#if STM32_HAS_GPIOA
gpio_init(GPIOA, &gpio_default_config.PAData);
#endif
#if STM32_HAS_GPIOB
gpio_init(GPIOB, &gpio_default_config.PBData);
#endif
#if STM32_HAS_GPIOC
gpio_init(GPIOC, &gpio_default_config.PCData);
#endif
#if STM32_HAS_GPIOD
gpio_init(GPIOD, &gpio_default_config.PDData);
#endif
#if STM32_HAS_GPIOE
gpio_init(GPIOE, &gpio_default_config.PEData);
#endif
#if STM32_HAS_GPIOF
gpio_init(GPIOF, &gpio_default_config.PFData);
#endif
#if STM32_HAS_GPIOG
gpio_init(GPIOG, &gpio_default_config.PGData);
#endif
#if STM32_HAS_GPIOH
gpio_init(GPIOH, &gpio_default_config.PHData);
#endif
#if STM32_HAS_GPIOI
gpio_init(GPIOI, &gpio_default_config.PIData);
#endif
#if STM32_HAS_GPIOJ
gpio_init(GPIOJ, &gpio_default_config.PJData);
#endif
#if STM32_HAS_GPIOK
gpio_init(GPIOK, &gpio_default_config.PKData);
#endif
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Early initialization code.
* @details GPIO ports and system clocks are initialized before everything
* else.
*/
void __early_init(void) {
stm32_gpio_init();
palSetLineMode(LINE_TCXO_EN, PAL_MODE_OUTPUT_PUSHPULL);
palSetLine(LINE_TCXO_EN);
stm32_clock_init();
}
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
void boardInit(void) {
}

Wyświetl plik

@ -244,12 +244,15 @@
*/
// IO
/*
#define LINE_GPIO_PIN1 PAL_LINE(GPIOA, 8U)
#define LINE_GPIO_PIN2 PAL_LINE(GPIOC, 15U)
#define LINE_IO_TXD PAL_LINE(GPIOB, 10U)
#define LINE_IO_RXD PAL_LINE(GPIOC, 11U)
*/
//APRS IO lines
/*
#define LINE_IO1 LINE_GPIO_PIN1
#define LINE_IO2 LINE_IO_TXD
#define LINE_IO3 LINE_IO_RXD
@ -258,29 +261,39 @@
#define LINE_IO6 PAL_NOLINE
#define LINE_IO7 PAL_NOLINE
#define LINE_IO8 PAL_NOLINE
*/
// LED
/*
#define LINE_IO_BLUE PAL_LINE(GPIOC, 1U)
#define LINE_IO_GREEN PAL_LINE(GPIOC, 3U)
*/
// GPS
/*
#define LINE_GPS_EN PAL_LINE(GPIOC, 5U)
#define LINE_GPS_RESET PAL_LINE(GPIOA, 15U)
#define LINE_GPS_TXD PAL_LINE(GPIOB, 13U)
#define LINE_GPS_RXD PAL_LINE(GPIOB, 12U)
#define LINE_GPS_TIMEPULSE PAL_LINE(GPIOB, 15U)
*/
// I2C
/*
#define LINE_I2C_SCL PAL_LINE(GPIOB, 8U)
#define LINE_I2C_SDA PAL_LINE(GPIOB, 9U)
*/
// SPI
/*
#define LINE_SPI_SCK PAL_LINE(GPIOB, 3U)
#define LINE_SPI_MISO PAL_LINE(GPIOB, 4U)
#define LINE_SPI_MOSI PAL_LINE(GPIOB, 5U)
*/
// Camera pins
/*
#define LINE_CAM_XCLK PAL_LINE(GPIOC, 9U)
#define LINE_CAM_PCLK PAL_LINE(GPIOC, 6U)
#define LINE_CAM_VSYNC PAL_LINE(GPIOB, 14U)
@ -294,41 +307,50 @@
#define LINE_CAM_D9 PAL_LINE(GPIOA, 7U)
#define LINE_CAM_EN PAL_LINE(GPIOC, 7U)
#define LINE_CAM_RESET PAL_LINE(GPIOB, 0U)
*/
// Radio pins
/*
#define LINE_RADIO_CS PAL_LINE(GPIOC, 12U)
#define LINE_RADIO_SDN PAL_LINE(GPIOC, 10U)
#define LINE_RADIO_IRQ PAL_LINE(GPIOD, 2U)
#define LINE_RADIO_GPIO0 PAL_LINE(GPIOB, 7U)
#define LINE_RADIO_GPIO1 PAL_LINE(GPIOB, 6U)
*/
// SD Card pins
/*
#define LINE_SD_CS PAL_LINE(GPIOC, 0U)
#define LINE_SD_DET PAL_LINE(GPIOC, 8U)
*/
// ADC
/*
#define LINE_ADC_VSOL PAL_LINE(GPIOC, 2U)
#define LINE_ADC_VBAT PAL_LINE(GPIOB, 1U)
#define LINE_ADC_VUSB PAL_LINE(GPIOC, 4U)
*/
// USB
/*
#define LINE_USB_ID PAL_LINE(GPIOA, 10U)
#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U)
#define LINE_USB_DM PAL_LINE(GPIOA, 11U)
#define LINE_USB_DP PAL_LINE(GPIOA, 12U)
*/
// Misc
#define LINE_TCXO_EN PAL_LINE(GPIOC, 13U)
// Hardware dependent settings
#define Si446x_MIN_FREQ 144000000 /* Minimum allowed frequency in Hz */
#define Si446x_MAX_FREQ 148000000 /* Maximum allowed frequency in Hz */
#define Si446x_BASE_FREQ Si446x_MIN_FREQ
#define Si446x_STEP_HZ 12500
#define Si446x_CLK STM32_HSECLK /* Oscillator frequency in Hz */
#define Si446x_CLK_OFFSET 22 /* Oscillator frequency drift in ppm */
#define Si446x_CLK_TCXO_EN true /* Set this true, if a TCXO is used, false for XTAL */
//#define Si446x_MIN_FREQ 144000000 /* Minimum allowed frequency in Hz */
//#define Si446x_MAX_FREQ 148000000 /* Maximum allowed frequency in Hz */
//#define Si446x_BASE_FREQ Si446x_MIN_FREQ
//#define Si446x_STEP_HZ 12500
//#define Si446x_CLK STM32_HSECLK /* Oscillator frequency in Hz */
//#define Si446x_CLK_OFFSET 22 /* Oscillator frequency drift in ppm */
//#define Si446x_CLK_TCXO_EN true /* Set this true, if a TCXO is used, false for XTAL */
/*

Wyświetl plik

@ -45,22 +45,6 @@ const radio_band_t band_70cm = {
/* Module exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
typedef struct SysProviders {
} providers_t;
@ -86,6 +70,22 @@ const SerialConfig debug_config = {
0
};
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* Get number of radios for this board type.
*/
@ -113,10 +113,27 @@ void pktConfigSerialPkt(void) {
}
/**
* TODO: Move this into pktconf.h and use general GPIO to setup.
*/
void pktSetLineModeICU(void) {
palSetLineMode(LINE_ICU, PAL_MODE_INPUT | PAL_MODE_ALTERNATE(2));
}
/*
* Read GPIO that are used for:
* a) general use or
* b) UART and s/w I2C external.
*
* @return State of lines regardless of general or specific use.
*/
uint8_t pktReadIOlines() {
return palReadLine(LINE_GPIO_PIN1)
| palReadLine(LINE_IO_TXD) << 1
| palReadLine(LINE_IO_RXD) << 2
| palReadLine(LINE_GPIO_PIN2);
}
void pktSerialStart(void) {
#if ENABLE_EXTERNAL_I2C == FALSE
pktConfigSerialDiag();
@ -155,26 +172,11 @@ int dbgPrintf(uint8_t level, const char *format, ...) {
#endif
}
/*
* Read GPIO that are used for:
* a) general use or
* b) UART and s/w I2C external.
*
* @return State of lines regardless of general or specific use.
*/
uint8_t pktReadIOlines() {
return palReadLine(LINE_GPIO_PIN1)
| palReadLine(LINE_IO_TXD) << 1
| palReadLine(LINE_IO_RXD) << 2
| palReadLine(LINE_GPIO_PIN2);
}
void pktWrite(uint8_t *buf, uint32_t len) {
chnWrite((BaseSequentialStream*)SERIAL_CFG_DEBUG_DRIVER, buf, len);
}
void sysConfigureCoreIO(void) {
void pktConfigureCoreIO(void) {
/* Setup SPI3. */
palSetLineMode(LINE_SPI_SCK, PAL_MODE_ALTERNATE(6)
| PAL_STM32_OSPEED_HIGHEST); // SCK

Wyświetl plik

@ -33,6 +33,72 @@
*/
#define PKT_RADIO_SPI &SPID3
// Camera pins
#define LINE_CAM_XCLK PAL_LINE(GPIOC, 9U)
#define LINE_CAM_PCLK PAL_LINE(GPIOC, 6U)
#define LINE_CAM_VSYNC PAL_LINE(GPIOB, 14U)
#define LINE_CAM_D2 PAL_LINE(GPIOA, 0U)
#define LINE_CAM_D3 PAL_LINE(GPIOA, 1U)
#define LINE_CAM_D4 PAL_LINE(GPIOA, 2U)
#define LINE_CAM_D5 PAL_LINE(GPIOA, 3U)
#define LINE_CAM_D6 PAL_LINE(GPIOA, 4U)
#define LINE_CAM_D7 PAL_LINE(GPIOA, 5U)
#define LINE_CAM_D8 PAL_LINE(GPIOA, 6U)
#define LINE_CAM_D9 PAL_LINE(GPIOA, 7U)
#define LINE_CAM_EN PAL_LINE(GPIOC, 7U)
#define LINE_CAM_RESET PAL_LINE(GPIOB, 0U)
// SD Card pins
#define LINE_SD_CS PAL_LINE(GPIOC, 0U)
#define LINE_SD_DET PAL_LINE(GPIOC, 8U)
// ADC
#define LINE_ADC_VSOL PAL_LINE(GPIOC, 2U)
#define LINE_ADC_VBAT PAL_LINE(GPIOB, 1U)
#define LINE_ADC_VUSB PAL_LINE(GPIOC, 4U)
// USB
#define LINE_USB_ID PAL_LINE(GPIOA, 10U)
#define LINE_USB_VBUS PAL_LINE(GPIOA, 9U)
#define LINE_USB_DM PAL_LINE(GPIOA, 11U)
#define LINE_USB_DP PAL_LINE(GPIOA, 12U)
// LED
#define LINE_IO_BLUE PAL_LINE(GPIOC, 1U)
#define LINE_IO_GREEN PAL_LINE(GPIOC, 3U)
// I2C
#define LINE_I2C_SCL PAL_LINE(GPIOB, 8U)
#define LINE_I2C_SDA PAL_LINE(GPIOB, 9U)
// GPS
#define LINE_GPS_EN PAL_LINE(GPIOC, 5U)
#define LINE_GPS_RESET PAL_LINE(GPIOA, 15U)
#define LINE_GPS_TXD PAL_LINE(GPIOB, 13U)
#define LINE_GPS_RXD PAL_LINE(GPIOB, 12U)
#define LINE_GPS_TIMEPULSE PAL_LINE(GPIOB, 15U)
// IO
#define LINE_GPIO_PIN1 PAL_LINE(GPIOA, 8U)
#define LINE_GPIO_PIN2 PAL_LINE(GPIOC, 15U)
#define LINE_IO_TXD PAL_LINE(GPIOB, 10U)
#define LINE_IO_RXD PAL_LINE(GPIOC, 11U)
// APRS IO lines
#define LINE_IO1 LINE_GPIO_PIN1
#define LINE_IO2 LINE_IO_TXD
#define LINE_IO3 LINE_IO_RXD
#define LINE_IO4 LINE_GPIO_PIN2
#define LINE_IO5 PAL_NOLINE
#define LINE_IO6 PAL_NOLINE
#define LINE_IO7 PAL_NOLINE
#define LINE_IO8 PAL_NOLINE
// Hardware dependent settings
#define Si446x_CLK STM32_HSECLK /* Oscillator frequency in Hz */
#define Si446x_CLK_OFFSET 22 /* Oscillator frequency drift in ppm */
#define Si446x_CLK_TCXO_EN true /* Set this true, if a TCXO is used, false for XTAL */
/*
* Radio GPIO definitions.
*/
@ -45,6 +111,11 @@
#define LINE_SPI_MISO PAL_LINE(GPIOB, 4U)
#define LINE_SPI_MOSI PAL_LINE(GPIOB, 5U)
// SPI
#define LINE_SPI_SCK PAL_LINE(GPIOB, 3U)
#define LINE_SPI_MISO PAL_LINE(GPIOB, 4U)
#define LINE_SPI_MOSI PAL_LINE(GPIOB, 5U)
#define BAND_MIN_2M_FREQ 144000000 /* Minimum allowed frequency in Hz */
#define BAND_MAX_2M_FREQ 148000000 /* Maximum allowed frequency in Hz */
#define BAND_STEP_2M_HZ 12500
@ -61,7 +132,6 @@
#define Si446x_CLK_OFFSET 22 /* Oscillator frequency drift in ppm */
#define Si446x_CLK_TCXO_EN true /* Set this true, if a TCXO is used, false for XTAL */
//#define NUM_PKT_RADIOS 1
#define NUM_BANDS_PER_RADIO 2
/* LED status indicators (set to PAL_NOLINE if not available). */
@ -74,6 +144,7 @@
/* Diagnostic PWM mirror port. */
#define LINE_PWM_MIRROR PAL_NOLINE
/* Radio ports. */
#define LINE_CCA LINE_RADIO_IRQ
#define LINE_ICU LINE_RADIO_GPIO1
@ -88,12 +159,6 @@
#define LINE_USART3_RX LINE_IO_RXD
#endif
/**
* ICU related definitions.
*/
#define PWM_ICU ICUD4
#define PWM_TIMER_CHANNEL 0
/* If set to true, the USB interface will be switched on. The tracker is also switched to
* 3V, because USB would not work at 1.8V. Note that the transmission power is increased
* too when operating at 3V. This option will also run the STM32 at 48MHz (AHB) permanently
@ -101,6 +166,13 @@
*/
#define ACTIVATE_USB TRUE
/**
* ICU related definitions.
*/
#define PWM_ICU ICUD4
#define PWM_TIMER_CHANNEL 0
#define PWM_ICU_CLK STM32_TIMCLK1
/* ICU counter frequency. */
/*
* TODO: This should be calculated using SYSTEM CLOCK.
@ -109,6 +181,10 @@
#define ICU_COUNT_FREQUENCY 6000000U
#if ((PWM_ICU_CLK % ICU_COUNT_FREQUENCY) != 0)
#error "Invalid ICU frequency for APBx clock setting"
#endif
#define USE_12_BIT_PWM FALSE
/*
@ -142,8 +218,11 @@
#define PKT_RX_RLS_USE_NO_FIFO FALSE
/* Number of general AX25/APRS processing & frame send buffers. */
#define NUMBER_COMMON_PKT_BUFFERS 10U
/*
* Number of general AX25/APRS processing & frame send buffers.
* Can configured as being in CCM to save system core memory use.
*/
#define NUMBER_COMMON_PKT_BUFFERS 10U
#define RESERVE_BUFFERS_FOR_INTERNAL 2U
#define MAX_BUFFERS_FOR_BURST_SEND 5U
#if (MAX_BUFFERS_FOR_BURST_SEND > \
@ -191,7 +270,7 @@ extern "C" {
#endif
void pktConfigSerialDiag(void);
void pktConfigSerialPkt(void);
void sysConfigureCoreIO(void);
void pktConfigureCoreIO(void);
void pktSetLineModeICU(void);
void pktSerialStart(void);
void dbgWrite(uint8_t level, uint8_t *buf, uint32_t len);

Wyświetl plik

@ -0,0 +1,14 @@
# Config for pp10 board with STM32F413.
# Debug probe is ST-LINK V2.
# Uses openocd config files for stlink and stm32f4
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/stm32f4x.cfg]
set remotetimeout 3000
# reset_config srst_only
# reset_config srst_push_pull
reset_config none

Wyświetl plik

@ -13,11 +13,22 @@ int main(void) {
chSysInit(); // Startup RTOS
/* Setup core IO peripherals. */
sysConfigureCoreIO();
pktConfigureCoreIO();
// Init debugging (Serial debug port, LEDs)
DEBUG_INIT();
#if ACTIVATE_USB
/*
* TODO: Defer configure of USB mode.
* Set D+ (LINE_USB_DP) as pushpull out and low in board.h.
* Then delay here before ALT 10 for USB.
*/
/* Start Serial Over USB. */
startSDU();
TRACE_INFO("MAIN > USB startup");
#endif
/*
* Setup buffers in CCM if available.
* Setup packet primary data.
@ -26,12 +37,7 @@ int main(void) {
chDbgAssert(pkt == true, "failed to init packet system");
#if ACTIVATE_USB
/* Start Serial Over USB. */
startSDU();
#endif
/* Start serial channels if selected. */
/* Start serial diagnostic channels if selected. */
pktSerialStart();
/* Create packet radio service. */
@ -41,12 +47,13 @@ int main(void) {
pktEnableEventTrace();
}
TRACE_INFO("MAIN > Startup");
TRACE_INFO("MAIN > Starting threads");
// Startup threads
start_essential_threads(); // Startup required modules (tracking manager, watchdog)
start_user_threads(); // Startup optional modules (eg. POSITION, LOG, ...)
TRACE_INFO("MAIN > Active");
while(true) {
#if ACTIVATE_USB
manageTraceAndShell();

Wyświetl plik

@ -178,7 +178,7 @@ const conf_t conf_flash_default = {
.gps_off_vbat = 3000, // mV
.gps_onper_vbat = 4000, // mV
// GPS altitude model control (air pressure determined by on-board BME280)
// GPS altitude model control (air pressure controlled using on-board BME280)
.gps_pressure = 90000, // Air pressure (Pa) threshold for alt model switch
.gps_low_alt = GPS_STATIONARY,
.gps_high_alt = GPS_AIRBORNE_1G,

Wyświetl plik

@ -1,131 +1,174 @@
#include "ch.h"
#include "hal.h"
#include "ff.h"
#include "debug.h"
//#include "config.h"
MMCDriver MMCD1;
bool sdInitialized = false;
bool initSD(void)
{
/*
* Quick check of card inserted.
* This is OK for in flight.
*/
if(palReadLine(LINE_SD_DET)) {
TRACE_INFO("SD > No SD card inserted");
sdInitialized = false;
return false;
}
TRACE_INFO("SD > Access SD card");
/* NOTE: SD_CS line is set in board.h and initialized to HIGH. */
// Maximum speed SPI configuration
static SPIConfig hs_spicfg = {
.ssport = PAL_PORT(LINE_SD_CS),
.sspad = PAL_PAD(LINE_SD_CS),
.cr1 = SPI_CR1_MSTR
};
// Low speed SPI configuration
static SPIConfig ls_spicfg = {
.ssport = PAL_PORT(LINE_SD_CS),
.sspad = PAL_PAD(LINE_SD_CS),
.cr1 = SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_MSTR
};
// MMC/SD over SPI driver configuration
static MMCConfig mmccfg = {&SPID3, &ls_spicfg, &hs_spicfg};
// Check SD card presence
spiAcquireBus(&SPID3);
// Init MMC
mmcObjectInit(&MMCD1);
mmcStart(&MMCD1, &mmccfg);
TRACE_DEBUG("SD > Connect");
if(mmcConnect(&MMCD1)) {
TRACE_ERROR("SD > SD card connection error");
} else {
TRACE_INFO("SD > SD card connection OK");
sdInitialized = true;
}
spiReleaseBus(&SPID3);
return sdInitialized;
}
bool writeBufferToFile(const char *filename, const uint8_t *buffer, uint32_t len)
{
if(!sdInitialized)
return false;
spiAcquireBus(&SPID3);
static FATFS fs;
static FIL fdst;
FRESULT res;
bool gres = true; // Optimist
// Mount SD card
TRACE_INFO("SD > Mount");
res = f_mount(&fs, "/", 0);
if(res != FR_OK)
{
TRACE_ERROR("SD > Mounting failed (err=%d)", res);
gres = false;
} else {
// Open file
TRACE_INFO("SD > Open file %s", filename);
res = f_open(&fdst, (TCHAR*)filename, FA_CREATE_ALWAYS | FA_WRITE);
if(res != FR_OK)
{
TRACE_ERROR("SD > Opening file failed (err=%d)", res);
gres = false;
} else {
// Write buffer into file
TRACE_INFO("SD > Write buffer to file (len=%d)", len);
uint32_t len_written;
f_write(&fdst, buffer, len, (UINT*)&len_written);
if(len_written != len)
{
TRACE_ERROR("SD > Writing failed (err=%d)", res);
gres = false;
}
// Close file
TRACE_INFO("SD > Close file");
res = f_close(&fdst);
if(res != FR_OK)
{
TRACE_ERROR("SD > Closing file failed (err=%d)", res);
gres = false;
}
}
// Unmount
TRACE_INFO("SD > Unmount");
res = f_mount(0, "", 0);
if(res != FR_OK)
{
TRACE_ERROR("SD > Unmounting failed (err=%d)", res);
gres = false;
}
}
spiReleaseBus(&SPID3);
return gres;
}
#include "ch.h"
#include "hal.h"
#include "ff.h"
#include "debug.h"
#include "portab.h"
//#include "config.h"
MMCDriver MMCD1;
bool sdInitialized = false;
bool initSD(void)
{
/*
* Quick check of card inserted.
* This is OK for in flight.
*/
if(palReadLine(LINE_SD_DET)) {
TRACE_INFO("SD > No SD card inserted");
sdInitialized = false;
return false;
}
TRACE_INFO("SD > Access SD card");
/* NOTE: SD_CS line is set in board.h and initialized to HIGH. */
// Maximum speed SPI configuration
static SPIConfig hs_spicfg = {
.ssport = PAL_PORT(LINE_SD_CS),
.sspad = PAL_PAD(LINE_SD_CS),
.cr1 = SPI_CR1_MSTR
};
// Low speed SPI configuration
static SPIConfig ls_spicfg = {
.ssport = PAL_PORT(LINE_SD_CS),
.sspad = PAL_PAD(LINE_SD_CS),
.cr1 = SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_MSTR
};
// MMC/SD over SPI driver configuration
static MMCConfig mmccfg = {&SPID3, &ls_spicfg, &hs_spicfg};
// Check SD card presence
spiAcquireBus(&SPID3);
// Init MMC
mmcObjectInit(&MMCD1);
mmcStart(&MMCD1, &mmccfg);
TRACE_DEBUG("SD > Connect");
if(mmcConnect(&MMCD1)) {
TRACE_ERROR("SD > SD card connection error");
} else {
TRACE_INFO("SD > SD card connection OK");
sdInitialized = true;
}
spiReleaseBus(&SPID3);
return sdInitialized;
}
bool writeBufferToFile(const char *filename, const uint8_t *buffer, uint32_t len)
{
if(!sdInitialized)
return false;
spiAcquireBus(&SPID3);
static FATFS fs;
static FIL fdst;
FRESULT res;
bool gres = true; // Optimist
// Mount SD card
TRACE_INFO("SD > Mount");
res = f_mount(&fs, "/", 0);
if(res != FR_OK)
{
TRACE_ERROR("SD > Mounting failed (err=%d)", res);
gres = false;
} else {
// Open file
TRACE_INFO("SD > Open file %s", filename);
res = f_open(&fdst, (TCHAR*)filename, FA_CREATE_ALWAYS | FA_WRITE);
if(res != FR_OK)
{
TRACE_ERROR("SD > Opening file failed (err=%d)", res);
gres = false;
} else {
// Write buffer into file
TRACE_INFO("SD > Write buffer to file (len=%d)", len);
uint32_t len_written;
f_write(&fdst, buffer, len, (UINT*)&len_written);
if(len_written != len)
{
TRACE_ERROR("SD > Writing failed (err=%d)", res);
gres = false;
}
// Close file
TRACE_INFO("SD > Close file");
res = f_close(&fdst);
if(res != FR_OK)
{
TRACE_ERROR("SD > Closing file failed (err=%d)", res);
gres = false;
}
}
// Unmount
TRACE_INFO("SD > Unmount");
res = f_mount(0, "", 0);
if(res != FR_OK)
{
TRACE_ERROR("SD > Unmounting failed (err=%d)", res);
gres = false;
}
}
spiReleaseBus(&SPID3);
return gres;
}
#if HAL_USE_SDC || defined(__DOXYGEN__)
/**
* @brief SDC card detection.
*/
bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {
(void)sdcp;
/* TODO: Fill the implementation.*/
return true;
}
/**
* @brief SDC card write protection detection.
*/
bool sdc_lld_is_write_protected(SDCDriver *sdcp) {
(void)sdcp;
/* TODO: Fill the implementation.*/
return false;
}
#endif /* HAL_USE_SDC */
#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
/**
* @brief MMC_SPI card detection.
*/
bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
(void)mmcp;
return palReadLine(LINE_SD_DET);
}
/**
* @brief MMC_SPI card write protection detection.
*/
bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
(void)mmcp;
/* TODO: Fill the implementation.*/
return false;
}
#endif

Wyświetl plik

@ -10,9 +10,10 @@
#include "debug.h"
#include "config.h"
#include "collector.h"
#include "portab.h"
bool gps_enabled = false;
int8_t gps_model = GPS_MODEL_UNSET;
uint8_t gps_model = GPS_MODEL_PORTABLE;
#if defined(UBLOX_UART_CONNECTED)
// Serial driver configuration for GPS
@ -25,6 +26,20 @@ const SerialConfig gps_config =
};
#endif
/**
* Array for looking up model name
*/
static const char *model[] = {GPS_MODEL_NAMES};
/**
* Get pointer to model name as string
*/
const char *gps_get_model_name(uint8_t index) {
if(index > GPS_MODEL_MAX)
return "INVALID";
return model[index];
}
/**
* Transmits a string of bytes to the GPS
*/
@ -264,11 +279,11 @@ bool gps_get_fix(gpsFix_t *fix) {
} else {
fix->alt = (uint16_t)alt_tmp;
}
/* }*/
TRACE_INFO("GPS > Polling OK time=%04d-%02d-%02d %02d:%02d:%02d lat=%d.%05d lon=%d.%05d alt=%dm sats=%d fixOK=%d pDOP=%02d.%02d model=%d",
fix->model = gps_model;
TRACE_INFO("GPS > Polling OK time=%04d-%02d-%02d %02d:%02d:%02d lat=%d.%05d lon=%d.%05d alt=%dm sats=%d fixOK=%d pDOP=%02d.%02d model=%s",
fix->time.year, fix->time.month, fix->time.day, fix->time.hour, fix->time.minute, fix->time.second,
fix->lat/10000000, (fix->lat > 0 ? 1:-1)*(fix->lat/100)%100000, fix->lon/10000000, (fix->lon > 0 ? 1:-1)*(fix->lon/100)%100000,
fix->alt, fix->num_svs, fix->fixOK, fix->pdop/100, fix->pdop%100, gps_model
fix->alt, fix->num_svs, fix->fixOK, fix->pdop/100, fix->pdop%100, gps_get_model_name(fix->model)
);
return true;
@ -599,7 +614,7 @@ bool GPS_Init() {
// Wait for GPS startup
chThdSleep(TIME_S2I(1));
gps_model = GPS_MODEL_UNSET;
gps_model = GPS_MODEL_PORTABLE;
// Configure GPS
TRACE_INFO("GPS > Transmit config to GPS");
@ -632,7 +647,7 @@ void GPS_Deinit(void)
palSetLineMode(LINE_GPS_RXD, PAL_MODE_INPUT); // UART RXD
palSetLineMode(LINE_GPS_TXD, PAL_MODE_INPUT); // UART TXD
#endif
gps_model = GPS_MODEL_UNSET;
gps_model = GPS_MODEL_PORTABLE;
gps_enabled = false;
}

Wyświetl plik

@ -9,7 +9,9 @@
#include "hal.h"
#include "ptime.h"
#define GPS_MODEL_UNSET -1
/**
* @brief GPS model values.
*/
#define GPS_MODEL_PORTABLE 0
#define GPS_MODEL_STATIONARY 2
#define GPS_MODEL_PEDESTRIAN 3
@ -19,6 +21,20 @@
#define GPS_MODEL_AIRBORNE2G 7
#define GPS_MODEL_AIRBORNE4G 8
/* Model limits. */
//#define GPS_MODEL_UNSET -1
#define GPS_MODEL_MAX GPS_MODEL_AIRBORNE4G
/**
* @brief GPS models as array of strings.
* @details Each element in an array initialized with this macro can be
* indexed using a numeric GPS model value.
*/
#define GPS_MODEL_NAMES \
"PORTABLE", "NONE", "STATIONARY", "PEDESTRIAN", "AUTOMOTIVE", "SEA", \
"AIRBORNE1G", "AIRBORNE2G", "AIRBORNE4G"
typedef enum {
GPS_PORTABLE = GPS_MODEL_PORTABLE,
GPS_STATIONARY = GPS_MODEL_STATIONARY,
@ -75,6 +91,7 @@ typedef struct {
int32_t alt; // altitude in m, range 0m, up to ~40000m, clamped
bool fixOK; // Flag that is set to true, when DOP is with the limits
uint16_t pdop; // Position DOP
uint8_t model; // Dynamic model
} gpsFix_t;
uint8_t gps_set_gps_only(void);
@ -92,6 +109,7 @@ bool GPS_Init(void);
void GPS_Deinit(void);
uint32_t GPS_get_mcu_frequency(void);
bool gps_calc_ubx_csum(uint8_t *mbuf, uint16_t mlen);
const char *gps_get_model_name(uint8_t index);
#endif

Wyświetl plik

@ -1,201 +1,202 @@
/**
* I2C driver for the external I2C bus which is addressed on the TXD and RXD
* pins of the Pecan. The I2C bus is bitbanged and operates at 45 kHz if the
* STM32 is operated at SYSCLK=48MHz.
*
* TXD pin: SCL
* RXD pin: SDA
*
* @see https://en.wikipedia.org/wiki/I%C2%B2C
*/
#include "ch.h"
#include "hal.h"
#include "debug.h"
#define SCL LINE_IO_TXD /* SCL is connected to the TXD labeled line */
#define SDA LINE_IO_RXD /* SDA is connected to the RXD labeled line */
static bool started = false;
static inline bool read_SCL(void) { // Return current level of SCL line, 0 or 1
palSetLineMode(SCL, PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST);
return palReadLine(SCL);
}
static inline bool read_SDA(void) { // Return current level of SDA line, 0 or 1
palSetLineMode(SDA, PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST);
return palReadLine(SDA);
}
static inline void set_SCL(void) { // Do not drive SCL(set pin high-impedance)
palSetLineMode(SCL, PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST);
}
static inline void clear_SCL(void) { // Actively drive SCL signal low
palSetLineMode(SCL, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
palClearLine(SCL);
}
static inline void set_SDA(void) { // Do not drive SDA(set pin high-impedance)
palSetLineMode(SDA, PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST);
}
static inline void clear_SDA(void) { // Actively drive SDA signal low
palSetLineMode(SDA, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
palClearLine(SDA);
}
static inline void arbitration_lost(void) {
TRACE_ERROR("arbitration_lost");
}
static void i2c_start_cond(void) {
if(started) {
// if started, do a restart condition
// set SDA to 1
set_SDA();
set_SCL();
sysinterval_t t0 = chVTGetSystemTime();
while(read_SCL() == 0 && TIME_I2MS(chVTGetSystemTime()-t0) < 10) { // Clock stretching
// You should add timeout to this loop
}
}
if(read_SDA() == 0)
arbitration_lost();
// SCL is high, set SDA from 1 to 0.
clear_SDA();
clear_SCL();
started = true;
}
static void i2c_stop_cond(void) {
// set SDA to 0
clear_SDA();
set_SCL();
// Clock stretching
sysinterval_t t0 = chVTGetSystemTime();
while(read_SCL() == 0 && TIME_I2MS(chVTGetSystemTime()-t0) < 10) { // Clock stretching
// add timeout to this loop.
}
// SCL is high, set SDA from 0 to 1
set_SDA();
if(read_SDA() == 0)
arbitration_lost();
started = false;
}
// Write a bit to I2C bus
static void i2c_write_bit(bool bit) {
if(bit) {
set_SDA();
} else {
clear_SDA();
}
// Set SCL high to indicate a new valid SDA value is available
set_SCL();
// Wait for SDA value to be read by slave, minimum of 4us for standard mode
sysinterval_t t0 = chVTGetSystemTime();
while(read_SCL() == 0 && TIME_I2MS(chVTGetSystemTime()-t0) < 10) { // Clock stretching
// You should add timeout to this loop
}
// SCL is high, now data is valid
// If SDA is high, check that nobody else is driving SDA
if(bit &&(read_SDA() == 0))
arbitration_lost();
// Clear the SCL to low in preparation for next change
clear_SCL();
}
// Read a bit from I2C bus
static bool i2c_read_bit(void) {
bool bit;
// Let the slave drive data
set_SDA();
// Set SCL high to indicate a new valid SDA value is available
set_SCL();
sysinterval_t t0 = chVTGetSystemTime();
while(read_SCL() == 0 && TIME_I2MS(chVTGetSystemTime()-t0) < 10) { // Clock stretching
// You should add timeout to this loop
}
// SCL is high, read out bit
bit = read_SDA();
// Set SCL low in preparation for next operation
clear_SCL();
return bit;
}
// Write a byte to I2C bus. Return 0 if ack by the slave.
static bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte) {
uint8_t bit;
bool nack;
if(send_start)
i2c_start_cond();
for(bit = 0; bit < 8; ++bit) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if(send_stop)
i2c_stop_cond();
return nack;
}
// Read a byte from I2C bus
static uint8_t i2c_read_byte(bool nack, bool send_stop) {
uint8_t byte = 0;
uint8_t bit;
for(bit = 0; bit < 8; ++bit)
byte =(byte << 1) | i2c_read_bit();
i2c_write_bit(nack);
if(send_stop)
i2c_stop_cond();
return byte;
}
bool eI2C_write8(uint8_t address, uint8_t reg, uint8_t value) {
i2c_write_byte(true, false, address << 1);
i2c_write_byte(false, false, reg);
i2c_write_byte(false, true, value);
return true;
}
bool eI2C_read8(uint8_t address, uint8_t reg, uint8_t *val) {
i2c_write_byte(true, false, address << 1);
i2c_write_byte(false, false, reg);
i2c_write_byte(true, false,(address << 1) | 0x1);
*val = i2c_read_byte(true, true);
return true;
}
bool eI2C_read16(uint8_t address, uint8_t reg, uint16_t *val) {
i2c_write_byte(true, false, address << 1);
i2c_write_byte(false, false, reg);
i2c_write_byte(true, false,(address << 1) | 0x1);
uint8_t b1 = i2c_read_byte(false, false);
uint8_t b2 = i2c_read_byte(true, true);
*val = b2 |(b1 << 8);
return true;
}
bool eI2C_read16_LE(uint8_t address, uint8_t reg, uint16_t *val) {
i2c_write_byte(true, false, address << 1);
i2c_write_byte(false, false, reg);
i2c_write_byte(true, false,(address << 1) | 0x1);
uint8_t b1 = i2c_read_byte(false, false);
uint8_t b2 = i2c_read_byte(true, true);
*val = b1 |(b2 << 8);
return true;
}
/**
* I2C driver for the external I2C bus which is addressed on the TXD and RXD
* pins of the Pecan. The I2C bus is bitbanged and operates at 45 kHz if the
* STM32 is operated at SYSCLK=48MHz.
*
* TXD pin: SCL
* RXD pin: SDA
*
* @see https://en.wikipedia.org/wiki/I%C2%B2C
*/
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "portab.h"
#define SCL LINE_IO_TXD /* SCL is connected to the TXD labeled line */
#define SDA LINE_IO_RXD /* SDA is connected to the RXD labeled line */
static bool started = false;
static inline bool read_SCL(void) { // Return current level of SCL line, 0 or 1
palSetLineMode(SCL, PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST);
return palReadLine(SCL);
}
static inline bool read_SDA(void) { // Return current level of SDA line, 0 or 1
palSetLineMode(SDA, PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST);
return palReadLine(SDA);
}
static inline void set_SCL(void) { // Do not drive SCL(set pin high-impedance)
palSetLineMode(SCL, PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST);
}
static inline void clear_SCL(void) { // Actively drive SCL signal low
palSetLineMode(SCL, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
palClearLine(SCL);
}
static inline void set_SDA(void) { // Do not drive SDA(set pin high-impedance)
palSetLineMode(SDA, PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST);
}
static inline void clear_SDA(void) { // Actively drive SDA signal low
palSetLineMode(SDA, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
palClearLine(SDA);
}
static inline void arbitration_lost(void) {
TRACE_ERROR("arbitration_lost");
}
static void i2c_start_cond(void) {
if(started) {
// if started, do a restart condition
// set SDA to 1
set_SDA();
set_SCL();
sysinterval_t t0 = chVTGetSystemTime();
while(read_SCL() == 0 && TIME_I2MS(chVTGetSystemTime()-t0) < 10) { // Clock stretching
// You should add timeout to this loop
}
}
if(read_SDA() == 0)
arbitration_lost();
// SCL is high, set SDA from 1 to 0.
clear_SDA();
clear_SCL();
started = true;
}
static void i2c_stop_cond(void) {
// set SDA to 0
clear_SDA();
set_SCL();
// Clock stretching
sysinterval_t t0 = chVTGetSystemTime();
while(read_SCL() == 0 && TIME_I2MS(chVTGetSystemTime()-t0) < 10) { // Clock stretching
// add timeout to this loop.
}
// SCL is high, set SDA from 0 to 1
set_SDA();
if(read_SDA() == 0)
arbitration_lost();
started = false;
}
// Write a bit to I2C bus
static void i2c_write_bit(bool bit) {
if(bit) {
set_SDA();
} else {
clear_SDA();
}
// Set SCL high to indicate a new valid SDA value is available
set_SCL();
// Wait for SDA value to be read by slave, minimum of 4us for standard mode
sysinterval_t t0 = chVTGetSystemTime();
while(read_SCL() == 0 && TIME_I2MS(chVTGetSystemTime()-t0) < 10) { // Clock stretching
// You should add timeout to this loop
}
// SCL is high, now data is valid
// If SDA is high, check that nobody else is driving SDA
if(bit &&(read_SDA() == 0))
arbitration_lost();
// Clear the SCL to low in preparation for next change
clear_SCL();
}
// Read a bit from I2C bus
static bool i2c_read_bit(void) {
bool bit;
// Let the slave drive data
set_SDA();
// Set SCL high to indicate a new valid SDA value is available
set_SCL();
sysinterval_t t0 = chVTGetSystemTime();
while(read_SCL() == 0 && TIME_I2MS(chVTGetSystemTime()-t0) < 10) { // Clock stretching
// You should add timeout to this loop
}
// SCL is high, read out bit
bit = read_SDA();
// Set SCL low in preparation for next operation
clear_SCL();
return bit;
}
// Write a byte to I2C bus. Return 0 if ack by the slave.
static bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte) {
uint8_t bit;
bool nack;
if(send_start)
i2c_start_cond();
for(bit = 0; bit < 8; ++bit) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if(send_stop)
i2c_stop_cond();
return nack;
}
// Read a byte from I2C bus
static uint8_t i2c_read_byte(bool nack, bool send_stop) {
uint8_t byte = 0;
uint8_t bit;
for(bit = 0; bit < 8; ++bit)
byte =(byte << 1) | i2c_read_bit();
i2c_write_bit(nack);
if(send_stop)
i2c_stop_cond();
return byte;
}
bool eI2C_write8(uint8_t address, uint8_t reg, uint8_t value) {
i2c_write_byte(true, false, address << 1);
i2c_write_byte(false, false, reg);
i2c_write_byte(false, true, value);
return true;
}
bool eI2C_read8(uint8_t address, uint8_t reg, uint8_t *val) {
i2c_write_byte(true, false, address << 1);
i2c_write_byte(false, false, reg);
i2c_write_byte(true, false,(address << 1) | 0x1);
*val = i2c_read_byte(true, true);
return true;
}
bool eI2C_read16(uint8_t address, uint8_t reg, uint16_t *val) {
i2c_write_byte(true, false, address << 1);
i2c_write_byte(false, false, reg);
i2c_write_byte(true, false,(address << 1) | 0x1);
uint8_t b1 = i2c_read_byte(false, false);
uint8_t b2 = i2c_read_byte(true, true);
*val = b2 |(b1 << 8);
return true;
}
bool eI2C_read16_LE(uint8_t address, uint8_t reg, uint16_t *val) {
i2c_write_byte(true, false, address << 1);
i2c_write_byte(false, false, reg);
i2c_write_byte(true, false,(address << 1) | 0x1);
uint8_t b1 = i2c_read_byte(false, false);
uint8_t b2 = i2c_read_byte(true, true);
*val = b1 |(b2 << 8);
return true;
}

Wyświetl plik

@ -1,92 +1,93 @@
#include "ch.h"
#include "hal.h"
#include "config.h"
#include "pac1720.h"
#include "pi2c.h"
#include <stdlib.h>
#define ADC_NUM_CHANNELS 4 /* Amount of channels (solar, battery, temperature) */
#define VCC_REF 3100 /* mV */
#define DIVIDER_VSOL 205/64 /* VSol -- 22kOhm -- ADC -- 10kOhm -- GND */
#define DIVIDER_VBAT 205/64 /* VBat -- 22KOhm -- ADC -- 10kOhm -- GND */
#define DIVIDER_VUSB 205/64 /* VUSB -- 22KOhm -- ADC -- 10kOhm -- GND */
static adcsample_t samples[ADC_NUM_CHANNELS]; // ADC sample buffer
void adccb(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
(void)adcp;
(void)buffer;
(void)n;
}
/*
* ADC conversion group.
* Mode: Linear buffer, 4 samples of 4 channels, SW triggered.
* Channels: Solar voltage divider ADC1_IN12
* USB voltage divider ADC1_IN14
* Battery voltage divider ADC1_IN9
* Temperature sensor ADC1_IN16
*/
static const ADCConversionGroup adcgrpcfg = {
FALSE,
ADC_NUM_CHANNELS,
adccb,
NULL,
/* HW dependent part.*/
0,
ADC_CR2_SWSTART,
ADC_SMPR1_SMP_AN14(ADC_SAMPLE_144) | ADC_SMPR1_SMP_AN12(ADC_SAMPLE_144) | ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_144),
ADC_SMPR2_SMP_AN9(ADC_SAMPLE_144),
ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
0,
ADC_SQR3_SQ1_N(ADC_CHANNEL_IN12) | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN14) | ADC_SQR3_SQ3_N(ADC_CHANNEL_IN9) | ADC_SQR3_SQ4_N(ADC_CHANNEL_SENSOR)
};
void initADC(void)
{
adcStart(&ADCD1, NULL);
adcSTM32EnableTSVREFE();
palSetLineMode(LINE_ADC_VSOL, PAL_MODE_INPUT_ANALOG); // Solar panels
palSetLineMode(LINE_ADC_VBAT, PAL_MODE_INPUT_ANALOG); // Battery
palSetLineMode(LINE_ADC_VUSB, PAL_MODE_INPUT_ANALOG); // USB
}
void deinitADC(void)
{
adcStop(&ADCD1);
}
void doConversion(void)
{
initADC();
adcStartConversion(&ADCD1, &adcgrpcfg, samples, 1);
chThdSleep(TIME_MS2I(50)); // Wait until conversion is finished
deinitADC();
}
uint16_t stm32_get_vbat(void)
{
doConversion();
return samples[2] * VCC_REF * DIVIDER_VBAT / 4096;
}
uint16_t stm32_get_vsol(void)
{
doConversion();
return samples[0] * VCC_REF * DIVIDER_VSOL / 4096;
}
uint16_t stm32_get_vusb(void)
{
doConversion();
return samples[1] * VCC_REF * DIVIDER_VUSB / 4096;
}
uint16_t stm32_get_temp(void)
{
doConversion();
return (((int32_t)samples[3]*40 * VCC_REF / 4096)-30400) + 2500 + 850/*Calibration*/;
}
#include "ch.h"
#include "hal.h"
#include "config.h"
#include "pac1720.h"
#include "pi2c.h"
#include <stdlib.h>
#include "portab.h"
#define ADC_NUM_CHANNELS 4 /* Amount of channels (solar, battery, temperature) */
#define VCC_REF 3100 /* mV */
#define DIVIDER_VSOL 205/64 /* VSol -- 22kOhm -- ADC -- 10kOhm -- GND */
#define DIVIDER_VBAT 205/64 /* VBat -- 22KOhm -- ADC -- 10kOhm -- GND */
#define DIVIDER_VUSB 205/64 /* VUSB -- 22KOhm -- ADC -- 10kOhm -- GND */
static adcsample_t samples[ADC_NUM_CHANNELS]; // ADC sample buffer
void adccb(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
(void)adcp;
(void)buffer;
(void)n;
}
/*
* ADC conversion group.
* Mode: Linear buffer, 4 samples of 4 channels, SW triggered.
* Channels: Solar voltage divider ADC1_IN12
* USB voltage divider ADC1_IN14
* Battery voltage divider ADC1_IN9
* Temperature sensor ADC1_IN16
*/
static const ADCConversionGroup adcgrpcfg = {
FALSE,
ADC_NUM_CHANNELS,
adccb,
NULL,
/* HW dependent part.*/
0,
ADC_CR2_SWSTART,
ADC_SMPR1_SMP_AN14(ADC_SAMPLE_144) | ADC_SMPR1_SMP_AN12(ADC_SAMPLE_144) | ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_144),
ADC_SMPR2_SMP_AN9(ADC_SAMPLE_144),
ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
0,
ADC_SQR3_SQ1_N(ADC_CHANNEL_IN12) | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN14) | ADC_SQR3_SQ3_N(ADC_CHANNEL_IN9) | ADC_SQR3_SQ4_N(ADC_CHANNEL_SENSOR)
};
void initADC(void)
{
adcStart(&ADCD1, NULL);
adcSTM32EnableTSVREFE();
palSetLineMode(LINE_ADC_VSOL, PAL_MODE_INPUT_ANALOG); // Solar panels
palSetLineMode(LINE_ADC_VBAT, PAL_MODE_INPUT_ANALOG); // Battery
palSetLineMode(LINE_ADC_VUSB, PAL_MODE_INPUT_ANALOG); // USB
}
void deinitADC(void)
{
adcStop(&ADCD1);
}
void doConversion(void)
{
initADC();
adcStartConversion(&ADCD1, &adcgrpcfg, samples, 1);
chThdSleep(TIME_MS2I(50)); // Wait until conversion is finished
deinitADC();
}
uint16_t stm32_get_vbat(void)
{
doConversion();
return samples[2] * VCC_REF * DIVIDER_VBAT / 4096;
}
uint16_t stm32_get_vsol(void)
{
doConversion();
return samples[0] * VCC_REF * DIVIDER_VSOL / 4096;
}
uint16_t stm32_get_vusb(void)
{
doConversion();
return samples[1] * VCC_REF * DIVIDER_VUSB / 4096;
}
uint16_t stm32_get_temp(void)
{
doConversion();
return (((int32_t)samples[3]*40 * VCC_REF / 4096)-30400) + 2500 + 850/*Calibration*/;
}

Wyświetl plik

@ -913,7 +913,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
*/
myDriver->decoder_state = DECODER_RESET;
continue; /* Continue in main loop. */
}
} /* End case. */
case PWM_ACK_DECODE_ERROR:
case PWM_ACK_DECODE_END: {
@ -928,8 +928,8 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
pktAddEventFlags(myHandler, EVT_PWM_INVALID_INBAND);
myDriver->decoder_state = DECODER_RESET;
continue; /* Enclosing state switch. */
} /* End case 0. */
continue; /* Decoder state switch. */
} /* End case. */
/* If CCA ends and the decoder has not validated any frame.
* The PWM side has already posted a PWM_STREAM_CLOSE event.
@ -941,27 +941,25 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
*/
case PWM_TERM_NO_DATA:
//case PWM_TERM_QUEUE_LOCK:
/* If the ICU timer overflows during PWM capture.
* The PWM side has already posted a ICU_OVERFLOW event.
*/
case PWM_TERM_ICU_OVERFLOW:
/* This is a debug error if a CCA is validated but a PWM is still active.
/* This is a debug error.
* CCA is validated but a PWM is still active.
* The PWM side has already posted a PWM_FIFO_REMNANT event.
*/
case PWM_TERM_QUEUE_ERR:
/* If there are no more PWM buffers available.
/* If there is no more PWM buffer space available.
* The PWM side has already posted a PWM_QUEUE_FULL event.
*/
case PWM_TERM_QUEUE_FULL: {
/* Transit to RESET state where all buffers/objects are released. */
myDriver->decoder_state = DECODER_RESET;
continue; /* Enclosing state switch. */
} /* End case 1. */
continue; /* Decoder state switch. */
} /* End case. */
#if USE_HEAP_PWM_BUFFER == TRUE
case PWM_INFO_QUEUE_SWAP: {
@ -988,24 +986,22 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
/* TODO: Need an EVT code freed up to add INVALID_SWAP. */
myDriver->decoder_state = DECODER_RESET;
}
continue; /* Enclosing state switch. */
}
continue; /* Decoder state switch. */
} /* End case. */
#endif
default: {
/* Unknown in-band message from PWM. */
pktAddEventFlags(myHandler, EVT_PWM_INVALID_INBAND);
//myDriver->active_demod_object->status |= EVT_PWM_INVALID_INBAND;
myDriver->decoder_state = DECODER_RESET;
continue; /* Enclosing state switch. */
} /* End case default. */
} /* End switch. */
/* Execute primary loop switch on state. */
continue;
} /* End switch on in-band. */
continue; /* Decoder state switch. */
} /* End if in-band. */
/*
* Process the AFSK into HDLC bit and AX25 data.
* If not in-band the process the AFSK into an HDLC bit and AX25 data.
*/
if(!pktProcessAFSK(myDriver, radio.array)) {
/* AX25 character decoded but buffer is full.
@ -1038,12 +1034,13 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
continue; /* From this case. */
}
} /* End switch. */
break; /* Keep GCC 7 happy. */
} /* End case DECODER_ACTIVE. */
/*
* RESET readies the decoder for the next session.
* It frees all still active buffer/objects.
* Then the DSP system is reset prior to set state to IDLE.
* It frees any held buffers/objects.
* The DSP system is reset and then transition to IDLE.
*/
case DECODER_RESET: {
if(myHandler->active_packet_object != NULL) {
@ -1059,7 +1056,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
chFifoReturnObject(pkt_fifo, myHandler->active_packet_object);
/* Forget the buffer management object. */
/* Forget the AX25 buffer management object. */
myHandler->active_packet_object = NULL;
}
@ -1119,6 +1116,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
case DECODER_DISPATCH: {
if(myHandler->active_packet_object != NULL) {
/* TODO: PWM chain is also released in RESET so this can be removed. */
#if USE_HEAP_PWM_BUFFER == TRUE
/* Release PWM queue/buffer objects back to the pool. */
radio_pwm_fifo_t *myFIFO = myDriver->active_demod_object;
@ -1134,7 +1132,8 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
#endif
#endif
/*
* Indicate AFSK decode done which also locks the PWM queue.
* Indicate AFSK decode done.
* If PWM is still being captured for this stream capture will cease.
*/
eventflags_t evtf = EVT_AFSK_DECODE_DONE;
myDriver->active_demod_object->status |= evtf;
@ -1149,38 +1148,13 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
/* Forget the packet object. */
myHandler->active_packet_object = NULL;
/*
* Send events then update PWM/demod object status.
* (the PWM input side doesn't care about AX25 events actually...)
*/
/* Send events then update demod object status. */
pktAddEventFlags(myHandler, evtf);
myDriver->active_demod_object->status |= evtf;
#if AFSK_DEBUG_TYPE == AFSK_PWM_DATA_CAPTURE_DEBUG
event_listener_t p_listener;
chEvtRegisterMaskWithFlags(
chnGetEventSource ((SerialDriver *)pkt_out),
&p_listener, DEC_DIAG_OUT_END,
CHN_TRANSMISSION_END);
char buf[80];
int out = chsnprintf(buf, sizeof(buf),
"\r\n======= END (%s) =========\r\n",
(myDriver->active_demod_object->status & EVT_AFSK_INVALID_FRAME)
? "invalid frame"
: (myDriver->active_demod_object->status & EVT_AX25_FRAME_RDY)
? "good CRC" : "bad CRC");
chnWrite(pkt_out, (uint8_t *)buf, out);
eventflags_t clear;
do {
clear = chEvtWaitAnyTimeout(DEC_DIAG_OUT_END, TIME_MS2I(100));
} while(clear != 0);
chEvtUnregister(chnGetEventSource ((SerialDriver *)pkt_out),
&p_listener);
#endif
} /* Active packet object != NULL. */
myDriver->decoder_state = DECODER_RESET;
break;
} /* End case DECODER_SUSPEND. */
} /* End case DECODER_DISPATCH. */
} /* End switch on decoder state. */
} /* End thread while(true). */
}

Wyświetl plik

@ -168,7 +168,10 @@ static void Si446x_init(const radio_unit_t radio) {
chDbgAssert(handler != NULL, "invalid radio ID");
pktPowerUpRadio(radio);
//pktPowerUpRadio(radio);
Si446x_powerup(radio);
//palClearLine(LINE_RADIO_SDN); // Radio SDN low (power up transceiver)
//chThdSleep(TIME_MS2I(10)); // Wait for transceiver to power up
// Power up (send oscillator type)
const uint8_t x3 = (Si446x_CCLK >> 24) & 0x0FF;
@ -376,7 +379,7 @@ bool Si446x_setBandParameters(const radio_unit_t radio,
Si446x_write(set_modem_freq_dev_command, 7);
}*/
static void Si446x_setPowerLevel(radio_pwr_t level)
static void Si446x_setPowerLevel(const radio_pwr_t level)
{
// Set the Power
uint8_t set_pa_pwr_lvl_property_command[] = {0x11, 0x22, 0x01, 0x01, level};
@ -469,7 +472,7 @@ static void Si446x_setModemAFSK_RX(const radio_unit_t radio) {
Si446x_setProperty8(Si446x_MODEM_CHFLT_RX2_CHFLT_COEM3, 0x00);*/
}
static void Si446x_setModem2FSK_TX(uint32_t speed)
static void Si446x_setModem2FSK_TX(const uint32_t speed)
{
// Setup the NCO modulo and oversampling mode
uint32_t s = Si446x_CCLK / 10;
@ -497,30 +500,32 @@ static void Si446x_setModem2FSK_TX(uint32_t speed)
/* ====================================================================== Radio Settings ====================================================================== */
static uint8_t __attribute__((unused)) Si446x_getChannel(void) {
static uint8_t __attribute__((unused)) Si446x_getChannel(const radio_unit_t radio) {
/* TODO: add hardware mapping. */
const uint8_t state_info[] = {Si446x_REQUEST_DEVICE_STATE};
uint8_t rxData[4];
Si446x_read(state_info, sizeof(state_info), rxData, sizeof(rxData));
return rxData[3];
(void)radio;
const uint8_t state_info[] = {Si446x_REQUEST_DEVICE_STATE};
uint8_t rxData[4];
Si446x_read(state_info, sizeof(state_info), rxData, sizeof(rxData));
return rxData[3];
}
/* ======================================================================= Radio FIFO ======================================================================= */
static void Si446x_writeFIFO(uint8_t *msg, uint8_t size) {
/* TODO: add hardware mapping. */
uint8_t write_fifo[size+1];
write_fifo[0] = Si446x_WRITE_TX_FIFO;
memcpy(&write_fifo[1], msg, size);
Si446x_write(write_fifo, size+1);
uint8_t write_fifo[size+1];
write_fifo[0] = Si446x_WRITE_TX_FIFO;
memcpy(&write_fifo[1], msg, size);
Si446x_write(write_fifo, size+1);
}
static uint8_t Si446x_getTXfreeFIFO(void) {
static uint8_t Si446x_getTXfreeFIFO(const radio_unit_t radio) {
/* TODO: add hardware mapping. */
const uint8_t fifo_info[] = {Si446x_FIFO_INFO, 0x00};
uint8_t rxData[4];
Si446x_read(fifo_info, sizeof(fifo_info), rxData, sizeof(rxData));
return rxData[3];
(void)radio;
const uint8_t fifo_info[] = {Si446x_FIFO_INFO, 0x00};
uint8_t rxData[4];
Si446x_read(fifo_info, sizeof(fifo_info), rxData, sizeof(rxData));
return rxData[3];
}
/* ====================================================================== Radio States ====================================================================== */
@ -539,64 +544,78 @@ void Si446x_getPartInfo(const radio_unit_t radio, si446x_info_t *info) {
/* TODO: add hardware mapping. */
(void)radio;
/* Get status. Leave any pending interrupts intact. */
const uint8_t status_info[] = {Si446x_GET_PART_INFO};
//uint8_t rxData[10];
Si446x_read(status_info, sizeof(status_info), (uint8_t *)info, sizeof(si446x_info_t));
//return rxData[4];
const uint8_t status_info[] = {Si446x_GET_PART_INFO};
Si446x_read(status_info, sizeof(status_info), (uint8_t *)info,
sizeof(si446x_info_t));
}
static uint8_t Si446x_getState(const radio_unit_t radio) {
/* TODO: add hardware mapping. */
(void)radio;
const uint8_t state_info[] = {Si446x_REQUEST_DEVICE_STATE};
uint8_t rxData[4];
Si446x_read(state_info, sizeof(state_info), rxData, sizeof(rxData));
return rxData[2] & 0xF;
const uint8_t state_info[] = {Si446x_REQUEST_DEVICE_STATE};
uint8_t rxData[4];
Si446x_read(state_info, sizeof(state_info), rxData, sizeof(rxData));
return rxData[2] & 0xF;
}
static void Si446x_setTXState(const radio_unit_t radio, uint8_t chan, uint16_t size){
/* TODO: add hardware mapping. */
(void)radio;
uint8_t change_state_command[] = {0x31, chan,
(Si446x_STATE_READY << 4),
(size >> 8) & 0x1F, size & 0xFF};
Si446x_write(change_state_command, sizeof(change_state_command));
uint8_t change_state_command[] = {0x31, chan,
(Si446x_STATE_READY << 4),
(size >> 8) & 0x1F, size & 0xFF};
Si446x_write(change_state_command, sizeof(change_state_command));
}
static void Si446x_setReadyState(const radio_unit_t radio) {
/* TODO: add hardware mapping. */
(void)radio;
const uint8_t change_state_command[] = {0x34, 0x03};
Si446x_write(change_state_command, sizeof(change_state_command));
const uint8_t change_state_command[] = {0x34, 0x03};
Si446x_write(change_state_command, sizeof(change_state_command));
}
static void Si446x_setRXState(const radio_unit_t radio, uint8_t chan){
/* TODO: add hardware mapping. */
(void)radio;
const uint8_t change_state_command[] = {0x32, chan, 0x00, 0x00,
0x00, 0x00, 0x08, 0x08};
Si446x_write(change_state_command, sizeof(change_state_command));
const uint8_t change_state_command[] = {0x32, chan, 0x00, 0x00,
0x00, 0x00, 0x08, 0x08};
Si446x_write(change_state_command, sizeof(change_state_command));
}
/**
*
*/
void Si446x_powerup(const radio_unit_t radio) {
TRACE_INFO("SI > Power up radio %i", radio);
packet_svc_t *handler = pktGetServiceObject(radio);
void Si446x_shutdown(radio_unit_t radio) {
chDbgAssert(handler != NULL, "invalid radio ID");
palClearLine(LINE_RADIO_SDN); // Radio SDN low (power up transceiver)
chThdSleep(TIME_MS2I(10)); // Wait for transceiver to power up
}
/**
*
*/
void Si446x_shutdown(const radio_unit_t radio) {
TRACE_INFO("SI > Shutdown radio %i", radio);
packet_svc_t *handler = pktGetServiceObject(radio);
chDbgAssert(handler != NULL, "invalid radio ID");
pktPowerDownRadio(radio);
//pktPowerDownRadio(radio);
palSetLine(LINE_RADIO_SDN);
handler->radio_init = false;
}
/* ====================================================================== Radio TX/RX ======================================================================= */
/*
/**
* Get CCA over measurement interval.
* Algorithm counts CCA pulses per millisecond (in systick time slices).
* If more than one pulse per millisecond is counted then CCA is not true.
*/
static bool Si446x_checkCCAthreshold(radio_unit_t radio, uint8_t ms) {
static bool Si446x_checkCCAthreshold(const radio_unit_t radio, uint8_t ms) {
/* TODO: Hardware mapping of radio. */
(void)radio;
uint16_t cca = 0;
@ -612,10 +631,10 @@ static bool Si446x_checkCCAthreshold(radio_unit_t radio, uint8_t ms) {
return cca > ms;
}
/*
/**
* Wait for a clear time slot and initiate packet transmission.
*/
static bool Si446x_transmit(radio_unit_t radio,
static bool Si446x_transmit(const radio_unit_t radio,
radio_freq_t freq,
channel_hz_t step,
radio_ch_t chan,
@ -699,7 +718,7 @@ static bool Si446x_transmit(radio_unit_t radio,
/*
*
*/
bool Si446x_receiveNoLock(radio_unit_t radio,
bool Si446x_receiveNoLock(const radio_unit_t radio,
radio_freq_t freq,
channel_hz_t step,
radio_ch_t channel,
@ -754,7 +773,7 @@ bool Si446x_receiveNoLock(radio_unit_t radio,
* return true if RX was enabled and/or resumed OK.
* return false if RX was not enabled.
*/
bool Si4464_resumeReceive(radio_unit_t radio,
bool Si4464_resumeReceive(const radio_unit_t radio,
radio_freq_t rx_frequency,
channel_hz_t rx_step,
radio_ch_t rx_chan,
@ -786,7 +805,7 @@ bool Si4464_resumeReceive(radio_unit_t radio,
/*
*
*/
void Si446x_disableReceive(radio_unit_t radio) {
void Si446x_disableReceive(const radio_unit_t radio) {
/* FIXME: */
if(Si446x_getState(radio) == Si446x_STATE_RX) {
//rx_frequency = 0;
@ -797,7 +816,7 @@ void Si446x_disableReceive(radio_unit_t radio) {
/*
*
*/
void Si446x_pauseReceive(radio_unit_t radio) {
void Si446x_pauseReceive(const radio_unit_t radio) {
/* FIXME: Should provide status. */
if(Si446x_getState(radio) == Si446x_STATE_RX) {
Si446x_setReadyState(radio);
@ -865,7 +884,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_afsk, arg) {
pktReleaseBufferChain(pp);
/* Schedule thread and task object memory release. */
pktScheduleSendComplete(rto, chThdGetSelfX());
pktLLDradioSendComplete(rto, chThdGetSelfX());
/* Exit thread. */
chThdExit(MSG_RESET);
@ -920,7 +939,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_afsk, arg) {
pktReleaseBufferChain(pp);
/* Schedule thread and task object memory release. */
pktScheduleSendComplete(rto, chThdGetSelfX());
pktLLDradioSendComplete(rto, chThdGetSelfX());
/* Unlock radio. */
pktReleaseRadio(radio);
@ -945,7 +964,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_afsk, arg) {
uint8_t localBuffer[Si446x_FIFO_COMBINED_SIZE];
/* Get the FIFO buffer amount currently available. */
uint8_t free = Si446x_getTXfreeFIFO();
uint8_t free = Si446x_getTXfreeFIFO(radio);
/* Calculate initial FIFO fill. */
uint16_t c = (all > free) ? free : all;
@ -980,7 +999,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_afsk, arg) {
/* Feed the FIFO while data remains to be sent. */
while((all - c) > 0) {
/* Get TX FIFO free count. */
uint8_t more = Si446x_getTXfreeFIFO();
uint8_t more = Si446x_getTXfreeFIFO(radio);
/* Update the FIFO free low water mark. */
lower = (more > lower) ? more : lower;
@ -1054,7 +1073,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_afsk, arg) {
rto->result = exit_msg;
/* Finished send so schedule thread memory and task object release. */
pktScheduleSendComplete(rto, chThdGetSelfX());
pktLLDradioSendComplete(rto, chThdGetSelfX());
/* Unlock radio. */
pktReleaseRadio(radio);
@ -1117,7 +1136,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_fsk, arg) {
pktReleaseBufferChain(pp);
/* Schedule thread and task object memory release. */
pktScheduleSendComplete(rto, chThdGetSelfX());
pktLLDradioSendComplete(rto, chThdGetSelfX());
/* Exit thread. */
chThdExit(MSG_RESET);
@ -1177,7 +1196,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_fsk, arg) {
rto->result = MSG_ERROR;
/* Schedule thread and task object memory release. */
pktScheduleSendComplete(rto, chThdGetSelfX());
pktLLDradioSendComplete(rto, chThdGetSelfX());
/* Unlock radio. */
pktReleaseRadio(radio);
@ -1196,7 +1215,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_fsk, arg) {
Si446x_write(reset_fifo, 2);
/* Get the FIFO buffer amount currently available. */
uint8_t free = Si446x_getTXfreeFIFO();
uint8_t free = Si446x_getTXfreeFIFO(radio);
/* Calculate initial FIFO fill. */
uint16_t c = (all > free) ? free : all;
@ -1230,7 +1249,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_fsk, arg) {
/* Feed the FIFO while data remains to be sent. */
while((all - c) > 0) {
/* Get TX FIFO free count. */
uint8_t more = Si446x_getTXfreeFIFO();
uint8_t more = Si446x_getTXfreeFIFO(radio);
/* Update the FIFO free low water mark. */
lower = (more > lower) ? more : lower;
@ -1301,7 +1320,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_fsk, arg) {
rto->result = exit_msg;
/* Finished send so schedule thread memory and task object release. */
pktScheduleSendComplete(rto, chThdGetSelfX());
pktLLDradioSendComplete(rto, chThdGetSelfX());
/* Unlock radio. */
pktReleaseRadio(radio);

Wyświetl plik

@ -19,13 +19,17 @@
#define Si446x_LOCK_BY_SEMAPHORE TRUE
/*
#ifndef Si446x_CLK
#error "Si446x_CLK is not defined which is needed for Si446x."
#endif
*/
/*
#ifndef Si446x_CLK_OFFSET
#define Si446x_CLK_OFFSET 0
#endif
*/
/* Si4464 States. */
#define Si446x_STATE_NOCHANGE 0
@ -245,6 +249,7 @@ extern void pktReleasePacketBuffer(packet_t pp);
extern "C" {
#endif
int16_t Si446x_getLastTemperature(const radio_unit_t radio);
void Si446x_powerup(const radio_unit_t radio);
void Si446x_shutdown(const radio_unit_t radio);
void Si446x_sendAFSK(packet_t pp);
bool Si446x_blocSendAFSK(radio_task_object_t *rto);

Wyświetl plik

@ -58,7 +58,7 @@ THD_FUNCTION(pktRadioManager, arg) {
(void *)&task_object, TIME_INFINITE);
/* Something to do. */
radio_unit_t radio = handler->radio;
const radio_unit_t radio = handler->radio;
/* Process command. */
switch(task_object->command) {
case PKT_RADIO_MGR_CLOSE: {
@ -110,6 +110,7 @@ THD_FUNCTION(pktRadioManager, arg) {
/* Switch on modulation type. */
switch(task_object->type) {
case MOD_AFSK: {
/* TODO: abstract this into the LLD for the radio. */
/* Create the AFSK decoder (includes PWM, filters, etc.). */
AFSKDemodDriver *driver = pktCreateAFSKDecoder(handler);
handler->link_controller = driver;
@ -129,8 +130,7 @@ THD_FUNCTION(pktRadioManager, arg) {
} /* End switch on modulation type. */
/* Initialise the radio. */
/* TODO: Move this 446x call into abstracted LLD. */
Si446x_conditional_init(radio);
pktLLDradioInit(radio);
break;
} /* End case PKT_RADIO_OPEN. */
@ -139,26 +139,14 @@ THD_FUNCTION(pktRadioManager, arg) {
/* The function switches on mod type so no need for switch here. */
switch(task_object->type) {
case MOD_AFSK: {
/* TODO: Add LLD abstraction. */
pktAcquireRadio(radio, TIME_INFINITE);
/* Enable receive. */
if(pktLLDradioEnableReceive(radio, task_object))
pktLLDradioStartDecoder(radio);
//pktStartDecoder(radio);
/* TODO: Move and aggregate these 446x calls into abstracted LLD.
* pktLLDenableReceive(...)
*/
Si446x_setBandParameters(radio,
task_object->base_frequency,
task_object->step_hz);
Si446x_receiveNoLock(radio,
task_object->base_frequency,
task_object->step_hz,
task_object->channel,
task_object->squelch,
MOD_AFSK);
/* TODO: If decoder is not running error out. */
pktStartDecoder(radio);
/* Allow transmit requests. */
/* Unlock radio and allow transmit requests. */
pktReleaseRadio(radio);
break;
} /* End case MOD_AFSK. */
@ -174,8 +162,10 @@ THD_FUNCTION(pktRadioManager, arg) {
case PKT_RADIO_RX_STOP: {
switch(task_object->type) {
case MOD_AFSK: {
/* TODO: Abstract acquire and release in LLD. */
pktAcquireRadio(radio, TIME_INFINITE);
pktStopDecoder(handler->radio);
pktLLDradioStopDecoder(radio);
//pktStopDecoder(handler->radio);
pktReleaseRadio(radio);
break;
} /* End case. */
@ -192,8 +182,9 @@ THD_FUNCTION(pktRadioManager, arg) {
/* Give each send a sequence number. */
++handler->radio_tx_config.tx_seq_num;
/* Pause the decoder. */
pktPauseDecoding(radio);
if(pktLLDsendPacket(task_object)) {
pktLLDradioPauseDecoding(radio);
//pktPauseDecoding(radio);
if(pktLLDradioSendPacket(task_object)) {
/*
* Keep count of active sends.
* Shutdown or resume receive when all done.
@ -210,7 +201,13 @@ THD_FUNCTION(pktRadioManager, arg) {
/* Send failed so release send packet object(s) and task object. */
packet_t pp = task_object->packet_out;
pktReleaseBufferChain(pp);
pktResumeDecoding(radio);
if(pktIsReceivePaused(radio)) {
if(!pktLLDradioResumeReceive(radio)) {
TRACE_ERROR("RAD > Receive failed to resume after transmit");
break;
}
pktLLDradioResumeDecoding(radio);
}
break;
} /* End case PKT_RADIO_TX. */
@ -220,9 +217,10 @@ THD_FUNCTION(pktRadioManager, arg) {
thread_t *decoder = NULL;
switch(task_object->type) {
case MOD_AFSK: {
/* TODO: Implement LLD function for this. */
Si446x_disableReceive(radio);
/* TODO: This should be a function back in pktservice or pktradio. */
/* TODO: Implement LLD abstraction closing decoder. */
//Si446x_disableReceive(radio);
pktLLDradioDisableReceive(radio);
/* TODO: This should be a function back in pktservice or rxafsk. */
esp = pktGetEventSource((AFSKDemodDriver *)handler->link_controller);
pktRegisterEventListener(esp, &el, USR_COMMAND_ACK, DEC_CLOSE_EXEC);
decoder = ((AFSKDemodDriver *)(handler->link_controller))->decoder_thd;
@ -279,26 +277,26 @@ THD_FUNCTION(pktRadioManager, arg) {
/* Get thread exit code and free memory. */
msg_t send_msg = chThdWait(task_object->thread);
//if(send_msg != MSG_OK) {
if(send_msg == MSG_TIMEOUT) {
TRACE_ERROR("RAD > Transmit timeout");
}
if(send_msg == MSG_RESET) {
TRACE_ERROR("RAD > Transmit failed to start");
}
//}
bool rxok = true;
/* If no transmissions pending then enable RX or shutdown. */
/* If no transmissions pending then enable RX or power down. */
if(--handler->tx_count == 0) {
/* Check at handler level is OK. No LLD required. */
if(pktIsReceivePaused(radio)) {
rxok = pktLLDresumeReceive(radio);
if(!rxok) {
if(!pktLLDradioResumeReceive(radio)) {
TRACE_ERROR("RAD > Receive failed to resume after transmit");
break;
}
pktResumeDecoding(radio);
/* TODO: Implement LLD since resume depends on radio and mod type. */
pktLLDradioResumeDecoding(radio);
//pktResumeDecoding(radio);
} else {
/* TODO: Implement LLD function for this. */
Si446x_shutdown(radio);
/* Power down radio. */
pktLLDradioPowerDown(radio);
}
} /* Else more TX tasks outstanding so let those complete. */
break;
@ -315,6 +313,7 @@ THD_FUNCTION(pktRadioManager, arg) {
/* Return radio task object to free list. */
chFifoReturnObject(radio_queue, (radio_task_object_t *)task_object);
} /* End while should terminate(). */
/* Thread has been terminated. */
chFactoryReleaseObjectsFIFO(handler->the_radio_fifo);
chThdExit(MSG_OK);
}
@ -322,7 +321,7 @@ THD_FUNCTION(pktRadioManager, arg) {
/**
* Create the radio manager thread.
*/
thread_t *pktRadioManagerCreate(radio_unit_t radio) {
thread_t *pktRadioManagerCreate(const radio_unit_t radio) {
packet_svc_t *handler = pktGetServiceObject(radio);
@ -376,7 +375,7 @@ thread_t *pktRadioManagerCreate(radio_unit_t radio) {
*
* @api
*/
void pktRadioManagerRelease(radio_unit_t radio) {
void pktRadioManagerRelease(const radio_unit_t radio) {
packet_svc_t *handler = pktGetServiceObject(radio);
/*
* Get a task object to send to the manager.
@ -404,7 +403,7 @@ void pktRadioManagerRelease(radio_unit_t radio) {
*
* @iclass
*/
msg_t pktGetRadioTaskObjectI(radio_unit_t radio,
msg_t pktGetRadioTaskObjectI(const radio_unit_t radio,
radio_task_object_t **rt) {
packet_svc_t *handler = pktGetServiceObject(radio);
@ -437,9 +436,9 @@ msg_t pktGetRadioTaskObjectI(radio_unit_t radio,
*
* @api
*/
void pktSubmitRadioTaskI(radio_unit_t radio,
void pktSubmitRadioTaskI(const radio_unit_t radio,
radio_task_object_t *object,
radio_task_cb_t cb) {
const radio_task_cb_t cb) {
packet_svc_t *handler = pktGetServiceObject(radio);
chDbgAssert(handler != NULL, "invalid radio ID");
@ -478,8 +477,8 @@ void pktSubmitRadioTaskI(radio_unit_t radio,
*
* @api
*/
msg_t pktGetRadioTaskObject(radio_unit_t radio,
sysinterval_t timeout,
msg_t pktGetRadioTaskObject(const radio_unit_t radio,
const sysinterval_t timeout,
radio_task_object_t **rt) {
packet_svc_t *handler = pktGetServiceObject(radio);
@ -515,9 +514,9 @@ msg_t pktGetRadioTaskObject(radio_unit_t radio,
*
* @api
*/
void pktSubmitRadioTask(radio_unit_t radio,
void pktSubmitRadioTask(const radio_unit_t radio,
radio_task_object_t *object,
radio_task_cb_t cb) {
const radio_task_cb_t cb) {
packet_svc_t *handler = pktGetServiceObject(radio);
chDbgAssert(handler != NULL, "invalid radio ID");
@ -551,7 +550,7 @@ void pktSubmitRadioTask(radio_unit_t radio,
*
* @api
*/
void pktScheduleSendComplete(radio_task_object_t *rto,
void pktLLDradioSendComplete(radio_task_object_t *rto,
thread_t *thread) {
packet_svc_t *handler = rto->handler;
@ -600,7 +599,7 @@ void pktReleaseRadio(const radio_unit_t radio) {
/*
*
*/
int pktDisplayFrequencyCode(radio_freq_t code, char *buf, size_t size) {
int pktDisplayFrequencyCode(const radio_freq_t code, char *buf, size_t size) {
char* str = NULL;
switch(code) {
case FREQ_RADIO_INVALID:
@ -691,7 +690,8 @@ radio_freq_t pktGetReceiveOperatingFrequency(const radio_unit_t radio) {
/*
*
*/
radio_freq_t pktCheckAllowedFrequency(radio_unit_t radio, radio_freq_t freq) {
radio_freq_t pktCheckAllowedFrequency(const radio_unit_t radio,
radio_freq_t freq) {
/* Check validity. */
uint8_t radios = pktGetNumRadios();
const radio_config_t *list = pktGetRadioList();
@ -767,7 +767,18 @@ radio_freq_t pktComputeOperatingFrequency(const radio_unit_t radio,
return pktCheckAllowedFrequency(radio, op_freq);
}
void pktPowerUpRadio(radio_unit_t radio) {
/**
*
*/
void pktLLDradioInit(const radio_unit_t radio) {
/* TODO: Implement hardware mapping. */
Si446x_conditional_init(radio);
}
/**
*
*/
void pktLLDradioPowerUp(const radio_unit_t radio) {
/* TODO: Implement hardware mapping. */
(void)radio;
/*
@ -779,11 +790,10 @@ void pktPowerUpRadio(radio_unit_t radio) {
*/
// Power up transceiver
palClearLine(LINE_RADIO_SDN); // Radio SDN low (power up transceiver)
chThdSleep(TIME_MS2I(10)); // Wait for transceiver to power up
Si446x_powerup(radio);
}
void pktPowerDownRadio(radio_unit_t radio) {
void pktLLDradioPowerDown(const radio_unit_t radio) {
/* TODO: Implement hardware mapping. */
(void)radio;
@ -791,7 +801,8 @@ void pktPowerDownRadio(radio_unit_t radio) {
* Put radio in shutdown mode.
* All registers are lost.
*/
palSetLine(LINE_RADIO_SDN);
//palSetLine(LINE_RADIO_SDN);
Si446x_shutdown(radio);
}
/**
@ -804,7 +815,7 @@ void pktPowerDownRadio(radio_unit_t radio) {
*
* @notapi
*/
bool pktLLDsendPacket(radio_task_object_t *rto) {
bool pktLLDradioSendPacket(radio_task_object_t *rto) {
bool status;
/* TODO: Implement VMT to functions per radio type. */
switch(rto->type) {
@ -822,6 +833,52 @@ bool pktLLDsendPacket(radio_task_object_t *rto) {
return status;
}
/**
* @brief Enable reception.
* @notes This is the API interface to the radio LLD.
* @notes Currently just map directly to 446x driver.
* @notes In future would implement a lookup and VMT to access radio methods.
*
* @param[in] radio radio unit ID.
* @param[in] rto pointer to radio task object
*
* @return status of the operation
* @retval true operation succeeded.
* retval false operation failed.
*
* @notapi
*/
bool pktLLDradioEnableReceive(const radio_unit_t radio,
radio_task_object_t *rto) {
packet_svc_t *handler = pktGetServiceObject(radio);
chDbgAssert(handler != NULL, "invalid radio ID");
if(handler == NULL)
return false;
Si446x_setBandParameters(radio,
rto->base_frequency,
rto->step_hz);
Si446x_receiveNoLock(radio,
rto->base_frequency,
rto->step_hz,
rto->channel,
rto->squelch,
rto->type);
return true;
}
/**
*
*/
void pktLLDradioDisableReceive(const radio_unit_t radio) {
/* TODO: Implement hardware mapping. */
Si446x_disableReceive(radio);
}
/**
* @brief Resume reception paused by transmit task.
* @notes This is the API interface to the radio LLD.
@ -836,7 +893,7 @@ bool pktLLDsendPacket(radio_task_object_t *rto) {
*
* @notapi
*/
bool pktLLDresumeReceive(const radio_unit_t radio) {
bool pktLLDradioResumeReceive(const radio_unit_t radio) {
packet_svc_t *handler = pktGetServiceObject(radio);
chDbgAssert(handler != NULL, "invalid radio ID");
@ -847,7 +904,6 @@ bool pktLLDresumeReceive(const radio_unit_t radio) {
radio_squelch_t rssi = handler->radio_rx_config.squelch;
mod_t mod = handler->radio_rx_config.type;
bool result = Si4464_resumeReceive(radio, freq, step, chan, rssi, mod);
//pktResumeDecoding(radio);
return result;
}
@ -859,13 +915,62 @@ bool pktLLDresumeReceive(const radio_unit_t radio) {
* @notes The function should be called directly from the RX front end handler.
* @notes Calling from a deferred level will not capture the instantaneous level.
*
* @param[in] handler pointer to packet handler object.
* @param[in] radio radio unit ID.
*
* @notapi
*/
void pktLLDcaptureReceiveStrength(packet_svc_t *handler) {
chDbgAssert(handler != NULL, "invalid handler");
handler->rx_stength = Si446x_getCurrentRSSI(handler->radio);
void pktLLDradioCaptureRSSI(const radio_unit_t radio) {
packet_svc_t *handler = pktGetServiceObject(radio);
chDbgAssert(handler != NULL, "invalid radio ID");
handler->rx_stength = Si446x_getCurrentRSSI(radio);
}
/**
*
*/
void pktLLDradioPauseDecoding(const radio_unit_t radio) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only one at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher of radio driver.
*/
pktPauseDecoding(radio);
}
/**
*
*/
void pktLLDradioResumeDecoding(const radio_unit_t radio) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only one at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher inside radio driver.
*/
pktResumeDecoding(radio);
}
/**
*
*/
void pktLLDradioStartDecoder(const radio_unit_t radio) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only one at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher inside radio driver.
*/
pktStartDecoder(radio);
}
/**
*
*/
void pktLLDradioStopDecoder(const radio_unit_t radio) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only one at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher inside radio driver.
*/
pktStopDecoder(radio);
}
/** @} */

Wyświetl plik

@ -139,27 +139,35 @@ extern "C" {
void pktSubmitRadioTask(const radio_unit_t radio,
radio_task_object_t *object,
radio_task_cb_t cb);
void pktScheduleThreadRelease(radio_unit_t radio,
void pktScheduleThreadRelease(const radio_unit_t radio,
thread_t *thread);
msg_t pktAcquireRadio(radio_unit_t radio, sysinterval_t timeout);
void pktReleaseRadio(radio_unit_t radio);
radio_freq_t pktCheckAllowedFrequency(radio_unit_t radio, radio_freq_t freq);
msg_t pktAcquireRadio(const radio_unit_t radio, sysinterval_t timeout);
void pktReleaseRadio(const radio_unit_t radio);
radio_freq_t pktCheckAllowedFrequency(const radio_unit_t radio,
radio_freq_t freq);
radio_freq_t pktComputeOperatingFrequency(const radio_unit_t radio,
radio_freq_t base_freq,
channel_hz_t step,
radio_ch_t chan,
const radio_mode_t mode);
bool pktLLDresumeReceive(const radio_unit_t radio);
bool pktLLDsendPacket(radio_task_object_t *rto);
void pktLLDcaptureReceiveStrength(packet_svc_t *handler);
void pktScheduleSendComplete(radio_task_object_t *rto,
bool pktLLDradioEnableReceive(const radio_unit_t radio,
radio_task_object_t *rto);
void pktLLDradioDisableReceive(const radio_unit_t radio);
bool pktLLDradioResumeReceive(const radio_unit_t radio);
bool pktLLDradioSendPacket(radio_task_object_t *rto);
void pktLLDradioCaptureRSSI(const radio_unit_t radio);
void pktLLDradioPowerUp(const radio_unit_t radio);
void pktLLDradioInit(const radio_unit_t radio);
void pktLLDradioPowerDown(const radio_unit_t radio);
void pktLLDradioPauseDecoding(const radio_unit_t radio);
void pktLLDradioResumeDecoding(const radio_unit_t radio);
void pktLLDradioStartDecoder(const radio_unit_t radio);
void pktLLDradioStopDecoder(const radio_unit_t radio);
void pktLLDradioSendComplete(radio_task_object_t *rto,
thread_t *thread);
void pktStartDecoder(const radio_unit_t radio);
void pktStopDecoder(const radio_unit_t radio);
int pktDisplayFrequencyCode(radio_freq_t code, char *buf, size_t size);
void pktPowerUpRadio(radio_unit_t radio);
void pktPowerDownRadio(radio_unit_t radio);
radio_freq_t pktCheckAllowedFrequency(radio_unit_t radio, radio_freq_t freq);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -668,7 +668,7 @@ thread_t *pktCreateBufferCallback(pkt_data_object_t *pkt_buffer) {
/* Create a callback thread name which is the address of the buffer. */
/* TODO: Create a more meaningful but still unique thread name. */
chsnprintf(pkt_buffer->cb_thd_name, sizeof(pkt_buffer->cb_thd_name),
"%x", pkt_buffer);
PKT_CALLBACK_THD_PREFIX"%x", pkt_buffer);
/* Start a callback dispatcher thread. */
thread_t *cb_thd = chThdCreateFromHeap(NULL,

Wyświetl plik

@ -17,6 +17,7 @@
#define PKT_FRAME_QUEUE_PREFIX "pktr_"
#define PKT_CALLBACK_TERMINATOR_PREFIX "cbte_"
#define PKT_CALLBACK_THD_PREFIX "cb_"
#define PKT_SEND_BUFFER_SEM_NAME "pbsem"
@ -67,7 +68,7 @@ typedef struct packetBuffer {
packet_svc_t *handler;
dyn_objects_fifo_t *pkt_factory;
thread_t *cb_thread;
char cb_thd_name[sizeof(size_t) + 1];
char cb_thd_name[PKT_THREAD_NAME_MAX];
pkt_buffer_cb_t cb_func;
volatile eventflags_t status;
size_t buffer_size;
@ -165,7 +166,6 @@ typedef struct packetHandlerData {
*/
pkt_data_object_t *active_packet_object;
/**
* @brief Counter for active callback threads.
* TODO: type should be of a generic counter?
@ -426,6 +426,7 @@ static inline void pktReleaseDataBuffer(pkt_data_object_t *object) {
* If the service is closed and all buffers freed then the FIFO is destroyed.
* Terminate this thread and have idle clean up memory.
*/
object->handler->cb_count--;
chFifoReturnObject(pkt_fifo, object);
chFactoryReleaseObjectsFIFO(pkt_factory);
pktThdTerminateSelf();
@ -436,8 +437,6 @@ static inline void pktReleaseDataBuffer(pkt_data_object_t *object) {
* It will be released in the collector thread.
* The callback thread memory will be recovered.
* The semaphore will be signaled.
* TODO: Release the FIFO here and send the thread to idle loop terminator.
* This will simplify the release mechanism and make the FIFO available sooner.
*/
chSysLock();
chFifoSendObjectI(pkt_fifo, object);

Wyświetl plik

@ -33,11 +33,26 @@ static dataPoint_t* lastDataPoint;
static bool threadStarted = false;
static uint8_t bme280_error;
/**
* Array for looking up model name
*/
static const char *state[] = {GPS_STATE_NAMES};
/*===========================================================================*/
/* Module external variables. */
/*===========================================================================*/
thread_t *collector_thd;
/**
* Get pointer to state name as string
*/
const char *get_gps_state_name(uint8_t index) {
if(index > GPS_STATE_MAX)
return "INVALID";
return state[index];
}
/**
* Returns most recent data point which is complete.
*/
@ -175,6 +190,8 @@ static bool aquirePosition(dataPoint_t* tp, dataPoint_t* ltp,
* Output SV info.
* Switch off GPS (unless cycle is less than 60 seconds).
*/
TRACE_INFO("GPS > Lock acquired. Model in use is %s",
gps_get_model_name(gpsFix.model));
gps_svinfo_t svinfo;
if(gps_get_sv_info(&svinfo, sizeof(svinfo))) {
TRACE_INFO("GPS > Space Vehicle info iTOW=%d numCh=%02d globalFlags=%d",
@ -399,7 +416,7 @@ THD_FUNCTION(collectorThread, arg) {
dataPoints[1].gps_time = date2UnixTimestamp(&time);
lastDataPoint = &dataPoints[0];
dataPoint_t *newDataPoint = lastDataPoint++;
//dataPoint_t *newDataPoint = lastDataPoint++;
// Get last data point from memory
TRACE_INFO("COLL > Read last data point from flash memory");
@ -491,12 +508,9 @@ THD_FUNCTION(collectorThread, arg) {
* Enable the GPS and attempt a lock which results in setting the RTC.
*/
TRACE_INFO("COLL > Acquire time using GPS");
if(aquirePosition(newDataPoint, lastDataPoint, TIME_S2I(600))) {
if(aquirePosition(tp, ltp, TIME_S2I(600))) {
/* Acquisition succeeded. */
TRACE_INFO("COLL > Time update acquired from GPS");
/* Update with freshly acquired data. */
lastDataPoint = newDataPoint;
GPS_Deinit();
} else {
/* Time is stale record. */
TRACE_INFO("COLL > Time update not acquired from GPS");
@ -541,10 +555,13 @@ THD_FUNCTION(collectorThread, arg) {
}
tp->id = ++id; // Serial ID
extern uint8_t gps_model;
// Trace data
unixTimestamp2Date(&time, tp->gps_time);
TRACE_INFO( "COLL > New data point available (ID=%d, GPS state=%d)\r\n"
TRACE_INFO( "COLL > GPS status: state=%s model=%s)",
get_gps_state_name(tp->gps_state),
gps_get_model_name(gps_model));
TRACE_INFO( "COLL > New data point (ID=%d)\r\n"
"%s Time %04d-%02d-%02d %02d:%02d:%02d\r\n"
"%s Pos %d.%05d %d.%05d Alt %dm\r\n"
"%s Sats %d TTFF %dsec\r\n"
@ -552,7 +569,7 @@ THD_FUNCTION(collectorThread, arg) {
"%s AIR p=%d.%01dPa T=%d.%02ddegC phi=%d.%01d%%\r\n"
"%s IOP IO1=%d IO2=%d IO3=%d IO4=%d\r\n"
"%s STN %s",
tp->id, tp->gps_state,
tp->id,
TRACE_TAB, time.year, time.month, time.day, time.hour, time.minute, time.day,
TRACE_TAB, tp->gps_lat/10000000, (tp->gps_lat > 0 ? 1:-1)*(tp->gps_lat/100)%100000, tp->gps_lon/10000000, (tp->gps_lon > 0 ? 1:-1)*(tp->gps_lon/100)%100000, tp->gps_alt,
TRACE_TAB, tp->gps_sats, tp->gps_ttff,

Wyświetl plik

@ -27,6 +27,15 @@
#define BME280_E1_IS_FITTED FALSE
#define BME280_E2_IS_FITTED TRUE
/**
* @brief GPS states as array of strings.
* @details Each element in an array initialized with this macro can be
* indexed using a numeric GPS model value.
*/
#define GPS_STATE_NAMES \
"LOCKED1", "LOCKED2", "LOSS", "LOWBATT1", "LOWBATT2", "LOG", "OFF", \
"ERROR", "FIXED"
typedef enum {
GPS_LOCKED1, // The GPS is locked, the GPS has been switched off
GPS_LOCKED2, // The GPS is locked, the GPS has been kept switched on
@ -39,6 +48,8 @@ typedef enum {
GPS_FIXED // Fixed location data used from APRS location
} gpsState_t;
#define GPS_STATE_MAX GPS_FIXED
typedef struct {
// Voltage and current measurement
uint16_t adc_vsol; // Current solar voltage in mV
@ -110,6 +121,7 @@ dataPoint_t* getLastDataPoint(void);
void getSensors(dataPoint_t* tp);
void setSystemStatus(dataPoint_t* tp);
void init_data_collector(void);
const char *get_gps_state_name(uint8_t index);
/*===========================================================================*/
/* Module inline functions. */
@ -170,11 +182,9 @@ void init_data_collector(void);
*
* @api
*/
#define isGPSbatteryOperable(dp) (!(dp->gps_state == GPS_LOWBATT1 \
|| dp->gps_state == GPS_LOWBATT2 \
|| dp->gps_state == GPS_FIXED \
|| dp->gps_state == GPS_ERROR \
|| dp->gps_state == GPS_OFF))
#define isGPSbatteryOperable(dp) (dp->gps_state == GPS_LOCKED1 \
|| dp->gps_state == GPS_LOCKED2 \
|| dp->gps_state == GPS_LOSS)
#endif /* __COLLECTOR_H__ */

Wyświetl plik

@ -47,19 +47,21 @@ THD_FUNCTION(bcnThread, arg) {
*/
dataPoint_t *dataPoint =
(dataPoint_t *)chMsgSend(collector_thd, (msg_t)conf);
/* Continue here when collector responds. */
if(!p_sleep(&conf->beacon.sleep_conf)) {
if(!isPositionValid(dataPoint) || dataPoint == NULL) {
TRACE_INFO("BCN > Waiting for position data for"
" %s (GPS state=%d)", conf->call, dataPoint->gps_state);
if(conf->run_once) {
/* If this is run once don't retry. */
/* If this is run once so don't retry. */
chHeapFree(conf);
pktThdTerminateSelf();
}
if(isGPSbatteryOperable(dataPoint)) {
/* If the battery is good retry quickly.
* TODO: Rework and involve the p_sleep setting? */
* TODO: Rework and involve the p_sleep setting?
* Limit to a number of retries? */
chThdSleep(TIME_S2I(60));
continue;
}

Wyświetl plik

@ -747,7 +747,7 @@ THD_FUNCTION(imgThread, arg) {
void start_image_thread(img_app_conf_t *conf)
{
thread_t *th = chThdCreateFromHeap(NULL,
THD_WORKING_AREA_SIZE(40 * 1024),
THD_WORKING_AREA_SIZE(30 * 1024),
"IMG", LOWPRIO, imgThread, conf);
if(!th) {
// Print startup error, do not start watchdog for this thread

Wyświetl plik

@ -1,73 +1,74 @@
#include "ch.h"
#include "hal.h"
#include "debug.h"
#ifndef DISABLE_HW_WATCHDOG
// Hardware Watchdog configuration
static const WDGConfig wdgcfg = {
.pr = STM32_IWDG_PR_256,
.rlr = STM32_IWDG_RL(10000)
};
#endif
static void flash_led(void) {
palSetLine(LINE_IO_GREEN);
chThdSleep(TIME_MS2I(50));
palClearLine(LINE_IO_GREEN);
}
THD_FUNCTION(wdgThread, arg) {
(void)arg;
// Setup LED
palSetLineMode(LINE_IO_GREEN, PAL_MODE_OUTPUT_PUSHPULL);
uint8_t counter = 0;
while(true)
{
chThdSleep(TIME_MS2I(500));
bool healthy = true;
// FIXME: Watchdog without functionality at the moment
/*for(uint8_t i=0; i<threads_cnt; i++) {
if(registered_threads[i]->wdg_timeout < chVTGetSystemTime())
{
TRACE_ERROR("WDG > Thread %s not healty", registered_threads[i]->name);
healthy = false; // Threads reached timeout
}
}*/
if(healthy)
#ifndef DISABLE_HW_WATCHDOG
wdgReset(&WDGD1); // Reset hardware watchdog at no error
#endif
// Switch LEDs
if(counter++ % (4*healthy) == 0)
{
flash_led();
}
}
}
void init_watchdog(void)
{
#ifndef DISABLE_HW_WATCHDOG
// Initialize Watchdog
TRACE_INFO("WDG > Initialize Watchdog");
wdgStart(&WDGD1, &wdgcfg);
wdgReset(&WDGD1);
#else
#warning "Hardware Watchdog is disabled"
TRACE_INFO("WDG > Watchdog disabled");
#endif
flash_led();
TRACE_INFO("WDG > Startup Watchdog thread");
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(256), "WDG", NORMALPRIO, wdgThread, NULL);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("TRAC > Could not startup thread (not enough memory available)");
}
}
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "portab.h"
#ifndef DISABLE_HW_WATCHDOG
// Hardware Watchdog configuration
static const WDGConfig wdgcfg = {
.pr = STM32_IWDG_PR_256,
.rlr = STM32_IWDG_RL(10000)
};
#endif
static void flash_led(void) {
palSetLine(LINE_IO_GREEN);
chThdSleep(TIME_MS2I(50));
palClearLine(LINE_IO_GREEN);
}
THD_FUNCTION(wdgThread, arg) {
(void)arg;
// Setup LED
palSetLineMode(LINE_IO_GREEN, PAL_MODE_OUTPUT_PUSHPULL);
uint8_t counter = 0;
while(true)
{
chThdSleep(TIME_MS2I(500));
bool healthy = true;
// FIXME: Watchdog without functionality at the moment
/*for(uint8_t i=0; i<threads_cnt; i++) {
if(registered_threads[i]->wdg_timeout < chVTGetSystemTime())
{
TRACE_ERROR("WDG > Thread %s not healty", registered_threads[i]->name);
healthy = false; // Threads reached timeout
}
}*/
if(healthy)
#ifndef DISABLE_HW_WATCHDOG
wdgReset(&WDGD1); // Reset hardware watchdog at no error
#endif
// Switch LEDs
if(counter++ % (4*healthy) == 0)
{
flash_led();
}
}
}
void init_watchdog(void)
{
#ifndef DISABLE_HW_WATCHDOG
// Initialize Watchdog
TRACE_INFO("WDG > Initialize Watchdog");
wdgStart(&WDGD1, &wdgcfg);
wdgReset(&WDGD1);
#else
#warning "Hardware Watchdog is disabled"
TRACE_INFO("WDG > Watchdog disabled");
#endif
flash_led();
TRACE_INFO("WDG > Startup Watchdog thread");
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(256), "WDG", NORMALPRIO, wdgThread, NULL);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("TRAC > Could not startup thread (not enough memory available)");
}
}