Added documentation in config

Merged configuration types
Made USB and 3V switch configureable
Removed USB debugging temporarly
Adjusted camera clocking
Removed Si4464 power conversion function
Implemented I2C communication with ublox module
Fixed endless-loop bug in tracking manager
Increased cutoff voltage at which PAC1720 is used
Implemented redundant tansmission option
Moved APRS definitions to APRS related files
Renamed variables (so they get more understandable)
Develop
Sven Steudte 2017-06-20 15:24:22 +02:00
rodzic 661ea01761
commit 5086edf310
25 zmienionych plików z 13986 dodań i 189 usunięć

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

Wyświetl plik

@ -640,8 +640,8 @@
PIN_PUPDR_PULLDOWN(GPIOC_PIN4) | \
PIN_PUPDR_PULLDOWN(GPIOC_PIN5) | \
PIN_PUPDR_PULLDOWN(GPIOC_PIN6) | \
PIN_PUPDR_FLOATING(GPIOC_PIN7) | \
PIN_PUPDR_PULLDOWN(GPIOC_PIN8) | \
PIN_PUPDR_PULLDOWN(GPIOC_PIN7) | \
PIN_PUPDR_FLOATING(GPIOC_PIN8) | \
PIN_PUPDR_PULLDOWN(GPIOC_PIN9) | \
PIN_PUPDR_PULLDOWN(GPIOC_PIN10) | \
PIN_PUPDR_PULLDOWN(GPIOC_PIN11) | \

Wyświetl plik

