Work in progress (note: POS may not be functional in this rev)

- Revise config.c structure to move items out to global level
- Rework collector to be service style thread
- Reworking beacon.c to become telem service for both DIGI and POS
pull/4/head
bob 2018-06-22 00:57:31 +10:00
rodzic 1ea876b6a8
commit 684ab321e2
17 zmienionych plików z 3265 dodań i 3075 usunięć

Wyświetl plik

@ -29,7 +29,6 @@
#define _CHCONF_H_
#define _CHIBIOS_RT_CONF_
#define _CHIBIOS_RT_CONF_VER_5_0_
#define _CHIBIOS_RT_CONF_VER_6_0_
/*===========================================================================*/

Wyświetl plik

@ -86,10 +86,12 @@ const SerialConfig debug_config = {
/*===========================================================================*/
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) {

Wyświetl plik

@ -81,7 +81,7 @@
//#define LINE_UART4_RX PAL_LINE(GPIOA, 11U)
/* The external port can be used for bit bang I2C. */
#define ENABLE_EXTERNAL_I2C FALSE
#define ENABLE_EXTERNAL_I2C TRUE
#if ENABLE_EXTERNAL_I2C == FALSE
#define LINE_USART3_TX LINE_IO_TXD

Wyświetl plik

@ -29,7 +29,6 @@
#define _CHCONF_H_
#define _CHIBIOS_RT_CONF_
#define _CHIBIOS_RT_CONF_VER_5_0_
#define _CHIBIOS_RT_CONF_VER_6_0_
/*===========================================================================*/

Wyświetl plik

@ -12,7 +12,7 @@ conf_t conf_sram;
const conf_t conf_flash_default = {
// Primary position app
.pos_pri = {
.thread_conf = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(60 * 5),
.init_delay = TIME_S2I(30)
@ -29,12 +29,12 @@ const conf_t conf_flash_default = {
.symbol = SYM_ANTENNA,
.aprs_msg = true,
// How often to send telemetry config
.tel_enc_cycle = TIME_S2I(60 * 60)
//.tel_enc_cycle = TIME_S2I(60 * 60)
},
// Secondary position app
.pos_sec = {
.thread_conf = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(180),
.init_delay = TIME_S2I(60)
@ -51,12 +51,12 @@ const conf_t conf_flash_default = {
.symbol = SYM_BALLOON,
.aprs_msg = true,
.tel_enc_cycle = TIME_S2I(0)
//.tel_enc_cycle = TIME_S2I(0)
},
// Primary image app
.img_pri = {
.thread_conf = {
.svc_conf = {
.active = false,
.cycle = CYCLE_CONTINUOUSLY,
.init_delay = TIME_S2I(90),
@ -82,7 +82,7 @@ const conf_t conf_flash_default = {
// Secondary image app
.img_sec = {
.thread_conf = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(60 * 30),
.init_delay = TIME_S2I(60 * 1),
@ -107,7 +107,7 @@ const conf_t conf_flash_default = {
// Log app
.log = {
.thread_conf = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(10),
.init_delay = TIME_S2I(5)
@ -126,14 +126,12 @@ const conf_t conf_flash_default = {
// APRS app
.aprs = {
.thread_conf = {
.svc_conf = {
// The packet receive service is enabled if true
// Receive is resumed after any transmission
.active = true,
.init_delay = TIME_S2I(20)
},
// The default APRS frequency when geofence is not resolved
.freq = APRS_FREQ_AUSTRALIA,
// The receive identity for APRS
.rx = {
// Receive radio configuration
@ -156,48 +154,48 @@ const conf_t conf_flash_default = {
.mod = MOD_AFSK,
.cca = 0x4F
},
// Digipeat identity
.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,
// Set to have digi beacon position, telemetry & APRSD information.
// This starts a BCN thread specifically for digi
.beacon = true,
.cycle = TIME_S2I(60 * 30), // Beacon interval
// Set true to have digi use GPS for position
// If valid position is not stored then default lat, lon and alt will be used.
// If RTC time is invalid then GPS will be enabled to get time.
// Once RTC is set then GPS is released and can be switched off.
// This will be the case if no other position thread is using GPS.
.gps = true,
// How often to send telemetry config (TODO: Move out to global level)
.tel_enc_cycle = TIME_S2I(60 * 60 * 2)
},
// The base station identity
.base = {
// Tracker originated messages will be sent to this call sign if enabled
.enabled = true,
.call = "VK2GJ-7",
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER
},
},
// Global controls
// Power control
.keep_cam_switched_on = false,
.gps_on_vbat = 1000, // mV
.gps_off_vbat = 1000, // mV
.gps_onper_vbat = 1000, // mV
.gps_on_vbat = 3800, // mV
.gps_off_vbat = 3600, // mV
.gps_onper_vbat = 4000, // mV
// GPS altitude model control (air pressure determined by 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,
// A pre-set location if GPS never enabled or unable to acquire lock.
.lat = -337331175, // Degrees (expressed in 1e-7 form)
.lon = 1511143478, // Degrees (expressed in 1e-7 form)
.alt = 144, // Altitude in metres
// 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
.base = {
// Tracker originated messages will be addressed to this call sign if enabled
.enabled = true,
.call = "VK2GJ-7",
.path = "WIDE2-1",
},
.magic = CONFIG_MAGIC_DEFAULT // Do not remove. This is the activation bit.
};

Wyświetl plik

@ -1,238 +1,223 @@
#ifndef __TYPES_H__
#define __TYPES_H__
#include "ch.h"
#include "ax25_pad.h"
#include "ublox.h"
typedef enum {
FREQ_RADIO_INVALID = 0,
FREQ_APRS_DYNAMIC, /* Geofencing frequency (144.8 default). */
FREQ_APRS_SCAN, /* Frequency last found in RX scan. - TBI */
FREQ_APRS_RECEIVE, /* Active RX frequency - fall back to DYNAMIC. */
FREQ_CMDC_RECEIVE, /* Frequency used for command and control. TBI */
FREQ_APRS_DEFAULT, /* Default frequency specified in configuration */
FREQ_CODES_END
} freq_codes_t;
#define FREQ_RADIO_INVALID 0
#define FREQ_APRS_DYNAMIC 1 /* Geofencing frequency (144.8 default). */
#define FREQ_APRS_SCAN 2 /* Frequency based on band base + channel scan. */
#define FREQ_APRS_RECEIVE 3 /* Active RX frequency - fall back to DYNAMIC. */
#define FREQ_CMDC_RECEIVE 4 /* Frequency used for command and control. TBI */
#define FREQ_APRS_DEFAULT 5 /* Default frequency specified in configuration */
#define FREQ_CODES_END 6
#define CYCLE_CONTINUOUSLY 0
#define TYPE_NULL 0
#define TYPE_INT 1
#define TYPE_TIME 2
#define TYPE_STR 3
typedef enum {
SLEEP_DISABLED = 0,
SLEEP_WHEN_VBAT_BELOW_THRES,
SLEEP_WHEN_VSOL_BELOW_THRES,
SLEEP_WHEN_VBAT_ABOVE_THRES,
SLEEP_WHEN_VSOL_ABOVE_THRES,
SLEEP_WHEN_DISCHARGING,
SLEEP_WHEN_CHARGING
} sleep_type_t;
typedef struct {
sleep_type_t type;
volt_level_t vbat_thres;
volt_level_t vsol_thres;
} sleep_conf_t;
typedef enum { // Modulation type
MOD_NONE,
MOD_AFSK,
MOD_2FSK
} mod_t;
typedef enum {
RES_NONE = 0,
RES_QQVGA,
RES_QVGA,
RES_VGA,
RES_VGA_ZOOMED,
RES_XGA,
RES_UXGA,
RES_MAX
} resolution_t;
/*typedef union {
radio_squelch_t cca;
radio_squelch_t rssi;
} radio_sq_t;*/
typedef struct {
radio_pwr_t pwr;
radio_freq_t freq;
mod_t mod;
link_speed_t speed;
union {
radio_squelch_t cca;
radio_squelch_t rssi;
};
} radio_conf_t;
typedef struct {
radio_pwr_t pwr;
radio_freq_t freq;
mod_t mod;
link_speed_t speed;
radio_squelch_t cca;
} radio_tx_conf_t; // Radio / Modulation
typedef struct {
radio_freq_t freq;
mod_t mod;
link_speed_t speed;
radio_squelch_t rssi;
} radio_rx_conf_t; // Radio / Modulation
typedef struct {
bool active;
sysinterval_t init_delay;
sysinterval_t send_spacing;
sleep_conf_t sleep_conf;
sysinterval_t cycle; // Cycle time (0: continously)
sysinterval_t duration;
} thread_conf_t; // Thread
typedef struct {
thread_conf_t thread_conf;
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
bool aprs_msg;
sysinterval_t tel_enc_cycle;
} thd_pos_conf_t;
typedef struct {
thread_conf_t thread_conf;
radio_tx_conf_t radio_conf;
bool redundantTx;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
resolution_t res; // Picture resolution
uint8_t quality; // SSDV Quality ranging from 0-7
uint32_t buf_size; // SRAM buffer size for the picture
} thd_img_conf_t;
typedef struct {
thread_conf_t thread_conf;
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
uint8_t density; // Density of log points being sent out in 1/x (value 10 => 10%)
} thd_log_conf_t;
typedef struct {
radio_rx_conf_t radio_conf;
aprs_sym_t symbol;
// Protocol
char call[AX25_MAX_ADDR_LEN];
} thd_rx_conf_t;
typedef struct {
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
} thd_tx_conf_t;
typedef struct {
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
bool enabled;
} thd_base_conf_t;
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;
bool enabled;
bool beacon;
bool gps;
/* gps_coord_t lat;
gps_coord_t lon;
gps_alt_t alt;*/
sysinterval_t cycle; // Beacon interval (0: continously)
sysinterval_t tel_enc_cycle;
} thd_digi_conf_t;
/* APRS configuration. */
typedef struct {
thread_conf_t thread_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;
} thd_aprs_conf_t;
typedef struct {
thd_pos_conf_t pos_pri; // Primary position thread configuration
thd_pos_conf_t pos_sec; // Secondary position thread configuration
thd_img_conf_t img_pri; // Primary image thread configuration
thd_img_conf_t img_sec; // Secondary image thread configuration
thd_log_conf_t log; // Log transmission configuration
thd_aprs_conf_t aprs;
bool keep_cam_switched_on; // Keep camera switched on and initialized, this makes image capturing faster but takes a lot of power over long time
volt_level_t gps_on_vbat; // Battery voltage threshold at which GPS is switched on
volt_level_t gps_off_vbat; // Battery voltage threshold at which GPS is switched off
volt_level_t gps_onper_vbat; // Battery voltage threshold at which GPS is kept switched on all time. This value must be larger
// When gps_on_vbat and gps_off_vbat otherwise this value has no effect. Value 0 disables this feature
uint32_t gps_pressure; // Air pressure below which GPS is switched to airborne mode
gps_hp_model_t gps_low_alt; // Model to use when air pressure is above gps_pa_threshold
gps_lp_model_t gps_high_alt; // Model to use when air pressure is below gps_pa_threshold
// Default lat, lon and alt when GPS is not enabled or not operable
gps_coord_t lat;
gps_coord_t lon;
gps_alt_t alt;
uint32_t magic; // Key that indicates if the flash is loaded or has been updated
uint16_t crc; // CRC to verify content
} conf_t;
typedef struct {
uint8_t type;
char name[64];
size_t size;
void *ptr;
} conf_command_t;
#endif /* __TYPES_H__ */
#ifndef __TYPES_H__
#define __TYPES_H__
#include "ch.h"
#include "ax25_pad.h"
#include "ublox.h"
typedef enum {
FREQ_RADIO_INVALID = 0,
FREQ_APRS_DYNAMIC, /* Geofencing frequency (144.8 default). */
FREQ_APRS_SCAN, /* Frequency last found in RX scan. - TBI */
FREQ_APRS_RECEIVE, /* Active RX frequency - fall back to DYNAMIC. */
FREQ_CMDC_RECEIVE, /* Frequency used for command and control. TBI */
FREQ_APRS_DEFAULT, /* Default frequency specified in configuration */
FREQ_CODES_END
} freq_codes_t;
#define FREQ_RADIO_INVALID 0
#define FREQ_APRS_DYNAMIC 1 /* Geofencing frequency (144.8 default). */
#define FREQ_APRS_SCAN 2 /* Frequency based on band base + channel scan. */
#define FREQ_APRS_RECEIVE 3 /* Active RX frequency - fall back to DYNAMIC. */
#define FREQ_CMDC_RECEIVE 4 /* Frequency used for command and control. TBI */
#define FREQ_APRS_DEFAULT 5 /* Default frequency specified in configuration */
#define FREQ_CODES_END 6
#define CYCLE_CONTINUOUSLY 0
#define TYPE_NULL 0
#define TYPE_INT 1
#define TYPE_TIME 2
#define TYPE_STR 3
typedef enum {
SLEEP_DISABLED = 0,
SLEEP_WHEN_VBAT_BELOW_THRES,
SLEEP_WHEN_VSOL_BELOW_THRES,
SLEEP_WHEN_VBAT_ABOVE_THRES,
SLEEP_WHEN_VSOL_ABOVE_THRES,
SLEEP_WHEN_DISCHARGING,
SLEEP_WHEN_CHARGING
} sleep_type_t;
typedef struct {
sleep_type_t type;
volt_level_t vbat_thres;
volt_level_t vsol_thres;
} sleep_conf_t;
typedef enum { // Modulation type
MOD_NONE,
MOD_AFSK,
MOD_2FSK
} mod_t;
typedef enum {
RES_NONE = 0,
RES_QQVGA,
RES_QVGA,
RES_VGA,
RES_VGA_ZOOMED,
RES_XGA,
RES_UXGA,
RES_MAX
} resolution_t;
typedef struct {
radio_pwr_t pwr;
radio_freq_t freq;
mod_t mod;
link_speed_t speed;
union {
radio_squelch_t cca;
radio_squelch_t rssi;
};
} radio_conf_t;
typedef struct {
radio_pwr_t pwr;
radio_freq_t freq;
mod_t mod;
link_speed_t speed;
radio_squelch_t cca;
} radio_tx_conf_t; // Radio / Modulation
typedef struct {
radio_freq_t freq;
mod_t mod;
link_speed_t speed;
radio_squelch_t rssi;
} radio_rx_conf_t; // Radio / Modulation
typedef struct {
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;
} thread_conf_t; // Thread
typedef struct {
thread_conf_t svc_conf;
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 {
thread_conf_t svc_conf;
radio_tx_conf_t radio_conf;
bool redundantTx;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
resolution_t res; // Picture resolution
uint8_t quality; // SSDV Quality ranging from 0-7
uint32_t buf_size; // SRAM buffer size for the picture
} thd_img_conf_t;
typedef struct {
thread_conf_t svc_conf;
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
uint8_t density; // Density of log points being sent out in 1/x (value 10 => 10%)
} thd_log_conf_t;
typedef struct {
radio_rx_conf_t radio_conf;
aprs_sym_t symbol;
// Protocol
char call[AX25_MAX_ADDR_LEN];
} thd_rx_conf_t;
typedef struct {
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
} thd_tx_conf_t;
typedef struct {
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
bool enabled;
} thd_base_conf_t;
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;
/* 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;
} thd_aprs_conf_t;
typedef struct {
thd_pos_conf_t pos_pri; // Primary position thread configuration
thd_pos_conf_t pos_sec; // Secondary position thread configuration
thd_img_conf_t img_pri; // Primary image thread configuration
thd_img_conf_t img_sec; // Secondary image thread configuration
thd_log_conf_t log; // Log transmission configuration
thd_aprs_conf_t aprs;
bool keep_cam_switched_on; // Keep camera switched on and initialized, this makes image capturing faster but takes a lot of power over long time
volt_level_t gps_on_vbat; // Battery voltage threshold at which GPS is switched on
volt_level_t gps_off_vbat; // Battery voltage threshold at which GPS is switched off
volt_level_t gps_onper_vbat; // Battery voltage threshold at which GPS is kept switched on all time. This value must be larger
// When gps_on_vbat and gps_off_vbat otherwise this value has no effect. Value 0 disables this feature
uint32_t gps_pressure; // Air pressure below which GPS is switched to airborne mode
gps_hp_model_t gps_low_alt; // Model to use when air pressure is above gps_pa_threshold
gps_lp_model_t gps_high_alt; // Model to use when air pressure is below gps_pa_threshold
//APRS global
sysinterval_t tel_enc_cycle; // Cycle for sending of telemetry config headers
radio_freq_t freq; // Default APRS frequency if geolocation not available
// 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;
uint32_t magic; // Key that indicates if the flash is loaded or has been updated
uint16_t crc; // CRC to verify content
} conf_t;
typedef struct {
uint8_t type;
char name[64];
size_t size;
void *ptr;
} conf_command_t;
#endif /* __TYPES_H__ */

Wyświetl plik

@ -647,8 +647,8 @@ radio_freq_t pktGetDefaultOperatingFrequency(const radio_unit_t radio) {
/* FIXME: Default frequency in config to be per radio. */
(void)radio;
/* FIXME: INVALID relies on 0 in conf if no default set. */
if(conf_sram.aprs.freq != FREQ_RADIO_INVALID)
return conf_sram.aprs.freq;
if(conf_sram.freq != FREQ_RADIO_INVALID)
return conf_sram.freq;
else
return DEFAULT_OPERATING_FREQ;
}

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.thread_conf.active), &conf_sram.pos_pri.thread_conf.active },
{TYPE_TIME, "pos_pri.init_delay", sizeof(conf_sram.pos_pri.thread_conf.init_delay), &conf_sram.pos_pri.thread_conf.init_delay },
{TYPE_INT, "pos_pri.sleep_conf.type", sizeof(conf_sram.pos_pri.thread_conf.sleep_conf.type), &conf_sram.pos_pri.thread_conf.sleep_conf.type },
{TYPE_INT, "pos_pri.sleep_conf.vbat_thres", sizeof(conf_sram.pos_pri.thread_conf.sleep_conf.vbat_thres), &conf_sram.pos_pri.thread_conf.sleep_conf.vbat_thres},
{TYPE_INT, "pos_pri.sleep_conf.vsol_thres", sizeof(conf_sram.pos_pri.thread_conf.sleep_conf.vsol_thres), &conf_sram.pos_pri.thread_conf.sleep_conf.vsol_thres},
{TYPE_TIME, "pos_pri.cycle", sizeof(conf_sram.pos_pri.thread_conf.cycle), &conf_sram.pos_pri.thread_conf.cycle },
{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.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 },
@ -57,14 +57,13 @@ const conf_command_t command_list[] = {
{TYPE_STR, "pos_pri.path", sizeof(conf_sram.pos_pri.path), &conf_sram.pos_pri.path },
{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_TIME, "pos_pri.tel_enc_cycle", sizeof(conf_sram.pos_pri.tel_enc_cycle), &conf_sram.pos_pri.tel_enc_cycle },
{TYPE_INT, "pos_sec.active", sizeof(conf_sram.pos_sec.thread_conf.active), &conf_sram.pos_sec.thread_conf.active },
{TYPE_TIME, "pos_sec.init_delay", sizeof(conf_sram.pos_sec.thread_conf.init_delay), &conf_sram.pos_sec.thread_conf.init_delay },
{TYPE_INT, "pos_sec.sleep_conf.type", sizeof(conf_sram.pos_sec.thread_conf.sleep_conf.type), &conf_sram.pos_sec.thread_conf.sleep_conf.type },
{TYPE_INT, "pos_sec.sleep_conf.vbat_thres", sizeof(conf_sram.pos_sec.thread_conf.sleep_conf.vbat_thres), &conf_sram.pos_sec.thread_conf.sleep_conf.vbat_thres},
{TYPE_INT, "pos_sec.sleep_conf.vsol_thres", sizeof(conf_sram.pos_sec.thread_conf.sleep_conf.vsol_thres), &conf_sram.pos_sec.thread_conf.sleep_conf.vsol_thres},
{TYPE_TIME, "pos_sec.cycle", sizeof(conf_sram.pos_sec.thread_conf.cycle), &conf_sram.pos_sec.thread_conf.cycle },
{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.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 },
@ -73,15 +72,14 @@ const conf_command_t command_list[] = {
{TYPE_STR, "pos_sec.path", sizeof(conf_sram.pos_sec.path), &conf_sram.pos_sec.path },
{TYPE_INT, "pos_sec.symbol", sizeof(conf_sram.pos_sec.symbol), &conf_sram.pos_sec.symbol },
{TYPE_INT, "pos_sec.aprs_msg", sizeof(conf_sram.pos_sec.aprs_msg), &conf_sram.pos_sec.aprs_msg },
{TYPE_TIME, "pos_sec.tel_enc_cycle", sizeof(conf_sram.pos_sec.tel_enc_cycle), &conf_sram.pos_sec.tel_enc_cycle },
{TYPE_INT, "img_pri.active", sizeof(conf_sram.img_pri.thread_conf.active), &conf_sram.img_pri.thread_conf.active },
{TYPE_TIME, "img_pri.init_delay", sizeof(conf_sram.img_pri.thread_conf.init_delay), &conf_sram.img_pri.thread_conf.init_delay },
{TYPE_TIME, "img_pri.send_spacing", sizeof(conf_sram.img_pri.thread_conf.send_spacing), &conf_sram.img_pri.thread_conf.send_spacing },
{TYPE_INT, "img_pri.sleep_conf.type", sizeof(conf_sram.img_pri.thread_conf.sleep_conf.type), &conf_sram.img_pri.thread_conf.sleep_conf.type },
{TYPE_INT, "img_pri.sleep_conf.vbat_thres", sizeof(conf_sram.img_pri.thread_conf.sleep_conf.vbat_thres), &conf_sram.img_pri.thread_conf.sleep_conf.vbat_thres},
{TYPE_INT, "img_pri.sleep_conf.vsol_thres", sizeof(conf_sram.img_pri.thread_conf.sleep_conf.vsol_thres), &conf_sram.img_pri.thread_conf.sleep_conf.vsol_thres},
{TYPE_TIME, "img_pri.cycle", sizeof(conf_sram.img_pri.thread_conf.cycle), &conf_sram.img_pri.thread_conf.cycle },
{TYPE_INT, "img_pri.active", sizeof(conf_sram.img_pri.svc_conf.active), &conf_sram.img_pri.svc_conf.active },
{TYPE_TIME, "img_pri.init_delay", sizeof(conf_sram.img_pri.svc_conf.init_delay), &conf_sram.img_pri.svc_conf.init_delay },
{TYPE_TIME, "img_pri.send_spacing", sizeof(conf_sram.img_pri.svc_conf.send_spacing), &conf_sram.img_pri.svc_conf.send_spacing },
{TYPE_INT, "img_pri.sleep_conf.type", sizeof(conf_sram.img_pri.svc_conf.sleep_conf.type), &conf_sram.img_pri.svc_conf.sleep_conf.type },
{TYPE_INT, "img_pri.sleep_conf.vbat_thres", sizeof(conf_sram.img_pri.svc_conf.sleep_conf.vbat_thres), &conf_sram.img_pri.svc_conf.sleep_conf.vbat_thres },
{TYPE_INT, "img_pri.sleep_conf.vsol_thres", sizeof(conf_sram.img_pri.svc_conf.sleep_conf.vsol_thres), &conf_sram.img_pri.svc_conf.sleep_conf.vsol_thres },
{TYPE_TIME, "img_pri.cycle", sizeof(conf_sram.img_pri.svc_conf.cycle), &conf_sram.img_pri.svc_conf.cycle },
{TYPE_INT, "img_pri.pwr", sizeof(conf_sram.img_pri.radio_conf.pwr), &conf_sram.img_pri.radio_conf.pwr },
{TYPE_INT, "img_pri.freq", sizeof(conf_sram.img_pri.radio_conf.freq), &conf_sram.img_pri.radio_conf.freq },
{TYPE_INT, "img_pri.mod", sizeof(conf_sram.img_pri.radio_conf.mod), &conf_sram.img_pri.radio_conf.mod },
@ -94,13 +92,13 @@ const conf_command_t command_list[] = {
{TYPE_INT, "img_pri.quality", sizeof(conf_sram.img_pri.quality), &conf_sram.img_pri.quality },
{TYPE_INT, "img_pri.buf_size", sizeof(conf_sram.img_pri.buf_size), &conf_sram.img_pri.buf_size },
{TYPE_INT, "img_sec.active", sizeof(conf_sram.img_sec.thread_conf.active), &conf_sram.img_sec.thread_conf.active },
{TYPE_TIME, "img_sec.init_delay", sizeof(conf_sram.img_sec.thread_conf.init_delay), &conf_sram.img_sec.thread_conf.init_delay },
{TYPE_TIME, "img_sec.send_spacing", sizeof(conf_sram.img_sec.thread_conf.send_spacing), &conf_sram.img_sec.thread_conf.send_spacing },
{TYPE_INT, "img_sec.sleep_conf.type", sizeof(conf_sram.img_sec.thread_conf.sleep_conf.type), &conf_sram.img_sec.thread_conf.sleep_conf.type },
{TYPE_INT, "img_sec.sleep_conf.vbat_thres", sizeof(conf_sram.img_sec.thread_conf.sleep_conf.vbat_thres), &conf_sram.img_sec.thread_conf.sleep_conf.vbat_thres},
{TYPE_INT, "img_sec.sleep_conf.vsol_thres", sizeof(conf_sram.img_sec.thread_conf.sleep_conf.vsol_thres), &conf_sram.img_sec.thread_conf.sleep_conf.vsol_thres},
{TYPE_TIME, "img_sec.cycle", sizeof(conf_sram.img_sec.thread_conf.cycle), &conf_sram.img_sec.thread_conf.cycle },
{TYPE_INT, "img_sec.active", sizeof(conf_sram.img_sec.svc_conf.active), &conf_sram.img_sec.svc_conf.active },
{TYPE_TIME, "img_sec.init_delay", sizeof(conf_sram.img_sec.svc_conf.init_delay), &conf_sram.img_sec.svc_conf.init_delay },
{TYPE_TIME, "img_sec.send_spacing", sizeof(conf_sram.img_sec.svc_conf.send_spacing), &conf_sram.img_sec.svc_conf.send_spacing },
{TYPE_INT, "img_sec.sleep_conf.type", sizeof(conf_sram.img_sec.svc_conf.sleep_conf.type), &conf_sram.img_sec.svc_conf.sleep_conf.type },
{TYPE_INT, "img_sec.sleep_conf.vbat_thres", sizeof(conf_sram.img_sec.svc_conf.sleep_conf.vbat_thres), &conf_sram.img_sec.svc_conf.sleep_conf.vbat_thres },
{TYPE_INT, "img_sec.sleep_conf.vsol_thres", sizeof(conf_sram.img_sec.svc_conf.sleep_conf.vsol_thres), &conf_sram.img_sec.svc_conf.sleep_conf.vsol_thres },
{TYPE_TIME, "img_sec.cycle", sizeof(conf_sram.img_sec.svc_conf.cycle), &conf_sram.img_sec.svc_conf.cycle },
{TYPE_INT, "img_sec.pwr", sizeof(conf_sram.img_sec.radio_conf.pwr), &conf_sram.img_sec.radio_conf.pwr },
{TYPE_INT, "img_sec.freq", sizeof(conf_sram.img_sec.radio_conf.freq), &conf_sram.img_sec.radio_conf.freq },
{TYPE_INT, "img_sec.mod", sizeof(conf_sram.img_sec.radio_conf.mod), &conf_sram.img_sec.radio_conf.mod },
@ -113,13 +111,13 @@ const conf_command_t command_list[] = {
{TYPE_INT, "img_sec.quality", sizeof(conf_sram.img_sec.quality), &conf_sram.img_sec.quality },
{TYPE_INT, "img_sec.buf_size", sizeof(conf_sram.img_sec.buf_size), &conf_sram.img_sec.buf_size },
{TYPE_INT, "log.active", sizeof(conf_sram.log.thread_conf.active), &conf_sram.log.thread_conf.active },
{TYPE_TIME, "log.init_delay", sizeof(conf_sram.log.thread_conf.init_delay), &conf_sram.log.thread_conf.init_delay },
{TYPE_TIME, "log.send_spacing", sizeof(conf_sram.log.thread_conf.send_spacing), &conf_sram.log.thread_conf.send_spacing },
{TYPE_INT, "log.sleep_conf.type", sizeof(conf_sram.log.thread_conf.sleep_conf.type), &conf_sram.log.thread_conf.sleep_conf.type },
{TYPE_INT, "log.sleep_conf.vbat_thres", sizeof(conf_sram.log.thread_conf.sleep_conf.vbat_thres), &conf_sram.log.thread_conf.sleep_conf.vbat_thres },
{TYPE_INT, "log.sleep_conf.vsol_thres", sizeof(conf_sram.log.thread_conf.sleep_conf.vsol_thres), &conf_sram.log.thread_conf.sleep_conf.vsol_thres },
{TYPE_TIME, "log.cycle", sizeof(conf_sram.log.thread_conf.cycle), &conf_sram.log.thread_conf.cycle },
{TYPE_INT, "log.active", sizeof(conf_sram.log.svc_conf.active), &conf_sram.log.svc_conf.active },
{TYPE_TIME, "log.init_delay", sizeof(conf_sram.log.svc_conf.init_delay), &conf_sram.log.svc_conf.init_delay },
{TYPE_TIME, "log.send_spacing", sizeof(conf_sram.log.svc_conf.send_spacing), &conf_sram.log.svc_conf.send_spacing },
{TYPE_INT, "log.sleep_conf.type", sizeof(conf_sram.log.svc_conf.sleep_conf.type), &conf_sram.log.svc_conf.sleep_conf.type },
{TYPE_INT, "log.sleep_conf.vbat_thres", sizeof(conf_sram.log.svc_conf.sleep_conf.vbat_thres), &conf_sram.log.svc_conf.sleep_conf.vbat_thres },
{TYPE_INT, "log.sleep_conf.vsol_thres", sizeof(conf_sram.log.svc_conf.sleep_conf.vsol_thres), &conf_sram.log.svc_conf.sleep_conf.vsol_thres },
{TYPE_TIME, "log.cycle", sizeof(conf_sram.log.svc_conf.cycle), &conf_sram.log.svc_conf.cycle },
{TYPE_INT, "log.pwr", sizeof(conf_sram.log.radio_conf.pwr), &conf_sram.log.radio_conf.pwr },
{TYPE_INT, "log.freq", sizeof(conf_sram.log.radio_conf.freq), &conf_sram.log.radio_conf.freq },
{TYPE_INT, "log.mod", sizeof(conf_sram.log.radio_conf.mod), &conf_sram.log.radio_conf.mod },
@ -129,20 +127,15 @@ 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.thread_conf.active), &conf_sram.aprs.thread_conf.active },
{TYPE_TIME, "aprs.init_delay", sizeof(conf_sram.aprs.thread_conf.init_delay), &conf_sram.aprs.thread_conf.init_delay },
{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.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.base.freq", sizeof(conf_sram.aprs.base.radio_conf.freq), &conf_sram.aprs.base.radio_conf.freq },
{TYPE_INT, "aprs.base.pwr", sizeof(conf_sram.aprs.base.radio_conf.pwr), &conf_sram.aprs.base.radio_conf.pwr },
{TYPE_INT, "aprs.base.mod", sizeof(conf_sram.aprs.base.radio_conf.mod), &conf_sram.aprs.base.radio_conf.mod },
{TYPE_INT, "aprs.base.cca", sizeof(conf_sram.aprs.base.radio_conf.cca), &conf_sram.aprs.base.radio_conf.cca },
{TYPE_STR, "aprs.base.call", sizeof(conf_sram.aprs.base.call), &conf_sram.aprs.base.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 },
@ -150,14 +143,13 @@ const conf_command_t command_list[] = {
{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), &conf_sram.aprs.digi.beacon },
{TYPE_INT, "aprs.digi.gps", sizeof(conf_sram.aprs.digi.gps), &conf_sram.aprs.digi.gps },
{TYPE_INT, "lat", sizeof(conf_sram.lat), &conf_sram.lat },
{TYPE_INT, "lon", sizeof(conf_sram.lon), &conf_sram.lon },
{TYPE_INT, "alt", sizeof(conf_sram.alt), &conf_sram.alt },
{TYPE_INT, "aprs.digi.cycle", sizeof(conf_sram.aprs.digi.cycle), &conf_sram.aprs.digi.cycle },
{TYPE_INT, "aprs.digi.digi_active", sizeof(conf_sram.aprs.digi.active), &conf_sram.aprs.digi.active },
{TYPE_INT, "aprs.freq", sizeof(conf_sram.aprs.freq), &conf_sram.aprs.freq },
{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.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, "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 },
{TYPE_INT, "gps_off_vbat", sizeof(conf_sram.gps_off_vbat), &conf_sram.gps_off_vbat },
@ -166,6 +158,16 @@ const conf_command_t command_list[] = {
{TYPE_INT, "gps_low_alt", sizeof(conf_sram.gps_low_alt), &conf_sram.gps_low_alt },
{TYPE_INT, "gps_high_alt", sizeof(conf_sram.gps_high_alt), &conf_sram.gps_high_alt },
{TYPE_INT, "default.freq", sizeof(conf_sram.freq), &conf_sram.freq },
{TYPE_INT, "base.freq", sizeof(conf_sram.base.radio_conf.freq), &conf_sram.base.radio_conf.freq },
{TYPE_INT, "base.pwr", sizeof(conf_sram.base.radio_conf.pwr), &conf_sram.base.radio_conf.pwr },
{TYPE_INT, "base.mod", sizeof(conf_sram.base.radio_conf.mod), &conf_sram.base.radio_conf.mod },
{TYPE_INT, "base.cca", sizeof(conf_sram.base.radio_conf.cca), &conf_sram.base.radio_conf.cca },
{TYPE_STR, "base.call", sizeof(conf_sram.base.call), &conf_sram.base.call },
{TYPE_TIME, "tel_enc_cycle", sizeof(conf_sram.tel_enc_cycle), &conf_sram.tel_enc_cycle },
{TYPE_NULL}
};
@ -1136,7 +1138,7 @@ static bool aprs_decode_message(packet_t pp) {
/* 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.thread_conf.active);
&& (conf_sram.pos_pri.svc_conf.active);
if(pos_pri) {
strcpy(identity.call, conf_sram.pos_pri.call);
@ -1146,7 +1148,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.thread_conf.active);
&& (conf_sram.pos_sec.svc_conf.active);
if(pos_sec) {
strcpy(identity.call, conf_sram.pos_sec.call);
strcpy(identity.path, conf_sram.pos_sec.path);
@ -1154,7 +1156,7 @@ static bool aprs_decode_message(packet_t pp) {
}
bool aprs_rx = (strcmp(conf_sram.aprs.rx.call, dest) == 0)
&& (conf_sram.aprs.thread_conf.active);
&& (conf_sram.aprs.svc_conf.active);
if(aprs_rx) {
strcpy(identity.call, conf_sram.aprs.rx.call);
identity.symbol = conf_sram.aprs.rx.symbol;
@ -1163,7 +1165,7 @@ 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.thread_conf.active)
&& (conf_sram.aprs.svc_conf.active)
/*&& (conf_sram.aprs.digi.active)*/;
/* Default already set tx parameters. */

Wyświetl plik

@ -31,10 +31,17 @@
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;
/*===========================================================================*/
/* Module external variables. */
/*===========================================================================*/
thread_t *collector_thd;
/**
* Returns most recent data point which is complete.
*/
@ -45,11 +52,11 @@ dataPoint_t* getLastDataPoint(void) {
/**
*
*/
void waitForNewDataPoint(void) {
/*void waitForNewDataPoint(void) {
uint32_t old_id = getLastDataPoint()->id;
while(old_id == getLastDataPoint()->id)
chThdSleep(TIME_S2I(1));
}
}*/
/**
* @brief Determine best fallback data when GPS not operable.
@ -107,8 +114,7 @@ static void aquirePosition(dataPoint_t* tp, dataPoint_t* ltp,
gpsFix_t gpsFix = {0};
/*
* Switch on GPS if...
* position/time is requested by a service and power is available.
* Is there enough battery voltage for GPS?
*/
uint16_t batt = stm32_get_vbat();
if(batt < conf_sram.gps_on_vbat) {
@ -144,8 +150,8 @@ static void aquirePosition(dataPoint_t* tp, dataPoint_t* ltp,
if(batt < conf_sram.gps_off_vbat) {
/*
* GPS was switched on but battery fell below threshold.
* Switch off GPS.
* GPS was switched on but battery fell below threshold during acquisition.
* Switch off GPS and get fallback position data.
*/
GPS_Deinit();
@ -156,7 +162,7 @@ static void aquirePosition(dataPoint_t* tp, dataPoint_t* ltp,
}
if(!isGPSLocked(&gpsFix)) {
/*
* GPS was switched on but it failed to get a lock in timeout period.
* GPS was switched on but it failed to get a lock within timeout period.
* Keep GPS switched on.
*/
TRACE_WARN("COLL > GPS sampling finished GPS LOSS");
@ -190,8 +196,10 @@ static void aquirePosition(dataPoint_t* tp, dataPoint_t* ltp,
if(timeout < TIME_S2I(60)) {
TRACE_INFO("COLL > Keep GPS switched on because cycle < 60sec");
tp->gps_state = GPS_LOCKED2;
} else if(conf_sram.gps_onper_vbat != 0 && batt >= conf_sram.gps_onper_vbat) {
TRACE_INFO("COLL > Keep GPS switched on because VBAT >= %dmV", conf_sram.gps_onper_vbat);
} else if(conf_sram.gps_onper_vbat != 0
&& batt >= conf_sram.gps_onper_vbat) {
TRACE_INFO("COLL > Keep GPS switched on because VBAT >= %dmV",
conf_sram.gps_onper_vbat);
tp->gps_state = GPS_LOCKED2;
} else {
TRACE_INFO("COLL > Switching off GPS");
@ -441,18 +449,20 @@ THD_FUNCTION(collectorThread, arg) {
// Determine cycle time and if GPS should be used.
sysinterval_t data_cycle_time = TIME_S2I(600); // Default.
if(conf_sram.pos_pri.thread_conf.active && conf_sram.pos_sec.thread_conf.active) { // Both position threads are active
data_cycle_time = conf_sram.pos_pri.thread_conf.cycle < conf_sram.pos_sec.thread_conf.cycle ? conf_sram.pos_pri.thread_conf.cycle : conf_sram.pos_sec.thread_conf.cycle; // Choose the smallest cycle
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.thread_conf.active) { // Only primary position thread is active
data_cycle_time = conf_sram.pos_pri.thread_conf.cycle;
} 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.thread_conf.active) { // Only secondary position thread is active
data_cycle_time = conf_sram.pos_sec.thread_conf.cycle;
} 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.thread_conf.active && conf_sram.aprs.digi.beacon) { // DIGI beacon is active
data_cycle_time = conf_sram.aprs.digi.cycle;
if(conf_sram.aprs.digi.gps) {
} 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
@ -495,7 +505,7 @@ THD_FUNCTION(collectorThread, arg) {
continue;
}
TRACE_INFO("COLL > Time acquired from GPS");
/* Switch GPS off. */
/* Switch GPS off since there are no other users. */
GPS_Deinit();
}
@ -513,9 +523,9 @@ THD_FUNCTION(collectorThread, arg) {
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_alt = conf_sram.alt;
//tp->gps_lat = conf_sram.lat;
//tp->gps_lon = conf_sram.lon;
tp->gps_state = GPS_FIXED;
}
@ -556,7 +566,6 @@ THD_FUNCTION(collectorThread, arg) {
* Any thread sending telemetry would request this service be started.
*/
THD_FUNCTION(configThread, arg) {
//uint8_t *useCFG = arg;
(void)arg;
while(true) chThdSleep(TIME_S2I(1));
}
@ -566,9 +575,167 @@ THD_FUNCTION(configThread, arg) {
* TODO: To provide GPS status and data.
*/
THD_FUNCTION(gpsThread, arg) {
//uint8_t *useCFG = arg;
(void)arg;
while(true) chThdSleep(TIME_S2I(1));
uint32_t id = 0;
//msg_t result;
// Read time from RTC
ptime_t time;
getTime(&time);
dataPoints[0].gps_time = date2UnixTimestamp(&time);
dataPoints[1].gps_time = date2UnixTimestamp(&time);
lastDataPoint = &dataPoints[0];
dataPoint_t *newDataPoint = lastDataPoint++;
// 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
//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
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();
// Determine cycle time and if GPS should be used.
sysinterval_t data_cycle_time = TIME_S2I(600); // Default.
getTime(&time);
if(time.year == RTC_BASE_YEAR) {
/*
* The RTC is not set.
* Enable the GPS and attempt a lock which results in setting the RTC.
*/
TRACE_INFO("COLL > Acquire time using GPS");
aquirePosition(newDataPoint, lastDataPoint, data_cycle_time - TIME_S2I(3));
/* RTC is set in aquirePosition(...). */
if(hasGPSacquiredLock(newDataPoint)) {
/* Acquisition succeeded. */
TRACE_INFO("COLL > Time acquisition from GPS succeeded");
/* Update with freshly acquired data. */
lastDataPoint = newDataPoint;
GPS_Deinit();
//result = MSG_OK;
} else {
TRACE_INFO("COLL > Time not acquired from GPS");
//result = MSG_TIMEOUT;
}
}
while(true) { /* Primary loop. */
/* Wait for a request from a client. */
thread_t *caller = chMsgWait();
/* Fetch the message. */
thd_pos_conf_t *config;
config = (thd_pos_conf_t *)chMsgGet(caller);
TRACE_INFO("COLL > Respond to request for 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
/* Clear remnant data. */
memset(tp, 0, sizeof(dataPoint_t));
/* Gather telemetry and system status data. */
measureVoltage(tp);
getSensors(tp);
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 {
/*
* Update datapoint time from RTC.
* Set fixed location.
*/
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_state = GPS_FIXED;
//result = MSG_OK;
}
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;
/* Reply to the calling thread. */
chMsgRelease(caller, (msg_t)tp);
}
}
/**
@ -578,7 +745,7 @@ 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),
@ -591,7 +758,9 @@ 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),
@ -615,6 +784,7 @@ void init_data_collector() {
TRACE_ERROR("GPS > Could not start"
" thread (not enough memory available)");
} else {
collector_thd = th;
chThdSleep(TIME_MS2I(300));
}
}

Wyświetl plik

@ -1,139 +1,148 @@
#ifndef __COLLECTOR_H__
#define __COLLECTOR_H__
#include "ch.h"
#include "hal.h"
#include "ptime.h"
#define BME_STATUS_BITS 2
#define BME_STATUS_MASK 0x3
#define BME_OK_VALUE 0x0
#define BME_FAIL_VALUE 0x1
#define BME_NOT_FITTED_VALUE 0x2
#define BME_ALL_STATUS_MASK 0x3F
#define BME_ALL_STATUS_SHIFT 8
#define BMEI1_STATUS_SHIFT BME_ALL_STATUS_SHIFT
#define BMEI1_STATUS_MASK (BME_STATUS_MASK << BMEI1_STATUS_SHIFT)
#define BMEE1_STATUS_SHIFT BMEI1_STATUS_SHIFT + BME_STATUS_BITS
#define BMEE1_STATUS_MASK (BME_STATUS_MASK << BMEE1_STATUS_SHIFT)
#define BMEE2_STATUS_SHIFT BMEI1_STATUS_SHIFT + BME_STATUS)BITS
#define BMEE2_STATUS_MASK (BME_STATUS_MASK << BMEE2_STATUS_SHIFT)
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
GPS_LOSS, // The GPS was switched on all time but it couln't acquire a fix
GPS_LOWBATT1, // The GPS wasn't switched on because the battery has not enough energy
GPS_LOWBATT2, // The GPS was switched on but has been switched off prematurely while the battery has not enough energy (or is too cold)
GPS_LOG, // The tracker has just been switched on and the position has been taken from the log
GPS_OFF, // There was no prior acquisition by GPS
GPS_ERROR, // The GPS has a communication error
GPS_FIXED // Fixed location data used from APRS location
} gpsState_t;
typedef struct {
// Voltage and current measurement
uint16_t adc_vsol; // Current solar voltage in mV
uint16_t adc_vbat; // Current battery voltage in mV
uint16_t pac_vsol;
uint16_t pac_vbat;
int16_t pac_pbat;
int16_t pac_psol;
uint16_t light_intensity;
// GPS
gpsState_t gps_state; // GPS state
uint8_t gps_sats; // Satellites used for solution
uint8_t gps_ttff; // Time to first fix in seconds
uint8_t gps_pdop; // Position DOP in 0.05 per arbitrary unit
uint16_t gps_alt; // Altitude in meter
int32_t gps_lat; // Latitude in 10^(-7)° per unit
int32_t gps_lon; // Longitude in 10^(-7)° per unit
// BME280 (on board i1 + off board e1 & e2)
uint32_t sen_i1_press; // Airpressure in Pa*10 (in 0.1Pa)
uint32_t sen_e1_press; // Airpressure in Pa*10 (in 0.1Pa)
uint32_t sen_e2_press; // Airpressure in Pa*10 (in 0.1Pa)
int16_t sen_i1_temp; // Temperature in 0.01°C per unit
int16_t sen_e1_temp; // Temperature in 0.01°C per unit
int16_t sen_e2_temp; // Temperature in 0.01°C per unit
uint8_t sen_i1_hum; // Rel. humidity in %
uint8_t sen_e1_hum; // Rel. humidity in %
uint8_t sen_e2_hum; // Rel. humidity in %
uint8_t dummy2;
int16_t stm32_temp;
int16_t si446x_temp;
uint16_t reset;
uint32_t id; // Serial ID
uint32_t gps_time; // GPS time
uint32_t sys_time; // System time (in seconds)
uint32_t sys_error; // System error flags
/*
* Set system errors.
*
* Bit usage:
* - 0:1 I2C status
* - 2:2 GPS status
* - 3:4 pac1720 status
* - 5:7 OV5640 status
* - 8:9 BMEi1 status (0 = OK, 1 = Fail, 2 = Not fitted)
* - 10:11 BMEe1 status (0 = OK, 1 = Fail, 2 = Not fitted)
* - 12:13 BMEe2 status (0 = OK, 1 = Fail, 2 = Not fitted)
*/
uint8_t gpio; // GPIO states
} dataPoint_t;
void waitForNewDataPoint(void);
dataPoint_t* getLastDataPoint(void);
void getSensors(dataPoint_t* tp);
void setSystemStatus(dataPoint_t* tp);
void init_data_collector(void);
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Has GPS achieved lock (even if now switched off).
*
* @param[in] pointer to data point
*
* @returns result of check
* @retval true if lock has been achieved
* @retval false if lock has not yet been achieved
*
* @api
*/
#define hasGPSacquiredLock(dp) (dp->gps_state == GPS_LOCKED1 \
|| dp->gps_state == GPS_LOCKED2)
/**
* @brief Is position valid.
*
* @param[in] pointer to data point
*
* @returns result of check
* @retval true if position data is valid
* @retval false if position not valid
*
* @api
*/
#define isPositionValid(dp) (dp->gps_state == GPS_LOCKED1 \
|| dp->gps_state == GPS_LOCKED2 \
|| dp->gps_state == GPS_FIXED \
|| dp->gps_state == GPS_LOG)
#endif /* __COLLECTOR_H__ */
#ifndef __COLLECTOR_H__
#define __COLLECTOR_H__
#include "ch.h"
#include "hal.h"
#include "ptime.h"
#include "types.h"
#define BME_STATUS_BITS 2
#define BME_STATUS_MASK 0x3
#define BME_OK_VALUE 0x0
#define BME_FAIL_VALUE 0x1
#define BME_NOT_FITTED_VALUE 0x2
#define BME_ALL_STATUS_MASK 0x3F
#define BME_ALL_STATUS_SHIFT 8
#define BMEI1_STATUS_SHIFT BME_ALL_STATUS_SHIFT
#define BMEI1_STATUS_MASK (BME_STATUS_MASK << BMEI1_STATUS_SHIFT)
#define BMEE1_STATUS_SHIFT BMEI1_STATUS_SHIFT + BME_STATUS_BITS
#define BMEE1_STATUS_MASK (BME_STATUS_MASK << BMEE1_STATUS_SHIFT)
#define BMEE2_STATUS_SHIFT BMEI1_STATUS_SHIFT + BME_STATUS)BITS
#define BMEE2_STATUS_MASK (BME_STATUS_MASK << BMEE2_STATUS_SHIFT)
#define USE_NEW_COLLECTOR TRUE
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
GPS_LOSS, // The GPS was switched on all time but it couln't acquire a fix
GPS_LOWBATT1, // The GPS wasn't switched on because the battery has not enough energy
GPS_LOWBATT2, // The GPS was switched on but has been switched off prematurely while the battery has not enough energy (or is too cold)
GPS_LOG, // The tracker has just been switched on and the position has been taken from the log
GPS_OFF, // There was no prior acquisition by GPS
GPS_ERROR, // The GPS has a communication error
GPS_FIXED // Fixed location data used from APRS location
} gpsState_t;
typedef struct {
// Voltage and current measurement
uint16_t adc_vsol; // Current solar voltage in mV
uint16_t adc_vbat; // Current battery voltage in mV
uint16_t pac_vsol;
uint16_t pac_vbat;
int16_t pac_pbat;
int16_t pac_psol;
uint16_t light_intensity;
// GPS
gpsState_t gps_state; // GPS state
uint8_t gps_sats; // Satellites used for solution
uint8_t gps_ttff; // Time to first fix in seconds
uint8_t gps_pdop; // Position DOP in 0.05 per arbitrary unit
uint16_t gps_alt; // Altitude in meter
int32_t gps_lat; // Latitude in 10^(-7)° per unit
int32_t gps_lon; // Longitude in 10^(-7)° per unit
// BME280 (on board i1 + off board e1 & e2)
uint32_t sen_i1_press; // Airpressure in Pa*10 (in 0.1Pa)
uint32_t sen_e1_press; // Airpressure in Pa*10 (in 0.1Pa)
uint32_t sen_e2_press; // Airpressure in Pa*10 (in 0.1Pa)
int16_t sen_i1_temp; // Temperature in 0.01°C per unit
int16_t sen_e1_temp; // Temperature in 0.01°C per unit
int16_t sen_e2_temp; // Temperature in 0.01°C per unit
uint8_t sen_i1_hum; // Rel. humidity in %
uint8_t sen_e1_hum; // Rel. humidity in %
uint8_t sen_e2_hum; // Rel. humidity in %
uint8_t dummy2;
int16_t stm32_temp;
int16_t si446x_temp;
uint16_t reset;
uint32_t id; // Serial ID
uint32_t gps_time; // GPS time
uint32_t sys_time; // System time (in seconds)
uint32_t sys_error; // System error flags
/*
* Set system errors.
*
* Bit usage:
* - 0:1 I2C status
* - 2:2 GPS status
* - 3:4 pac1720 status
* - 5:7 OV5640 status
* - 8:9 BMEi1 status (0 = OK, 1 = Fail, 2 = Not fitted)
* - 10:11 BMEe1 status (0 = OK, 1 = Fail, 2 = Not fitted)
* - 12:13 BMEe2 status (0 = OK, 1 = Fail, 2 = Not fitted)
*/
uint8_t gpio; // GPIO states
} dataPoint_t;
/*typedef struct telemRequest {
dataPoint_t dp;
thd_pos_conf_t *conf;
} telem_request_t;*/
//void waitForNewDataPoint(void);
dataPoint_t* getLastDataPoint(void);
void getSensors(dataPoint_t* tp);
void setSystemStatus(dataPoint_t* tp);
void init_data_collector(void);
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @brief Has GPS achieved lock (even if now switched off).
*
* @param[in] pointer to data point
*
* @returns result of check
* @retval true if lock has been achieved
* @retval false if lock has not yet been achieved
*
* @api
*/
#define hasGPSacquiredLock(dp) (dp->gps_state == GPS_LOCKED1 \
|| dp->gps_state == GPS_LOCKED2)
/**
* @brief Is position valid.
*
* @param[in] pointer to data point
*
* @returns result of check
* @retval true if position data is valid
* @retval false if position not valid
*
* @api
*/
#define isPositionValid(dp) (dp->gps_state == GPS_LOCKED1 \
|| dp->gps_state == GPS_LOCKED2 \
|| dp->gps_state == GPS_FIXED \
|| dp->gps_state == GPS_LOG)
#endif /* __COLLECTOR_H__ */

Wyświetl plik

@ -1,157 +1,177 @@
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "threads.h"
#include "config.h"
#include "radio.h"
#include "aprs.h"
#include "sleep.h"
#include "chprintf.h"
#include <string.h>
#include <math.h>
#include "watchdog.h"
/*
*
*/
THD_FUNCTION(bcnThread, arg) {
thd_aprs_conf_t* conf = (thd_aprs_conf_t *)arg;
// Wait
if(conf->thread_conf.init_delay) chThdSleep(conf->thread_conf.init_delay);
// Start data collector (if not running yet)
init_data_collector();
// Start position thread
TRACE_INFO("BCN > Startup beacon thread");
// Set telemetry configuration transmission variables
sysinterval_t last_conf_transmission =
chVTGetSystemTime() - conf->digi.tel_enc_cycle;
sysinterval_t time = chVTGetSystemTime();
while(true) {
char code_s[100];
pktDisplayFrequencyCode(conf->digi.radio_conf.freq,
code_s, sizeof(code_s));
TRACE_INFO("POS > Do module BEACON cycle for %s on %s",
conf->digi.call, code_s);
dataPoint_t* dataPoint = getLastDataPoint();
if(!p_sleep(&conf->thread_conf.sleep_conf)) {
// Telemetry encoding parameter transmissions
if(conf->digi.tel_enc_cycle != 0 && last_conf_transmission
+ conf->digi.tel_enc_cycle < chVTGetSystemTime()) {
TRACE_INFO("BCN > Transmit telemetry configuration");
// 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,
type);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects for"
" telemetry config transmission");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.radio_conf.cca)) {
TRACE_ERROR("BCN > Failed to transmit telemetry config");
}
}
chThdSleep(TIME_S2I(5));
}
last_conf_transmission += conf->digi.tel_enc_cycle;
}
while(!isPositionValid(dataPoint)) {
TRACE_INFO("BCN > Waiting for position data for beacon");
chThdSleep(TIME_S2I(60));
continue;
}
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,
dataPoint, true);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects"
" for position transmission");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.radio_conf.cca)) {
TRACE_ERROR("BCN > failed to transmit beacon data");
}
chThdSleep(TIME_S2I(5));
}
TRACE_INFO("BCN > Transmit recently heard direct");
/*
* Encode/Transmit APRSD packet.
* This is a tracker originated message (not a reply to a request).
* The message will be addressed to the base station if set.
* Else send it to device identity.
*/
char *call = conf_sram.aprs.base.enabled
? conf_sram.aprs.base.call : conf->digi.call;
/*
* Send message from this device.
* Use call sign and path as specified in base config.
* There is no acknowledgment requested.
*/
packet = aprs_compose_aprsd_message(
conf->digi.call,
conf->base.path,
call);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects "
"or badly formed APRSD message");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.radio_conf.cca
)) {
TRACE_ERROR("BCN > Failed to transmit APRSD data");
}
chThdSleep(TIME_S2I(5));
}
} /* psleep */
time = waitForTrigger(time, conf->digi.cycle);
}
}
/*
*
*/
void start_beacon_thread(thd_aprs_conf_t *conf) {
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(10*1024),
"BCN", LOWPRIO, bcnThread, conf);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("BCN > Could not start thread (not enough memory available)");
}
}
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "threads.h"
#include "config.h"
#include "radio.h"
#include "aprs.h"
#include "sleep.h"
#include "chprintf.h"
#include <string.h>
#include <math.h>
#include "watchdog.h"
/*
*
*/
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);
// Start data collector (if not running yet)
init_data_collector();
// Start position thread
TRACE_INFO("BCN > Startup beacon thread");
// Set telemetry configuration transmission variables
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;
chThdSleep(delay);
while(true) {
char code_s[100];
pktDisplayFrequencyCode(conf->digi.radio_conf.freq,
code_s, sizeof(code_s));
TRACE_INFO("POS > Do module BEACON cycle for %s on %s",
conf->digi.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);
#else
dataPoint_t* dataPoint = getLastDataPoint();
#endif
if(!p_sleep(&conf->svc_conf.sleep_conf)) {
// Telemetry encoding parameter transmissions
if(conf_sram.tel_enc_cycle != 0 && last_conf_transmission
+ conf_sram.tel_enc_cycle < chVTGetSystemTime()) {
TRACE_INFO("BCN > Transmit telemetry configuration");
// 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,
type);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects for"
" telemetry config transmission");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.radio_conf.cca)) {
TRACE_ERROR("BCN > Failed to transmit telemetry config");
}
}
chThdSleep(TIME_S2I(5));
}
last_conf_transmission += conf_sram.tel_enc_cycle;
}
while(!isPositionValid(dataPoint)) {
TRACE_INFO("BCN > Waiting for position data for beacon");
chThdSleep(TIME_S2I(60));
continue;
}
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,
dataPoint, true);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects"
" for position transmission");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.radio_conf.cca)) {
TRACE_ERROR("BCN > failed to transmit beacon data");
}
chThdSleep(TIME_S2I(5));
}
TRACE_INFO("BCN > Transmit recently heard direct");
/*
* Encode/Transmit APRSD packet.
* This is a tracker originated message (not a reply to a request).
* The message will be addressed to the base station if set.
* Else send it to device identity.
*/
char *call = conf_sram.base.enabled
? conf_sram.base.call : conf->digi.call;
/*
* Send message from this device.
* Use call sign and path as specified in base config.
* There is no acknowledgment requested.
*/
packet = aprs_compose_aprsd_message(
conf_sram.aprs.digi.call,
//conf->digi.call,
conf_sram.base.path,
//conf->base.path,
call);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects "
"or badly formed APRSD message");
} else {
if(!transmitOnRadio(packet,
conf->digi.radio_conf.freq,
0,
0,
conf->digi.radio_conf.pwr,
conf->digi.radio_conf.mod,
conf->digi.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);
}
}
/*
*
*/
void start_beacon_thread(thd_aprs_conf_t *conf) {
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(10*1024),
"BCN", LOWPRIO, bcnThread, conf);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("BCN > Could not start thread (not enough memory available)");
}
}

