Complete implementation of common beacon service for POS and DIGI.

pull/4/head
bob 2018-06-22 17:11:00 +10:00
rodzic 655ffa1bb0
commit e20c1bc582
15 zmienionych plików z 346 dodań i 565 usunięć

Wyświetl plik

@ -1,15 +1,15 @@
<?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="125190521113748506" 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>
<?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

@ -129,6 +129,7 @@
#define USE_HEAP_PWM_BUFFER TRUE
#define USE_CCM_BASED_HEAP TRUE
#define USE_PWM_QUEUE_LINK TRUE
#define TRACE_PWM_BUFFER_STATS FALSE
/* Definitions for ICU FIFO implemented using chfactory. */
#if USE_HEAP_PWM_BUFFER == TRUE

Wyświetl plik

@ -123,6 +123,7 @@
#define USE_HEAP_PWM_BUFFER FALSE
#define USE_CCM_BASED_HEAP TRUE
#define USE_PWM_QUEUE_LINK TRUE
#define TRACE_PWM_BUFFER_STATS FALSE
/* Definitions for ICU FIFO implemented using chfactory. */
#if USE_HEAP_PWM_BUFFER == TRUE

Wyświetl plik

@ -20,7 +20,7 @@ THD_FUNCTION(posThread, arg)
thd_pos_conf_t* conf = (thd_pos_conf_t*)arg;
// Wait
if(conf->svc_conf.init_delay) chThdSleep(conf->svc_conf.init_delay);
if(conf->beacon.init_delay) chThdSleep(conf->beacon.init_delay);
// Start data collector (if not running yet)
init_data_collector();
@ -43,7 +43,7 @@ THD_FUNCTION(posThread, arg)
TRACE_INFO("POS > Get last data point");
dataPoint_t* dataPoint = getLastDataPoint();
if(!p_sleep(&conf->svc_conf.sleep_conf)) {
if(!p_sleep(&conf->beacon.sleep_conf)) {
TRACE_INFO("POS > Transmit position");
// Telemetry encoding parameter transmission
@ -134,7 +134,7 @@ THD_FUNCTION(posThread, arg)
chThdSleep(TIME_S2I(5));
}
}
time = waitForTrigger(time, conf->svc_conf.cycle);
time = waitForTrigger(time, conf->beacon.cycle);
}
}

Wyświetl plik