@ -5,17 +5,178 @@ module_conf_t config[9];
uint8_t ssdv_buffer[1024*50];
uint8_t ssdv_buffer2[1024*100];
/*
* Position module configuration description
* =========================================
*
* power int(0-127) Defines the radio power level. It ranges from 0 (low) to 127 (high). This value is sent into the Si4464 register. The
* (required) real output power is operation voltage dependent. The operation voltage can be set by RUN_3V in config.h. If USB is
* activated the operation voltage is 3V regardsless to which value RUN_3V is set. Running the PCB at 3V following table
* applies:
* 20 dBm => 127
* 15 dBm => 40
* 10 dBm => 20
* 5 dBm => 12
* 0 dBm => 8
*
* protocol prot_t Possible Options:
* (required) - PROT_APRS_AFSK FM AFSK 1200baud transmission using the APRS protocol
* this option requires aprs_conf to be set
* - PROT_APRS_2GFSK 2GFSK transmission using the APRS protocol
* this option requires aprs_conf and gfsk_conf to be set
* - PROT_UKHAS_2FSK Comma separated 2FSK transmission (RTTY) using the UKHAS standard
* this option requires ukhas_conf and fsk_conf to be set
* - PROT_MORSE Morse transmission
* this option requires morse_conf and ook_conf to be set
*
* frequency.type freq_type_t Defines the frequency type. This option will be FREQ_STATIC if not set.
* (default FREQ_STATIC) Possible Options:
* - FREQ_STATIC Static frequency taken from frequency.hz
* - FREQ_APRS_REGION Using the APRS region frequency. The tracker will change its frequency specificly to the region
* where it is located. e.g. 144.8MHz in Europe or 144.39MHz in the US. If the tracker doesnt know its
* position it takes its frequency from frequency.hz as default. Note that the tracker knows its
* position from its position log too. So it might use the last frequency which has been used before
* resetting it.
*
* frequency.hz int Frequency that this Module will transmit on (in Hz). The tracker can transmit in the 2m band. This value will be used
* (required) as default when frequency.type == FREQ_APRS_REGION and it doesnt know its position
*
* init_delay int Initial delay (in ms) before the module starts. This might be useful if you dont want to transmit so many APRS packets
* (default 0ms) at the same time on the APRS network. This option is optional. It will be 0ms if not set.
*
* trigger.type trigger_type_t Event at which this module is triggered to transmit. This option will be TRIG_ONCE if not set.
* (default TRIG_ONCE) Possible options:
* - TRIG_ONCE Trigger once and never again (e.g. transmit specific position packet only at startup)
* - TRIG_NEW_POINT Triggered when new track point available
* - TRIG_TIMEOUT Triggered by timeout (e.g. trasmit position every 120sec)
* this option requires trigger.timeout to be set
* - TRIG_CONTINOUSLY Continue continously (e.g. send new image once old image sent completely)
*
* ============================== The following options are needed if protocol == PROT_APRS_AFSK or protocol == PROT_APRS_2GFSK ===============================
*
* aprs_conf.callsign string Your amateur radio callsign (this requires an amateur radio license). This callsign will be used in the APRS protocol.
* (required) You can transmit on the 70cm band without a license but the transmitter would need a 70cm LPF therefore.
*
* aprs_conf.ssid int(0-15) APRS SSID (no SSID = 0)
* (default 0)
*
* aprs_conf.symbol int APRS Symbol (according to this table http://www.aprs.org/symbols.html)
* (required) Possible Options: SYM_BALLOON, SYM_SMALLAIRCRAFT, SYM_SATELLITE
*
* aprs_conf.path string APRS digipeating path (default: no digipeating)
* (optional)
*
* aprs_conf.preamble int AFSK or 2GFSK preamble length (in ms). This value is required while its default is 0ms (and this would simply not work ;-) )
* (required)
*
* aprs_conf.tel[0-4] telemetry_t There are numerous telemetry values which can be sent in the APRS position packet. One packet can contain 5 values.
* (required) There are possible options:
* - TEL_SATS GPS Satellites
* - TEL_TTFF Time to first fix (amount of seconds which it needed to aquire a GPS fix)
* - TEL_VBAT Battery voltage
* - TEL_VSOL Solar voltage
* - TEL_PBAT Battery power (positive charge, negative discharge)
* - TEL_ISOL Solar short current (works only if USB is unattached)
* - TEL_PRESS Air pressure (by BME280)
* - TEL_TEMP Air temperature (by BME280)
* - TEL_HUM Air humidity (by BME280)
*
* aprs_conf.tel_enc bool The telemetry in the position packets do only contain the raw values. Receivers (like aprs.fi) dont know what these
* (default false) values stands for. So we must tell them (e.g. that value 1 is air pressure measured in Pascal). If set to true, the
* tracker will transmit additional packets containing these informations. This option requires aprs_conf.tel_enc_cycle.
*
* aprs_conf.tel_enc_cycle int This values defines how often telemetry configuration packets are sent. Transmitting those packets every two
* (default 0sec) hours (7200sec) is a good value. This value is set in seconds.
*
* aprs_conf.tel_comment string There can be set a short comment which is sent with the APRS configuration packets. It has no affect if
* (optional) aprs_conf.tel_enc is set false. Its default is empty.
*
* ============================================= The following options are needed if protocol == PROT_APRS_2GFSK ==============================================
*
* gfsk_conf.speed int 2GFSK speed. Following values have been tested successfully: 9600, 19200, 38400, 76800, 96000.
* (required)
*
* ============================================= The following options are needed if protocol == PROT_UKHAS_2FSK ==============================================
*
* fsk_conf.bits int(7-8) Bits
* (required)
*
* fsk_conf.stopbits int(1-2) Stopbits
* (required)
*
* fsk_conf.predelay int Predelay (in ms). The receiver needs to settle on the frequency for a while. Therefore is switched on some seconds
* (default 0ms) before. By default its 0ms but that wouldnt work.
*
* fsk_conf.baud int Baudrate. Following values have been tested successfully: 50, 300, 600.
* (required)
*
* fsk_conf.shift int Frequency shift of 2FSK
* (required)
*
* ukhas_conf.callsign string Your amateur radio callsign (this requires an amateur radio license). This callsign will be used in the UKHAS protocol.
* (required) You can transmit on the 70cm band without a license but the transmitter would need a 70cm LPF therefore.
*
* ukhas_conf.format string UKHAS format. This is the string which will be sent. This string contains variables (e.g. <VBAT>) which will be
* (required) replaced by the actual values.
* For example: "<CALL>,<ID>,<TIME>,<LAT>,<LON>,<ALT>" will become "MYCALL,324,14:23:35,52.4537,13.9362,8462"
* The prefix "$$$$$" and CRC will be added automatically. Following variables can be used:
* - <ID> Incremental ID
* - <DATE> Date
* - <TIME> Time
* - <LAT> Latitude
* - <LON> Longitude
* - <ALT> Altitude (in meter!)
* - <SATS> GPS Satellites
* - <TTFF> Time to first fix
* - <VBAT> Battery voltage
* - <VSOL> Solar voltage
* - <PBAT> Battery power consumption
* - <ISOL> Solar short current
* - <PRESS> Air pressure
* - <TEMP> Air temperature
* - <HUM> Air humidity
* - <LOC> Maidenhead locator
*
* ================================================ The following options are needed if protocol == PROT_MORSE ================================================
*
* ook_conf.speed int Morse Speed in Wpm
* (required)
*
* morse_conf.callsign string Your amateur radio callsign (this requires an amateur radio license). This callsign will be used in the morse "protocol".
* (required) You can transmit on the 70cm band without a license but the transmitter would need a 70cm LPF therefore.
*
* morse_conf.format string Morse format. This is the string which will be sent. This string contains variables (e.g. <VBAT>) which will be
* (required) replaced by the actual values.
* For example: "BALLOON <CALL> <LOC> <ALT>M" will become "BALLOON MYCALL JO62CF 9362M"
* The following variables can be used:
* - <ID> Incremental ID
* - <DATE> Date
* - <TIME> Time
* - <LAT> Latitude
* - <LON> Longitude
* - <ALT> Altitude (in meter!)
* - <SATS> GPS Satellites
* - <TTFF> Time to first fix
* - <VBAT> Battery voltage
* - <VSOL> Solar voltage
* - <PBAT> Battery power consumption
* - <ISOL> Solar short current
* - <PRESS> Air pressure
* - <TEMP> Air temperature
* - <HUM> Air humidity
* - <LOC> Maidenhead locator
*/
// Put your configuration settings here
void start_user_modules(void)
{
// Module POSITION, APRS 2m AFSK
config[0].power = 20; // Power 20 dBm
/*config[0].power = 127; // Power 20 dBm
config[0].protocol = PROT_APRS_AFSK; // Protocol APRS, modulation AFSK
config[0].frequency.type = FREQ_APRS_REGION; // Dynamic frequency allocation
config[0].frequency.hz = 144800000; // Default frequency 144.800 MHz
config[0].init_delay = 0; // Module startup delay in msec
config[0].trigger.type = TRIG_EVENT; // Trigger transmission on event
config[0].trigger.event = EVENT_NEW_POINT; // Trigger when new track point released
config[0].trigger.type = TRIG_NEW_POINT; // Trigger when new track point released
chsnprintf(config[0].aprs_conf.callsign, 6, "DL7AD"); // APRS Callsign
config[0].aprs_conf.ssid = 12; // APRS SSID
config[0].aprs_conf.symbol = SYM_BALLOON; // APRS Symbol
@ -26,20 +187,19 @@ void start_user_modules(void)
config[0].aprs_conf.tel[2] = TEL_TEMP; // APRS Telemetry parameter 3
config[0].aprs_conf.tel[3] = TEL_PBAT; // APRS Telemetry parameter 4
config[0].aprs_conf.tel[4] = TEL_ISOL; // APRS Telemetry parameter 5
config[0].aprs_conf.tel_encoding = TRUE; // Transmit Telemetry encoding information activated
config[0].aprs_conf.tel_encoding_cycle = 3600; // Transmit Telemetry encoding information every 3600sec
config[0].aprs_conf.tel_enc = TRUE; // Transmit Telemetry encoding information activated
config[0].aprs_conf.tel_enc_cycle = 3600; // Transmit Telemetry encoding information every 3600sec
chsnprintf(config[0].aprs_conf.tel_comment, 18, "http://tkrahn.org");// Telemetry comment
start_position_thread(&config[0]);
start_position_thread(&config[0]);*/
// Module POSITION, APRS 2m 2GFSK
/*config[1].power = 20; // Power 10 dBm
/*config[1].power = 127; // Power 10 dBm
config[1].protocol = PROT_APRS_2GFSK; // Protocol APRS, modulation 2GFSK
config[1].gfsk_conf.speed = 9600; // 2GFSK Speed
config[1].frequency.type = FREQ_STATIC; // Static frequency allocation
config[1].frequency.hz = 144860000; // Default frequency 144.860 MHz
config[1].init_delay = 0; // Module startup delay in msec
config[1].trigger.type = TRIG_EVENT; // Trigger transmission on event
config[1].trigger.event = EVENT_NEW_POINT; // Trigger when new track point released
config[1].trigger.type = TRIG_NEW_POINT; // Trigger when new track point released
chsnprintf(config[1].aprs_conf.callsign, 7, "DL4MDW"); // APRS Callsign
config[1].aprs_conf.ssid = 11; // APRS SSID
config[1].aprs_conf.symbol = SYM_BALLOON; // APRS Symbol
@ -50,19 +210,18 @@ void start_user_modules(void)
config[0].aprs_conf.tel[2] = TEL_PRESS; // APRS Telemetry parameter 3
config[0].aprs_conf.tel[3] = TEL_TEMP; // APRS Telemetry parameter 4
config[0].aprs_conf.tel[4] = TEL_PBAT; // APRS Telemetry parameter 5
config[1].aprs_conf.tel_encoding = TRUE; // Transmit Telemetry encoding information enabled
config[1].aprs_conf.tel_encoding_cycle = 3600; // Transmit Telemetry encoding information every 3600sec
config[1].aprs_conf.tel_enc = TRUE; // Transmit Telemetry encoding information enabled
config[1].aprs_conf.tel_enc_cycle = 3600; // Transmit Telemetry encoding information every 3600sec
chsnprintf(config[1].aprs_conf.tel_comment, 18, "http://tkrahn.net");// Telemetry comment
start_position_thread(&config[1]);*/
// Module POSITION, UKHAS 2m 2FSK
/*config[2].power = 20; // Power 10 dBm
/*config[2].power = 127; // Power 10 dBm
config[2].protocol = PROT_UKHAS_2FSK; // Protocol UKHAS, modulation 2FSK
config[2].frequency.type = FREQ_STATIC; // Static frequency allocation
config[2].frequency.hz = 144860000; // Transmission frequency 144.860 MHz
config[2].init_delay = 2000; // Module startup delay in msec
config[2].trigger.type = TRIG_EVENT; // Trigger transmission on event
config[2].trigger.event = EVENT_NEW_POINT; // Trigger when new track point released
config[2].trigger.type = TRIG_NEW_POINT; // Trigger when new track point released
config[2].fsk_conf.bits = 8; // 8bit
config[2].fsk_conf.stopbits = 2; // 2 Stopbits
config[2].fsk_conf.predelay = 1000; // Predelay in ms (continuos carrier before actual transmission)
@ -73,25 +232,27 @@ void start_user_modules(void)
start_position_thread(&config[2]);*/
// Module IMAGE, APRS 2m AFSK low-duty cycle
/*config[3].power = 20; // Power 20 dBm
config[3].power = 127; // Power 20 dBm
config[3].protocol = PROT_APRS_AFSK; // Protocol APRS SSDV, modulation AFSK
config[3].frequency.type = FREQ_APRS_REGION; // Dynamic frequency allocation
config[3].frequency.hz = 144800000; // Transmission frequency 144.800 MHz
config[3].init_delay = 2000; // Module startup delay in msec
config[3].packet_spacing = 15000; // Packet spacing in ms
config[3].packet_spacing = 60000; // Packet spacing in ms
config[3].trigger.type = TRIG_TIMEOUT; // Trigger transmission on timeout (Periodic cycling)
config[3].trigger.timeout = 10; // Timeout 10 sec
chsnprintf(config[3].aprs_conf.callsign, 6, "DL7AD"); // APRS Callsign
config[3].aprs_conf.ssid = 12; // APRS SSID
config[3].aprs_conf.preamble = 500; // APRS Preamble
chsnprintf(config[3].aprs_conf.path, 16, "WIDE1-1"); // APRS Path
config[3].aprs_conf.preamble = 300; // APRS Preamble
chsnprintf(config[3].ssdv_conf.callsign, 6, "DL7AD"); // SSDV Callsign
config[3].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer
config[3].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size
config[3].ssdv_conf.res = RES_QVGA; // Resolution VGA
start_image_thread(&config[3]);*/
config[3].ssdv_conf.redundantTx = true; // Transmit packets twice
start_image_thread(&config[3]);
// Module POSITION, Morse 2m OOK
/*config[4].power = 10; // Power 10 dBm
/*config[4].power = 127; // Power 10 dBm
config[4].protocol = PROT_MORSE; // Protocol Morse, modulation OOK
config[4].frequency.type = FREQ_STATIC; // Static frequency allocation
config[4].frequency.hz = 144857400; // Transmission frequency 144.8574 MHz
@ -104,7 +265,7 @@ void start_user_modules(void)
start_position_thread(&config[4]);*/
// Module IMAGE, APRS 2m 2GFSK
/*config[5].power = 20; // Power 20 dBm
/*config[5].power = 127; // Power 20 dBm
config[5].protocol = PROT_APRS_2GFSK; // Protocol APRS SSDV, modulation 2GFSK
config[5].gfsk_conf.speed = 9600; // 2GFSK Speed
config[5].frequency.type = FREQ_STATIC; // Static frequency allocation
@ -122,7 +283,7 @@ void start_user_modules(void)
start_image_thread(&config[5]);*/
// Module IMAGE, SSDV 2m 2FSK
/*config[6].power = 20; // Power 20 dBm
/*config[6].power = 127; // Power 20 dBm
config[6].protocol = PROT_SSDV_2FSK; // Protocol SSDV, modulation 2FSK
config[6].frequency.type = FREQ_STATIC; // Static frequency allocation
config[6].frequency.hz = 144860000; // Transmission frequency 144.860 MHz
@ -142,7 +303,7 @@ void start_user_modules(void)
start_image_thread(&config[6]);*/
// Module LOG, APRS 2m AFSK
/*config[8].power = 20; // Power 20 dBm
/*config[8].power = 127; // Power 20 dBm
config[8].protocol = PROT_APRS_AFSK; // Protocol APRS, modulation AFSK
config[8].frequency.type = FREQ_APRS_REGION; // Dynamic frequency allocation
config[8].frequency.hz = 144800000; // Default frequency 144.800 MHz

Wyświetl plik

@ -8,17 +8,24 @@
#include "radio.h"
#include "sleep.h"
extern module_conf_t config[9];
//extern module_conf_t config[9];
#define TRACK_CYCLE_TIME 60 /* Tracking cycle (all peripheral data [airpressure, GPS, temperature, ...] is collected each x seconds */
#define LOG_CYCLE_TIME 1800 /* Log cycle in seconds */
#define LOG_CYCLE_TIME 1800 /* Log cycle time in seconds */
#define GPS_ON_VBAT 5000 /* Battery voltage threshold at which GPS is switched on */
#define GPS_OFF_VBAT 5000 /* Battery voltage threshold at which GPS is switched off */
#define GPS_ON_VBAT 2500 /* Battery voltage threshold at which GPS is switched on */
#define GPS_OFF_VBAT 3000 /* Battery voltage threshold at which GPS is switched off */
#define TRACE_TIME TRUE /* Enables time tracing on serial connection */
#define TRACE_FILE TRUE /* Enables file and line tracing on serial connection */
#define TRACE_TIME TRUE /* Enables time tracing on debugging port */
#define TRACE_FILE TRUE /* Enables file and line tracing on debugging port */
#define RUN_3V TRUE /* Lets the tracker run a 3V otherwise 1.8V. 3V is needed to do 20dBm radio output power.
* With 1.8V only 15dBm can be done. Some serial-USB adapters also need a 3V IO level in
* order to work. However 3V takes a lot of power in idle. You can save energy using 1.8V. */
#define BUILD_USB FALSE /* This enables USB data output to be used for debugging. It switches the tracker to an
* operation voltage of 3V even when RUN_3V is set to false, because USB requires 3V. I
* recommend not to use USB on a real flight while it takes around 2mA. */
void start_user_modules(void);

Wyświetl plik

@ -7,7 +7,10 @@
#include "ptime.h"
#include "config.h"
#include <string.h>
#if BUILD_USB
#include "usbcfg.h"
#endif
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
@ -39,17 +42,6 @@ extern const SerialConfig uart_config;
chprintf((BaseSequentialStream*)&SD3, " "); \
chprintf((BaseSequentialStream*)&SD3, (format), ##args); \
chprintf((BaseSequentialStream*)&SD3, "\r\n"); \
\
if(TRACE_TIME) { \
chprintf((BaseSequentialStream*)&SDU1, "[%8d.%03d]", chVTGetSystemTimeX()/CH_CFG_ST_FREQUENCY, (chVTGetSystemTimeX()*1000/CH_CFG_ST_FREQUENCY)%1000); \
} \
chprintf((BaseSequentialStream*)&SDU1, "[%s]", type); \
if(TRACE_FILE) { \
chprintf((BaseSequentialStream*)&SDU1, "[%10s %04d]", __FILENAME__, __LINE__); \
} \
chprintf((BaseSequentialStream*)&SDU1, " "); \
chprintf((BaseSequentialStream*)&SDU1, (format), ##args); \
chprintf((BaseSequentialStream*)&SDU1, "\r\n"); \
chMtxUnlock(&trace_mtx); \
}

Wyświetl plik

@ -7,9 +7,5 @@
#define HIGH true
#define LOW false
#define SYM_BALLOON 0x2F4F
#define SYM_SMALLAIRCRAFT 0x2F27
#define SYM_SATELLITE 0x5C53
#endif

Wyświetl plik

@ -312,7 +312,7 @@ static const struct regval_list ov2640_init_regs[] = {
{ 0x2e, 0xdf },
{ BANK_SEL, BANK_SEL_SENS },
{ 0x3c, 0x32 },
{ CLKRC, CLKRC_DIV_SET(1) },
{ CLKRC, CLKRC_DIV_SET(2) },
{ COM2, COM2_OCAP_Nx_SET(3) },
{ REG04, REG04_DEF | REG04_HREF_EN },
{ COM8, COM8_DEF | COM8_AGC_EN | COM8_AEC_EN | COM8_BNDF_EN },
@ -666,7 +666,6 @@ uint32_t OV2640_getBuffer(uint8_t** buffer) {
void OV2640_Capture(void)
{
TRACE_INFO("CAM > Start capture");
while(1)
{
while(palReadLine(LINE_CAM_VSYNC));
@ -794,13 +793,29 @@ void OV2640_init(ssdv_conf_t *config) {
TRACE_INFO("CAM > Transmit config to camera");
OV2640_TransmitConfig();
chThdSleepMilliseconds(300);
chThdSleepMilliseconds(3000);
}
void OV2640_deinit(void) {
// Power off OV2640
TRACE_INFO("CAM > Switch off");
palClearLine(LINE_CAM_EN); // Switch off camera
palSetLineMode(LINE_CAM_HREF, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_PCLK, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_VSYNC, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_XCLK, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_D2, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_D3, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_D4, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_D5, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_D6, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_D7, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_D8, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_D9, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_EN, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT);
// Release I2C (due to silicon bug of OV2640, it interferes if byte 0x30 transmitted on I2C bus)
I2C_unlock();

Wyświetl plik

@ -39,14 +39,14 @@ int16_t pac1720_getIsol(void) {
if(getUSBVoltageMV() < 300) // USB not connected
{
// Short solar cells
palClearLine(LINE_SOL_SHORT_EN);
//palClearLine(LINE_SOL_SHORT_EN);
chThdSleepMilliseconds(300); // Wait a little bit to measure a correct value
int16_t val;
uint8_t ret = I2C_read16(PAC1720_ADDRESS, PAC1720_CH1_VSENSE_HIGH, (uint16_t*)&val);
// Unshort solar cells
palSetLine(LINE_SOL_SHORT_EN);
//palSetLine(LINE_SOL_SHORT_EN);
// Calculate solar current
if(ret) {

Wyświetl plik

@ -273,7 +273,7 @@ void setModem2GFSK(gfsk_conf_t* conf) {
void setPowerLevel(int8_t level) {
// Set the Power
uint8_t set_pa_pwr_lvl_property_command[] = {0x11, 0x22, 0x01, 0x01, dBm2powerLvl(level)};
uint8_t set_pa_pwr_lvl_property_command[] = {0x11, 0x22, 0x01, 0x01, level};
Si4464_write(set_pa_pwr_lvl_property_command, 5);
}
@ -339,7 +339,6 @@ uint8_t Si4464_freeFIFO(void) {
return rxData[3];
}
/**
* Returns internal state of Si4464
*/
@ -358,28 +357,6 @@ int8_t Si4464_getTemperature(void) {
return (899*adc)/4096 - 293;
}
/**
* Converts power level from dBm to Si4464 power level. The calculation
* assumes Vcc = 3.3V
*/
uint8_t dBm2powerLvl(int32_t dBm) {
if(dBm < -35) {
return 0;
} else if(dBm < -7) {
return (uint8_t)((2*dBm+74)/15);
} else if(dBm < 2) {
return (uint8_t)((2*dBm+26)/3);
} else if(dBm < 8) {
return (uint8_t)((5*dBm+20)/3);
} else if(dBm < 13) {
return (uint8_t)(3*dBm-4);
} else if(dBm < 18) {
return (uint8_t)((92*dBm-1021)/5);
} else {
return 127;
}
}
bool isRadioInitialized(void) {
return initialized;
}

Wyświetl plik

@ -27,7 +27,6 @@ void Si4464_writeFIFO(uint8_t *msg, uint8_t size);
uint8_t Si4464_freeFIFO(void);
uint8_t Si4464_getState(void);
int8_t Si4464_getTemperature(void);
uint8_t dBm2powerLvl(int32_t dBm);
bool isRadioInitialized(void);
#endif

Wyświetl plik

@ -26,7 +26,21 @@ const SerialConfig gps_config =
*/
void gps_transmit_string(uint8_t *cmd, uint8_t length)
{
sdWrite(&SD6, cmd, length);
I2C_writeN(UBLOX_MAX_ADDRESS, cmd, length);
}
uint8_t gps_receive_byte(void)
{
uint8_t val;
I2C_read8(UBLOX_MAX_ADDRESS, 0xFF, &val);
return val;
}
uint16_t gps_bytes_avail(void)
{
uint16_t val;
I2C_read16(UBLOX_MAX_ADDRESS, 0xFD, &val);
return val;
}
/*
@ -50,10 +64,15 @@ uint8_t gps_receive_ack(uint8_t class_id, uint8_t msg_id, uint16_t timeout) {
// runs until ACK/NAK packet is received
systime_t sTimeout = chVTGetSystemTimeX() + MS2ST(timeout);
while(chVTGetSystemTimeX() <= sTimeout) {
while(sTimeout >= chVTGetSystemTimeX()) {
// Receive one byte
rx_byte = sdGetTimeout(&SD6, sTimeout - chVTGetSystemTimeX());
if(gps_bytes_avail()) {
rx_byte = gps_receive_byte();
} else {
chThdSleepMilliseconds(10);
continue;
}
// Process one byte
if (rx_byte == ack[match_count] || rx_byte == nak[match_count]) {
@ -93,14 +112,15 @@ uint16_t gps_receive_payload(uint8_t class_id, uint8_t msg_id, unsigned char *pa
uint16_t payload_len = 0;
systime_t sTimeout = chVTGetSystemTimeX() + MS2ST(timeout);
while(true) {
while(sTimeout >= chVTGetSystemTimeX()) {
// Receive one byte
systime_t uartTimeout = sTimeout - chVTGetSystemTimeX();
if(!uartTimeout)
break;
rx_byte = sdGetTimeout(&SD6, uartTimeout);
if(gps_bytes_avail()) {
rx_byte = gps_receive_byte();
} else {
chThdSleepMilliseconds(10);
continue;
}
// Process one byte
switch (state) {
@ -326,8 +346,8 @@ bool GPS_Init(void) {
palSetLineMode(LINE_GPS_TXD, PAL_MODE_ALTERNATE(8)); // UART TXD
// Init UART
TRACE_INFO("GPS > Init GPS UART");
sdStart(&SD6, &gps_config);
//TRACE_INFO("GPS > Init GPS UART");
//sdStart(&SD6, &gps_config);
// Switch MOSFET
TRACE_INFO("GPS > Switch on");

Wyświetl plik

@ -7,7 +7,7 @@
#include "debug.h"
#define ADC_NUM_CHANNELS 4 /* Amount of channels (solar, battery, temperature) */
#define VCC_REF_LOW 1860 /* mV */
#define VCC_REF_LOW 1850 /* mV */
#define VCC_REF_HIGH 3070 /* mV */
#define DIVIDER_VSOL 205/64 /* VSol -- 22kOhm -- ADC -- 10kOhm -- GND */
@ -74,7 +74,7 @@ uint16_t getBatteryVoltageMV(void)
uint16_t vbat = samples[2] * vcc_ref * DIVIDER_VBAT / 4096;
// Get voltage from PAC1720 (PAC1720 returns false redings below 2.35V)
if(vbat >= 2400)
if(vbat >= 2500)
{
uint16_t vbat_pac = pac1720_getBatteryVoltage(); // Get value from PAC1720
if(vbat_pac) // Apply it if valid
@ -87,7 +87,7 @@ uint16_t getBatteryVoltageMV(void)
uint16_t getSolarVoltageMV(void)
{
// Get voltage from PAC1720 (PAC1720 returns false redings below 2.35V)
if(getBatteryVoltageMV() >= 2400)
if(getBatteryVoltageMV() >= 2500)
{
uint16_t vsol_pac = pac1720_getSolarVoltage(); // Get value from PAC1720
if(vsol_pac)

Wyświetl plik

@ -4,7 +4,10 @@
#include "debug.h"
#include "modules.h"
#include "padc.h"
#if BUILD_USB
#include "usbcfg.h"
#endif
/**
* Main routine is starting up system, runs the software watchdog (module monitoring), controls LEDs
@ -13,11 +16,13 @@ int main(void) {
halInit(); // Startup HAL
chSysInit(); // Startup RTOS
chThdSleepMilliseconds(100);
#if BUILD_USB || RUN_3V
boost_voltage(true); // Ramp up voltage to 3V
chThdSleepMilliseconds(100);
#endif
// Start USB
#if BUILD_USB
sduObjectInit(&SDU1);
sduStart(&SDU1, &serusbcfg);
@ -25,6 +30,7 @@ int main(void) {
chThdSleepMilliseconds(100);
usbStart(serusbcfg.usbp, &usbcfg);
usbConnectBus(serusbcfg.usbp);
#endif
// Init debugging (Serial debug port, LEDs)
DEBUG_INIT();

Wyświetl plik

@ -42,19 +42,19 @@
#define STM32_HSE_ENABLED TRUE
#define STM32_LSE_ENABLED FALSE
#define STM32_CLOCK48_REQUIRED TRUE
#define STM32_SW STM32_SW_HSE
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PLLM_VALUE 26
#define STM32_PLLN_VALUE 192
#define STM32_PLLP_VALUE 4
#define STM32_PLLP_VALUE 2
#define STM32_PLLQ_VALUE 4
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV4
#define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_RTCSEL STM32_RTCSEL_LSI
#define STM32_RTCPRE_VALUE 8
#define STM32_MCO1SEL STM32_MCO1SEL_HSE
#define STM32_MCO1PRE STM32_MCO1PRE_DIV5
#define STM32_MCO1PRE STM32_MCO1PRE_DIV3
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
#define STM32_I2SSRC STM32_I2SSRC_CKIN
@ -183,7 +183,7 @@
#define STM32_SERIAL_USE_USART1 FALSE
#define STM32_SERIAL_USE_USART2 FALSE
#define STM32_SERIAL_USE_USART3 TRUE
#define STM32_SERIAL_USE_USART6 TRUE
#define STM32_SERIAL_USE_USART6 FALSE
#define STM32_SERIAL_USART1_PRIORITY 12
#define STM32_SERIAL_USART2_PRIORITY 12
#define STM32_SERIAL_USART3_PRIORITY 12

Wyświetl plik

@ -18,7 +18,7 @@
static uint8_t gimage_id; // Global image ID (for all image threads)
mutex_t camera_mtx;
void encode_ssdv(uint8_t *image, uint32_t image_len, module_conf_t* config, uint8_t image_id)
void encode_ssdv(uint8_t *image, uint32_t image_len, module_conf_t* conf, uint8_t image_id, bool redudantTx)
{
ssdv_t ssdv;
uint8_t pkt[SSDV_PKT_SIZE];
@ -30,7 +30,7 @@ void encode_ssdv(uint8_t *image, uint32_t image_len, module_conf_t* config, uint
uint16_t i = 0;
// Count packets
ssdv_enc_init(&ssdv, SSDV_TYPE_NORMAL, config->ssdv_conf.callsign, image_id);
ssdv_enc_init(&ssdv, SSDV_TYPE_NORMAL, conf->ssdv_conf.callsign, image_id);
ssdv_enc_set_buffer(&ssdv, pkt);
while(true)
@ -55,12 +55,12 @@ void encode_ssdv(uint8_t *image, uint32_t image_len, module_conf_t* config, uint
// Init SSDV (FEC at 2FSK, non FEC at APRS)
bi = 0;
ssdv_enc_init(&ssdv, SSDV_TYPE_NORMAL, config->ssdv_conf.callsign, image_id);
ssdv_enc_init(&ssdv, SSDV_TYPE_NORMAL, conf->ssdv_conf.callsign, image_id);
ssdv_enc_set_buffer(&ssdv, pkt);
while(true)
{
config->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
conf->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
while((c = ssdv_enc_get_packet(&ssdv)) == SSDV_FEED_ME)
{
@ -87,35 +87,37 @@ void encode_ssdv(uint8_t *image, uint32_t image_len, module_conf_t* config, uint
// Transmit packet
radioMSG_t msg;
msg.freq = getFrequency(&config->frequency);
msg.power = config->power;
msg.freq = getFrequency(&conf->frequency);
msg.power = conf->power;
switch(config->protocol) {
switch(conf->protocol) {
case PROT_APRS_2GFSK:
case PROT_APRS_AFSK:
msg.mod = config->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
msg.afsk_conf = &(config->afsk_conf);
msg.gfsk_conf = &(config->gfsk_conf);
msg.mod = conf->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
msg.afsk_conf = &(conf->afsk_conf);
msg.gfsk_conf = &(conf->gfsk_conf);
// Deleting buffer
for(uint16_t t=0; t<256; t++)
pkt_base91[t] = 0;
base91_encode(&pkt[1], pkt_base91, sizeof(pkt)-37); // Sync byte, CRC and FEC of SSDV not transmitted
msg.bin_len = aprs_encode_experimental('I', msg.msg, msg.mod, &config->aprs_conf, pkt_base91, strlen((char*)pkt_base91));
msg.bin_len = aprs_encode_experimental('I', msg.msg, msg.mod, &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91));
// Transmit on radio (keep transmitter switched on if packet spacing=0ms and it isnt the last packet being sent)
transmitOnRadio(&msg, config->packet_spacing != 0 || i == packet_count-1);
if(redudantTx) transmitOnRadio(&msg, false);
transmitOnRadio(&msg, conf->packet_spacing != 0 || i == packet_count-1);
break;
case PROT_SSDV_2FSK:
msg.mod = MOD_2FSK;
msg.fsk_conf = &(config->fsk_conf);
msg.fsk_conf = &(conf->fsk_conf);
memcpy(msg.msg, pkt, sizeof(pkt));
msg.bin_len = 8*sizeof(pkt);
transmitOnRadio(&msg, true);
if(redudantTx) transmitOnRadio(&msg, false);
transmitOnRadio(&msg, conf->packet_spacing != 0 || i == packet_count-1);
break;
default:
@ -123,29 +125,29 @@ void encode_ssdv(uint8_t *image, uint32_t image_len, module_conf_t* config, uint
}
// Packet spacing (delay)
if(config->packet_spacing)
chThdSleepMilliseconds(config->packet_spacing);
if(conf->packet_spacing)
chThdSleepMilliseconds(conf->packet_spacing);
i++;
}
}
THD_FUNCTION(imgThread, arg) {
module_conf_t* config = (module_conf_t*)arg;
module_conf_t* conf = (module_conf_t*)arg;
systime_t time = chVTGetSystemTimeX();
while(true)
{
TRACE_INFO("IMG > Do module IMAGE cycle");
config->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
conf->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
if(!p_sleep(&config->sleep_conf))
if(!p_sleep(&conf->sleep_conf))
{
uint32_t image_len = 0;
uint8_t *image;
// Take photo if camera activated (if camera disabled, camera buffer is probably shared in config file)
if(!config->ssdv_conf.no_camera)
if(!conf->ssdv_conf.no_camera)
{
// Lock camera
TRACE_INFO("IMG > Lock camera");
@ -165,14 +167,14 @@ THD_FUNCTION(imgThread, arg) {
{
TRACE_INFO("IMG > OV2640 found");
if(config->ssdv_conf.res == RES_MAX) // Attempt maximum resolution (limited by memory)
if(conf->ssdv_conf.res == RES_MAX) // Attempt maximum resolution (limited by memory)
{
config->ssdv_conf.res = RES_UXGA; // Try maximum resolution
conf->ssdv_conf.res = RES_UXGA; // Try maximum resolution
do {
// Init camera
OV2640_init(&config->ssdv_conf);
OV2640_init(&conf->ssdv_conf);
// Sample data from DCMI through DMA into RAM
tries = 5; // Try 5 times at maximum
@ -180,16 +182,16 @@ THD_FUNCTION(imgThread, arg) {
status = OV2640_Snapshot2RAM();
} while(!status && --tries);
config->ssdv_conf.res--; // Decrement resolution in next attempt (if status==false)
conf->ssdv_conf.res--; // Decrement resolution in next attempt (if status==false)
} while(OV2640_BufferOverflow() && config->ssdv_conf.res >= RES_QVGA);
} while(OV2640_BufferOverflow() && conf->ssdv_conf.res >= RES_QVGA);
config->ssdv_conf.res = RES_MAX; // Revert register
conf->ssdv_conf.res = RES_MAX; // Revert register
} else { // Static resolution
// Init camera
OV2640_init(&config->ssdv_conf);
OV2640_init(&conf->ssdv_conf);
// Sample data from DCMI through DMA into RAM
tries = 5; // Try 5 times at maximum
@ -227,7 +229,7 @@ THD_FUNCTION(imgThread, arg) {
{
gimage_id++;
TRACE_INFO("IMG > Encode/Transmit SSDV ID=%d", gimage_id-1);
encode_ssdv(image, image_len, config, gimage_id-1);
encode_ssdv(image, image_len, conf, gimage_id-1, conf->ssdv_conf.redundantTx);
}
} else {
@ -237,18 +239,18 @@ THD_FUNCTION(imgThread, arg) {
TRACE_INFO("IMG > Camera disabled");
TRACE_INFO("IMG > Encode/Transmit SSDV ID=%d", gimage_id);
encode_ssdv(image, image_len, config, gimage_id);
encode_ssdv(image, image_len, conf, gimage_id, conf->ssdv_conf.redundantTx);
}
}
time = waitForTrigger(time, &config->trigger);
time = waitForTrigger(time, &conf->trigger);
}
}
void start_image_thread(module_conf_t *conf)
{
if(config->init_delay) chThdSleepMilliseconds(config->init_delay);
if(conf->init_delay) chThdSleepMilliseconds(conf->init_delay);
TRACE_INFO("IMG > Startup image thread");
chsnprintf(conf->name, sizeof(conf->name), "IMG");
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(6*1024), "IMG", NORMALPRIO, imgThread, conf);

Wyświetl plik

@ -109,15 +109,15 @@ uint16_t cpr_encode(bool cprFormat, double lat, double lon)
THD_FUNCTION(logThread, arg)
{
module_conf_t* config = (module_conf_t*)arg;
module_conf_t* conf = (module_conf_t*)arg;
systime_t time = chVTGetSystemTimeX();
while(true)
{
TRACE_INFO("LOG > Do module LOG cycle");
config->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
conf->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
if(!p_sleep(&config->sleep_conf))
if(!p_sleep(&conf->sleep_conf))
{
// Get log from memory
trackPoint_t log;
@ -152,22 +152,22 @@ THD_FUNCTION(logThread, arg)
// Encode radio message
radioMSG_t msg;
msg.freq = getFrequency(&config->frequency);
msg.power = config->power;
msg.freq = getFrequency(&conf->frequency);
msg.power = conf->power;
switch(config->protocol) {
switch(conf->protocol) {
case PROT_APRS_2GFSK:
case PROT_APRS_AFSK:
msg.mod = config->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
msg.afsk_conf = &(config->afsk_conf);
msg.gfsk_conf = &(config->gfsk_conf);
msg.mod = conf->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
msg.afsk_conf = &(conf->afsk_conf);
msg.gfsk_conf = &(conf->gfsk_conf);
// Deleting buffer
for(uint16_t t=0; t<sizeof(pkt_base91); t++)
pkt_base91[t] = 0;
base91_encode((uint8_t*)pkt, pkt_base91, sizeof(pkt));
msg.bin_len = aprs_encode_message(msg.msg, msg.mod, &config->aprs_conf, APRS_DEST_CALLSIGN, (char*)pkt_base91);
msg.bin_len = aprs_encode_message(msg.msg, msg.mod, &conf->aprs_conf, APRS_DEST_CALLSIGN, (char*)pkt_base91);
transmitOnRadio(&msg, true);
break;
@ -177,13 +177,13 @@ THD_FUNCTION(logThread, arg)
}
}
time = waitForTrigger(time, &config->trigger);
time = waitForTrigger(time, &conf->trigger);
}
}
void start_logging_thread(module_conf_t *conf)
{
if(config->init_delay) chThdSleepMilliseconds(config->init_delay);
if(conf->init_delay) chThdSleepMilliseconds(conf->init_delay);
TRACE_INFO("LOG > Startup logging thread");
chsnprintf(conf->name, sizeof(conf->name), "LOG");
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2*1024), "LOG", NORMALPRIO, logThread, conf);

Wyświetl plik

@ -106,7 +106,7 @@ void replace_placeholders(char* fskmsg, uint16_t size, trackPoint_t *tp) {
}
THD_FUNCTION(posThread, arg) {
module_conf_t* config = (module_conf_t*)arg;
module_conf_t* conf = (module_conf_t*)arg;
trackPoint_t *trackPoint = getLastTrackPoint();
systime_t time = chVTGetSystemTimeX();
@ -117,49 +117,49 @@ THD_FUNCTION(posThread, arg) {
while(true)
{
TRACE_INFO("POS > Do module POSITION cycle");
config->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
conf->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
TRACE_INFO("POS > Get last track point");
trackPoint = getLastTrackPoint();
if(!p_sleep(&config->sleep_conf))
if(!p_sleep(&conf->sleep_conf))
{
TRACE_INFO("POS > Transmit GPS position");
radioMSG_t msg;
msg.freq = getFrequency(&config->frequency);
msg.power = config->power;
msg.freq = getFrequency(&conf->frequency);
msg.power = conf->power;
switch(config->protocol) {
switch(conf->protocol) {
case PROT_APRS_2GFSK: // Encode APRS
case PROT_APRS_AFSK:
// Position transmission
msg.mod = config->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
msg.gfsk_conf = &(config->gfsk_conf);
msg.afsk_conf = &(config->afsk_conf);
msg.mod = conf->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
msg.gfsk_conf = &(conf->gfsk_conf);
msg.afsk_conf = &(conf->afsk_conf);
msg.bin_len = aprs_encode_position(msg.msg, msg.mod, &(config->aprs_conf), trackPoint); // Encode packet
msg.bin_len = aprs_encode_position(msg.msg, msg.mod, &(conf->aprs_conf), trackPoint); // Encode packet
transmitOnRadio(&msg, true);
// Telemetry encoding parameter transmission
if(config->aprs_conf.tel_encoding)
if(conf->aprs_conf.tel_enc)
{
// Telemetry encoding parameter transmission trigger
if(last_conf_transmission + S2ST(config->aprs_conf.tel_encoding_cycle) < chVTGetSystemTimeX() && current_conf_count >= 4)
if(last_conf_transmission + S2ST(conf->aprs_conf.tel_enc_cycle) < chVTGetSystemTimeX() && current_conf_count >= 4)
{
last_conf_transmission += S2ST(config->aprs_conf.tel_encoding_cycle);
last_conf_transmission += S2ST(conf->aprs_conf.tel_enc_cycle);
current_conf_count = 0;
}
// Actual transmission (each cycle a different config type will be sent)
if(config->aprs_conf.tel_encoding && current_conf_count < 4)
if(conf->aprs_conf.tel_enc && current_conf_count < 4)
{
chThdSleepMilliseconds(5000); // Take a litte break between the package transmissions
const telemetry_conf_t tel_conf[] = {CONF_PARM, CONF_UNIT, CONF_EQNS, CONF_BITS};
msg.bin_len = aprs_encode_telemetry_configuration(msg.msg, msg.mod, &(config->aprs_conf), tel_conf[current_conf_count]); // Encode packet
msg.bin_len = aprs_encode_telemetry_configuration(msg.msg, msg.mod, &(conf->aprs_conf), tel_conf[current_conf_count]); // Encode packet
transmitOnRadio(&msg, true);
current_conf_count++;
@ -170,13 +170,13 @@ THD_FUNCTION(posThread, arg) {
case PROT_UKHAS_2FSK: // Encode UKHAS
msg.mod = MOD_2FSK;
msg.fsk_conf = &(config->fsk_conf);
msg.fsk_conf = &(conf->fsk_conf);
// Encode packet
char fskmsg[256];
memcpy(fskmsg, config->ukhas_conf.format, sizeof(config->ukhas_conf.format));
memcpy(fskmsg, conf->ukhas_conf.format, sizeof(conf->ukhas_conf.format));
replace_placeholders(fskmsg, sizeof(fskmsg), trackPoint);
str_replace(fskmsg, sizeof(fskmsg), "<CALL>", config->ukhas_conf.callsign);
str_replace(fskmsg, sizeof(fskmsg), "<CALL>", conf->ukhas_conf.callsign);
msg.bin_len = 8*chsnprintf((char*)msg.msg, sizeof(fskmsg), "$$$$$%s*%04X\n", fskmsg, crc16(fskmsg));
// Transmit message
@ -185,13 +185,13 @@ THD_FUNCTION(posThread, arg) {
case PROT_MORSE: // Encode Morse
msg.mod = MOD_OOK;
msg.ook_conf = &(config->ook_conf);
msg.ook_conf = &(conf->ook_conf);
// Encode morse message
char morse[128];
memcpy(morse, config->morse_conf.format, sizeof(config->morse_conf.format));
memcpy(morse, conf->morse_conf.format, sizeof(conf->morse_conf.format));
replace_placeholders(morse, sizeof(morse), trackPoint);
str_replace(morse, sizeof(morse), "<CALL>", config->morse_conf.callsign);
str_replace(morse, sizeof(morse), "<CALL>", conf->morse_conf.callsign);
// Transmit message
msg.bin_len = morse_encode(msg.msg, morse); // Convert message to binary stream
@ -203,13 +203,13 @@ THD_FUNCTION(posThread, arg) {
}
}
time = waitForTrigger(time, &config->trigger);
time = waitForTrigger(time, &conf->trigger);
}
}
void start_position_thread(module_conf_t *conf)
{
if(config->init_delay) chThdSleepMilliseconds(config->init_delay);
if(conf->init_delay) chThdSleepMilliseconds(conf->init_delay);
TRACE_INFO("POS > Startup position thread");
chsnprintf(conf->name, sizeof(conf->name), "POS");
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2*1024), "POS", NORMALPRIO, posThread, conf);

Wyświetl plik

@ -42,6 +42,10 @@
#define APRS_DEST_CALLSIGN "APECAN" // APExxx = Pecan device
#define APRS_DEST_SSID 0
#define SYM_BALLOON 0x2F4F
#define SYM_SMALLAIRCRAFT 0x2F27
#define SYM_SATELLITE 0x5C53
uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *config, trackPoint_t *trackPoint);
uint32_t aprs_encode_telemetry_configuration(uint8_t* message, mod_t mod, const aprs_conf_t *config, const telemetry_conf_t type);
uint32_t aprs_encode_message(uint8_t* message, mod_t mod, const aprs_conf_t *config, const char *receiver, const char *text);

Wyświetl plik

@ -314,14 +314,14 @@ bool transmitOnRadio(radioMSG_t *msg, bool shutdown) {
// Lock radio
chMtxLock(&radio_mtx);
if(inRadioBand(msg->freq)) { // Radio found
if(inRadioBand(msg->freq)) { // Frequency in radio radio band
// Lock interference mutex
chMtxLock(&interference_mtx);
TRACE_INFO( "RAD > Transmit %d.%03d MHz, %d dBm (%d), %s, %d bits",
TRACE_INFO( "RAD > Transmit %d.%03d MHz, Pwr %d, %s, %d bits",
msg->freq/1000000, (msg->freq%1000000)/1000, msg->power,
dBm2powerLvl(msg->power), getModulation(msg->mod), msg->bin_len
getModulation(msg->mod), msg->bin_len
);
switch(msg->mod) {
@ -360,11 +360,10 @@ bool transmitOnRadio(radioMSG_t *msg, bool shutdown) {
chMtxUnlock(&interference_mtx); // Heavy interference finished (HF)
} else { // Error
} else { // Frequency out of radio band
TRACE_ERROR("RAD > Radio cant transmit on this frequency, %d.%03d MHz, %d dBm (%d), %s, %d bits",
msg->freq/1000000, (msg->freq%1000000)/1000, msg->power,
dBm2powerLvl(msg->power), getModulation(msg->mod), msg->bin_len
TRACE_ERROR("RAD > Radio cant transmit on this frequency, %d.%03d MHz, Pwr dBm, %s, %d bits",
msg->freq/1000000, (msg->freq%1000000)/1000, msg->power, getModulation(msg->mod), msg->bin_len
);
}

Wyświetl plik

@ -43,16 +43,9 @@ systime_t waitForTrigger(systime_t prev, trigger_conf_t *config)
{
switch(config->type)
{
case TRIG_EVENT: // Wait for new tracking point
switch(config->event)
{
case EVENT_NEW_POINT:
waitForNewTrackPoint();
return chVTGetSystemTimeX();
case NO_EVENT: // No event defined
while(1); // Assert
}
case TRIG_NEW_POINT: // Wait for new tracking point
waitForNewTrackPoint();
return chVTGetSystemTimeX();
case TRIG_TIMEOUT: // Wait for specified timeout
return chThdSleepUntilWindowed(prev, prev + S2ST(config->timeout));
@ -61,7 +54,7 @@ systime_t waitForTrigger(systime_t prev, trigger_conf_t *config)
return chVTGetSystemTimeX();
case TRIG_ONCE: // No trigger defined
while(1); // Assert
chThdSleepMilliseconds(10000);
}
return chVTGetSystemTimeX();

Wyświetl plik

@ -44,8 +44,8 @@ typedef struct {
char path[16]; // APRS path
uint16_t preamble; // Preamble in milliseconds
telemetry_t tel[5]; // Telemetry types
bool tel_encoding; // Transmit telemetry encoding information
uint16_t tel_encoding_cycle;// Telemetry encoding cycle in seconds
bool tel_enc; // Transmit telemetry encoding information
uint16_t tel_enc_cycle; // Telemetry encoding cycle in seconds
char tel_comment[32]; // Telemetry comment
} aprs_conf_t;
@ -117,6 +117,7 @@ typedef struct {
uint8_t *ram_buffer; // Camera Buffer (do not set in config)
size_t ram_size; // Size of buffer (do not set in config)
bool no_camera; // Camera disabled
bool redundantTx; // Redundand packet transmission (APRS only)
} ssdv_conf_t;
typedef enum {
@ -131,20 +132,14 @@ typedef struct {
typedef enum {
TRIG_ONCE, // Trigger once and never again (e.g. transmit specific position packet only at startup)
TRIG_EVENT, // Triggered by specific event (e.g. transmit when new track point available)
TRIG_NEW_POINT, // Triggered when new track point available
TRIG_TIMEOUT, // Triggered by timeout (e.g. trasmit position every 120sec)
TRIG_CONTINOUSLY // Continue continously (e.g. send new image once old image sent completely)
} trigger_type_t;
typedef enum {
NO_EVENT, // No event, triggered once and never again
EVENT_NEW_POINT // Triggered when new track point available
} event_t;
typedef struct {
trigger_type_t type; // Trigger type
uint32_t timeout; // Timeout in seconds
event_t event; // Trigger events
} trigger_conf_t;
typedef struct {

Wyświetl plik

@ -15,6 +15,9 @@
*/
#include "hal.h"
#include "config.h"
#if BUILD_USB
/* Virtual serial port over USB.*/
SerialUSBDriver SDU1;
@ -340,3 +343,5 @@ const SerialUSBConfig serusbcfg = {
USBD1_DATA_AVAILABLE_EP,
USBD1_INTERRUPT_REQUEST_EP
};
#endif

Wyświetl plik

@ -17,10 +17,14 @@
#ifndef USBCFG_H
#define USBCFG_H
#if BUILD_USB
extern const USBConfig usbcfg;
extern SerialUSBConfig serusbcfg;
extern SerialUSBDriver SDU1;
#endif
#endif /* USBCFG_H */
/** @} */