Wyświetl plik

@ -1,89 +1,89 @@
/**
* Logging module
*
*/
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "threads.h"
#include "base91.h"
#include "aprs.h"
#include "sleep.h"
#include "radio.h"
#include "log.h"
#include "pflash.h"
static uint16_t log_id = 0;
static dataPoint_t* getNextLogDataPoint(uint8_t density)
{
// Determine sector
dataPoint_t *tp;
uint32_t i = 0;
do {
if((tp = flash_getLogBuffer(log_id))) {
log_id += density;
} else {
log_id = 0;
tp = flash_getLogBuffer(0);
}
} while(LOG_IS_EMPTY(tp) && i++ < LOG_FLASH_SIZE / sizeof(dataPoint_t));
return LOG_IS_EMPTY(tp) ? NULL : tp;
}
THD_FUNCTION(logThread, arg)
{
thd_log_conf_t* conf = (thd_log_conf_t*)arg;
if(conf->thread_conf.init_delay) chThdSleep(conf->thread_conf.init_delay);
TRACE_INFO("LOG > Startup logging thread");
sysinterval_t time = chVTGetSystemTime();
while(true)
{
TRACE_INFO("LOG > Do module LOG cycle");
if(!p_sleep(&conf->thread_conf.sleep_conf))
{
// Get log from memory
dataPoint_t *log = getNextLogDataPoint(conf->density);
if(log) {
// Encode Base91
uint8_t pkt_base91[BASE91LEN(sizeof(dataPoint_t))];
base91_encode((uint8_t*)log, pkt_base91, sizeof(dataPoint_t));
// Encode and transmit log packet
packet_t packet = aprs_encode_data_packet(conf->call, conf->path, 'L', pkt_base91); // Encode packet
if(packet == NULL) {
TRACE_WARN("LOG > No free packet objects for log transmission");
} else {
// Transmit packet
transmitOnRadio(packet,
conf->radio_conf.freq,
0,
0,
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca);
}
} else {
TRACE_INFO("LOG > No log point in memory");
}
}
time = waitForTrigger(time, conf->thread_conf.cycle);
}
}
void start_logging_thread(thd_log_conf_t *conf)
{
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(6*1024), "LOG", LOWPRIO, logThread, conf);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("LOG > Could not startup thread (not enough memory available)");
}
}
/**
* Logging module
*
*/
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "threads.h"
#include "base91.h"
#include "aprs.h"
#include "sleep.h"
#include "radio.h"
#include "log.h"
#include "pflash.h"
static uint16_t log_id = 0;
static dataPoint_t* getNextLogDataPoint(uint8_t density)
{
// Determine sector
dataPoint_t *tp;
uint32_t i = 0;
do {
if((tp = flash_getLogBuffer(log_id))) {
log_id += density;
} else {
log_id = 0;
tp = flash_getLogBuffer(0);
}
} while(LOG_IS_EMPTY(tp) && i++ < LOG_FLASH_SIZE / sizeof(dataPoint_t));
return LOG_IS_EMPTY(tp) ? NULL : tp;
}
THD_FUNCTION(logThread, arg)
{
thd_log_conf_t* conf = (thd_log_conf_t*)arg;
if(conf->svc_conf.init_delay) chThdSleep(conf->svc_conf.init_delay);
TRACE_INFO("LOG > Startup logging thread");
sysinterval_t time = chVTGetSystemTime();
while(true)
{
TRACE_INFO("LOG > Do module LOG cycle");
if(!p_sleep(&conf->svc_conf.sleep_conf))
{
// Get log from memory
dataPoint_t *log = getNextLogDataPoint(conf->density);
if(log) {
// Encode Base91
uint8_t pkt_base91[BASE91LEN(sizeof(dataPoint_t))];
base91_encode((uint8_t*)log, pkt_base91, sizeof(dataPoint_t));
// Encode and transmit log packet
packet_t packet = aprs_encode_data_packet(conf->call, conf->path, 'L', pkt_base91); // Encode packet
if(packet == NULL) {
TRACE_WARN("LOG > No free packet objects for log transmission");
} else {
// Transmit packet
transmitOnRadio(packet,
conf->radio_conf.freq,
0,
0,
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca);
}
} else {
TRACE_INFO("LOG > No log point in memory");
}
}
time = waitForTrigger(time, conf->svc_conf.cycle);
}
}
void start_logging_thread(thd_log_conf_t *conf)
{
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(6*1024), "LOG", LOWPRIO, logThread, conf);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("LOG > Could not startup thread (not enough memory available)");
}
}

