Update to dynamic frequency selection.

pull/4/head
CInsights 2018-05-12 19:16:00 +10:00
rodzic 4653053210
commit 03fcacd0c8
10 zmienionych plików z 187 dodań i 125 usunięć

Wyświetl plik

@ -29,13 +29,15 @@
const radio_band_t band_2m = {
.start = BAND_MIN_2M_FREQ,
.end = BAND_MAX_2M_FREQ,
.step = 12500
.step = 12500,
.def = BAND_DEF_2M_FREQ
};
const radio_band_t band_70cm = {
.start = BAND_MIN_70CM_FREQ,
.end = BAND_MAX_70CM_FREQ,
.step = 25000
.step = 25000,
.def = BAND_DEF_70CM_FREQ
};
/*===========================================================================*/

Wyświetl plik

@ -47,8 +47,10 @@
#define BAND_MIN_2M_FREQ 144000000 /* Minimum allowed frequency in Hz */
#define BAND_MAX_2M_FREQ 148000000 /* Maximum allowed frequency in Hz */
#define BAND_DEF_2M_FREQ 144800000 /* Default frequency in Hz. */
#define BAND_MIN_70CM_FREQ 420000000 /* Minimum allowed frequency in Hz */
#define BAND_MAX_70CM_FREQ 450000000 /* Maximum allowed frequency in Hz */
#define BAND_DEF_70CM_FREQ 439100000 /* Default frequency in Hz. */
#define DEFAULT_OPERATING_FREQ 144800000

Wyświetl plik

@ -21,7 +21,7 @@ const conf_t conf_flash_default = {
.mod = MOD_AFSK,
.cca = 0x4F,
},
// Node identity
// App identity
.call = "VK2GJ-12",
.path = "WIDE2-1",
.symbol = SYM_ANTENNA,
@ -43,7 +43,7 @@ const conf_t conf_flash_default = {
.mod = MOD_AFSK,
.cca = 0x4F
},
// Node identity
// App identity
.call = "DL7AD-14",
.path = "WIDE1-1",
.symbol = SYM_BALLOON,
@ -64,16 +64,18 @@ const conf_t conf_flash_default = {
.pwr = 0x7F,
.freq = 144800000,
.mod = MOD_2FSK,
.cca = 0x4F,
.redundantTx = false
.cca = 0x4F
},
// App identity
.call = "VK2GJ-15",
.path = "",
// Image settings
.res = RES_VGA,
.quality = 4,
.buf_size = 40*1024
.buf_size = 40*1024,
.redundantTx = false
},
// Secondary image app
@ -94,9 +96,11 @@ const conf_t conf_flash_default = {
.call = "VK2GJ-14",
.path = "",
// Image settings
.res = RES_QVGA,
.quality = 4,
.buf_size = 15*1024
.buf_size = 15*1024,
.redundantTx = false
},
// Log app

Wyświetl plik

