kopia lustrzana https://github.com/DL7AD/pecanpico10
Follow up to prior commit with additional files.
rodzic
b878ce6977
commit
1fefc9818d
|
@ -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
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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.
|
||||
};
|
|
@ -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.
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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. */
|
||||
|
|
Ładowanie…
Reference in New Issue