Wyświetl plik

@ -1,153 +1,153 @@
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "threads.h"
#include "config.h"
#include "radio.h"
#include "aprs.h"
#include "sleep.h"
#include "chprintf.h"
#include <string.h>
#include <math.h>
#include "watchdog.h"
/*
*
*/
THD_FUNCTION(posThread, arg)
{
thd_pos_conf_t* conf = (thd_pos_conf_t*)arg;
// Wait
if(conf->thread_conf.init_delay) chThdSleep(conf->thread_conf.init_delay);
// Start data collector (if not running yet)
init_data_collector();
// Start position thread
TRACE_INFO("POS > Startup position thread");
// Set telemetry configuration transmission variables
sysinterval_t last_conf_transmission =
chVTGetSystemTime() - conf->tel_enc_cycle;
sysinterval_t time = chVTGetSystemTime();
while(true) {
char code_s[100];
pktDisplayFrequencyCode(conf->radio_conf.freq,
code_s, sizeof(code_s));
TRACE_INFO("POS > Do module POSITION cycle for %s on %s",
conf->call, code_s);
TRACE_INFO("POS > Get last data point");
dataPoint_t* dataPoint = getLastDataPoint();
if(!p_sleep(&conf->thread_conf.sleep_conf)) {
TRACE_INFO("POS > Transmit position");
// Telemetry encoding parameter transmission
if(conf->tel_enc_cycle != 0 && last_conf_transmission
+ conf->tel_enc_cycle < chVTGetSystemTime()) {
TRACE_INFO("POS > Transmit telemetry configuration");
// 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->call,
conf->path,
conf->call,
type);
if(packet == NULL) {
TRACE_WARN("POS > No free packet objects for"
" telemetry transmission");
} else {
if(!transmitOnRadio(packet,
conf->radio_conf.freq,
0,
0,
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca)) {
TRACE_ERROR("POS > Failed to transmit telemetry data");
}
}
chThdSleep(TIME_S2I(5));
}
last_conf_transmission += conf->tel_enc_cycle;
}
// Encode/Transmit position packet
packet_t packet = aprs_encode_position_and_telemetry(conf->call,
conf->path,
conf->symbol,
dataPoint,
true);
if(packet == NULL) {
TRACE_WARN("POS > No free packet objects"
" for position transmission");
} else {
if(!transmitOnRadio(packet,
conf->radio_conf.freq,
0,
0,
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca)) {
TRACE_ERROR("POS > failed to transmit position data");
}
chThdSleep(TIME_S2I(5));
}
/*
* Encode/Transmit APRSD packet.
* This is a tracker originated message (not a reply to a request).
* The message will be sent to the base station if set.
* Else send it to device identity.
*/
char *call = conf_sram.aprs.base.enabled
? conf_sram.aprs.base.call : conf->call;
/*
* Send message from this device.
* Use call sign and path as specified in base config.
* There is no acknowledgment requested.
*/
packet = aprs_compose_aprsd_message(
conf->call,
conf->path,
call);
if(packet == NULL) {
TRACE_WARN("POS > No free packet objects "
"or badly formed APRSD message");
} else {
if(!transmitOnRadio(packet,
conf->radio_conf.freq,
0,
0,
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca
)) {
TRACE_ERROR("POS > Failed to transmit APRSD data");
}
chThdSleep(TIME_S2I(5));
}
}
time = waitForTrigger(time, conf->thread_conf.cycle);
}
}
/*
*
*/
void start_position_thread(thd_pos_conf_t *conf)
{
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(10*1024),
"POS", LOWPRIO, posThread, conf);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("POS > Could not startup thread (not enough memory available)");
}
}
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "threads.h"
#include "config.h"
#include "radio.h"
#include "aprs.h"
#include "sleep.h"
#include "chprintf.h"
#include <string.h>
#include <math.h>
#include "watchdog.h"
/*
*
*/
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);
// Start data collector (if not running yet)
init_data_collector();
// Start position thread
TRACE_INFO("POS > Startup position thread");
// Set telemetry configuration transmission variables
sysinterval_t last_conf_transmission =
chVTGetSystemTime() - conf_sram.tel_enc_cycle;
sysinterval_t time = chVTGetSystemTime();
while(true) {
char code_s[100];
pktDisplayFrequencyCode(conf->radio_conf.freq,
code_s, sizeof(code_s));
TRACE_INFO("POS > Do module POSITION cycle for %s on %s",
conf->call, code_s);
TRACE_INFO("POS > Get last data point");
dataPoint_t* dataPoint = getLastDataPoint();
if(!p_sleep(&conf->svc_conf.sleep_conf)) {
TRACE_INFO("POS > Transmit position");
// Telemetry encoding parameter transmission
if(conf_sram.tel_enc_cycle != 0 && last_conf_transmission
+ conf_sram.tel_enc_cycle < chVTGetSystemTime()) {
TRACE_INFO("POS > Transmit telemetry configuration");
// 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->call,
conf->path,
conf->call,
type);
if(packet == NULL) {
TRACE_WARN("POS > No free packet objects for"
" telemetry transmission");
} else {
if(!transmitOnRadio(packet,
conf->radio_conf.freq,
0,
0,
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca)) {
TRACE_ERROR("POS > Failed to transmit telemetry data");
}
}
chThdSleep(TIME_S2I(5));
}
last_conf_transmission += conf_sram.tel_enc_cycle;
}
// Encode/Transmit position packet
packet_t packet = aprs_encode_position_and_telemetry(conf->call,
conf->path,
conf->symbol,
dataPoint,
true);
if(packet == NULL) {
TRACE_WARN("POS > No free packet objects"
" for position transmission");
} else {
if(!transmitOnRadio(packet,
conf->radio_conf.freq,
0,
0,
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca)) {
TRACE_ERROR("POS > failed to transmit position data");
}
chThdSleep(TIME_S2I(5));
}
/*
* Encode/Transmit APRSD packet.
* This is a tracker originated message (not a reply to a request).
* The message will be sent to the base station if set.
* Else send it to device identity.
*/
char *call = conf_sram.base.enabled
? conf_sram.base.call : conf->call;
/*
* Send message from this device.
* Use call sign and path as specified in base config.
* There is no acknowledgment requested.
*/
packet = aprs_compose_aprsd_message(
conf->call,
conf->path,
call);
if(packet == NULL) {
TRACE_WARN("POS > No free packet objects "
"or badly formed APRSD message");
} else {
if(!transmitOnRadio(packet,
conf->radio_conf.freq,
0,
0,
conf->radio_conf.pwr,
conf->radio_conf.mod,
conf->radio_conf.cca
)) {
TRACE_ERROR("POS > Failed to transmit APRSD data");
}
chThdSleep(TIME_S2I(5));
}
}
time = waitForTrigger(time, conf->svc_conf.cycle);
}
}
/*
*
*/
void start_position_thread(thd_pos_conf_t *conf)
{
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(10*1024),
"POS", LOWPRIO, posThread, conf);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("POS > Could not startup thread (not enough memory available)");
}
}