@ -5,12 +5,23 @@
#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 last found in RX scan. - TBI */
#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
@ -52,111 +63,126 @@ typedef enum {
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; // 0: APRS region frequency (determined by geofencing), f>0 static frequency
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;
bool redundantTx;
} radio_tx_conf_t; // Radio / Modulation
typedef struct {
radio_freq_t freq; // 0: APRS region frequency (determined by geofencing), f>0 static frequency
mod_t mod;
link_speed_t speed;
radio_squelch_t rssi;
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;
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;
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;
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;
thread_conf_t thread_conf;
radio_tx_conf_t radio_conf;
bool redundantTx;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
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
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;
thread_conf_t thread_conf;
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
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%)
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;
radio_rx_conf_t radio_conf;
aprs_sym_t symbol;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char call[AX25_MAX_ADDR_LEN];
} thd_rx_conf_t;
typedef struct {
radio_tx_conf_t radio_conf;
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
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;
radio_tx_conf_t radio_conf;
// Protocol
char call[AX25_MAX_ADDR_LEN];
char path[16];
aprs_sym_t symbol;
bool enabled;
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;
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;
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;
@ -194,11 +220,11 @@ typedef struct {
} conf_t;
typedef struct {
uint8_t type;
char name[64];
size_t size;
void *ptr;
uint8_t type;
char name[64];
size_t size;
void *ptr;
} conf_command_t;
#endif
#endif /* __TYPES_H__ */

Wyświetl plik

@ -653,7 +653,7 @@ static bool isPointInBrazil(int32_t lat, int32_t lon) {
* use the APRS default frequency set in the config file if no GPS fix has
* been received.
*/
uint32_t getAPRSRegionFrequency(void) {
uint32_t getAPRSRegionFrequency() {
dataPoint_t *point = getLastDataPoint();
// Position unknown

Wyświetl plik

@ -499,23 +499,50 @@ void pktReleaseRadio(const radio_unit_t radio) {
}
/**
* @brief Get current receive operating frequency.
* @brief Get default operating frequency.
*
* @param[in] radio Radio unit ID.
*
* @return operating frequency
* @retval 0 if requested frequency or radio ID is invalid
* @retval FREQ_RADIO_INVALID if radio ID is invalid
* @retval Default frequency otherwise
*
* @api
*/
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;
else
return DEFAULT_OPERATING_FREQ;
}
/**
* @brief Get current receive operating frequency.
*
* @param[in] radio Radio unit ID.
*
* @return actual operating frequency or special code
* @retval 0 if requested frequency or radio ID is invalid
*
* @notapi
*/
radio_freq_t pktGetReceiveOperatingFrequency(const radio_unit_t radio) {
packet_svc_t *handler = pktGetServiceObject(radio);
radio_freq_t op_freq;
if(pktIsReceiveActive(radio)) {
radio_freq_t op_freq = handler->radio_rx_config.base_frequency
if(handler->radio_rx_config.base_frequency < FREQ_CODES_END)
/* Frequency code. */
return handler->radio_rx_config.base_frequency;
/* Normal frequency. */
op_freq = handler->radio_rx_config.base_frequency
+ (handler->radio_rx_config.step_hz * handler->radio_rx_config.channel);
return op_freq;
}
return FREQ_RADIO_INVALID;
/* Receive is not active so return default operating frequency. */
return pktGetDefaultOperatingFrequency(radio);
}
/**
@ -539,14 +566,24 @@ radio_freq_t pktComputeOperatingFrequency(const radio_unit_t radio,
radio_ch_t chan,
const radio_mode_t mode) {
radio_freq_t op_freq;
if((base_freq == FREQ_APRS_RECEIVE || base_freq == FREQ_APRS_SCAN)
&& mode == RADIO_TX) {
/* Get current RX frequency (or default) and use that. */
step = 0;
chan = 0;
/* FIXME: Should switch on all special codes to make system robust. */
base_freq = pktGetReceiveOperatingFrequency(radio);
}
/*
* Check for dynamic frequency determination.
* Dynamic can return an absolute frequency or a further special code.
*/
if(base_freq == FREQ_APRS_DYNAMIC) {
/* Get frequency by geofencing. */
/*
* Get frequency by geofencing.
* Geofencing can return special code FREQ_APRS_DEFAULT.
*/
base_freq = getAPRSRegionFrequency();
step = 0;
chan = 0;
@ -554,29 +591,13 @@ radio_freq_t pktComputeOperatingFrequency(const radio_unit_t radio,
/* Check for default. */
if(base_freq == FREQ_APRS_DEFAULT) {
/* FIXME: INVALID relies on 0 in conf if no default set. */
if(conf_sram.aprs.freq != FREQ_RADIO_INVALID)
return conf_sram.aprs.freq;
else
return DEFAULT_OPERATING_FREQ;
}
if((base_freq == FREQ_APRS_RECEIVE || base_freq == FREQ_APRS_SCAN)
&& mode == RADIO_TX) {
/* Get current RX frequency (if valid) and use that. */
if((op_freq = pktGetReceiveOperatingFrequency(radio))
!= FREQ_RADIO_INVALID)
return op_freq;
else {
/* Get frequency by geofencing. */
base_freq = getAPRSRegionFrequency();
step = 0;
chan = 0;
}
base_freq = pktGetDefaultOperatingFrequency(radio);
step = 0;
chan = 0;
}
/* Calculate operating frequency. */
op_freq = base_freq + (step * chan);
radio_freq_t op_freq = base_freq + (step * chan);
/* Check validity. */
uint8_t radios = sizeof(radio_list) / sizeof(radio_param_t);
@ -588,7 +609,7 @@ radio_freq_t pktComputeOperatingFrequency(const radio_unit_t radio,
else
return FREQ_RADIO_INVALID;
}
}
} /* End for */
return FREQ_RADIO_INVALID;
}

Wyświetl plik

@ -78,6 +78,7 @@ typedef struct radioBand {
radio_freq_t start;
radio_freq_t end;
channel_hz_t step;
radio_freq_t def;
} radio_band_t;
typedef struct radioParam {

Wyświetl plik

@ -87,7 +87,7 @@ const conf_command_t command_list[] = {
{TYPE_INT, "img_pri.mod", sizeof(conf_sram.img_pri.radio_conf.mod), &conf_sram.img_pri.radio_conf.mod },
{TYPE_INT, "img_pri.cca", sizeof(conf_sram.img_pri.radio_conf.cca), &conf_sram.img_pri.radio_conf.cca },
{TYPE_INT, "img_pri.speed", sizeof(conf_sram.img_pri.radio_conf.speed), &conf_sram.img_pri.radio_conf.speed },
{TYPE_INT, "img_pri.redundantTx", sizeof(conf_sram.img_pri.radio_conf.redundantTx), &conf_sram.img_pri.radio_conf.redundantTx },
{TYPE_INT, "img_pri.redundantTx", sizeof(conf_sram.img_pri.redundantTx), &conf_sram.img_pri.redundantTx },
{TYPE_STR, "img_pri.call", sizeof(conf_sram.img_pri.call), &conf_sram.img_pri.call },
{TYPE_STR, "img_pri.path", sizeof(conf_sram.img_pri.path), &conf_sram.img_pri.path },
{TYPE_INT, "img_pri.res", sizeof(conf_sram.img_pri.res), &conf_sram.img_pri.res },
@ -104,9 +104,9 @@ const conf_command_t command_list[] = {
{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 },
{TYPE_INT, "img_sec.cca", sizeof(conf_sram.img_sec.radio_conf.cca), &conf_sram.img_sec.radio_conf.cca },
{TYPE_INT, "img_sec.cca", sizeof(conf_sram.img_sec.radio_conf.cca), &conf_sram.img_sec.radio_conf.cca },
{TYPE_INT, "img_sec.speed", sizeof(conf_sram.img_sec.radio_conf.speed), &conf_sram.img_sec.radio_conf.speed },
{TYPE_INT, "img_sec.redundantTx", sizeof(conf_sram.img_sec.radio_conf.redundantTx), &conf_sram.img_sec.radio_conf.redundantTx },
{TYPE_INT, "img_sec.redundantTx", sizeof(conf_sram.img_sec.redundantTx), &conf_sram.img_sec.redundantTx },
{TYPE_STR, "img_sec.call", sizeof(conf_sram.img_sec.call), &conf_sram.img_sec.call },
{TYPE_STR, "img_sec.path", sizeof(conf_sram.img_sec.path), &conf_sram.img_sec.path },
{TYPE_INT, "img_sec.res", sizeof(conf_sram.img_sec.res), &conf_sram.img_sec.res },
@ -125,7 +125,6 @@ const conf_command_t command_list[] = {
{TYPE_INT, "log.mod", sizeof(conf_sram.log.radio_conf.mod), &conf_sram.log.radio_conf.mod },
{TYPE_INT, "log.cca", sizeof(conf_sram.log.radio_conf.cca), &conf_sram.log.radio_conf.cca },
{TYPE_INT, "log.speed", sizeof(conf_sram.log.radio_conf.speed), &conf_sram.log.radio_conf.speed },
{TYPE_INT, "log.redundantTx", sizeof(conf_sram.log.radio_conf.redundantTx), &conf_sram.log.radio_conf.redundantTx },
{TYPE_STR, "log.call", sizeof(conf_sram.log.call), &conf_sram.log.call },
{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 },
@ -157,7 +156,7 @@ const conf_command_t command_list[] = {
{TYPE_INT, "aprs.digi.lon", sizeof(conf_sram.aprs.digi.lon), &conf_sram.aprs.digi.lon },
{TYPE_INT, "aprs.digi.alt", sizeof(conf_sram.aprs.digi.alt), &conf_sram.aprs.digi.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.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, "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 },
@ -249,6 +248,13 @@ static msg_t aprs_cmd_exec(const APRSCommand *acp,
return MSG_TIMEOUT;
}
/**
*
*/
void aprs_get_identity(void) {
}
/**
*
*/
@ -1152,7 +1158,7 @@ static bool aprs_decode_message(packet_t pp) {
memcpy(msg_id_rx, &pinfo[i+1], sizeof(msg_id_rx)-1);
// Cut off non-printable chars
for(uint8_t j=0; j<sizeof(msg_id_rx); j++) {
if(msg_id_rx[j] < 32 || msg_id_rx[j] > 126) {
if(msg_id_rx[j] < ' ' || msg_id_rx[j] > '~') {
msg_id_rx[j] = 0;
break;
}

Wyświetl plik

@ -41,7 +41,6 @@
#define ORIGIN_DIGIPEATER_CONVERSION 0x7
#define APRS_DEVICE_CALLSIGN "APECAN" // APExxx = Pecan device
//#define APRS_DEST_SSID 0
#define SYM_BALLOON 0x2F4F
#define SYM_SMALLAIRCRAFT 0x2F27
@ -51,6 +50,8 @@
#define SYM_DIGIPEATER 0x2F23
#define SYM_ANTENNA 0x2F72
#define APRS_PATH_LENGTH 16
#define APRS_NUM_TELEM_GROUPS 4
#define APRS_HEARD_LIST_SIZE 20
@ -59,16 +60,16 @@
typedef struct APRSIdentity {
/* APRS parameters. */
char num[8]; /**< @brief Message number. */
char src[AX25_MAX_ADDR_LEN]; /**< @brief Source call. */
char call[AX25_MAX_ADDR_LEN]; /**< @brief Destination call. */
char path[16]; /**< @brief Path. */
uint16_t symbol; /**< @brief symbol. */
char num[8]; /**< @brief Message number. */
char src[AX25_MAX_ADDR_LEN]; /**< @brief Source call. */
char call[AX25_MAX_ADDR_LEN]; /**< @brief Destination call. */
char path[APRS_PATH_LENGTH]; /**< @brief Path. */
aprs_sym_t symbol; /**< @brief symbol. */
/* Radio parameters. */
uint32_t freq;
uint8_t pwr;
mod_t mod;
uint8_t cca;
radio_freq_t freq;
radio_pwr_t pwr;
mod_t mod;
radio_squelch_t cca;
} aprs_identity_t;
/**
@ -80,18 +81,16 @@ typedef msg_t (*aprscmd_t)(aprs_identity_t *id, int argc, char *argv[]);
* @brief APRS command entry type.
*/
typedef struct {
const char *ac_name; /**< @brief Command name. */
aprscmd_t ac_function; /**< @brief Command function. */
const char *ac_name; /**< @brief Command name. */
aprscmd_t ac_function; /**< @brief Command function. */
} APRSCommand;
/* Temporary. Will be deprecated when fixed station feature is implemented. */
//extern bool test_gps_enabled;
#ifdef __cplusplus
extern "C" {
#endif
void aprs_debug_getPacket(packet_t pp, char* buf, uint32_t len);
packet_t aprs_encode_stamped_position_and_telemetry(const char *callsign,
packet_t aprs_encode_stamped_position_and_telemetry(const char *callsign,
const char *path, aprs_sym_t symbol,
dataPoint_t *dataPoint);
packet_t aprs_encode_position_and_telemetry(const char *callsign,
@ -126,10 +125,11 @@ extern "C" {
int argc, char *argv[]);
msg_t aprs_execute_img_command(aprs_identity_t *id,
int argc, char *argv[]);
msg_t aprs_execute_system_reset(aprs_identity_t *id,
msg_t aprs_execute_system_reset(aprs_identity_t *id,
int argc, char *argv[]);
#ifdef __cplusplus
}
#endif
#endif
#endif /* __cplusplus */
#endif /* __APRS_H__ */

Wyświetl plik

@ -367,7 +367,7 @@ static bool transmit_image_packets(const uint8_t *image,
/* FIXME: This doesn't work with burst mode packet sends. */
// Process redundant transmission from last cycle
if(strlen((char*)pkt_base91)
&& conf->radio_conf.redundantTx) {
&& conf->redundantTx) {
packet_t packet = aprs_encode_data_packet(conf->call, conf->path,
'I', pkt_base91);
if(packet == NULL) {
@ -412,7 +412,7 @@ static bool transmit_image_packets(const uint8_t *image,
uint8_t buffers = fmin((NUMBER_COMMON_PKT_BUFFERS / 2),
MAX_BUFFERS_FOR_BURST_SEND);
uint8_t chain = (conf->radio_conf.mod == MOD_2FSK
&& !conf->radio_conf.redundantTx) ?
&& !conf->redundantTx) ?
buffers : 1;
TRACE_INFO("IMG > Encode %i APRS/SSDV packet%s", chain,
(chain > 1 ? " burst" : ""));
@ -715,7 +715,7 @@ THD_FUNCTION(imgThread, arg) {
} /* End initSD() */
/* Transmit on radio. */
if(conf->radio_conf.mod == MOD_2FSK && conf->radio_conf.redundantTx) {
if(conf->radio_conf.mod == MOD_2FSK && conf->redundantTx) {
TRACE_WARN("IMG > Redundant TX disables 2FSK burst send mode");
}