@ -12,10 +12,11 @@ conf_t conf_sram;
const conf_t conf_flash_default = {
// Primary position app
.pos_pri = {
.svc_conf = {
.active = false,
.beacon = {
.active = true,
.cycle = TIME_S2I(60 * 5),
.init_delay = TIME_S2I(30)
.init_delay = TIME_S2I(60),
.fixed = false
},
.radio_conf = {
.pwr = 0x7F,
@ -28,16 +29,15 @@ const conf_t conf_flash_default = {
.path = "WIDE1-1",
.symbol = SYM_ANTENNA,
.aprs_msg = true,
// How often to send telemetry config
//.tel_enc_cycle = TIME_S2I(60 * 60)
},
// Secondary position app
.pos_sec = {
.svc_conf = {
.beacon = {
.active = false,
.cycle = TIME_S2I(180),
.init_delay = TIME_S2I(60)
.init_delay = TIME_S2I(60),
.fixed = false
},
.radio_conf = {
.pwr = 0x7F,
@ -50,8 +50,6 @@ const conf_t conf_flash_default = {
.path = "",
.symbol = SYM_BALLOON,
.aprs_msg = true,
//.tel_enc_cycle = TIME_S2I(0)
},
// Primary image app
@ -126,14 +124,14 @@ const conf_t conf_flash_default = {
// APRS app
.aprs = {
.svc_conf = {
// The packet receive service is enabled if true
// Receive is resumed after any transmission
.active = true,
.init_delay = TIME_S2I(20)
},
// The receive identity for APRS
.rx = {
.svc_conf = {
// The packet receive service is enabled if true
// Receive is resumed after any transmission
.active = true,
.init_delay = TIME_S2I(20)
},
// Receive radio configuration
.radio_conf = {
.freq = FREQ_APRS_DYNAMIC,
@ -144,37 +142,36 @@ const conf_t conf_flash_default = {
.call = "VK2GJ-4",
.symbol = SYM_ANTENNA
},
// The digipeat transmit identity
.digi = {
.active = true,
// Transmit radio configuration
.radio_conf = {
.freq = FREQ_APRS_RECEIVE,
.pwr = 0x7F,
.mod = MOD_AFSK,
.cca = 0x4F
.digi = true,
.tx = {
// Transmit radio configuration
.radio_conf = {
.freq = FREQ_APRS_RECEIVE,
.pwr = 0x7F,
.mod = MOD_AFSK,
.cca = 0x4F
},
// Digipeat transmission identity
.call = "VK2GJ-5",
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER,
.aprs_msg = true,
.beacon = {
// The telemetry beacon service is enabled if true when RX and DIGI are enabled
// Receive is resumed after any transmission
.active = true,
.init_delay = TIME_S2I(20),
.cycle = TIME_S2I(60 * 30), // Beacon interval
.fixed = true, // Use fixed position data if true
.lat = -337331175, // Degrees (expressed in 1e-7 form)
.lon = 1511143478, // Degrees (expressed in 1e-7 form)
.alt = 144 // Altitude in metres
},
.beacon = {
.svc_conf = {
// The telemetry beacon service is enabled if true
// Receive is resumed after any transmission
.active = true,
.init_delay = TIME_S2I(20),
.cycle = TIME_S2I(60 * 30), // Beacon interval
},
.fixed = true, // Use fixed position data if true
.lat = -337331175, // Degrees (expressed in 1e-7 form)
.lon = 1511143478, // Degrees (expressed in 1e-7 form)
.alt = 144, // Altitude in metres
},
// Digipeat transmission identity
.call = "VK2GJ-5",
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER
},
},
},
// Global controls
// Power control
.keep_cam_switched_on = false,
.gps_on_vbat = 3800, // mV
@ -186,16 +183,20 @@ const conf_t conf_flash_default = {
.gps_low_alt = GPS_STATIONARY,
.gps_high_alt = GPS_AIRBORNE_1G,
// APRS
// How often to send telemetry config
.tel_enc_cycle = TIME_S2I(60 * 60 * 2),
// The default APRS frequency when geofence is not resolved
.freq = APRS_FREQ_AUSTRALIA,
// The base station identity
// The base station identity.
.base = {
// Tracker originated messages will be addressed to this call sign if enabled
// If enabled APRS messages are addressed to this call sign
.enabled = true,
.call = "VK2GJ-7",
.path = "WIDE2-1",
},
.magic = CONFIG_MAGIC_DEFAULT // Do not remove. This is the activation bit.
};

Wyświetl plik

@ -99,18 +99,27 @@ typedef struct {
} thread_conf_t; // Thread
typedef struct {
thread_conf_t svc_conf;
bool active;
sysinterval_t init_delay;
sysinterval_t send_spacing;
sleep_conf_t sleep_conf;
sysinterval_t cycle; // Cycle time (0: continuously)
sysinterval_t duration;
// Default lat, lon and alt when fixed is enabled
bool fixed;
gps_coord_t lat;
gps_coord_t lon;
gps_alt_t alt;
} thd_bcn_conf_t; // Thread
typedef struct {
thd_bcn_conf_t beacon;
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
bool aprs_msg;
// Default lat, lon and alt when fixed is enabled
bool fixed;
gps_coord_t lat;
gps_coord_t lon;
gps_alt_t alt;
} thd_pos_conf_t;
typedef struct {
@ -135,6 +144,7 @@ typedef struct {
} thd_log_conf_t;
typedef struct {
thread_conf_t svc_conf;
radio_rx_conf_t radio_conf;
aprs_sym_t symbol;
// Protocol
@ -158,27 +168,20 @@ typedef struct {
bool enabled;
} thd_base_conf_t;
typedef struct {
/*typedef struct {
bool active; // Digipeater active flag
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
thd_pos_conf_t beacon;
//sysinterval_t tel_enc_cycle;
} thd_digi_conf_t;
} thd_digi_conf_t;*/
/* APRS configuration. */
typedef struct {
thread_conf_t svc_conf;
thd_rx_conf_t rx;
thd_digi_conf_t digi;
// Base station call sign for receipt of tracker initiated sends
// These are sends by the tracker which are not in response to a query.
//thd_base_conf_t base;
// Default APRS frequency if geolocation is not available (GPS offline)
//radio_freq_t freq;
bool digi;
thd_pos_conf_t tx;
} thd_aprs_conf_t;
typedef struct {

Wyświetl plik

@ -268,20 +268,20 @@ void usb_cmd_send_aprs_message(BaseSequentialStream *chp, int argc, char *argv[]
chprintf(chp, "Message: %s\r\n", m);
/* Send with ack request (last arg true). */
packet_t packet = aprs_encode_message(conf_sram.aprs.digi.call,
conf_sram.aprs.digi.path,
packet_t packet = aprs_encode_message(conf_sram.aprs.tx.call,
conf_sram.aprs.tx.path,
argv[0], m, true);
if(packet == NULL) {
TRACE_WARN("CMD > No free packet objects");
return;
}
transmitOnRadio(packet,
conf_sram.aprs.digi.radio_conf.freq,
conf_sram.aprs.tx.radio_conf.freq,
0,
0,
conf_sram.aprs.digi.radio_conf.pwr,
conf_sram.aprs.digi.radio_conf.mod,
conf_sram.aprs.digi.radio_conf.cca);
conf_sram.aprs.tx.radio_conf.pwr,
conf_sram.aprs.tx.radio_conf.mod,
conf_sram.aprs.tx.radio_conf.cca);
chprintf(chp, "Message sent!\r\n");
}

Wyświetl plik

@ -1,106 +1,119 @@
#include "flash.h"
#include "pflash.h"
#include "debug.h"
dataPoint_t* flash_getLogBuffer(uint16_t id)
{
uint32_t addr = LOG_FLASH_ADDR + LOG_SECTOR_ID(id) * LOG_SECTOR_SIZE + LOG_POS_IN_SECTOR(id) * sizeof(dataPoint_t);
if(addr >= LOG_FLASH_ADDR && addr <= LOG_FLASH_ADDR+LOG_FLASH_SIZE-sizeof(dataPoint_t))
return (dataPoint_t*)addr;
else
return NULL; // Outside of memory address allocation
}
/**
* Returns next free log entry address in memory.
* Returns NULL if all entries are used.
*/
static dataPoint_t* flash_getNextFreeLogAddress(void) {
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(LOG_IS_EMPTY(tp))
return tp;
}
return NULL;
}
/*
*
*/
dataPoint_t* flash_getNewestLogEntry(void) {
dataPoint_t* last_tp = NULL;
uint64_t last_id = 0x0;
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(!LOG_IS_EMPTY(tp) && last_id <= LOG_RSTandID(tp)) {
last_id = LOG_RSTandID(tp);
last_tp = tp;
} else {
break;
}
}
return last_tp;
}
/*
*
*/
dataPoint_t* flash_getOldestLogEntry(void) {
dataPoint_t* first_tp = NULL;
uint64_t first_id = 0xFFFFFFFFFFFFFFFF;
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(!LOG_IS_EMPTY(tp) && first_id >= LOG_RSTandID(tp)) {
first_id = LOG_RSTandID(tp);
first_tp = tp;
} else {
break;
}
}
return first_tp;
}
/**
* Erases oldest data
*/
static void flash_eraseOldestLogData(void)
{
uint32_t last_tp = (uint32_t)flash_getOldestLogEntry();
if(last_tp) {
last_tp = (last_tp / LOG_SECTOR_SIZE) * LOG_SECTOR_SIZE; // Get start address of sector
TRACE_INFO("LOG > Erase flash %08x", last_tp);
flashErase(last_tp, LOG_SECTOR_SIZE);
}
}
void flash_writeLogDataPoint(dataPoint_t* tp)
{
// Get address to write on
dataPoint_t* address = flash_getNextFreeLogAddress();
if(address == NULL) // Memory completly used, erase oldest data
{
flash_eraseOldestLogData();
address = flash_getNextFreeLogAddress();
}
if(address == NULL) // Something went wrong at erasing the memory
{
TRACE_ERROR("LOG > Erasing flash failed");
return;
}
// Write data into flash
TRACE_INFO("LOG > Flash write (ADDR=%08x)", address);
flashSectorBegin(flashSectorAt((uint32_t)address));
flashWrite((uint32_t)address, (char*)tp, sizeof(dataPoint_t));
flashSectorEnd(flashSectorAt((uint32_t)address));
// Verify
if(flashCompare((uint32_t)address, (char*)tp, sizeof(dataPoint_t))) {
TRACE_INFO("LOG > Flash write OK");
} else {
TRACE_ERROR("LOG > Flash write failed");
}
}
#include "flash.h"
#include "pflash.h"
#include "debug.h"
dataPoint_t* flash_getLogBuffer(uint16_t id)
{
uint32_t addr = LOG_FLASH_ADDR + LOG_SECTOR_ID(id) * LOG_SECTOR_SIZE + LOG_POS_IN_SECTOR(id) * sizeof(dataPoint_t);
if(addr >= LOG_FLASH_ADDR && addr <= LOG_FLASH_ADDR+LOG_FLASH_SIZE-sizeof(dataPoint_t))
return (dataPoint_t*)addr;
else
return NULL; // Outside of memory address allocation
}
/**
* Returns next free log entry address in memory.
* Returns NULL if all entries are used.
*/
static dataPoint_t* flash_getNextFreeLogAddress(void) {
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(LOG_IS_EMPTY(tp))
return tp;
}
return NULL;
}
/*
*
*/
/*dataPoint_t* flash_getNewestLogEntry(void) {
dataPoint_t* last_tp = NULL;
uint64_t last_id = 0x0;
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(!LOG_IS_EMPTY(tp) && last_id <= LOG_RSTandID(tp)) {
last_id = LOG_RSTandID(tp);
last_tp = tp;
} else {
break;
}
}
return last_tp;
}*/
/*
*
*/
dataPoint_t* flash_getNewestLogEntry(void) {
dataPoint_t* tp;
uint32_t i = 0;
while((tp = flash_getLogBuffer(i++)) != NULL) {
if(LOG_IS_EMPTY(tp))
break;
}
return (i > 1 && tp != NULL ? flash_getLogBuffer(i - 1) : NULL);
}
/*
*
*/
dataPoint_t* flash_getOldestLogEntry(void) {
dataPoint_t* first_tp = NULL;
uint64_t first_id = 0xFFFFFFFFFFFFFFFF;
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(!LOG_IS_EMPTY(tp) && first_id >= LOG_RSTandID(tp)) {
first_id = LOG_RSTandID(tp);
first_tp = tp;
} else {
break;
}
}
return first_tp;
}
/**
* Erases oldest data
*/
static void flash_eraseOldestLogData(void)
{
uint32_t last_tp = (uint32_t)flash_getOldestLogEntry();
if(last_tp) {
last_tp = (last_tp / LOG_SECTOR_SIZE) * LOG_SECTOR_SIZE; // Get start address of sector
TRACE_INFO("LOG > Erase flash %08x", last_tp);
flashErase(last_tp, LOG_SECTOR_SIZE);
}
}
void flash_writeLogDataPoint(dataPoint_t* tp)
{
// Get address to write on
dataPoint_t* address = flash_getNextFreeLogAddress();
if(address == NULL) // Memory completly used, erase oldest data
{
flash_eraseOldestLogData();
address = flash_getNextFreeLogAddress();
}
if(address == NULL) // Something went wrong at erasing the memory
{
TRACE_ERROR("LOG > Erasing flash failed");
return;
}
// Write data into flash
TRACE_INFO("LOG > Flash write (ADDR=%08x)", address);
flashSectorBegin(flashSectorAt((uint32_t)address));
flashWrite((uint32_t)address, (char*)tp, sizeof(dataPoint_t));
flashSectorEnd(flashSectorAt((uint32_t)address));
// Verify
if(flashCompare((uint32_t)address, (char*)tp, sizeof(dataPoint_t))) {
TRACE_INFO("LOG > Flash write OK");
} else {
TRACE_ERROR("LOG > Flash write failed");
}
}

Wyświetl plik

@ -1064,9 +1064,14 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
radio_pwm_fifo_t *myFIFO = myDriver->active_demod_object;
uint8_t u = myFIFO->in_use;
uint8_t n = pktReleasePWMbuffers(myDriver);
#if TRACE_PWM_BUFFER_STATS == TRUE
TRACE_DEBUG("AFSK > PWM buffer use:"
" allocated %d, consumed %d, released %d, peak lag %d",
PWM_DATA_BUFFERS, u, n, myFIFO->peak);
#else
(void)u;
(void)n;
#endif
#endif
/* Reset will release the stream FIFO. */
myDriver->decoder_state = DECODER_RESET;
@ -1116,9 +1121,14 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
radio_pwm_fifo_t *myFIFO = myDriver->active_demod_object;
uint8_t u = myFIFO->in_use;
uint8_t n = pktReleasePWMbuffers(myDriver);
#if TRACE_PWM_BUFFER_STATS == TRUE
TRACE_DEBUG("AFSK > PWM buffer use:"
" allocated %d, consumed %d, released %d, peak lag %d",
PWM_DATA_BUFFERS, u, n, myFIFO->peak);
#else
(void)u;
(void)n;
#endif
#endif
/*
* Indicate AFSK decode done & lock the PWM queue.

Wyświetl plik

@ -43,12 +43,12 @@ static heard_t heard_list[APRS_HEARD_LIST_SIZE];
static bool dedupe_initialized;
const conf_command_t command_list[] = {
{TYPE_INT, "pos_pri.active", sizeof(conf_sram.pos_pri.svc_conf.active), &conf_sram.pos_pri.svc_conf.active },
{TYPE_TIME, "pos_pri.init_delay", sizeof(conf_sram.pos_pri.svc_conf.init_delay), &conf_sram.pos_pri.svc_conf.init_delay },
{TYPE_INT, "pos_pri.sleep_conf.type", sizeof(conf_sram.pos_pri.svc_conf.sleep_conf.type), &conf_sram.pos_pri.svc_conf.sleep_conf.type },
{TYPE_INT, "pos_pri.sleep_conf.vbat_thres", sizeof(conf_sram.pos_pri.svc_conf.sleep_conf.vbat_thres), &conf_sram.pos_pri.svc_conf.sleep_conf.vbat_thres },
{TYPE_INT, "pos_pri.sleep_conf.vsol_thres", sizeof(conf_sram.pos_pri.svc_conf.sleep_conf.vsol_thres), &conf_sram.pos_pri.svc_conf.sleep_conf.vsol_thres },
{TYPE_TIME, "pos_pri.cycle", sizeof(conf_sram.pos_pri.svc_conf.cycle), &conf_sram.pos_pri.svc_conf.cycle },
{TYPE_INT, "pos_pri.active", sizeof(conf_sram.pos_pri.beacon.active), &conf_sram.pos_pri.beacon.active },
{TYPE_TIME, "pos_pri.init_delay", sizeof(conf_sram.pos_pri.beacon.init_delay), &conf_sram.pos_pri.beacon.init_delay },
{TYPE_INT, "pos_pri.sleep_conf.type", sizeof(conf_sram.pos_pri.beacon.sleep_conf.type), &conf_sram.pos_pri.beacon.sleep_conf.type },
{TYPE_INT, "pos_pri.sleep_conf.vbat_thres", sizeof(conf_sram.pos_pri.beacon.sleep_conf.vbat_thres), &conf_sram.pos_pri.beacon.sleep_conf.vbat_thres },
{TYPE_INT, "pos_pri.sleep_conf.vsol_thres", sizeof(conf_sram.pos_pri.beacon.sleep_conf.vsol_thres), &conf_sram.pos_pri.beacon.sleep_conf.vsol_thres },
{TYPE_TIME, "pos_pri.cycle", sizeof(conf_sram.pos_pri.beacon.cycle), &conf_sram.pos_pri.beacon.cycle },
{TYPE_INT, "pos_pri.pwr", sizeof(conf_sram.pos_pri.radio_conf.pwr), &conf_sram.pos_pri.radio_conf.pwr },
{TYPE_INT, "pos_pri.freq", sizeof(conf_sram.pos_pri.radio_conf.freq), &conf_sram.pos_pri.radio_conf.freq },
{TYPE_INT, "pos_pri.mod", sizeof(conf_sram.pos_pri.radio_conf.mod), &conf_sram.pos_pri.radio_conf.mod },
@ -58,12 +58,12 @@ const conf_command_t command_list[] = {
{TYPE_INT, "pos_pri.symbol", sizeof(conf_sram.pos_pri.symbol), &conf_sram.pos_pri.symbol },
{TYPE_INT, "pos_pri.aprs_msg", sizeof(conf_sram.pos_pri.aprs_msg), &conf_sram.pos_pri.aprs_msg },
{TYPE_INT, "pos_sec.active", sizeof(conf_sram.pos_sec.svc_conf.active), &conf_sram.pos_sec.svc_conf.active },
{TYPE_TIME, "pos_sec.init_delay", sizeof(conf_sram.pos_sec.svc_conf.init_delay), &conf_sram.pos_sec.svc_conf.init_delay },
{TYPE_INT, "pos_sec.sleep_conf.type", sizeof(conf_sram.pos_sec.svc_conf.sleep_conf.type), &conf_sram.pos_sec.svc_conf.sleep_conf.type },
{TYPE_INT, "pos_sec.sleep_conf.vbat_thres", sizeof(conf_sram.pos_sec.svc_conf.sleep_conf.vbat_thres), &conf_sram.pos_sec.svc_conf.sleep_conf.vbat_thres },
{TYPE_INT, "pos_sec.sleep_conf.vsol_thres", sizeof(conf_sram.pos_sec.svc_conf.sleep_conf.vsol_thres), &conf_sram.pos_sec.svc_conf.sleep_conf.vsol_thres },
{TYPE_TIME, "pos_sec.cycle", sizeof(conf_sram.pos_sec.svc_conf.cycle), &conf_sram.pos_sec.svc_conf.cycle },
{TYPE_INT, "pos_sec.active", sizeof(conf_sram.pos_sec.beacon.active), &conf_sram.pos_sec.beacon.active },
{TYPE_TIME, "pos_sec.init_delay", sizeof(conf_sram.pos_sec.beacon.init_delay), &conf_sram.pos_sec.beacon.init_delay },
{TYPE_INT, "pos_sec.sleep_conf.type", sizeof(conf_sram.pos_sec.beacon.sleep_conf.type), &conf_sram.pos_sec.beacon.sleep_conf.type },
{TYPE_INT, "pos_sec.sleep_conf.vbat_thres", sizeof(conf_sram.pos_sec.beacon.sleep_conf.vbat_thres), &conf_sram.pos_sec.beacon.sleep_conf.vbat_thres },
{TYPE_INT, "pos_sec.sleep_conf.vsol_thres", sizeof(conf_sram.pos_sec.beacon.sleep_conf.vsol_thres), &conf_sram.pos_sec.beacon.sleep_conf.vsol_thres },
{TYPE_TIME, "pos_sec.cycle", sizeof(conf_sram.pos_sec.beacon.cycle), &conf_sram.pos_sec.beacon.cycle },
{TYPE_INT, "pos_sec.pwr", sizeof(conf_sram.pos_sec.radio_conf.pwr), &conf_sram.pos_sec.radio_conf.pwr },
{TYPE_INT, "pos_sec.freq", sizeof(conf_sram.pos_sec.radio_conf.freq), &conf_sram.pos_sec.radio_conf.freq },
{TYPE_INT, "pos_sec.mod", sizeof(conf_sram.pos_sec.radio_conf.mod), &conf_sram.pos_sec.radio_conf.mod },
@ -127,28 +127,28 @@ const conf_command_t command_list[] = {
{TYPE_STR, "log.path", sizeof(conf_sram.log.path), &conf_sram.log.path },
{TYPE_INT, "log.density", sizeof(conf_sram.log.density), &conf_sram.log.density },
{TYPE_INT, "aprs.active", sizeof(conf_sram.aprs.svc_conf.active), &conf_sram.aprs.svc_conf.active },
{TYPE_TIME, "aprs.init_delay", sizeof(conf_sram.aprs.svc_conf.init_delay), &conf_sram.aprs.svc_conf.init_delay },
{TYPE_INT, "aprs.rx.active", sizeof(conf_sram.aprs.rx.svc_conf.active), &conf_sram.aprs.rx.svc_conf.active },
{TYPE_TIME, "aprs.rx.init_delay", sizeof(conf_sram.aprs.rx.svc_conf.init_delay), &conf_sram.aprs.rx.svc_conf.init_delay },
{TYPE_INT, "aprs.rx.freq", sizeof(conf_sram.aprs.rx.radio_conf.freq), &conf_sram.aprs.rx.radio_conf.freq },
{TYPE_INT, "aprs.rx.mod", sizeof(conf_sram.aprs.rx.radio_conf.mod), &conf_sram.aprs.rx.radio_conf.mod },
{TYPE_INT, "aprs.rx.speed", sizeof(conf_sram.aprs.rx.radio_conf.speed), &conf_sram.aprs.rx.radio_conf.speed },
{TYPE_STR, "aprs.rx.call", sizeof(conf_sram.aprs.rx.call), &conf_sram.aprs.rx.call },
{TYPE_INT, "aprs.digi.active", sizeof(conf_sram.aprs.digi.active), &conf_sram.aprs.digi.active },
{TYPE_INT, "aprs.digi.freq", sizeof(conf_sram.aprs.digi.radio_conf.freq), &conf_sram.aprs.digi.radio_conf.freq },
{TYPE_INT, "aprs.digi.pwr", sizeof(conf_sram.aprs.digi.radio_conf.pwr), &conf_sram.aprs.digi.radio_conf.pwr },
{TYPE_INT, "aprs.digi.mod", sizeof(conf_sram.aprs.digi.radio_conf.mod), &conf_sram.aprs.digi.radio_conf.mod },
{TYPE_INT, "aprs.digi.cca", sizeof(conf_sram.aprs.digi.radio_conf.cca), &conf_sram.aprs.digi.radio_conf.cca },
{TYPE_STR, "aprs.digi.call", sizeof(conf_sram.aprs.digi.call), &conf_sram.aprs.digi.call },
{TYPE_STR, "aprs.digi.path", sizeof(conf_sram.aprs.digi.path), &conf_sram.aprs.digi.path },
{TYPE_INT, "aprs.digi.symbol", sizeof(conf_sram.aprs.digi.symbol), &conf_sram.aprs.digi.symbol },
{TYPE_INT, "aprs.digi.beacon", sizeof(conf_sram.aprs.digi.beacon.svc_conf.active), &conf_sram.aprs.digi.beacon.svc_conf.active },
{TYPE_INT, "aprs.digi", sizeof(conf_sram.aprs.digi), &conf_sram.aprs.digi },
{TYPE_INT, "aprs.tx.freq", sizeof(conf_sram.aprs.tx.radio_conf.freq), &conf_sram.aprs.tx.radio_conf.freq },
{TYPE_INT, "aprs.tx.pwr", sizeof(conf_sram.aprs.tx.radio_conf.pwr), &conf_sram.aprs.tx.radio_conf.pwr },
{TYPE_INT, "aprs.tx.mod", sizeof(conf_sram.aprs.tx.radio_conf.mod), &conf_sram.aprs.tx.radio_conf.mod },
{TYPE_INT, "aprs.tx.cca", sizeof(conf_sram.aprs.tx.radio_conf.cca), &conf_sram.aprs.tx.radio_conf.cca },
{TYPE_STR, "aprs.tx.call", sizeof(conf_sram.aprs.tx.call), &conf_sram.aprs.tx.call },
{TYPE_STR, "aprs.tx.path", sizeof(conf_sram.aprs.tx.path), &conf_sram.aprs.tx.path },
{TYPE_INT, "aprs.tx.symbol", sizeof(conf_sram.aprs.tx.symbol), &conf_sram.aprs.tx.symbol },
{TYPE_INT, "aprs.beacon.lat", sizeof(conf_sram.aprs.digi.beacon.lat), &conf_sram.aprs.digi.beacon.lat },
{TYPE_INT, "aprs.beacon.lon", sizeof(conf_sram.aprs.digi.beacon.lon), &conf_sram.aprs.digi.beacon.lon },
{TYPE_INT, "aprs.beacon.alt", sizeof(conf_sram.aprs.digi.beacon.alt), &conf_sram.aprs.digi.beacon.alt },
{TYPE_INT, "aprs.beacon.cycle", sizeof(conf_sram.aprs.digi.beacon.svc_conf.cycle), &conf_sram.aprs.digi.beacon.svc_conf.cycle },
{TYPE_INT, "aprs.beacon", sizeof(conf_sram.aprs.tx.beacon.active), &conf_sram.aprs.tx.beacon.active },
{TYPE_INT, "aprs.beacon.lat", sizeof(conf_sram.aprs.tx.beacon.lat), &conf_sram.aprs.tx.beacon.lat },
{TYPE_INT, "aprs.beacon.lon", sizeof(conf_sram.aprs.tx.beacon.lon), &conf_sram.aprs.tx.beacon.lon },
{TYPE_INT, "aprs.beacon.alt", sizeof(conf_sram.aprs.tx.beacon.alt), &conf_sram.aprs.tx.beacon.alt },
{TYPE_INT, "aprs.beacon.cycle", sizeof(conf_sram.aprs.tx.beacon.cycle), &conf_sram.aprs.tx.beacon.cycle },
{TYPE_INT, "keep_cam_switched_on", sizeof(conf_sram.keep_cam_switched_on), &conf_sram.keep_cam_switched_on },
{TYPE_INT, "gps_on_vbat", sizeof(conf_sram.gps_on_vbat), &conf_sram.gps_on_vbat },
@ -849,9 +849,7 @@ msg_t aprs_send_position_response(aprs_identity_t *id,
if(argc != 0)
return MSG_ERROR;
/*
* TODO: This should just send a request to a TEL service.
* The TEL service should then transmit config data at a spaced interval.
* The same applies to BCN and POS threads which should also use a TEL service.
* TODO: This should just send a request to the collector service.
*/
// Encode and transmit telemetry config first
for(uint8_t type = 0; type < APRS_NUM_TELEM_GROUPS; type++) {
@ -1126,19 +1124,19 @@ static bool aprs_decode_message(packet_t pp) {
aprs_identity_t identity = {0};
strcpy(identity.src, src);
strcpy(identity.call, conf_sram.aprs.digi.call);
strcpy(identity.call, conf_sram.aprs.tx.call);
/* TODO: define a length for path. */
strcpy(identity.path, conf_sram.aprs.digi.path);
identity.symbol = conf_sram.aprs.digi.symbol;
identity.freq = conf_sram.aprs.digi.radio_conf.freq;
identity.pwr = conf_sram.aprs.digi.radio_conf.pwr;
identity.mod = conf_sram.aprs.digi.radio_conf.mod;
identity.cca = conf_sram.aprs.digi.radio_conf.cca;
strcpy(identity.path, conf_sram.aprs.tx.path);
identity.symbol = conf_sram.aprs.tx.symbol;
identity.freq = conf_sram.aprs.tx.radio_conf.freq;
identity.pwr = conf_sram.aprs.tx.radio_conf.pwr;
identity.mod = conf_sram.aprs.tx.radio_conf.mod;
identity.cca = conf_sram.aprs.tx.radio_conf.cca;
/* Check which apps are enabled to accept APRS messages. */
bool pos_pri = (strcmp(conf_sram.pos_pri.call, dest) == 0)
&& (conf_sram.pos_pri.aprs_msg)
&& (conf_sram.pos_pri.svc_conf.active);
&& (conf_sram.pos_pri.beacon.active);
if(pos_pri) {
strcpy(identity.call, conf_sram.pos_pri.call);
@ -1148,7 +1146,7 @@ static bool aprs_decode_message(packet_t pp) {
bool pos_sec = (strcmp(conf_sram.pos_sec.call, dest) == 0)
&& (conf_sram.pos_sec.aprs_msg)
&& (conf_sram.pos_sec.svc_conf.active);
&& (conf_sram.pos_sec.beacon.active);
if(pos_sec) {
strcpy(identity.call, conf_sram.pos_sec.call);
strcpy(identity.path, conf_sram.pos_sec.path);
@ -1156,7 +1154,7 @@ static bool aprs_decode_message(packet_t pp) {
}
bool aprs_rx = (strcmp(conf_sram.aprs.rx.call, dest) == 0)
&& (conf_sram.aprs.svc_conf.active);
&& (conf_sram.aprs.rx.svc_conf.active);
if(aprs_rx) {
strcpy(identity.call, conf_sram.aprs.rx.call);
identity.symbol = conf_sram.aprs.rx.symbol;
@ -1164,8 +1162,8 @@ static bool aprs_decode_message(packet_t pp) {
}
/* Even if the digi is not active respond on the digi (TX) call. */
bool aprs_tx = (strcmp(conf_sram.aprs.digi.call, dest) == 0)
&& (conf_sram.aprs.svc_conf.active)
bool aprs_tx = (strcmp(conf_sram.aprs.tx.call, dest) == 0)
&& (conf_sram.aprs.rx.svc_conf.active)
/*&& (conf_sram.aprs.digi.active)*/;
/* Default already set tx parameters. */
@ -1285,18 +1283,18 @@ static void aprs_digipeat(packet_t pp) {
if(!dedupe_check(pp, 0)) { // Last identical packet older than 10 seconds
packet_t result = digipeat_match(0, pp, conf_sram.aprs.rx.call,
conf_sram.aprs.digi.call, alias_re,
conf_sram.aprs.tx.call, alias_re,
wide_re, 0, preempt, NULL);
if(result != NULL) { // Should be digipeated
dedupe_remember(result, 0);
/* If transmit fails the packet buffer is released. */
if(!transmitOnRadio(result,
conf_sram.aprs.digi.radio_conf.freq,
conf_sram.aprs.tx.radio_conf.freq,
0,
0,
conf_sram.aprs.digi.radio_conf.pwr,
conf_sram.aprs.digi.radio_conf.mod,
conf_sram.aprs.digi.radio_conf.cca)) {
conf_sram.aprs.tx.radio_conf.pwr,
conf_sram.aprs.tx.radio_conf.mod,
conf_sram.aprs.tx.radio_conf.cca)) {
TRACE_INFO("RX > Failed to digipeat packet");
} /* TX failed. */
} /* Should be digipeated. */
@ -1377,7 +1375,7 @@ void aprs_decode_packet(packet_t pp) {
}
// Digipeat packet
if(conf_sram.aprs.digi.active && digipeat) {
if(conf_sram.aprs.digi && digipeat) {
aprs_digipeat(pp);
}
}

Wyświetl plik

@ -31,10 +31,6 @@
static dataPoint_t dataPoints[2];
static dataPoint_t* lastDataPoint;
static bool threadStarted = false;
#if USE_NEW_COLLECTOR != TRUE
static uint8_t useGPS = 0;
#endif
static uint8_t useCFG = 0;
static uint8_t bme280_error;
/*===========================================================================*/
@ -76,9 +72,7 @@ static void getPositionFallback(dataPoint_t* tp,
tp->gps_lat = 0;
tp->gps_lon = 0;
tp->gps_alt = 0;
if(hasGPSacquiredLock(ltp)
|| ltp->gps_state == GPS_FIXED
|| ltp->gps_state == GPS_LOG) {
if(isPositionValid(ltp)) {
tp->gps_lat = ltp->gps_lat;
tp->gps_lon = ltp->gps_lon;
tp->gps_alt = ltp->gps_alt;
@ -374,211 +368,13 @@ void setSystemStatus(dataPoint_t* tp) {
/* Data collector thread. */
/*===========================================================================*/
/**
*
*/
THD_FUNCTION(collectorThread, arg) {
uint8_t *useGPS = arg;
uint32_t id = 0;
// Read time from RTC
ptime_t time;
getTime(&time);
dataPoints[0].gps_time = date2UnixTimestamp(&time);
dataPoints[1].gps_time = date2UnixTimestamp(&time);
lastDataPoint = &dataPoints[0];
// Get last data point from memory
TRACE_INFO("COLL > Read last data point from flash memory");
dataPoint_t* lastLogPoint = flash_getNewestLogEntry();
if(lastLogPoint != NULL) { // If there is stored data point, then get it.
dataPoints[0].reset = lastLogPoint->reset+1;
dataPoints[1].reset = lastLogPoint->reset+1;
unixTimestamp2Date(&time, lastDataPoint->gps_time);
lastDataPoint->gps_lat = lastLogPoint->gps_lat;
lastDataPoint->gps_lon = lastLogPoint->gps_lon;
lastDataPoint->gps_alt = lastLogPoint->gps_alt;
lastDataPoint->gps_sats = lastLogPoint->gps_sats;
lastDataPoint->gps_ttff = lastLogPoint->gps_ttff;
TRACE_INFO(
"COLL > Last data point (from memory)\r\n"
"%s Reset %d ID %d\r\n"
"%s Time %04d-%02d-%02d %02d:%02d:%02d\r\n"
"%s Latitude: %d.%07ddeg\r\n"
"%s Longitude: %d.%07ddeg\r\n"
"%s Altitude: %d Meter",
TRACE_TAB, lastLogPoint->reset, lastLogPoint->id,
TRACE_TAB, time.year, time.month, time.day, time.hour,
time.minute, time.day,
TRACE_TAB, lastDataPoint->gps_lat/10000000,
(lastDataPoint->gps_lat > 0
? 1:-1)*lastDataPoint->gps_lat%10000000,
TRACE_TAB, lastDataPoint->gps_lon/10000000,
(lastDataPoint->gps_lon > 0
? 1:-1)*lastDataPoint->gps_lon%10000000,
TRACE_TAB, lastDataPoint->gps_alt
);
lastDataPoint->gps_state = GPS_LOG; // Mark dataPoint as LOG packet
} else {
TRACE_INFO("COLL > No data point found in flash memory");
/* State indicates that no valid stored position is available. */
lastDataPoint->gps_state = GPS_OFF;
/* Continue get telemetry and acquire position and time if required. */
}
// Measure telemetry
measureVoltage(lastDataPoint);
getSensors(lastDataPoint);
getGPIO(lastDataPoint);
setSystemStatus(lastDataPoint);
// Write data point to Flash memory
flash_writeLogDataPoint(lastDataPoint);
// Wait for position threads to start
chThdSleep(TIME_MS2I(500));
sysinterval_t cycle_time = chVTGetSystemTime();
/* TODO: The collector will be revised when the overall scheduler is implemented.
* Then app execution will be managed by the scheduler alone.
* i.e. There will be no schedule control within an app itself.
*/
// Determine cycle time and if GPS should be used.
sysinterval_t data_cycle_time = TIME_S2I(600); // Default.
if(conf_sram.pos_pri.svc_conf.active && conf_sram.pos_sec.svc_conf.active) { // Both position threads are active
data_cycle_time = conf_sram.pos_pri.svc_conf.cycle < conf_sram.pos_sec.svc_conf.cycle ? conf_sram.pos_pri.svc_conf.cycle : conf_sram.pos_sec.svc_conf.cycle; // Choose the smallest cycle
(*useGPS)++;
} else if(conf_sram.pos_pri.svc_conf.active) { // Only primary position thread is active
data_cycle_time = conf_sram.pos_pri.svc_conf.cycle;
(*useGPS)++;
} else if(conf_sram.pos_sec.svc_conf.active) { // Only secondary position thread is active
data_cycle_time = conf_sram.pos_sec.svc_conf.cycle;
(*useGPS)++;
} else if(conf_sram.aprs.svc_conf.active
&& conf_sram.aprs.digi.active
&& conf_sram.aprs.digi.beacon.svc_conf.active) { // DIGI beacon is active
data_cycle_time = conf_sram.aprs.digi.beacon.svc_conf.cycle;
if(conf_sram.aprs.digi.beacon.svc_conf.active) {
(*useGPS)++;
}
} else { // There must be an error
TRACE_ERROR("COLL > Data collector started but no position thread is active");
}
while(true) { /* Primary loop. */
/* TODO: Separate collector from GPS (put GPS in its own thread).
* That will allow collection to run per its schedule (won't be stalled by GPS).
*/
TRACE_INFO("COLL > Do module DATA COLLECTOR cycle");
dataPoint_t* tp = &dataPoints[(id+1) % 2]; // Current data point (the one which is processed now)
dataPoint_t* ltp = &dataPoints[ id % 2]; // Last data point
// Gather telemetry and system status data
measureVoltage(tp);
getSensors(tp);
getGPIO(tp);
setSystemStatus(tp);
/*
* Enable GPS position acquisition if...
* a) The RTC was not set then enable GPS temporarily to set it.
* b) If any app is using GPS for position.
*/
getTime(&time);
if(*useGPS == 0 && time.year == RTC_BASE_YEAR) {
/*
* There are no apps requiring GPS position but the uC RTC is not set.
* Enable the GPS and get a lock which results in setting the RTC.
*/
TRACE_INFO("COLL > Acquire time using GPS");
aquirePosition(tp, ltp, data_cycle_time - TIME_S2I(3));
/* RTC is set in aquirePosition(...). */
if(!hasGPSacquiredLock(tp)) {
/* Acquisition failed. Wait and then try again. */
TRACE_INFO("COLL > Time acquisition from GPS failed");
chThdSleep(TIME_S2I(60));
continue;
}
TRACE_INFO("COLL > Time acquired from GPS");
/* Switch GPS off since there are no other users. */
GPS_Deinit();
}
/* Check if any app requires position. */
if(*useGPS > 0) {
TRACE_INFO("COLL > Acquire position using GPS");
aquirePosition(tp, ltp, data_cycle_time - TIME_S2I(3));
/* RTC is set in aquirePosition(...). */
} else {
/*
* No threads using GPS.
* Update datapoint time from RTC.
* Set fixed location.
*/
TRACE_INFO("COLL > Using fixed location");
getTime(&time);
unixTimestamp2Date(&time, tp->gps_time);
//tp->gps_alt = conf_sram.alt;
//tp->gps_lat = conf_sram.lat;
//tp->gps_lon = conf_sram.lon;
tp->gps_state = GPS_FIXED;
}
tp->id = ++id; // Serial ID
// Trace data
unixTimestamp2Date(&time, tp->gps_time);
TRACE_INFO( "COLL > New data point available (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"
"%s ADC Vbat=%d.%03dV Vsol=%d.%03dV Pbat=%dmW\r\n"
"%s AIR p=%d.%01dPa T=%d.%02ddegC phi=%d.%01d%%\r\n"
"%s IOP IO1=%d IO2=%d IO3=%d IO4=%d",
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,
TRACE_TAB, tp->adc_vbat/1000, (tp->adc_vbat%1000), tp->adc_vsol/1000, (tp->adc_vsol%1000), tp->pac_pbat,
TRACE_TAB, tp->sen_i1_press/10, tp->sen_i1_press%10, tp->sen_i1_temp/100, tp->sen_i1_temp%100, tp->sen_i1_hum/10, tp->sen_i1_hum%10,
TRACE_TAB, tp->gpio & 1, (tp->gpio >> 1) & 1, (tp->gpio >> 2) & 1, (tp->gpio >> 3) & 1
);
// Write data point to Flash memory
flash_writeLogDataPoint(tp);
// Switch last data point
lastDataPoint = tp;
// Wait until cycle
cycle_time = chThdSleepUntilWindowed(cycle_time, cycle_time + data_cycle_time);
}
}
/**
* Telemetry config (Thread)
* TODO: Make this service thread run on system level time schedule to send config packets.
* Any thread sending telemetry would request this service be started.
*/
THD_FUNCTION(configThread, arg) {
(void)arg;
while(true) chThdSleep(TIME_S2I(1));
}
/**
* GPS operation (Thread)
* TODO: To provide GPS status and data.
*/
THD_FUNCTION(gpsThread, arg) {
(void)arg;
uint32_t id = 0;
//msg_t result;
// Read time from RTC
ptime_t time;
@ -622,12 +418,10 @@ THD_FUNCTION(gpsThread, arg) {
TRACE_TAB, lastDataPoint->gps_alt
);
lastDataPoint->gps_state = GPS_LOG; // Mark dataPoint as LOG packet
//result = MSG_OK;
} else {
TRACE_INFO("COLL > No data point found in flash memory");
/* State indicates that no valid stored position is available. */
lastDataPoint->gps_state = GPS_OFF;
//result = MSG_TIMEOUT;
}
// Measure telemetry
@ -639,11 +433,6 @@ THD_FUNCTION(gpsThread, arg) {
// Write data point to Flash memory
flash_writeLogDataPoint(lastDataPoint);
// Wait for position threads to start
//chThdSleep(TIME_MS2I(500));
//sysinterval_t cycle_time = chVTGetSystemTime();
// Determine cycle time and if GPS should be used.
sysinterval_t data_cycle_time = TIME_S2I(600); // Default.
@ -662,10 +451,8 @@ THD_FUNCTION(gpsThread, arg) {
/* Update with freshly acquired data. */
lastDataPoint = newDataPoint;
GPS_Deinit();
//result = MSG_OK;
} else {
TRACE_INFO("COLL > Time not acquired from GPS");
//result = MSG_TIMEOUT;
}
}
@ -690,36 +477,36 @@ THD_FUNCTION(gpsThread, arg) {
getGPIO(tp);
setSystemStatus(tp);
if(!config->fixed) {
TRACE_INFO("COLL > Acquire position using GPS");
aquirePosition(tp, ltp, data_cycle_time - TIME_S2I(3));
//result = MSG_OK;
} else {
if(config->beacon.fixed) {
/*
* Update datapoint time from RTC.
* Set fixed location.
* Use fixed position data.
* Update set fixed position.
* Time will be set in data below.
*/
TRACE_INFO("COLL > Using fixed location");
getTime(&time);
unixTimestamp2Date(&time, tp->gps_time);
tp->gps_alt = config->alt;
tp->gps_lat = config->lat;
tp->gps_lon = config->lon;
tp->gps_alt = config->beacon.alt;
tp->gps_lat = config->beacon.lat;
tp->gps_lon = config->beacon.lon;
tp->gps_state = GPS_FIXED;
//result = MSG_OK;
} else {
/* Try GPS lock to get data. If lock not attained fallback data is set. */
TRACE_INFO("COLL > Acquire position using GPS");
aquirePosition(tp, ltp, data_cycle_time - TIME_S2I(3));
}
tp->id = ++id; // Serial ID
// Trace data
getTime(&time);
unixTimestamp2Date(&time, tp->gps_time);
TRACE_INFO( "COLL > New data point available (ID=%d)\r\n"
TRACE_INFO( "COLL > New data point available (ID=%d, GPS state=%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"
"%s ADC Vbat=%d.%03dV Vsol=%d.%03dV Pbat=%dmW\r\n"
"%s AIR p=%d.%01dPa T=%d.%02ddegC phi=%d.%01d%%\r\n"
"%s IOP IO1=%d IO2=%d IO3=%d IO4=%d",
tp->id,
tp->id, tp->gps_state,
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,
@ -745,12 +532,12 @@ void init_data_collector() {
if(!threadStarted) {
threadStarted = true;
#if USE_NEW_COLLECTOR != TRUE
TRACE_INFO("COLL > Startup data collector thread");
thread_t *th = chThdCreateFromHeap(NULL,
THD_WORKING_AREA_SIZE(10*1024),
"COL", LOWPRIO,
collectorThread, &useGPS);
collectorThread, NULL);
collector_thd = th;
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("COLL > Could not start"
@ -758,35 +545,6 @@ void init_data_collector() {
} else {
chThdSleep(TIME_MS2I(300)); // Wait a little bit until data collector has initialized first dataset
}
#else
thread_t *th;
#endif
TRACE_INFO("CFG > Startup telemetry config thread");
th = chThdCreateFromHeap(NULL,
THD_WORKING_AREA_SIZE(2*1024),
"CFG", LOWPRIO,
configThread, &useCFG);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("CFG > Could not start"
" thread (not enough memory available)");
} else {
chThdSleep(TIME_MS2I(300));
}
TRACE_INFO("GPS > Startup GPS manager thread");
th = chThdCreateFromHeap(NULL,
THD_WORKING_AREA_SIZE(2*1024),
"GPS", LOWPRIO,
gpsThread, NULL);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("GPS > Could not start"
" thread (not enough memory available)");
} else {
collector_thd = th;
chThdSleep(TIME_MS2I(300));
}
}
}

Wyświetl plik

@ -16,10 +16,7 @@
*
*/
THD_FUNCTION(bcnThread, arg) {
thd_aprs_conf_t* conf = (thd_aprs_conf_t *)arg;
// Wait
if(conf->svc_conf.init_delay) chThdSleep(conf->svc_conf.init_delay);
thd_pos_conf_t* conf = (thd_pos_conf_t *)arg;
// Start data collector (if not running yet)
init_data_collector();
@ -28,37 +25,33 @@ THD_FUNCTION(bcnThread, arg) {
TRACE_INFO("BCN > Startup beacon thread");
// Set telemetry configuration transmission variables
// Each beacon send configuration data as the call signs may differ
sysinterval_t last_conf_transmission =
chVTGetSystemTime() - conf_sram.tel_enc_cycle;
sysinterval_t time = chVTGetSystemTime();
/*
* Already waited for APRS start delay.
* Now wait for our further delay before starting.
*/
sysinterval_t delay = conf->digi.beacon.svc_conf.init_delay;
/* Now wait for our delay before starting. */
sysinterval_t delay = conf->beacon.init_delay;
chThdSleep(delay);
while(true) {
char code_s[100];
pktDisplayFrequencyCode(conf->digi.radio_conf.freq,
code_s, sizeof(code_s));
pktDisplayFrequencyCode(conf->radio_conf.freq, code_s, sizeof(code_s));
TRACE_INFO("POS > Do module BEACON cycle for %s on %s",
conf->digi.call, code_s);
conf->call, code_s);
#if USE_NEW_COLLECTOR == TRUE
extern thread_t *collector_thd;
/*
* Pass pointer to beacon config to the collector thread.
* TODO: return message should be pointer to latest updated datapoint?
*/
dataPoint_t * dataPoint =
(dataPoint_t *)chMsgSend(collector_thd, (msg_t)&conf->digi.beacon);
(dataPoint_t *)chMsgSend(collector_thd, (msg_t)conf);
#else
dataPoint_t* dataPoint = getLastDataPoint();
#endif
if(!p_sleep(&conf->svc_conf.sleep_conf)) {
if(!p_sleep(&conf->beacon.sleep_conf)) {
// Telemetry encoding parameter transmissions
if(conf_sram.tel_enc_cycle != 0 && last_conf_transmission
@ -69,21 +62,21 @@ THD_FUNCTION(bcnThread, arg) {
// Encode and transmit telemetry config packet
for(uint8_t type = 0; type < APRS_NUM_TELEM_GROUPS; type++) {
packet_t packet = aprs_encode_telemetry_configuration(
conf->digi.call,
conf->digi.path,
conf->digi.call,
conf->call,
conf->path,
conf->call,
type);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects for"
" telemetry config transmission");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
conf->radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.radio_conf.cca)) {
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca)) {
TRACE_ERROR("BCN > Failed to transmit telemetry config");
}
}
@ -93,7 +86,8 @@ THD_FUNCTION(bcnThread, arg) {
}
while(!isPositionValid(dataPoint)) {
TRACE_INFO("BCN > Waiting for position data for beacon");
TRACE_INFO("BCN > Waiting for position data for %s (GPS state=%d)"
, conf->call, dataPoint->gps_state);
chThdSleep(TIME_S2I(60));
continue;
}
@ -101,21 +95,21 @@ THD_FUNCTION(bcnThread, arg) {
TRACE_INFO("BCN > Transmit position and telemetry");
// Encode/Transmit position packet
packet_t packet = aprs_encode_position_and_telemetry(conf->digi.call,
conf->digi.path,
conf->digi.symbol,
packet_t packet = aprs_encode_position_and_telemetry(conf->call,
conf->path,
conf->symbol,
dataPoint, true);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects"
" for position transmission");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
conf->radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.radio_conf.cca)) {
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca)) {
TRACE_ERROR("BCN > failed to transmit beacon data");
}
chThdSleep(TIME_S2I(5));
@ -129,7 +123,7 @@ THD_FUNCTION(bcnThread, arg) {
* Else send it to device identity.
*/
char *call = conf_sram.base.enabled
? conf_sram.base.call : conf->digi.call;
? conf_sram.base.call : conf->call;
/*
* Send message from this device.
@ -137,8 +131,8 @@ THD_FUNCTION(bcnThread, arg) {
* There is no acknowledgment requested.
*/
packet = aprs_compose_aprsd_message(
conf_sram.aprs.digi.call,
//conf->digi.call,
//conf_sram.aprs.tx.call,
conf->call,
conf_sram.base.path,
//conf->base.path,
call);
@ -147,26 +141,26 @@ THD_FUNCTION(bcnThread, arg) {
"or badly formed APRSD message");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
conf->radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.radio_conf.cca
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca
)) {
TRACE_ERROR("BCN > Failed to transmit APRSD data");
}
chThdSleep(TIME_S2I(5));
}
} /* psleep */
time = waitForTrigger(time, conf->digi.beacon.svc_conf.cycle);
time = waitForTrigger(time, conf->beacon.cycle);
}
}
/*
*
*/
void start_beacon_thread(thd_aprs_conf_t *conf) {
void start_beacon_thread(thd_pos_conf_t *conf) {
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(10*1024),
"BCN", LOWPRIO, bcnThread, conf);
if(!th) {

Wyświetl plik

@ -1,14 +1,14 @@
#ifndef __BEACON_H__
#define __BEACON_H__
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
void start_beacon_thread(const thd_aprs_conf_t *conf);
#ifdef __cplusplus
}
#endif
#endif /* __BEACON_H__ */
#ifndef __BEACON_H__
#define __BEACON_H__
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
void start_beacon_thread(thd_pos_conf_t *conf);
#ifdef __cplusplus
}
#endif
#endif /* __BEACON_H__ */

Wyświetl plik

@ -7,7 +7,7 @@
#include "radio.h"
#include "si446x.h"
#include "image.h"
#include "position.h"
//#include "position.h"
#include "beacon.h"
#include "log.h"
#include "radio.h"
@ -41,10 +41,11 @@ void start_user_threads(void)
// Copy
memcpy(&conf_sram, conf_flash, sizeof(conf_t));
if(conf_sram.pos_pri.svc_conf.active)
start_position_thread(&conf_sram.pos_pri);
if(conf_sram.pos_sec.svc_conf.active)
start_position_thread(&conf_sram.pos_sec);
/* TODO: Implement scheduler that will run threads based on schedule. */
if(conf_sram.pos_pri.beacon.active)
start_beacon_thread(&conf_sram.pos_pri);
if(conf_sram.pos_sec.beacon.active)
start_beacon_thread(&conf_sram.pos_sec);
if(conf_sram.img_pri.svc_conf.active)
start_image_thread(&conf_sram.img_pri);
@ -54,13 +55,14 @@ void start_user_threads(void)
if(conf_sram.log.svc_conf.active)
start_logging_thread(&conf_sram.log);
if(conf_sram.aprs.svc_conf.active
&& conf_sram.aprs.digi.beacon.svc_conf.active) {
start_beacon_thread(&conf_sram.aprs);
if(conf_sram.aprs.rx.svc_conf.active
&& conf_sram.aprs.digi
&& conf_sram.aprs.tx.beacon.active) {
start_beacon_thread(&conf_sram.aprs.tx);
}
if(conf_sram.aprs.svc_conf.active) {
chThdSleep(conf_sram.aprs.svc_conf.init_delay);
if(conf_sram.aprs.rx.svc_conf.active) {
chThdSleep(conf_sram.aprs.rx.svc_conf.init_delay);
start_aprs_threads(PKT_RADIO_1,
conf_sram.aprs.rx.radio_conf.freq,
0,