Wyświetl plik

@ -1,64 +1,71 @@
#include "ch.h"
#include "hal.h"
#include "watchdog.h"
#include "pi2c.h"
#include "pac1720.h"
#include "radio.h"
#include "si446x.h"
#include "image.h"
#include "position.h"
#include "beacon.h"
#include "log.h"
#include "radio.h"
#include "ax25_pad.h"
#include "flash.h"
sysinterval_t watchdog_tracking;
void start_essential_threads(void)
{
init_watchdog(); // Init watchdog
pac1720_init(); // Initialize current measurement
chThdSleep(TIME_MS2I(300)); // Wait for tracking manager to initialize
}
void start_user_threads(void)
{
conf_t *conf_flash = (conf_t*)0x08060000;
/* Check if a user update has been made to configuration in flash. */
if(conf_flash->magic != CONFIG_MAGIC_UPDATED) {
if(conf_flash->magic != CONFIG_MAGIC_DEFAULT
|| memcmp(&conf_flash, &conf_flash_default, sizeof(conf_t)) != 0) {
/* No configuration found in flash memory or default config has changed. */
flashSectorBegin(flashSectorAt((uint32_t)conf_flash));
flashErase((uint32_t)conf_flash, 0x20000);
flashWrite((uint32_t)conf_flash, (char*)&conf_flash_default, sizeof(conf_t));
flashSectorEnd(flashSectorAt((uint32_t)conf_flash));
}
}
// Copy
memcpy(&conf_sram, conf_flash, sizeof(conf_t));
if(conf_sram.pos_pri.thread_conf.active) start_position_thread(&conf_sram.pos_pri);
if(conf_sram.pos_sec.thread_conf.active) start_position_thread(&conf_sram.pos_sec);
if(conf_sram.img_pri.thread_conf.active) start_image_thread(&conf_sram.img_pri);
if(conf_sram.img_sec.thread_conf.active) start_image_thread(&conf_sram.img_sec);
if(conf_sram.log.thread_conf.active) start_logging_thread(&conf_sram.log);
if(conf_sram.aprs.thread_conf.active && conf_sram.aprs.digi.beacon)
start_beacon_thread(&conf_sram.aprs);
if(conf_sram.aprs.thread_conf.active) {
chThdSleep(conf_sram.aprs.thread_conf.init_delay);
start_aprs_threads(PKT_RADIO_1,
conf_sram.aprs.rx.radio_conf.freq,
0,
0,
conf_sram.aprs.rx.radio_conf.rssi);
}
}
#include "ch.h"
#include "hal.h"
#include "watchdog.h"
#include "pi2c.h"
#include "pac1720.h"
#include "radio.h"
#include "si446x.h"
#include "image.h"
#include "position.h"
#include "beacon.h"
#include "log.h"
#include "radio.h"
#include "ax25_pad.h"
#include "flash.h"
sysinterval_t watchdog_tracking;
void start_essential_threads(void)
{
init_watchdog(); // Init watchdog
pac1720_init(); // Initialize current measurement
chThdSleep(TIME_MS2I(300)); // Wait for tracking manager to initialize
}
void start_user_threads(void)
{
conf_t *conf_flash = (conf_t*)0x08060000;
/* Check if a user update has been made to configuration in flash. */
if(conf_flash->magic != CONFIG_MAGIC_UPDATED) {
if(conf_flash->magic != CONFIG_MAGIC_DEFAULT
|| memcmp(&conf_flash, &conf_flash_default, sizeof(conf_t)) != 0) {
/* No configuration found in flash memory or default config has changed. */
flashSectorBegin(flashSectorAt((uint32_t)conf_flash));
flashErase((uint32_t)conf_flash, 0x20000);
flashWrite((uint32_t)conf_flash, (char*)&conf_flash_default, sizeof(conf_t));
flashSectorEnd(flashSectorAt((uint32_t)conf_flash));
}
}
// 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);
if(conf_sram.img_pri.svc_conf.active)
start_image_thread(&conf_sram.img_pri);
if(conf_sram.img_sec.svc_conf.active)
start_image_thread(&conf_sram.img_sec);
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.svc_conf.active) {
chThdSleep(conf_sram.aprs.svc_conf.init_delay);
start_aprs_threads(PKT_RADIO_1,
conf_sram.aprs.rx.radio_conf.freq,
0,
0,
conf_sram.aprs.rx.radio_conf.rssi);
}
}