kopia lustrzana https://github.com/DL7AD/pecanpico10
Improve error checking for packet buffers. Improve 446x driver.
rodzic
e329bbb2bf
commit
b33c2ebe46
|
|
@ -24,7 +24,7 @@ const conf_t conf_flash_default = {
|
|||
.preamble = 200
|
||||
},
|
||||
|
||||
.call = "VK2GJ-15",
|
||||
.call = "VK2GJ-12",
|
||||
.path = "WIDE2-1",
|
||||
.symbol = SYM_DIGIPEATER,
|
||||
|
||||
|
|
@ -63,9 +63,9 @@ const conf_t conf_flash_default = {
|
|||
},
|
||||
.radio_conf = {
|
||||
.pwr = 0x7F,
|
||||
.freq = 144800000,
|
||||
.freq = 144000000,
|
||||
.step = 12500,
|
||||
.chan = 0,
|
||||
.chan = 64,
|
||||
.mod = MOD_2FSK,
|
||||
.preamble = 200,
|
||||
.redundantTx = true
|
||||
|
|
@ -135,7 +135,7 @@ const conf_t conf_flash_default = {
|
|||
.preamble = 200
|
||||
},
|
||||
|
||||
.call = "VK2GJ-15",
|
||||
.call = "VK2GJ-4",
|
||||
.path = "WIDE2-1",
|
||||
.symbol = SYM_DIGIPEATER
|
||||
},
|
||||
|
|
|
|||
|
|
@ -599,8 +599,6 @@ static bool Si446x_transmit(radio_unit_t radio,
|
|||
// Transmit
|
||||
TRACE_INFO("SI > Tune Si446x (TX)");
|
||||
Si446x_setReadyState(radio);
|
||||
/* Set band parameters back to normal TX. */
|
||||
//Si446x_setBandParameters(radio, freq, step); // Set frequency
|
||||
Si446x_setPowerLevel(power); // Set power level
|
||||
Si446x_setTXState(radio, chan, size);
|
||||
|
||||
|
|
@ -727,119 +725,14 @@ void Si446x_pauseReceive(radio_unit_t radio) {
|
|||
|
||||
/* ==================================================================== AFSK Transmitter ==================================================================== */
|
||||
|
||||
#define PLAYBACK_RATE 13200
|
||||
#define BAUD_RATE 1200 /* APRS AFSK baudrate */
|
||||
#define SAMPLES_PER_BAUD (PLAYBACK_RATE / BAUD_RATE) /* Samples per baud (13200Hz / 1200baud = 11samp/baud) */
|
||||
#define PHASE_DELTA_1200 (((2 * 1200) << 16) / PLAYBACK_RATE) /* Delta-phase per sample for 1200Hz tone */
|
||||
#define PHASE_DELTA_2200 (((2 * 2200) << 16) / PLAYBACK_RATE) /* Delta-phase per sample for 2200Hz tone */
|
||||
|
||||
static uint32_t phase_delta; // 1200/2200 for standard AX.25
|
||||
/*static uint32_t phase_delta; // 1200/2200 for standard AX.25
|
||||
static uint32_t phase; // Fixed point 9.7 (2PI = TABLE_SIZE)
|
||||
static uint32_t packet_pos; // Next bit to be sent out
|
||||
static uint32_t current_sample_in_baud; // 1 bit = SAMPLES_PER_BAUD samples
|
||||
static uint8_t current_byte;
|
||||
//static uint8_t ctone = 0;
|
||||
static uint8_t current_byte;*/
|
||||
|
||||
/*static bool Si446x_getBitAsNRZI(bool bit) {
|
||||
if((bit & 0x1) == 0)
|
||||
ctone = !ctone;
|
||||
return ctone;
|
||||
}*/
|
||||
|
||||
/*
|
||||
* Create a bit stream of AFSK (NRZI & HDLC) encoded packet data.
|
||||
*/
|
||||
/*static uint32_t Si446x_encodeDataToAFSK(uint8_t *inbuf, uint32_t inlen,
|
||||
uint8_t* buf, uint32_t buf_len, uint8_t pre_len) {
|
||||
memset(buf, 0, buf_len); // Clear buffer
|
||||
uint32_t blen = 0;
|
||||
|
||||
// Preamble (HDLC flags)
|
||||
for(uint8_t i = 0; i < pre_len; i++) {
|
||||
for(uint8_t j = 0; j < 8; j++) {
|
||||
|
||||
if(blen >> 3 >= buf_len) { // Buffer overflow
|
||||
|
||||
TRACE_ERROR("SI > Preamble too long");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[blen >> 3] |= Si446x_getBitAsNRZI((0x7E >> j) & 0x1) << (blen % 8);
|
||||
blen++;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert CRC to buffer
|
||||
uint16_t crc = calc_crc16(inbuf, 0, inlen);
|
||||
inbuf[inlen++] = crc & 0xFF;
|
||||
inbuf[inlen++] = crc >> 8;
|
||||
|
||||
uint32_t pos = 0;
|
||||
uint8_t bitstuff_cntr = 0;
|
||||
|
||||
while(pos < inlen*8)
|
||||
{
|
||||
if(blen >> 3 >= buf_len) { // Buffer overflow
|
||||
|
||||
TRACE_ERROR("SI > Packet too long");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bit;
|
||||
if(bitstuff_cntr < 5) { // Normal bit
|
||||
|
||||
bit = (inbuf[pos >> 3] >> (pos%8)) & 0x1;
|
||||
if(bit == 1) {
|
||||
bitstuff_cntr++;
|
||||
} else {
|
||||
bitstuff_cntr = 0;
|
||||
}
|
||||
pos++;
|
||||
|
||||
} else { // Fill stuffing bit
|
||||
|
||||
bit = 0;
|
||||
bitstuff_cntr = 0;
|
||||
|
||||
}
|
||||
|
||||
// NRZ-I encode bit
|
||||
bool nrzi = Si446x_getBitAsNRZI(bit);
|
||||
|
||||
buf[blen >> 3] |= nrzi << (blen % 8);
|
||||
blen++;
|
||||
}
|
||||
|
||||
// Final flag
|
||||
for(uint8_t i=0; i<10; i++)
|
||||
for(uint8_t j=0; j<8; j++) {
|
||||
|
||||
if(blen >> 3 >= buf_len) { // Buffer overflow
|
||||
|
||||
|
||||
TRACE_ERROR("SI > Packet too long");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[blen >> 3] |= Si446x_getBitAsNRZI((0x7E >> j) & 0x1) << (blen % 8);
|
||||
blen++;
|
||||
}
|
||||
|
||||
return blen;
|
||||
}*/
|
||||
|
||||
static uint8_t Si446x_getUpsampledAFSKbits(uint8_t* buf/*, uint32_t blen*/)
|
||||
{
|
||||
/* This function may be called with different bit stream sources.
|
||||
* These will have their own blen so checking is not valid.
|
||||
*/
|
||||
//if(packet_pos == blen)
|
||||
/* Packet transmission finished already so just return a zero. */
|
||||
//return 0;
|
||||
/*static uint8_t __attribute__((unused)) Si446x_getUpsampledAFSKbits(uint8_t* buf) {
|
||||
|
||||
uint8_t b = 0;
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
|
|
@ -854,7 +747,7 @@ static uint8_t Si446x_getUpsampledAFSKbits(uint8_t* buf/*, uint32_t blen*/)
|
|||
|
||||
// Toggle tone (1200 <> 2200)
|
||||
phase_delta = (current_byte & 1) ? PHASE_DELTA_1200 : PHASE_DELTA_2200;
|
||||
/* Add delta-phase (bit count within SAMPLES_PER_BAUD). */
|
||||
|
||||
phase += phase_delta;
|
||||
b |= ((phase >> 16) & 1) << i; // Set modulation bit
|
||||
|
||||
|
|
@ -866,9 +759,43 @@ static uint8_t Si446x_getUpsampledAFSKbits(uint8_t* buf/*, uint32_t blen*/)
|
|||
}
|
||||
}
|
||||
return b;
|
||||
}*/
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static uint8_t Si446x_getUpsampledNRZIbits(up_iterator_t *upsampler,
|
||||
uint8_t *buf) {
|
||||
uint8_t b = 0;
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
if(upsampler->current_sample_in_baud == 0) {
|
||||
if((upsampler->packet_pos & 7) == 0) { // Load up next byte
|
||||
upsampler->current_byte = buf[upsampler->packet_pos >> 3];
|
||||
} else { // Load up next bit
|
||||
upsampler->current_byte >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle tone (1200 <> 2200)
|
||||
upsampler->phase_delta = (upsampler->current_byte & 1) ? PHASE_DELTA_1200 : PHASE_DELTA_2200;
|
||||
/* Add delta-phase (position within SAMPLES_PER_BAUD). */
|
||||
upsampler->phase += upsampler->phase_delta;
|
||||
b |= ((upsampler->phase >> 16) & 1) << i; // Set modulation bit
|
||||
|
||||
//upsampler->current_sample_in_baud++;
|
||||
|
||||
if(++upsampler->current_sample_in_baud == SAMPLES_PER_BAUD) { // Old bit consumed, load next bit
|
||||
upsampler->current_sample_in_baud = 0;
|
||||
upsampler->packet_pos++;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) Si446x_upsampleNRZIstream(uint8_t current_byte,
|
||||
/*
|
||||
*
|
||||
*/
|
||||
/*static void __attribute__((unused)) Si446x_upsampleNRZIstream(uint8_t current_byte,
|
||||
uint8_t *buf,
|
||||
uint8_t upsample_rate) {
|
||||
uint8_t b = 0, i = 0, usr;
|
||||
|
|
@ -876,7 +803,7 @@ static void __attribute__((unused)) Si446x_upsampleNRZIstream(uint8_t current_by
|
|||
do {
|
||||
// Toggle tone (1200 <> 2200)
|
||||
phase_delta = (current_byte & 1) ? PHASE_DELTA_1200 : PHASE_DELTA_2200;
|
||||
/* Add delta-phase (bit count within SAMPLES_PER_BAUD). */
|
||||
|
||||
phase += phase_delta;
|
||||
b |= ((phase >> 16) & 1) << i; // Set modulation bit
|
||||
current_byte >>= (usr / upsample_rate) * 8;
|
||||
|
|
@ -884,13 +811,13 @@ static void __attribute__((unused)) Si446x_upsampleNRZIstream(uint8_t current_by
|
|||
i = 0;
|
||||
buf[usr] = b;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
#define SI446X_EVT_AFSK_TX_TIMEOUT EVENT_MASK(0)
|
||||
#define SI446X_EVT_TX_TIMEOUT EVENT_MASK(0)
|
||||
|
||||
static void Si446x_transmitTimeoutI(thread_t *tp) {
|
||||
/* The tell the thread to terminate. */
|
||||
chEvtSignal(tp, SI446X_EVT_AFSK_TX_TIMEOUT);
|
||||
chEvtSignal(tp, SI446X_EVT_TX_TIMEOUT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -942,8 +869,7 @@ THD_FUNCTION(min_si_fifo_feeder_afsk, arg) {
|
|||
if(all == 0) {
|
||||
/* Nothing encoded. Release packet send object. */
|
||||
|
||||
|
||||
TRACE_DEBUG("SI > AFSK TX no NRZI data encoded");
|
||||
TRACE_ERROR("SI > AFSK TX no NRZI data encoded");
|
||||
|
||||
// Free packet object memory
|
||||
pktReleaseSendObject(pp);
|
||||
|
|
@ -964,12 +890,15 @@ THD_FUNCTION(min_si_fifo_feeder_afsk, arg) {
|
|||
const uint8_t reset_fifo[] = {0x15, 0x01};
|
||||
Si446x_write(reset_fifo, 2);
|
||||
|
||||
up_iterator_t upsampler = {0};
|
||||
upsampler.phase_delta = PHASE_DELTA_1200;
|
||||
|
||||
/* Initialize variables for up sampler. */
|
||||
phase_delta = PHASE_DELTA_1200;
|
||||
/* phase_delta = PHASE_DELTA_1200;
|
||||
phase = 0;
|
||||
packet_pos = 0;
|
||||
current_sample_in_baud = 0;
|
||||
current_byte = 0;
|
||||
current_byte = 0;*/
|
||||
|
||||
/* Maximum amount of FIFO data when using combined TX+RX (safe size). */
|
||||
uint8_t localBuffer[Si446x_FIFO_COMBINED_SIZE];
|
||||
|
|
@ -992,7 +921,8 @@ THD_FUNCTION(min_si_fifo_feeder_afsk, arg) {
|
|||
|
||||
/* Initial FIFO load. */
|
||||
for(uint16_t i = 0; i < c; i++)
|
||||
localBuffer[i] = Si446x_getUpsampledAFSKbits(layer0);
|
||||
//localBuffer[i] = Si446x_getUpsampledAFSKbits(layer0);
|
||||
localBuffer[i] = Si446x_getUpsampledNRZIbits(&upsampler, layer0);
|
||||
Si446x_writeFIFO(localBuffer, c);
|
||||
|
||||
uint8_t lower = 0;
|
||||
|
|
@ -1018,7 +948,8 @@ THD_FUNCTION(min_si_fifo_feeder_afsk, arg) {
|
|||
|
||||
/* Load the FIFO. */
|
||||
for(uint16_t i = 0; i < more; i++)
|
||||
localBuffer[i] = Si446x_getUpsampledAFSKbits(layer0);
|
||||
//localBuffer[i] = Si446x_getUpsampledAFSKbits(layer0);
|
||||
localBuffer[i] = Si446x_getUpsampledNRZIbits(&upsampler, layer0);
|
||||
Si446x_writeFIFO(localBuffer, more); // Write into FIFO
|
||||
c += more;
|
||||
|
||||
|
|
@ -1027,7 +958,7 @@ THD_FUNCTION(min_si_fifo_feeder_afsk, arg) {
|
|||
* Time delay allows ~SAMPLES_PER_BAUD bytes to be consumed from FIFO.
|
||||
* If no timeout event go back and load more data to FIFO.
|
||||
*/
|
||||
eventmask_t evt = chEvtWaitAnyTimeout(SI446X_EVT_AFSK_TX_TIMEOUT,
|
||||
eventmask_t evt = chEvtWaitAnyTimeout(SI446X_EVT_TX_TIMEOUT,
|
||||
chTimeUS2I(833 * 8));
|
||||
if(evt) {
|
||||
/* Force 446x out of TX state. */
|
||||
|
|
@ -1052,9 +983,10 @@ THD_FUNCTION(min_si_fifo_feeder_afsk, arg) {
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TRACE_INFO("SI > AFSK TX FIFO lowest free level %i", lower);
|
||||
if(lower > (free / 2)) {
|
||||
/* Warn when level drops below 50% of FIFO size. */
|
||||
TRACE_DEBUG("SI > AFSK TX FIFO dropped below safe threshold %i", lower);
|
||||
}
|
||||
|
||||
// Free packet object memory
|
||||
pktReleaseSendObject(pp);
|
||||
|
|
@ -1147,8 +1079,7 @@ THD_FUNCTION(min_si_fifo_feeder_fsk, arg) {
|
|||
if(all == 0) {
|
||||
/* Nothing encoded. Release packet send object. */
|
||||
|
||||
|
||||
TRACE_DEBUG("SI > 2FSK TX no NRZI data encoded");
|
||||
TRACE_ERROR("SI > 2FSK TX no NRZI data encoded");
|
||||
|
||||
// Free packet object memory
|
||||
pktReleaseSendObject(pp);
|
||||
|
|
@ -1220,7 +1151,7 @@ THD_FUNCTION(min_si_fifo_feeder_fsk, arg) {
|
|||
* Time delay allows ~10 bytes to be consumed from FIFO.
|
||||
* If no timeout event go back and load more data to FIFO.
|
||||
*/
|
||||
eventmask_t evt = chEvtWaitAnyTimeout(SI446X_EVT_AFSK_TX_TIMEOUT,
|
||||
eventmask_t evt = chEvtWaitAnyTimeout(SI446X_EVT_TX_TIMEOUT,
|
||||
chTimeUS2I(104 * 8 * 10));
|
||||
if(evt) {
|
||||
/* Force 446x out of TX state. */
|
||||
|
|
@ -1245,7 +1176,10 @@ THD_FUNCTION(min_si_fifo_feeder_fsk, arg) {
|
|||
continue;
|
||||
}
|
||||
|
||||
TRACE_INFO("SI > 2FSK TX FIFO lowest free level %i", lower);
|
||||
if(lower > (free / 2)) {
|
||||
/* Warn when level drops below 50% of FIFO size. */
|
||||
TRACE_DEBUG("SI > AFSK TX FIFO dropped below safe threshold %i", lower);
|
||||
}
|
||||
|
||||
// Free packet object memory
|
||||
pktReleaseSendObject(pp);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef __si446x__H__
|
||||
#define __si446x__H__
|
||||
|
||||
//#include "ch.h"
|
||||
//#include "hal.h"
|
||||
//#include "types.h"
|
||||
/*===========================================================================*/
|
||||
/* Module constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define Si446x_LOCK_BY_SEMAPHORE TRUE
|
||||
|
||||
|
|
@ -192,12 +192,31 @@
|
|||
#define SI_AFSK_FIFO_MIN_FEEDER_WA_SIZE 1024
|
||||
#define SI_FSK_FIFO_FEEDER_WA_SIZE 1024
|
||||
|
||||
/* AFSK NRZI up-sampler definitions. */
|
||||
#define PLAYBACK_RATE 13200
|
||||
#define BAUD_RATE 1200 /* APRS AFSK baudrate */
|
||||
#define SAMPLES_PER_BAUD (PLAYBACK_RATE / BAUD_RATE) /* Samples per baud (13200Hz / 1200baud = 11samp/baud) */
|
||||
#define PHASE_DELTA_1200 (((2 * 1200) << 16) / PLAYBACK_RATE) /* Delta-phase per sample for 1200Hz tone */
|
||||
#define PHASE_DELTA_2200 (((2 * 2200) << 16) / PLAYBACK_RATE) /* Delta-phase per sample for 2200Hz tone */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
typedef enum radioMode {
|
||||
RADIO_RX,
|
||||
RADIO_TX,
|
||||
RADIO_CCA
|
||||
} radio_mode_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t phase_delta; // 1200/2200 for standard AX.25
|
||||
uint32_t phase; // Fixed point 9.7 (2PI = TABLE_SIZE)
|
||||
uint32_t packet_pos; // Next bit to be sent out
|
||||
uint32_t current_sample_in_baud; // 1 bit = SAMPLES_PER_BAUD samples
|
||||
uint8_t current_byte;
|
||||
} up_iterator_t;
|
||||
|
||||
// Public methods
|
||||
|
||||
int16_t Si446x_getLastTemperature(radio_unit_t radio);
|
||||
|
|
|
|||
|
|
@ -50,10 +50,10 @@ eventmask_t evt = chEvtGetAndClearEvents(EVENT_MASK(1));
|
|||
TRACE_ERROR("PKT > Decoder error");
|
||||
}
|
||||
if(flags & EVT_PWM_UNKNOWN_INBAND) {
|
||||
TRACE_ERROR("PKT > Unknown PWM inband flag");
|
||||
TRACE_ERROR("PKT > Unknown PWM in-band flag");
|
||||
}
|
||||
if(flags & EVT_ICU_OVERFLOW) {
|
||||
TRACE_WARN("PKT > PWM ICU overflow");
|
||||
TRACE_DEBUG("PKT > PWM ICU overflow");
|
||||
}
|
||||
if(flags & EVT_PWM_STREAM_TIMEOUT) {
|
||||
TRACE_WARN("PKT > PWM stream timeout");
|
||||
|
|
@ -61,5 +61,14 @@ eventmask_t evt = chEvtGetAndClearEvents(EVENT_MASK(1));
|
|||
if(flags & EVT_PWM_NO_DATA) {
|
||||
TRACE_WARN("PKT > PWM data not started from radio");
|
||||
}
|
||||
if(flags & EVT_AFSK_START_FAIL) {
|
||||
TRACE_ERROR("PKT > AFSK decoder failed to start");
|
||||
}
|
||||
if(flags & EVT_PKT_BUFFER_MGR_FAIL) {
|
||||
TRACE_ERROR("PKT > Unable to start packet RX buffer");
|
||||
}
|
||||
if(flags & EVT_PKT_CBK_MGR_FAIL) {
|
||||
TRACE_ERROR("PKT > Unable to start packet RX callback manager");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ ssdv_packet_t packetRepeats[16];
|
|||
bool reject_pri;
|
||||
bool reject_sec;
|
||||
|
||||
static void transmit_image_packet(const uint8_t *image, uint32_t image_len, thd_img_conf_t* conf, uint8_t image_id, uint16_t packet_id)
|
||||
static bool transmit_image_packet(const uint8_t *image, uint32_t image_len, thd_img_conf_t* conf, uint8_t image_id, uint16_t packet_id)
|
||||
{
|
||||
ssdv_t ssdv;
|
||||
uint8_t pkt[SSDV_PKT_SIZE];
|
||||
|
|
@ -311,34 +311,35 @@ static void transmit_image_packet(const uint8_t *image, uint32_t image_len, thd_
|
|||
if(r <= 0)
|
||||
{
|
||||
TRACE_ERROR("SSDV > Premature end of file");
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
ssdv_enc_feed(&ssdv, b, r);
|
||||
}
|
||||
|
||||
if(c == SSDV_EOI) {
|
||||
break;
|
||||
return true;
|
||||
} else if(c != SSDV_OK) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(i == packet_id) {
|
||||
// Sync byte, CRC and FEC of SSDV not transmitted (because its not neccessary inside an APRS packet)
|
||||
// Sync byte, CRC and FEC of SSDV not transmitted (because its not necessary inside an APRS packet)
|
||||
base91_encode(&pkt[6], pkt_base91, 174);
|
||||
/* TODO: Check for failure to get packet (NULL). */
|
||||
packet_t packet = aprs_encode_data_packet(conf->call, conf->path, 'I', pkt_base91);
|
||||
if(packet == NULL) {
|
||||
TRACE_WARN("SSDV > No free packet objects");
|
||||
break;
|
||||
TRACE_WARN("IMG > No free packet objects for transmission");
|
||||
return false;
|
||||
}
|
||||
transmitOnRadio(packet,
|
||||
if(!transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
conf->radio_conf.mod)) {
|
||||
|
||||
return;
|
||||
TRACE_ERROR("IMG > Unable to send image packet TX on radio");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
chThdSleep(TIME_MS2I(10)); // Leave other threads some time
|
||||
|
|
@ -347,7 +348,11 @@ static void transmit_image_packet(const uint8_t *image, uint32_t image_len, thd_
|
|||
}
|
||||
}
|
||||
|
||||
static void transmit_image_packets(const uint8_t *image, uint32_t image_len, thd_img_conf_t* conf, uint8_t image_id)
|
||||
/*
|
||||
* Transmit image packets.
|
||||
* Return true if success or false on fail.
|
||||
*/
|
||||
static bool transmit_image_packets(const uint8_t *image, uint32_t image_len, thd_img_conf_t* conf, uint8_t image_id)
|
||||
{
|
||||
ssdv_t ssdv;
|
||||
uint8_t pkt[SSDV_PKT_SIZE];
|
||||
|
|
@ -368,15 +373,19 @@ static void transmit_image_packets(const uint8_t *image, uint32_t image_len, thd
|
|||
if(strlen((char*)pkt_base91) && conf->radio_conf.redundantTx) {
|
||||
packet_t packet = aprs_encode_data_packet(conf->call, conf->path, 'I', pkt_base91);
|
||||
if(packet == NULL) {
|
||||
TRACE_WARN("SSDV > No free packet objects");
|
||||
break;
|
||||
TRACE_WARN("IMG > No free packet objects for redundant TX");
|
||||
return false;
|
||||
}
|
||||
transmitOnRadio(packet,
|
||||
if(!transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
conf->radio_conf.mod)) {
|
||||
TRACE_ERROR("IMG > Unable to send redundant TX on radio");
|
||||
return false;
|
||||
}
|
||||
chThdSleep(TIME_MS2I(10)); // Leave other threads some time
|
||||
}
|
||||
|
||||
// Encode packet
|
||||
|
|
@ -385,13 +394,13 @@ static void transmit_image_packets(const uint8_t *image, uint32_t image_len, thd
|
|||
while((c = ssdv_enc_get_packet(&ssdv)) == SSDV_FEED_ME)
|
||||
{
|
||||
b = &image[bi];
|
||||
uint8_t r = bi < image_len-128 ? 128 : image_len - bi;
|
||||
int16_t r = bi < image_len-128 ? 128 : image_len - bi;
|
||||
bi += r;
|
||||
|
||||
if(r <= 0)
|
||||
{
|
||||
TRACE_ERROR("SSDV > Premature end of file");
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
ssdv_enc_feed(&ssdv, b, r);
|
||||
}
|
||||
|
|
@ -399,34 +408,39 @@ static void transmit_image_packets(const uint8_t *image, uint32_t image_len, thd
|
|||
if(c == SSDV_EOI)
|
||||
{
|
||||
TRACE_INFO("SSDV > ssdv_enc_get_packet said EOI");
|
||||
break;
|
||||
return true;
|
||||
} else if(c != SSDV_OK) {
|
||||
TRACE_ERROR("SSDV > ssdv_enc_get_packet failed: %i", c);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sync byte, CRC and FEC of SSDV not transmitted (because its not neccessary inside an APRS packet)
|
||||
// Sync byte, CRC and FEC of SSDV not transmitted (because its not necessary inside an APRS packet)
|
||||
base91_encode(&pkt[6], pkt_base91, 174);
|
||||
|
||||
packet_t packet = aprs_encode_data_packet(conf->call, conf->path, 'I', pkt_base91);
|
||||
if(packet == NULL) {
|
||||
TRACE_WARN("SSDV > No free packet objects");
|
||||
break;
|
||||
TRACE_WARN("IMG > No free packet objects for normal TX");
|
||||
return false;
|
||||
}
|
||||
transmitOnRadio(packet,
|
||||
if(!transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
|
||||
conf->radio_conf.mod)) {
|
||||
TRACE_ERROR("IMG > Unable to send normal TX on radio");
|
||||
return false;
|
||||
}
|
||||
chThdSleep(TIME_MS2I(10)); // Leave other threads some time
|
||||
|
||||
// Repeat packets
|
||||
for(uint8_t i=0; i<16; i++) {
|
||||
if(packetRepeats[i].n_done && image_id == packetRepeats[i].image_id) {
|
||||
transmit_image_packet(image, image_len, conf, image_id, packetRepeats[i].packet_id);
|
||||
packetRepeats[i].n_done = false; // Set done
|
||||
if(!transmit_image_packet(image, image_len, conf, image_id, packetRepeats[i].packet_id)) {
|
||||
TRACE_ERROR("IMG > Failed on re-send of image %i", image_id);
|
||||
} else {
|
||||
packetRepeats[i].n_done = false; // Set done
|
||||
}
|
||||
}
|
||||
chThdSleep(TIME_MS2I(100)); // Leave other threads some time
|
||||
}
|
||||
|
|
@ -438,11 +452,11 @@ static void transmit_image_packets(const uint8_t *image, uint32_t image_len, thd
|
|||
// Handle image rejection flag
|
||||
if(conf == &conf_sram.img_pri && reject_pri) { // Image rejected
|
||||
reject_pri = false;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if(conf == &conf_sram.img_sec && reject_sec) { // Image rejected
|
||||
reject_sec = false;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
|
@ -599,21 +613,25 @@ THD_FUNCTION(imgThread, arg)
|
|||
|
||||
// Find SOI
|
||||
uint32_t soi;
|
||||
for(soi=0; soi<conf->buf_size; soi++)
|
||||
for(soi=0; soi<conf->buf_size; soi++) {
|
||||
if(buffer[soi] == 0xFF && buffer[soi+1] == 0xD8)
|
||||
break;
|
||||
}
|
||||
TRACE_DEBUG("IMG > SOI at byte %d");
|
||||
|
||||
writeBufferToFile(filename, &buffer[soi], size_sampled-soi);
|
||||
}
|
||||
|
||||
// Encode and transmit picture
|
||||
TRACE_INFO("IMG > Encode/Transmit SSDV ID=%d", gimage_id-1);
|
||||
transmit_image_packets(buffer, size_sampled, conf, (uint8_t)(gimage_id-1));
|
||||
if(!transmit_image_packets(buffer, size_sampled, conf, (uint8_t)(gimage_id-1))) {
|
||||
TRACE_ERROR("IMG > Failure in image packet transmit");
|
||||
}
|
||||
|
||||
} else { // No camera found
|
||||
TRACE_INFO("IMG > Encode/Transmit SSDV (camera error) ID=%d", gimage_id-1);
|
||||
transmit_image_packets(noCameraFound, sizeof(noCameraFound), conf, (uint8_t)(gimage_id-1));
|
||||
if(!transmit_image_packets(noCameraFound, sizeof(noCameraFound), conf, (uint8_t)(gimage_id-1))) {
|
||||
TRACE_ERROR("IMG > Failure in image packet transmit");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -621,6 +639,9 @@ THD_FUNCTION(imgThread, arg)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void start_image_thread(thd_img_conf_t *conf)
|
||||
{
|
||||
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE((conf->thread_conf.packet_spacing ? 70:70) * 1024 + conf->buf_size), "IMG", NORMALPRIO, imgThread, conf);
|
||||
|
|
|
|||
|
|
@ -58,16 +58,16 @@ THD_FUNCTION(logThread, arg)
|
|||
// Encode and transmit log packet
|
||||
packet_t packet = aprs_encode_data_packet(conf->call, conf->path, 'L', pkt_base91); // Encode packet
|
||||
if(packet == NULL) {
|
||||
TRACE_WARN("LOG > No free packet objects");
|
||||
break;
|
||||
}
|
||||
TRACE_WARN("LOG > No free packet objects for log transmission");
|
||||
} else {
|
||||
// Transmit packet
|
||||
transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
}
|
||||
} else {
|
||||
TRACE_INFO("LOG > No log point in memory");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,29 +43,29 @@ THD_FUNCTION(posThread, arg)
|
|||
// Encode/Transmit position packet
|
||||
packet_t packet = aprs_encode_position(conf->call, conf->path, conf->symbol, dataPoint);
|
||||
if(packet == NULL) {
|
||||
TRACE_WARN("POS > No free packet objects");
|
||||
break;
|
||||
TRACE_WARN("POS > No free packet objects for position transmission");
|
||||
} else {
|
||||
transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
}
|
||||
transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
chThdSleep(TIME_S2I(5));
|
||||
|
||||
// Encode/Transmit APRSD packet
|
||||
packet_t pp = aprs_encode_query_answer_aprsd(conf->call, conf->path, conf->call);
|
||||
if(packet == NULL) {
|
||||
TRACE_WARN("POS > No free packet objects");
|
||||
break;
|
||||
TRACE_WARN("POS > No free packet objects for APRSD transmission");
|
||||
} else {
|
||||
transmitOnRadio(pp,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
}
|
||||
transmitOnRadio(pp,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
|
||||
// Telemetry encoding parameter transmission
|
||||
if(conf->tel_enc_cycle != 0 && last_conf_transmission + conf->tel_enc_cycle < chVTGetSystemTime())
|
||||
|
|
@ -79,16 +79,16 @@ THD_FUNCTION(posThread, arg)
|
|||
{
|
||||
packet = aprs_encode_telemetry_configuration(conf->call, conf->path, type);
|
||||
if(packet == NULL) {
|
||||
TRACE_WARN("POS > No free packet objects");
|
||||
break;
|
||||
TRACE_WARN("POS > No free packet objects for telemetry transmission");
|
||||
} else {
|
||||
transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
chThdSleep(TIME_S2I(5));
|
||||
}
|
||||
transmitOnRadio(packet,
|
||||
conf->radio_conf.freq,
|
||||
conf->radio_conf.step,
|
||||
conf->radio_conf.chan,
|
||||
conf->radio_conf.pwr,
|
||||
conf->radio_conf.mod);
|
||||
chThdSleep(TIME_S2I(5));
|
||||
}
|
||||
|
||||
last_conf_transmission += conf->tel_enc_cycle;
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue