Follow up to prior commit with additional files.

pull/4/head
bob 2018-08-10 01:13:08 +10:00
rodzic b878ce6977
commit 1fefc9818d
15 zmienionych plików z 1048 dodań i 851 usunięć

Wyświetl plik

@ -34,7 +34,7 @@ const conf_t conf_flash_default = {
// Secondary position app
.pos_sec = {
.beacon = {
.active = true,
.active = false,
.cycle = TIME_S2I(60 * 30), // Beacon interval
.init_delay = TIME_S2I(60),
.fixed = true, // Add lat, lon alt fields when enabling fixed
@ -85,13 +85,13 @@ const conf_t conf_flash_default = {
.img_sec = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(60 * 15),
.init_delay = TIME_S2I(30 * 1),
.send_spacing = TIME_S2I(30)
.cycle = TIME_S2I(60 * 2),
.init_delay = TIME_S2I(15 * 1),
.send_spacing = TIME_S2I(0)
},
.radio_conf = {
.pwr = 0x1F,
.freq = FREQ_APRS_DYNAMIC,
.freq = 144800000,
.mod = MOD_AFSK,
.cca = 0x4F
},
@ -146,7 +146,7 @@ const conf_t conf_flash_default = {
.symbol = SYM_ANTENNA
},
.aprs_msg = false, // Set true to enable messages to be accepted on RX call sign
.digi = true,
.digi = false,
.tx = {
// Transmit radio configuration
.radio_conf = {
@ -160,7 +160,7 @@ const conf_t conf_flash_default = {
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER,
// A digipeater beacon can be added using one of the POS apps
// Set the POS identity the same as the dipipeater TX call sign
// Set the POS identity the same as the dipipeater TX identity
// Alternatively the digipeater can have its own .beacon entry here
},
},

Wyświetl plik

@ -0,0 +1,197 @@
/**
* Put your configuration settings here. See description of all fields in types.h
*/
#include "config.h"
#include "aprs.h"
#include "geofence.h"
conf_t conf_sram;
const conf_t conf_flash_default = {
// Primary position app
.pos_pri = {
.beacon = {
.active = true,
.cycle = TIME_S2I(60 * 5),
.init_delay = TIME_S2I(60),
.fixed = false // Add lat, lon, alt fields when enabling fixed
},
.radio_conf = {
.pwr = 0x1F,
.freq = 144800000,
.mod = MOD_2FSK,
.cca = 0x4F,
},
// App identity
.call = "VK2GJ-12",
.path = "WIDE1-1",
.symbol = SYM_ANTENNA,
.aprs_msg = true, // Enable APRS message reception on this app
},
// Secondary position app
.pos_sec = {
.beacon = {
.active = true,
.cycle = TIME_S2I(60 * 30), // Beacon interval
.init_delay = TIME_S2I(60),
.fixed = true, // Add lat, lon alt fields when enabling fixed
.lat = -337331175, // Degrees (expressed in 1e-7 form)
.lon = 1511143478, // Degrees (expressed in 1e-7 form)
.alt = 144 // Altitude in metres
},
.radio_conf = {
.pwr = 0x7F,
.freq = FREQ_APRS_RECEIVE,
.mod = MOD_AFSK,
.cca = 0x4F
},
// App identity
.call = "VK2GJ-5",
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER,
.aprs_msg = false, // Enable APRS message reception on this app
},
// Primary image app
.img_pri = {
.svc_conf = {
.active = true,
.cycle = TIME_S2I(60 * 5),
.init_delay = TIME_S2I(60 * 1),
.send_spacing = TIME_S2I(5)
},
.radio_conf = {
.pwr = 0x7F,
.freq = 144800000,
.mod = MOD_2FSK,
.cca = 0x4F
},
// App identity
.call = "VK2GJ-15",
.path = "",
// Image settings
.res = RES_VGA,
.quality = 4,
.buf_size = 40 * 1024,
.redundantTx = false
},
// Secondary image app
.img_sec = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(60 * 15),
.init_delay = TIME_S2I(15 * 1),
.send_spacing = TIME_S2I(2)
},
.radio_conf = {
.pwr = 0x1F,
.freq = APRS_FREQ_AUSTRALIA,
.mod = MOD_AFSK,
.cca = 0x4F
},
// App identity
.call = "VK2GJ-12",
.path = "",
// Image settings
.res = RES_QVGA,
.quality = 4,
.buf_size = 15 * 1024,
.redundantTx = false
},
// Log app
.log = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(10),
.init_delay = TIME_S2I(5)
},
.radio_conf = {
.pwr = 0x7F,
.freq = FREQ_APRS_DYNAMIC,
.mod = MOD_AFSK,
.cca = 0x4F
},
// Node identity
.call = "VK2GJ-13",
.path = "WIDE1-1",
.density = 10
},
// APRS app
.aprs = {
// The receive identity for APRS
.rx = {
.svc_conf = {
// The packet receive service is enabled if true
// Receive is paused and resumed by transmission
.active = true,
.init_delay = TIME_S2I(20)
},
// Receive radio configuration
.radio_conf = {
.freq = FREQ_APRS_DYNAMIC,
.mod = MOD_AFSK,
.rssi = 0x3F
},
// APRS identity used in message responses if digipeat is not enabled
.call = "VK2GJ-4",
.symbol = SYM_ANTENNA
},
.aprs_msg = false, // Set true to enable messages to be accepted on RX call sign
.digi = true,
.tx = {
// Transmit radio configuration
.radio_conf = {
.freq = FREQ_APRS_RECEIVE,
.pwr = 0x7F,
.mod = MOD_AFSK,
.cca = 0x4F
},
// Digipeat transmission identity
.call = "VK2GJ-5",
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER,
// A digipeater beacon can be added using one of the POS apps
// Set the POS identity the same as the dipipeater TX identity
// Alternatively the digipeater can have its own .beacon entry here
},
},
// Global controls
// Power control
.keep_cam_switched_on = false,
.gps_on_vbat = 3600, // mV
.gps_off_vbat = 3400, // mV
.gps_onper_vbat = 4000, // mV
// GPS altitude model control (air pressure controlled using on-board BME280)
.gps_pressure = 90000, // Air pressure (Pa) threshold for alt model switch
.gps_low_alt = GPS_STATIONARY,
.gps_high_alt = GPS_AIRBORNE_1G,
// APRS
// How often to send telemetry config
.tel_enc_cycle = TIME_S2I(60 * 60 * 2),
// The default APRS frequency when geofence is not resolved
.freq = APRS_FREQ_AUSTRALIA,
// The base station identity.
.base = {
// If enabled tracker initiated APRS messages are addressed to this call sign
.enabled = true,
.call = "VK2GJ-7",
.path = "WIDE2-1",
},
.magic = CONFIG_MAGIC_DEFAULT // Do not remove. This is the activation bit.
};

Wyświetl plik

@ -1,190 +1,197 @@
/**
* Put your configuration settings here. See description of all fields in types.h
*/
#include "config.h"
#include "aprs.h"
conf_t conf_sram;
const conf_t conf_flash_default = {
// Primary position app
.pos_pri = {
.thread_conf = {
.active = true,
.cycle = TIME_S2I(60),
.init_delay = TIME_S2I(0)
},
.radio_conf = {
.pwr = 0x7F,
.freq = 144800000,
.mod = MOD_AFSK,
.cca = 0xFF,
},
// App identity
.call = "DL7AD-12",
.path = "WIDE1-1",
.symbol = SYM_BALLOON,
.aprs_msg = true,
// How often to send telemetry config
.tel_enc_cycle = TIME_S2I(60 * 60)
},
// Secondary position app
.pos_sec = {
.thread_conf = {
.active = true,
.cycle = TIME_S2I(180),
.init_delay = TIME_S2I(60)
},
.radio_conf = {
.pwr = 0x7F,
.freq = 145825000,
.mod = MOD_AFSK,
.cca = 0xFF
},
// App identity
.call = "DL7AD-15",
.path = "",
.symbol = SYM_BALLOON,
.aprs_msg = true,
.tel_enc_cycle = TIME_S2I(0)
},
// Primary image app
.img_pri = {
.thread_conf = {
.active = true,
.cycle = CYCLE_CONTINUOUSLY,
.init_delay = TIME_S2I(300),
.send_spacing = TIME_S2I(30)
},
.radio_conf = {
.pwr = 0x7F,
.freq = FREQ_APRS_DYNAMIC,
.mod = MOD_AFSK,
.cca = 0xFF
},
// App identity
.call = "DL7AD-15",
.path = "",
// Image settings
.res = RES_QVGA,
.quality = 4,
.buf_size = 40 * 1024,
.redundantTx = false
},
// Secondary image app
.img_sec = {
.thread_conf = {
.active = false,
.cycle = TIME_S2I(60 * 30),
.init_delay = TIME_S2I(60 * 1),
.send_spacing = TIME_S2I(30)
},
.radio_conf = {
.pwr = 0x7F,
.freq = 145175000,
.mod = MOD_AFSK,
.cca = 0x4F
},
// App identity
.call = "VK2GJ-14",
.path = "",
// Image settings
.res = RES_QVGA,
.quality = 4,
.buf_size = 15 * 1024,
.redundantTx = false
},
// Log app
.log = {
.thread_conf = {
.active = false,
.cycle = TIME_S2I(10),
.init_delay = TIME_S2I(5)
},
.radio_conf = {
.pwr = 0x7F,
.freq = FREQ_APRS_DYNAMIC,
.mod = MOD_AFSK,
.cca = 0x4F
},
// Node identity
.call = "VK2GJ-13",
.path = "WIDE1-1",
.density = 10
},
// APRS app
.aprs = {
.thread_conf = {
.active = true,
.init_delay = TIME_S2I(10)
},
// Default APRS frequency when geofence not resolved
.freq = 145825000,
// The receive identity for APRS
.rx = {
.radio_conf = {
.freq = 145825000,
.mod = MOD_AFSK,
.rssi = 0x5F
},
// App rx identity
.call = "DL7AD-15",
.symbol = SYM_BALLOON // Use this symbol in message responses
},
// The digipeat transmit identity and messages responses
.digi = {
.radio_conf = {
.freq = 145825000,
.pwr = 0x7F,
.mod = MOD_AFSK,
.cca = 0xFF
},
.active = true,
// Digipeat identity
.call = "DL7AD-15",
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER,
.beacon = false, // Set to have digi beacon position and telem
.cycle = TIME_S2I(60 * 30), // Position and telem beacon interval
.gps = false, // Set to have digi use GPS for position
// A set location if GPS not 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 (TODO: Move out to global level)
.tel_enc_cycle = TIME_S2I(0)
},
// The base station identity
.base = {
// Tracker originated messages will be sent to this call sign if enabled
.enabled = false,
.call = "VK2GJ-7",
.path = "WIDE2-1",
},
},
// 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 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,
.magic = CONFIG_MAGIC_DEFAULT // Do not remove. This is the activation bit.
};
/**
* Put your configuration settings here. See description of all fields in types.h
*/
#include "config.h"
#include "aprs.h"
#include "geofence.h"
conf_t conf_sram;
const conf_t conf_flash_default = {
// Primary position app
.pos_pri = {
.beacon = {
.active = true,
.cycle = TIME_S2I(60),
.init_delay = TIME_S2I(10),
.fixed = false // Add lat, lon, alt fields when enabling fixed
},
.radio_conf = {
.pwr = 0x7F,
.freq = 144800000,
.mod = MOD_AFSK,
.cca = 0x4F,
},
// App identity
.call = "DL7AD-12",
.path = "WIDE1-1",
.symbol = SYM_ANTENNA,
.aprs_msg = true, // Enable APRS message reception on this app
},
// Secondary position app
.pos_sec = {
.beacon = {
.active = false,
.cycle = TIME_S2I(60 * 30), // Beacon interval
.init_delay = TIME_S2I(60),
.fixed = true, // Add lat, lon alt fields when enabling fixed
.lat = -337331175, // Degrees (expressed in 1e-7 form)
.lon = 1511143478, // Degrees (expressed in 1e-7 form)
.alt = 144 // Altitude in metres
},
.radio_conf = {
.pwr = 0x7F,
.freq = FREQ_APRS_RECEIVE,
.mod = MOD_AFSK,
.cca = 0x4F
},
// App identity
.call = "DL7AD-5",
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER,
.aprs_msg = false, // Enable APRS message reception on this app
},
// Primary image app
.img_pri = {
.svc_conf = {
.active = true,
.cycle = CYCLE_CONTINUOUSLY,
.init_delay = TIME_S2I(30),
.send_spacing = TIME_S2I(10)
},
.radio_conf = {
.pwr = 0x7F,
.freq = 144800000,
.mod = MOD_AFSK,
.cca = 0x4F
},
// App identity
.call = "DL7AD-12",
.path = "",
// Image settings
.res = RES_QVGA,
.quality = 4,
.buf_size = 40 * 1024,
.redundantTx = true
},
// Secondary image app
.img_sec = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(60 * 15),
.init_delay = TIME_S2I(30 * 1),
.send_spacing = TIME_S2I(30)
},
.radio_conf = {
.pwr = 0x1F,
.freq = FREQ_APRS_DYNAMIC,
.mod = MOD_AFSK,
.cca = 0x4F
},
// App identity
.call = "DL7AD-12",
.path = "",
// Image settings
.res = RES_QVGA,
.quality = 4,
.buf_size = 15 * 1024,
.redundantTx = false
},
// Log app
.log = {
.svc_conf = {
.active = false,
.cycle = TIME_S2I(10),
.init_delay = TIME_S2I(5)
},
.radio_conf = {
.pwr = 0x7F,
.freq = FREQ_APRS_DYNAMIC,
.mod = MOD_AFSK,
.cca = 0x4F
},
// Node identity
.call = "DL7AD-13",
.path = "WIDE1-1",
.density = 10
},
// APRS app
.aprs = {
// The receive identity for APRS
.rx = {
.svc_conf = {
// The packet receive service is enabled if true
// Receive is paused and resumed by transmission
.active = false,
.init_delay = TIME_S2I(20)
},
// Receive radio configuration
.radio_conf = {
.freq = 144800000,
.mod = MOD_AFSK,
.rssi = 0x3F
},
// APRS identity used in message responses if digipeat is not enabled
.call = "DL7AD-4",
.symbol = SYM_ANTENNA
},
.aprs_msg = false, // Set true to enable messages to be accepted on RX call sign
.digi = true,
.tx = {
// Transmit radio configuration
.radio_conf = {
.freq = FREQ_APRS_RECEIVE,
.pwr = 0x7F,
.mod = MOD_AFSK,
.cca = 0x4F
},
// Digipeat transmission identity
.call = "DL7AD-5",
.path = "WIDE2-1",
.symbol = SYM_DIGIPEATER,
// A digipeater beacon can be added using one of the POS apps
// Set the POS identity the same as the dipipeater TX call sign
// Alternatively the digipeater can have its own .beacon entry here
},
},
// Global controls
// Power control
.keep_cam_switched_on = false,
.gps_on_vbat = 3600, // mV
.gps_off_vbat = 3400, // mV
.gps_onper_vbat = 4000, // mV
// GPS altitude model control (air pressure controlled using on-board BME280)
.gps_pressure = 90000, // Air pressure (Pa) threshold for alt model switch
.gps_low_alt = GPS_STATIONARY,
.gps_high_alt = GPS_AIRBORNE_1G,
// APRS
// How often to send telemetry config
.tel_enc_cycle = TIME_S2I(60 * 60 * 2),
// The default APRS frequency when geofence is not resolved
.freq = APRS_FREQ_AUSTRALIA,
// The base station identity.
.base = {
// If enabled tracker initiated APRS messages are addressed to this call sign
.enabled = false,
.call = "DL7AD-7",
.path = "WIDE2-1",
},
.magic = CONFIG_MAGIC_DEFAULT // Do not remove. This is the activation bit.
};

Wyświetl plik

@ -430,8 +430,6 @@ static bool Si446x_init(const radio_unit_t radio) {
/* TODO: We should clear interrupts here with a GET_INT_STATUS. */
/* If Si446x is using its own xtal set the trim capacitor value. */
#if !Si446x_CLK_TCXO_EN
Si446x_setProperty8(radio, Si446x_GLOBAL_XO_TUNE, 0x40);
@ -554,10 +552,8 @@ bool Si446x_setBandParameters(const radio_unit_t radio,
if(freq < 239000000UL) {outdiv = 16; band = 4;}
if(freq < 177000000UL) {outdiv = 24; band = 5;}
/* TODO: Is this redundant now?
* The radio is set in sleep versus shutdown when inactive (not receiving).
* Shutdown is only used when the channel is completely closed.
* The radio is initialized again when the channel is (re)opened.
/*
* Initialize radio.
*/
Si446x_conditional_init(radio);
@ -648,6 +644,9 @@ static void Si446x_setModemAFSK_TX(const radio_unit_t radio) {
// Use up-sampled AFSK from FIFO (PH)
Si446x_setProperty8(radio, Si446x_MODEM_MOD_TYPE, 0x02);
/* Set PH bit order for AFSK. */
Si446x_setProperty8(radio, Si446x_PKT_CONFIG1, 0x01);
// Set AFSK filter
const uint8_t coeff[] = {0x81, 0x9f, 0xc4, 0xee, 0x18, 0x3e, 0x5c, 0x70, 0x76};
uint8_t i;
@ -704,10 +703,10 @@ static void Si446x_setModemAFSK_RX(const radio_unit_t radio) {
Si446x_setProperty8(radio, Si446x_MODEM_AFC_WAIT, 0x36);
Si446x_setProperty16(radio, Si446x_MODEM_AFC_GAIN, 0x80, 0xAB);
Si446x_setProperty16(radio, Si446x_MODEM_AFC_LIMITER, 0x02, 0x50);
Si446x_setProperty8(radio, Si446x_MODEM_AFC_MISC, 0x80);
Si446x_setProperty8(radio, Si446x_MODEM_AFC_MISC, 0xC0); // 0x80
/* RX AGC control. */
Si446x_setProperty8(radio, Si446x_MODEM_AGC_CONTROL, 0xE0); // 0xE2
Si446x_setProperty8(radio, Si446x_MODEM_AGC_CONTROL, 0xE0); // 0xE2 (bit 1 not used in 4464. It is used in 4463.)
Si446x_setProperty8(radio, Si446x_MODEM_AGC_WINDOW_SIZE, 0x11);
Si446x_setProperty8(radio, Si446x_MODEM_AGC_RFPD_DECAY, 0x63);
Si446x_setProperty8(radio, Si446x_MODEM_AGC_IFPD_DECAY, 0x63);
@ -724,7 +723,7 @@ static void Si446x_setModemAFSK_RX(const radio_unit_t radio) {
Si446x_setProperty8(radio, Si446x_MODEM_IF_CONTROL, 0x08);
Si446x_setProperty24(radio, Si446x_MODEM_IF_FREQ, 0x02, 0x80, 0x00);
/* RX If filter decimation controls. */
/* RX IF filter decimation controls. */
Si446x_setProperty8(radio, Si446x_MODEM_DECIMATION_CFG1, 0x70);
Si446x_setProperty8(radio, Si446x_MODEM_DECIMATION_CFG0, 0x10);
if(is_part_Si4463(handler->radio_part)) {
@ -810,6 +809,9 @@ static void Si446x_setModem2FSK_TX(const radio_unit_t radio,
// Use 2GFSK from FIFO (PH)
Si446x_setProperty8(radio, Si446x_MODEM_MOD_TYPE, 0x03);
/* Set PH bit order for 2FSK. */
Si446x_setProperty8(radio, Si446x_PKT_CONFIG1, 0x01);
// Set 2GFSK filter (default per Si).
const uint8_t coeff[] = {0x01, 0x03, 0x08, 0x11, 0x21, 0x36, 0x4d, 0x60, 0x67};
uint8_t i;
@ -1246,9 +1248,8 @@ THD_FUNCTION(bloc_si_fifo_feeder_afsk, arg) {
chSysHalt("TX AFSK exit");
}
/* Initialize radio. */
/* TODO: This is redundant as the radio is initialized by the manager. */
//Si446x_conditional_init(radio);
/* Initialize radio as it may have been powered down. */
Si446x_conditional_init(radio);
/* Base frequency is an absolute frequency in Hz. */
Si446x_setBandParameters(radio, rto->base_frequency,
@ -1504,9 +1505,8 @@ THD_FUNCTION(bloc_si_fifo_feeder_fsk, arg) {
/* We never arrive here. */
}
/* Initialize radio.
* TODO: This is redundant as the radio is initialized by the manager. */
//Si446x_conditional_init(radio);
/* Initialize radio as it may have been powered down. */
Si446x_conditional_init(radio);
/* Set 446x back to READY from RX (if active). */
Si446x_terminateReceive(radio);

Wyświetl plik

@ -86,6 +86,8 @@
#define Si446x_SYNC_CONFIG 0x1100
#define Si446x_PKT_CONFIG1 0x1206
#define Si446x_PKT_LEN 0x1208
#define Si446x_PKT_LEN_FIELD_SOURCE 0x1209
#define Si446x_MODEM_MOD_TYPE 0x2000
#define Si446x_MODEM_MAP_CONTROL 0x2001

Wyświetl plik

@ -278,7 +278,7 @@ void usb_cmd_send_aprs_message(BaseSequentialStream *chp, int argc, char *argv[]
chprintf(chp, "Message: %s\r\n", m);
/* Send with ack request (last arg true). */
packet_t packet = aprs_transmit_message(conf_sram.aprs.tx.call,
packet_t packet = aprs_format_transmit_message(conf_sram.aprs.tx.call,
conf_sram.aprs.tx.path,
argv[0], m, true);
if(packet == NULL) {

Wyświetl plik

@ -1090,25 +1090,19 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
#endif
/*
* Indicate AFSK decode done.
* If PWM is still being captured for this stream capture will cease.
* If PWM is still being captured the capture will terminate.
*/
//eventflags_t evtf = EVT_NONE;
myDriver->active_demod_object->status |= STA_AFSK_DECODE_DONE;
/* Copy latest status into packet buffer object. */
myHandler->active_packet_object->status =
myDriver->active_demod_object->status;
/* Dispatch the packet buffer object and get AX25 events. */
myHandler->active_packet_object->status |=
pktDispatchReceivedBuffer(myHandler->active_packet_object);
/* Set AX25 status and dispatch the packet buffer object. */
pktDispatchReceivedBuffer(myHandler->active_packet_object);
/* Remove the packet object reference. */
/* Packet object has been handed over. Remove our reference. */
myHandler->active_packet_object = NULL;
/* Send events then update demod object status. */
//pktAddEventFlags(myHandler, evtf);
//myDriver->active_demod_object->status |= evtf;
} /* Active packet object != NULL. */
myDriver->decoder_state = DECODER_RESET;
break;

Wyświetl plik

@ -638,8 +638,6 @@ eventflags_t pktDispatchReceivedBuffer(pkt_data_object_t *pkt_buffer) {
/* Failed to create CB thread. Release buffer. Broadcast event. */
chFifoReturnObject(pkt_fifo, pkt_buffer);
pktAddEventFlags(handler, EVT_PKT_FAILED_CB_THD);
//flags |= EVT_PKT_FAILED_CB_THD;
} else {
/* Increase outstanding callback count. */
handler->cb_count++;

Wyświetl plik

@ -553,7 +553,7 @@ static inline bool pktIsBufferValidAX25Frame(pkt_data_object_t *object) {
*/
static inline bool pktGetAX25FrameStatus(pkt_data_object_t *object) {
chDbgAssert(object != NULL, "no pointer to packet object buffer");
return !(object->status & (STA_PKT_INVALID_FRAME | STA_PKT_CRC_ERROR));
return (object->status & (STA_PKT_INVALID_FRAME | STA_PKT_CRC_ERROR)) == 0;
}
/**

Wyświetl plik

@ -241,7 +241,7 @@ static inline msg_t pktSendRadioCommand(radio_unit_t radio,
radio_task_object_t *task,
radio_task_cb_t cb) {
radio_task_object_t *rt = NULL;
msg_t msg = pktGetRadioTaskObject(radio, TIME_MS2I(3000), &rt);
msg_t msg = pktGetRadioTaskObject(radio, TIME_INFINITE, &rt);
if(msg != MSG_OK)
return MSG_TIMEOUT;
*rt = *task;

Wyświetl plik

@ -1,244 +1,241 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2013 John Langner, WB2OSZ
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
/*------------------------------------------------------------------
*
* Name: dedupe.c
*
* Purpose: Avoid transmitting duplicate packets which are too
* close together.
*
*
* Description: We want to avoid digipeating duplicate packets to
* to help reduce radio channel congestion with
* redundant information.
* Duplicate packets can occur in several ways:
*
* (1) A digipeated packet can loop between 2 or more
* digipeaters. For example:
*
* W1ABC>APRS,WIDE3-3
* W1ABC>APRS,mycall*,WIDE3-2
* W1ABC>APRS,mycall,RPT1*,WIDE3-1
* W1ABC>APRS,mycall,RPT1,mycall*
*
* (2) We could hear our own original transmission
* repeated by someone else. Example:
*
* mycall>APRS,WIDE3-3
* mycall>APRS,RPT1*,WIDE3-2
* mycall>APRS,RPT1*,mycall*,WIDE3-1
*
* (3) We could hear the same packet from multiple
* digipeaters (with or without the original).
*
* W1ABC>APRS,WIDE3-2
* W1ABC>APRS,RPT1*,WIDE3-2
* W1ABC>APRS,RPT2*,WIDE3-2
* W1ABC>APRS,RPT3*,WIDE3-2
*
* (4) Someone could be sending the same thing over and
* over with very little delay in between.
*
* W1ABC>APRS,WIDE3-3
* W1ABC>APRS,WIDE3-3
* W1ABC>APRS,WIDE3-3
*
* We can catch the first two by looking for 'mycall' in
* the source or digipeater fields.
*
* The other two cases require us to keep a record of what
* we transmitted recently and test for duplicates that
* should be dropped.
*
* Once we have the solution to catch cases (3) and (4)
* there is no reason for the special case of looking for
* mycall. The same technique catches all four situations.
*
* For detecting duplicates, we need to look
* + source station
* + destination
* + information field
* but NOT the changing list of digipeaters.
*
* Typically, only a checksum is kept to reduce memory
* requirements and amount of compution for comparisons.
* There is a very very small probability that two unrelated
* packets will result in the same checksum, and the
* undesired dropping of the packet.
*
* References: Original APRS specification:
*
* TBD...
*
* "The New n-N Paradigm"
*
* http://www.aprs.org/fix14439.html
*
*------------------------------------------------------------------*/
#define DEDUPE_C
#include "ch.h"
#include "hal.h"
#include <stdlib.h>
#include <string.h>
#include "ax25_pad.h"
#include "dedupe.h"
#include "fcs_calc.h"
/*------------------------------------------------------------------------------
*
* Name: dedupe_init
*
* Purpose: Initialize the duplicate detection subsystem.
*
* Input: ttl - Number of seconds to retain information
* about recent transmissions.
*
*
* Returns: None
*
* Description: This should be called at application startup.
*
*
*------------------------------------------------------------------------------*/
static sysinterval_t history_time = 30; /* Number of seconds to keep information */
/* about recent transmissions. */
#define HISTORY_MAX 25 /* Maximum number of transmission */
/* records to keep. If we run out of */
/* room the oldest ones are overwritten */
/* before they expire. */
static int insert_next; /* Index, in array below, where next */
/* item should be stored. */
static struct {
sysinterval_t time_stamp; /* When the packet was transmitted. */
unsigned short checksum; /* Some sort of checksum for the */
/* source, destination, and information. */
/* is is not used anywhere else. */
short xmit_channel; /* Radio channel number. */
} history[HISTORY_MAX];
void dedupe_init (sysinterval_t ttl)
{
history_time = ttl;
insert_next = 0;
memset (history, 0, sizeof(history));
}
/*------------------------------------------------------------------------------
*
* Name: dedupe_remember
*
* Purpose: Save information about a packet being transmitted so we
* can detect, and avoid, duplicates later.
*
* Input: pp - Pointer to packet object.
*
* chan - Radio channel for transmission.
*
* Returns: None
*
* Rambling: At one time, my thinking is that we want to keep track of
* ALL transmitted packets regardless of origin or type.
*
* + my beacons
* + anything from a connected application
* + anything digipeated
*
* The easiest way to catch all cases is to call dedup_remember()
* from inside tq_append().
*
* But I don't think that is the right approach.
* When acting as a KISS TNC, we should just shovel everything
* through and not question what the application is doing.
* If the connected application has a digipeating function,
* it's responsible for those decisions.
*
* My current thinking is that dedupe_remember() should be
* called BEFORE tq_append() in the digipeater case.
*
* We should also capture our own beacon transmissions.
*
*------------------------------------------------------------------------------*/
void dedupe_remember (packet_t pp, int chan)
{
history[insert_next].time_stamp = chVTGetSystemTime();
history[insert_next].checksum = ax25_dedupe_crc(pp);
history[insert_next].xmit_channel = chan;
insert_next++;
if (insert_next >= HISTORY_MAX) {
insert_next = 0;
}
/* If we send something by digipeater, we don't */
/* want to do it again if it comes from APRS-IS. */
/* Not sure about the other way around. */
}
/*------------------------------------------------------------------------------
*
* Name: dedupe_check
*
* Purpose: Check whether this is a duplicate of another sent recently.
*
* Input: pp - Pointer to packet object.
*
* chan - Radio channel for transmission.
*
* Returns: True if it is a duplicate.
*
*
*------------------------------------------------------------------------------*/
int dedupe_check (packet_t pp, int chan)
{
unsigned short crc = ax25_dedupe_crc(pp);
sysinterval_t now = chVTGetSystemTime();
int j;
for (j=0; j<HISTORY_MAX; j++) {
if (history[j].time_stamp >= now - history_time &&
history[j].checksum == crc &&
history[j].xmit_channel == chan) {
return 1;
}
}
return 0;
}
/* end dedupe.c */
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2013 John Langner, WB2OSZ
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
/*------------------------------------------------------------------
*
* Name: dedupe.c
*
* Purpose: Avoid transmitting duplicate packets which are too
* close together.
*
*
* Description: We want to avoid digipeating duplicate packets
* to help reduce radio channel congestion with
* redundant information.
* Duplicate packets can occur in several ways:
*
* (1) A digipeated packet can loop between 2 or more
* digipeaters. For example:
*
* W1ABC>APRS,WIDE3-3
* W1ABC>APRS,mycall*,WIDE3-2
* W1ABC>APRS,mycall,RPT1*,WIDE3-1
* W1ABC>APRS,mycall,RPT1,mycall*
*
* (2) We could hear our own original transmission
* repeated by someone else. Example:
*
* mycall>APRS,WIDE3-3
* mycall>APRS,RPT1*,WIDE3-2
* mycall>APRS,RPT1*,mycall*,WIDE3-1
*
* (3) We could hear the same packet from multiple
* digipeaters (with or without the original).
*
* W1ABC>APRS,WIDE3-2
* W1ABC>APRS,RPT1*,WIDE3-2
* W1ABC>APRS,RPT2*,WIDE3-2
* W1ABC>APRS,RPT3*,WIDE3-2
*
* (4) Someone could be sending the same thing over and
* over with very little delay in between.
*
* W1ABC>APRS,WIDE3-3
* W1ABC>APRS,WIDE3-3
* W1ABC>APRS,WIDE3-3
*
* We can catch the first two by looking for 'mycall' in
* the source or digipeater fields.
*
* The other two cases require us to keep a record of what
* we transmitted recently and test for duplicates that
* should be dropped.
*
* Once we have the solution to catch cases (3) and (4)
* there is no reason for the special case of looking for
* mycall. The same technique catches all four situations.
*
* For detecting duplicates, we need to look
* + source station
* + destination
* + information field
* but NOT the changing list of digipeaters.
*
* Typically, only a checksum is kept to reduce memory
* requirements and amount of compution for comparisons.
* There is a very very small probability that two unrelated
* packets will result in the same checksum, and the
* undesired dropping of the packet.
*
* References: Original APRS specification:
*
* TBD...
*
* "The New n-N Paradigm"
*
* http://www.aprs.org/fix14439.html
*
*------------------------------------------------------------------*/
#define DEDUPE_C
#include "ch.h"
#include "hal.h"
#include <stdlib.h>
#include <string.h>
#include "ax25_pad.h"
#include "dedupe.h"
#include "fcs_calc.h"
/*------------------------------------------------------------------------------
*
* Name: dedupe_init
*
* Purpose: Initialize the duplicate detection subsystem.
*
* Input: ttl - Number of seconds to retain information
* about recent transmissions.
*
*
* Returns: None
*
* Description: This should be called at application startup.
*
*
*------------------------------------------------------------------------------*/
/* Number of seconds to keep history information */
static sysinterval_t history_time;
#define HISTORY_MAX 25 /* Maximum number of transmission */
/* records to keep. If we run out of */
/* room the oldest ones are overwritten */
/* before they expire. */
static int insert_next; /* Index, in array below, where next */
/* item should be stored. */
static struct {
sysinterval_t time_stamp; /* When the packet was transmitted. */
unsigned short checksum; /* Some sort of checksum for the */
/* source, destination, and information. */
/* is is not used anywhere else. */
short xmit_channel; /* Radio channel number. */
} history[HISTORY_MAX];
void dedupe_init (sysinterval_t ttl) {
history_time = ttl;
insert_next = 0;
memset (history, 0, sizeof(history));
}
/*------------------------------------------------------------------------------
*
* Name: dedupe_remember
*
* Purpose: Save information about a packet being transmitted so we
* can detect, and avoid, duplicates later.
*
* Input: pp - Pointer to packet object.
*
* chan - Radio channel for transmission.
*
* Returns: None
*
* Rambling: At one time, my thinking is that we want to keep track of
* ALL transmitted packets regardless of origin or type.
*
* + my beacons
* + anything from a connected application
* + anything digipeated
*
* The easiest way to catch all cases is to call dedup_remember()
* from inside tq_append().
*
* But I don't think that is the right approach.
* When acting as a KISS TNC, we should just shovel everything
* through and not question what the application is doing.
* If the connected application has a digipeating function,
* it's responsible for those decisions.
*
* My current thinking is that dedupe_remember() should be
* called BEFORE tq_append() in the digipeater case.
*
* We should also capture our own beacon transmissions.
*
*------------------------------------------------------------------------------*/
void dedupe_remember (packet_t pp, int chan) {
history[insert_next].time_stamp = chVTGetSystemTime();
history[insert_next].checksum = ax25_dedupe_crc(pp);
history[insert_next].xmit_channel = chan;
insert_next++;
if (insert_next >= HISTORY_MAX) {
insert_next = 0;
}
/* If we send something by digipeater, we don't */
/* want to do it again if it comes from APRS-IS. */
/* Not sure about the other way around. */
}
/*------------------------------------------------------------------------------
*
* Name: dedupe_check
*
* Purpose: Check whether this is a duplicate of another sent recently.
*
* Input: pp - Pointer to packet object.
*
* chan - Radio channel for transmission.
*
* Returns: True if it is a duplicate.
*
*
*------------------------------------------------------------------------------*/
int dedupe_check (packet_t pp, int chan) {
unsigned short crc = ax25_dedupe_crc(pp);
///sysinterval_t now = chVTGetSystemTime();
int j;
for (j=0; j<HISTORY_MAX; j++) {
if (chVTTimeElapsedSinceX(history[j].time_stamp) > history_time &&
history[j].checksum == crc &&
history[j].xmit_channel == chan) {
return 1;
}
}
return 0;
}
/* end dedupe.c */

Wyświetl plik

@ -1,337 +1,339 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2013, 2014, 2015 John Langner, WB2OSZ
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
/*------------------------------------------------------------------
*
* Name: digipeater.c
*
* Purpose: Act as an APRS digital repeater.
* Similar cdigipeater.c is for connected mode.
*
*
* Description: Decide whether the specified packet should
* be digipeated and make necessary modifications.
*
*
* References: APRS Protocol Reference, document version 1.0.1
*
* http://www.aprs.org/doc/APRS101.PDF
*
* APRS SPEC Addendum 1.1
*
* http://www.aprs.org/aprs11.html
*
* APRS SPEC Addendum 1.2
*
* http://www.aprs.org/aprs12.html
*
* "The New n-N Paradigm"
*
* http://www.aprs.org/fix14439.html
*
* Preemptive Digipeating (new in version 0.8)
*
* http://www.aprs.org/aprs12/preemptive-digipeating.txt
*
*------------------------------------------------------------------*/
#define DIGIPEATER_C
#include "ch.h"
#include "hal.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h> /* for isdigit, isupper */
#include "crx.h"
#include "ax25_pad.h"
#include "digipeater.h"
#include "dedupe.h"
#include "fcs_calc.h"
#include "debug.h"
/*------------------------------------------------------------------------------
*
* Name: digipeat_match
*
* Purpose: A simple digipeater for APRS.
*
* Input: pp - Pointer to a packet object.
*
* mycall_rec - Call of my station, with optional SSID,
* associated with the radio channel where the
* packet was received.
*
* mycall_xmit - Call of my station, with optional SSID,
* associated with the radio channel where the
* packet is to be transmitted. Could be the same as
* mycall_rec or different.
*
* alias - Compiled pattern for my station aliases or
* "trapping" (repeating only once).
*
* wide - Compiled pattern for normal WIDEn-n digipeating.
*
* to_chan - Channel number that we are transmitting to.
* This is needed to maintain a history for
* removing duplicates during specified time period.
*
* preempt - Option for "preemptive" digipeating.
*
* filter_str - Filter expression string or NULL.
*
* Returns: Packet object for transmission or NULL.
* The original packet is not modified. (with one exception, probably obsolete)
* We make a copy and return that modified copy!
* This is very important because we could digipeat from one channel to many.
*
* Description: The packet will be digipeated if the next unused digipeater
* field matches one of the following:
*
* - mycall_rec
* - udigi list (only once)
* - wide list (usual wideN-N rules)
*
*------------------------------------------------------------------------------*/
packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, char *mycall_xmit, char *alias, char *wide, int to_chan, enum preempt_e preempt, char *filter_str)
{
(void)from_chan;
(void)filter_str;
char source[AX25_MAX_ADDR_LEN];
int ssid;
int r;
char repeater[AX25_MAX_ADDR_LEN];
int found_len;
/*
* Find the first repeater station which doesn't have "has been repeated" set.
*
* r = index of the address position in the frame.
*/
r = ax25_get_first_not_repeated(pp);
if (r < AX25_REPEATER_1) {
return (NULL);
}
ax25_get_addr_with_ssid(pp, r, repeater);
ssid = ax25_get_ssid(pp, r);
/*
* First check for explicit use of my call, including SSID.
* Someone might explicitly specify a particular path for testing purposes.
* This will bypass the usual checks for duplicates and my call in the source.
*
* In this case, we don't check the history so it would be possible
* to have a loop (of limited size) if someone constructed the digipeater paths
* correctly. I would expect it only for testing purposes.
*/
if (strcmp(repeater, mycall_rec) == 0) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
/* If using multiple radio channels, they */
/* could have different calls. */
ax25_set_addr (result, r, mycall_xmit);
ax25_set_h (result, r);
return (result);
}
/*
* Don't digipeat my own. Fixed in 1.4 dev H.
* Alternatively we might feed everything transmitted into
* dedupe_remember rather than only frames out of digipeater.
*/
ax25_get_addr_with_ssid(pp, AX25_SOURCE, source);
if (strcmp(source, mycall_rec) == 0) {
return (NULL);
}
/*
* Next try to avoid retransmitting redundant information.
* Duplicates are detected by comparing only:
* - source
* - destination
* - info part
* - but not the via path. (digipeater addresses)
* A history is kept for some amount of time, typically 30 seconds.
* For efficiency, only a checksum, rather than the complete fields
* might be kept but the result is the same.
* Packets transmitted recently will not be transmitted again during
* the specified time period.
*
*/
if (dedupe_check(pp, to_chan)) {
//#if DEBUG
/* Might be useful if people are wondering why */
/* some are not repeated. Might also cause confusion. */
TRACE_DEBUG("Digipeater: Drop redundant packet to channel %d.\n", to_chan);
//#endif
return NULL;
}
/*
* For the alias pattern, we unconditionally digipeat it once.
* i.e. Just replace it with MYCALL.
*
* My call should be an implied member of this set.
* In this implementation, we already caught it further up.
*/
regex(alias, repeater, &found_len);
if(found_len) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
ax25_set_addr (result, r, mycall_xmit);
ax25_set_h (result, r);
return (result);
}
/*
* If preemptive digipeating is enabled, try matching my call
* and aliases against all remaining unused digipeaters.
*/
if (preempt != PREEMPT_OFF) {
int r2;
for (r2 = r+1; r2 < ax25_get_num_addr(pp); r2++) {
char repeater2[AX25_MAX_ADDR_LEN];
ax25_get_addr_with_ssid(pp, r2, repeater2);
regex(alias, repeater2, &found_len);
if (strcmp(repeater2, mycall_rec) == 0 ||
found_len != 0) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
ax25_set_addr (result, r2, mycall_xmit);
ax25_set_h (result, r2);
switch (preempt) {
case PREEMPT_DROP: /* remove all prior */
while (r2 > AX25_REPEATER_1) {
ax25_remove_addr (result, r2-1);
r2--;
}
break;
case PREEMPT_MARK:
r2--;
while (r2 >= AX25_REPEATER_1 && ax25_get_h(result,r2) == 0) {
ax25_set_h (result, r2);
r2--;
}
break;
case PREEMPT_TRACE: /* remove prior unused */
default:
while (r2 > AX25_REPEATER_1 && ax25_get_h(result,r2-1) == 0) {
ax25_remove_addr (result, r2-1);
r2--;
}
break;
}
return (result);
}
}
}
/*
* For the wide pattern, we check the ssid and decrement it.
*/
regex(wide, repeater, &found_len);
if (found_len != 0) {
/*
* If ssid == 1, we simply replace the repeater with my call and
* mark it as being used.
*
* Otherwise, if ssid in range of 2 to 7,
* Decrement y and don't mark repeater as being used.
* Insert own call ahead of this one for tracing if we don't already have the
* maximum number of repeaters.
*/
if (ssid == 1) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
ax25_set_addr (result, r, mycall_xmit);
ax25_set_h (result, r);
return (result);
}
if (ssid >= 2 && ssid <= 7) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
ax25_set_ssid(result, r, ssid-1); // should be at least 1
if (ax25_get_num_repeaters(pp) < AX25_MAX_REPEATERS) {
ax25_insert_addr (result, r, mycall_xmit);
ax25_set_h (result, r);
}
return (result);
}
}
/*
* Don't repeat it if we get here.
*/
return (NULL);
}
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2013, 2014, 2015 John Langner, WB2OSZ
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
/*------------------------------------------------------------------
*
* Name: digipeater.c
*
* Purpose: Act as an APRS digital repeater.
* Similar cdigipeater.c is for connected mode.
*
*
* Description: Decide whether the specified packet should
* be digipeated and make necessary modifications.
*
*
* References: APRS Protocol Reference, document version 1.0.1
*
* http://www.aprs.org/doc/APRS101.PDF
*
* APRS SPEC Addendum 1.1
*
* http://www.aprs.org/aprs11.html
*
* APRS SPEC Addendum 1.2
*
* http://www.aprs.org/aprs12.html
*
* "The New n-N Paradigm"
*
* http://www.aprs.org/fix14439.html
*
* Preemptive Digipeating (new in version 0.8)
*
* http://www.aprs.org/aprs12/preemptive-digipeating.txt
*
*------------------------------------------------------------------*/
#define DIGIPEATER_C
#include "ch.h"
#include "hal.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h> /* for isdigit, isupper */
#include "crx.h"
#include "ax25_pad.h"
#include "digipeater.h"
#include "dedupe.h"
#include "fcs_calc.h"
#include "debug.h"
/*------------------------------------------------------------------------------
*
* Name: digipeat_match
*
* Purpose: A simple digipeater for APRS.
*
* Input: pp - Pointer to a packet object.
*
* mycall_rec - Call of my station, with optional SSID,
* associated with the radio channel where the
* packet was received.
*
* mycall_xmit - Call of my station, with optional SSID,
* associated with the radio channel where the
* packet is to be transmitted. Could be the same as
* mycall_rec or different.
*
* alias - Compiled pattern for my station aliases or
* "trapping" (repeating only once).
*
* wide - Compiled pattern for normal WIDEn-n digipeating.
*
* to_chan - Channel number that we are transmitting to.
* This is needed to maintain a history for
* removing duplicates during specified time period.
*
* preempt - Option for "preemptive" digipeating.
*
* filter_str - Filter expression string or NULL.
*
* Returns: Packet object for transmission or NULL.
* The original packet is not modified. (with one exception, probably obsolete)
* We make a copy and return that modified copy!
* This is very important because we could digipeat from one channel to many.
*
* Description: The packet will be digipeated if the next unused digipeater
* field matches one of the following:
*
* - mycall_rec
* - udigi list (only once)
* - wide list (usual wideN-N rules)
*
*------------------------------------------------------------------------------*/
packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec,
char *mycall_xmit, char *alias, char *wide,
int to_chan, enum preempt_e preempt,
char *filter_str) {
(void)from_chan;
(void)filter_str;
char source[AX25_MAX_ADDR_LEN];
int ssid;
int r;
char repeater[AX25_MAX_ADDR_LEN];
int found_len;
/*
* Find the first repeater station which doesn't have "has been repeated" set.
*
* r = index of the address position in the frame.
*/
r = ax25_get_first_not_repeated(pp);
if (r < AX25_REPEATER_1) {
return (NULL);
}
ax25_get_addr_with_ssid(pp, r, repeater);
ssid = ax25_get_ssid(pp, r);
/*
* First check for explicit use of my call, including SSID.
* Someone might explicitly specify a particular path for testing purposes.
* This will bypass the usual checks for duplicates and my call in the source.
*
* In this case, we don't check the history so it would be possible
* to have a loop (of limited size) if someone constructed the digipeater paths
* correctly. I would expect it only for testing purposes.
*/
if (strcmp(repeater, mycall_rec) == 0) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
/* If using multiple radio channels, they */
/* could have different calls. */
ax25_set_addr (result, r, mycall_xmit);
ax25_set_h (result, r);
return (result);
}
/*
* Don't digipeat my own. Fixed in 1.4 dev H.
* Alternatively we might feed everything transmitted into
* dedupe_remember rather than only frames out of digipeater.
*/
ax25_get_addr_with_ssid(pp, AX25_SOURCE, source);
if (strcmp(source, mycall_rec) == 0) {
return (NULL);
}
/*
* Next try to avoid retransmitting redundant information.
* Duplicates are detected by comparing only:
* - source
* - destination
* - info part
* - but not the via path. (digipeater addresses)
* A history is kept for some amount of time, typically 30 seconds.
* For efficiency, only a checksum, rather than the complete fields
* might be kept but the result is the same.
* Packets transmitted recently will not be transmitted again during
* the specified time period.
*
*/
if (dedupe_check(pp, to_chan)) {
//#if DEBUG
/* Might be useful if people are wondering why */
/* some are not repeated. Might also cause confusion. */
TRACE_DEBUG("Digipeater: Drop redundant packet to channel %d.\n", to_chan);
//#endif
return NULL;
}
/*
* For the alias pattern, we unconditionally digipeat it once.
* i.e. Just replace it with MYCALL.
*
* My call should be an implied member of this set.
* In this implementation, we already caught it further up.
*/
regex(alias, repeater, &found_len);
if(found_len) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
ax25_set_addr (result, r, mycall_xmit);
ax25_set_h (result, r);
return (result);
}
/*
* If preemptive digipeating is enabled, try matching my call
* and aliases against all remaining unused digipeaters.
*/
if (preempt != PREEMPT_OFF) {
int r2;
for (r2 = r+1; r2 < ax25_get_num_addr(pp); r2++) {
char repeater2[AX25_MAX_ADDR_LEN];
ax25_get_addr_with_ssid(pp, r2, repeater2);
regex(alias, repeater2, &found_len);
if (strcmp(repeater2, mycall_rec) == 0 ||
found_len != 0) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
ax25_set_addr (result, r2, mycall_xmit);
ax25_set_h (result, r2);
switch (preempt) {
case PREEMPT_DROP: /* remove all prior */
while (r2 > AX25_REPEATER_1) {
ax25_remove_addr (result, r2-1);
r2--;
}
break;
case PREEMPT_MARK:
r2--;
while (r2 >= AX25_REPEATER_1 && ax25_get_h(result,r2) == 0) {
ax25_set_h (result, r2);
r2--;
}
break;
case PREEMPT_TRACE: /* remove prior unused */
default:
while (r2 > AX25_REPEATER_1 && ax25_get_h(result,r2-1) == 0) {
ax25_remove_addr (result, r2-1);
r2--;
}
break;
}
return (result);
}
}
}
/*
* For the wide pattern, we check the ssid and decrement it.
*/
regex(wide, repeater, &found_len);
if (found_len != 0) {
/*
* If ssid == 1, we simply replace the repeater with my call and
* mark it as being used.
*
* Otherwise, if ssid in range of 2 to 7,
* Decrement y and don't mark repeater as being used.
* Insert own call ahead of this one for tracing if we don't already have the
* maximum number of repeaters.
*/
if (ssid == 1) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
ax25_set_addr (result, r, mycall_xmit);
ax25_set_h (result, r);
return (result);
}
if (ssid >= 2 && ssid <= 7) {
packet_t result;
result = ax25_dup (pp);
if(result == NULL)
return NULL;
ax25_set_ssid(result, r, ssid-1); // should be at least 1
if (ax25_get_num_repeaters(pp) < AX25_MAX_REPEATERS) {
ax25_insert_addr (result, r, mycall_xmit);
ax25_set_h (result, r);
}
return (result);
}
}
/*
* Don't repeat it if we get here.
*/
return (NULL);
}

Wyświetl plik

@ -531,7 +531,7 @@ packet_t aprs_encode_data_packet(const char *callsign, const char *path,
* @param[in text text of the message
* @param[in] ack true if message acknowledgment requested
*/
packet_t aprs_transmit_message(const char *originator, const char *path,
packet_t aprs_format_transmit_message(const char *originator, const char *path,
const char *recipient, const char *text,
const bool ack) {
char xmit[256];
@ -560,7 +560,7 @@ packet_t aprs_transmit_message(const char *originator, const char *path,
/*
* @brief Compose an APRSD message
* @notes Used by position service.
* @notes Used by beacon service.
*
* @param[in] originator originator of this message
* @param[in] path path to use
@ -585,7 +585,7 @@ packet_t aprs_compose_aprsd_message(const char *originator,
buf[out-1] = 0; // Remove last space
}
return aprs_transmit_message(originator, path, recipient, buf, false);
return aprs_format_transmit_message(originator, path, recipient, buf, false);
}
/*
@ -606,7 +606,7 @@ msg_t aprs_send_aprsd_message(aprs_identity_t *id,
packet_t pp = aprs_compose_aprsd_message(id->call, id->path, id->src);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
TRACE_WARN("TX > APRSD: No free packet objects or badly formed message");
return MSG_ERROR;
}
if(!transmitOnRadio(pp,
@ -616,7 +616,7 @@ msg_t aprs_send_aprsd_message(aprs_identity_t *id,
id->pwr,
id->mod,
id->cca)) {
TRACE_ERROR("RX > Transmit of APRSD failed");
TRACE_ERROR("TX > APRSD: Transmit failed");
return MSG_ERROR;
}
return MSG_OK;
@ -641,23 +641,25 @@ msg_t aprs_send_aprsh_message(aprs_identity_t *id,
uint32_t out = 0;
strupr(argv[0]);
for(uint8_t i = 0; i < APRS_HEARD_LIST_SIZE; i++) {
if(heard_list[i].time && (strncmp(heard_list[i].call, argv[0],
strlen(argv[0])) == 0)) {
/* Convert time to human readable form. */
time_secs_t diff = chTimeI2S(chVTTimeElapsedSinceX(heard_list[i].time));
out = chsnprintf(buf, sizeof(buf),
"%s heard %02i:%02i ago",
heard_list[i].call, diff/60, diff % 60);
break;
}
if(out == 0) {
out = chsnprintf(buf, sizeof(buf),
"%s not heard", argv[0]);
}
if(heard_list[i].time && (strncmp(heard_list[i].call, argv[0],
strlen(argv[0])) == 0)) {
/* Convert time to human readable form. */
time_secs_t diff = chTimeI2S(chVTTimeElapsedSinceX(heard_list[i].time));
out = chsnprintf(buf, sizeof(buf),
"%s heard %02i:%02i ago",
heard_list[i].call, diff/60, diff % 60);
break;
}
if(out == 0) {
out = chsnprintf(buf, sizeof(buf),
"%s not heard", argv[0]);
}
}
packet_t pp = aprs_transmit_message(id->call, id->path, id->src, buf, false);
TRACE_INFO("TX > APRSH response: %s", buf);
packet_t pp = aprs_format_transmit_message(id->call, id->path, id->src,
buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
TRACE_WARN("TX > APRSH: No free packet objects or badly formed message");
return MSG_ERROR;
}
if(!transmitOnRadio(pp,
@ -667,7 +669,7 @@ msg_t aprs_send_aprsh_message(aprs_identity_t *id,
id->pwr,
id->mod,
id->cca)) {
TRACE_ERROR("RX > Transmit of APRSH failed");
TRACE_ERROR("TX > APRSH: Transmit failed");
return MSG_ERROR;
}
return MSG_OK;
@ -762,7 +764,7 @@ msg_t aprs_execute_gpio_command(aprs_identity_t *id,
(pktReadGPIOline(LINE_IO1) == PAL_HIGH) ? "HIGH" : "LOW");
TRACE_INFO("RX > Message: GPIO query IO1 is %s",
(pktReadGPIOline(LINE_IO1) == PAL_HIGH) ? "HIGH" : "LOW");
pp = aprs_transmit_message(id->call, id->path, id->src, buf, false);
pp = aprs_format_transmit_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
@ -778,7 +780,7 @@ msg_t aprs_execute_gpio_command(aprs_identity_t *id,
(pktReadGPIOline(LINE_IO2) == PAL_HIGH) ? "HIGH" : "LOW");
TRACE_INFO("RX > Message: GPIO query IO2 is %s",
(pktReadGPIOline(LINE_IO2) == PAL_HIGH) ? "HIGH" : "LOW");
pp = aprs_transmit_message(id->call, id->path, id->src, buf, false);
pp = aprs_format_transmit_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
@ -794,7 +796,7 @@ msg_t aprs_execute_gpio_command(aprs_identity_t *id,
(pktReadGPIOline(LINE_IO3) == PAL_HIGH) ? "HIGH" : "LOW");
TRACE_INFO("RX > Message: GPIO query IO3 is %s",
(pktReadGPIOline(LINE_IO3) == PAL_HIGH) ? "HIGH" : "LOW");
pp = aprs_transmit_message(id->call, id->path, id->src, buf, false);
pp = aprs_format_transmit_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
@ -810,7 +812,7 @@ msg_t aprs_execute_gpio_command(aprs_identity_t *id,
(pktReadGPIOline(LINE_IO4) == PAL_HIGH) ? "HIGH" : "LOW");
TRACE_INFO("RX > Message: GPIO query IO4 is %s",
(pktReadGPIOline(LINE_IO4) == PAL_HIGH) ? "HIGH" : "LOW");
pp = aprs_transmit_message(id->call, id->path, id->src, buf, false);
pp = aprs_format_transmit_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
@ -865,7 +867,7 @@ msg_t aprs_transmit_telemetry_response(aprs_identity_t *id,
*aprsd = *id->beacon;
aprsd->run_once = true;
aprsd->beacon.init_delay = 0;
thread_t *th = start_beacon_thread(aprsd, "APRSD");
thread_t *th = start_beacon_thread(aprsd, "APRSP");
if(th == NULL) {
chHeapFree(aprsd);
return MSG_ERROR;
@ -893,7 +895,7 @@ msg_t aprs_execute_system_reset(aprs_identity_t *id,
TRACE_INFO("RX > Message: System Reset");
char buf[16];
chsnprintf(buf, sizeof(buf), "ack%s", id->num);
packet_t pp = aprs_transmit_message(id->call,
packet_t pp = aprs_format_transmit_message(id->call,
id->path,
id->src, buf, false);
if(pp == NULL) {
@ -1147,7 +1149,7 @@ static bool aprs_decode_message(packet_t pp) {
/*&& (conf_sram.aprs.digi.active)*/;
/* Default already set tx parameters. */
/* Check if this is message and address is one of the apps on this device. */
/* Check for a message with address being one of the apps on this device. */
if(!((pinfo[10] == ':') && (pos_pri || pos_sec || aprs_rx || aprs_tx))) {
/*
* Not a command or not addressed to one of the active apps on this device.
@ -1158,7 +1160,6 @@ static bool aprs_decode_message(packet_t pp) {
/* Proceed with command analysis. */
char msg_id_rx[8] = {0};
//memset(msg_id_rx, 0, sizeof(msg_id_rx));
// Cut off control chars
for(uint16_t i = 11; pinfo[i] != 0
@ -1208,7 +1209,7 @@ static bool aprs_decode_message(packet_t pp) {
int n = 0;
while ((lp = aprs_parse_arguments(NULL, &tokp)) != NULL) {
if (n >= APRS_MAX_MSG_ARGUMENTS) {
TRACE_INFO("RX > Too many APRS command arguments");
TRACE_WARN("RX > Too many APRS command arguments");
cmd = NULL;
break;
}
@ -1233,7 +1234,7 @@ static bool aprs_decode_message(packet_t pp) {
* Use the receiving node identity as sender.
* Don't request acknowledgment.
*/
packet_t pp = aprs_transmit_message(identity.call,
packet_t pp = aprs_format_transmit_message(identity.call,
identity.path,
identity.src, buf, false);
if(pp == NULL) {
@ -1266,7 +1267,8 @@ static void aprs_digipeat(packet_t pp) {
conf_sram.aprs.tx.call, alias_re,
wide_re, 0, preempt, NULL);
if(result != NULL) { // Should be digipeated
dedupe_remember(result, 0);
/* Remember the transmission. Frequency may be a code or absolute. */
dedupe_remember(result, conf_sram.aprs.tx.radio_conf.freq);
/* If transmit fails the packet buffer is released. */
if(!transmitOnRadio(result,
conf_sram.aprs.tx.radio_conf.freq,
@ -1289,15 +1291,15 @@ packet_t aprs_encode_telemetry_configuration(const char *originator,
const char *destination,
uint8_t type) {
switch(type) {
case 0: return aprs_transmit_message(originator, path, destination,
case 0: return aprs_format_transmit_message(originator, path, destination,
"PARM.Vbat,Vsol,Pbat,Temp,AirP,"
"IO1,IO2,IO3,IO4,IO5,IO6,IO7,IO8", false);
case 1: return aprs_transmit_message(originator, path, destination,
case 1: return aprs_format_transmit_message(originator, path, destination,
"UNIT.V,V,W,degC,Pa,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi", false);
case 2: return aprs_transmit_message(originator, path, destination,
case 2: return aprs_format_transmit_message(originator, path, destination,
"EQNS.0,0.001,0,0,0.001,0,0,0.001,"
"-4.096,0,0.1,-100,0,12.5,500", false);
case 3: return aprs_transmit_message(originator, path, destination,
case 3: return aprs_format_transmit_message(originator, path, destination,
"BITS.11111111,Pecan Pico", false);
default: return NULL;
}
@ -1341,18 +1343,15 @@ void aprs_decode_packet(packet_t pp) {
}
// Decode message packets
bool digipeat = true;
unsigned char *pinfo;
if(ax25_get_info(pp, &pinfo) == 0)
return;
/*
* Check if the message is for us.
* Check if this is a message and is for us.
* Execute any command found in the message.
* If not then digipeat it.
*/
if(pinfo[0] == ':') {
digipeat = aprs_decode_message(pp); // ax25_get_dti(pp)
}
bool digipeat = (pinfo[0] == ':' ? aprs_decode_message(pp) : true);
// Digipeat packet
if(conf_sram.aprs.digi && digipeat) {

Wyświetl plik

@ -102,7 +102,7 @@ extern "C" {
const char *path,
const char *destination,
uint8_t type);
packet_t aprs_transmit_message(const char *callsign, const char *path,
packet_t aprs_format_transmit_message(const char *callsign, const char *path,
const char *receiver, const char *text,
const bool ack);
packet_t aprs_encode_data_packet(const char *callsign, const char *path,

Wyświetl plik

@ -525,7 +525,8 @@ THD_FUNCTION(collectorThread, arg) {
* The RTC is not set.
* Enable the GPS and attempt a lock which results in setting the RTC.
*/
TRACE_INFO("COLL > Attempt time acquisition using GPS for 60 seconds");
TRACE_INFO("COLL > Attempt time acquisition using GPS for %d seconds",
chTimeI2S(gps_wait_time));
if(aquirePosition(tp, ltp, gps_wait_time)) {
/* Acquisition succeeded. */