kopia lustrzana https://github.com/DL7AD/pecanpico9
Implemented grouped APRS packet transmission properly
Fixed packet losses (incomplete)Develop
rodzic
afd3b96352
commit
056fb067a0
|
@ -820,9 +820,7 @@ bool OV5640_Snapshot2RAM(void)
|
||||||
do {
|
do {
|
||||||
|
|
||||||
TRACE_INFO("CAM > Capture image");
|
TRACE_INFO("CAM > Capture image");
|
||||||
lockRadio(); // Lock radio because SPI and pseudo DCMI use the same DMA
|
|
||||||
status = OV5640_Capture();
|
status = OV5640_Capture();
|
||||||
unlockRadio(); // Unlock radio
|
|
||||||
TRACE_INFO("CAM > Capture finished");
|
TRACE_INFO("CAM > Capture finished");
|
||||||
|
|
||||||
ov5640_conf->size_sampled = ov5640_conf->ram_size - 1;
|
ov5640_conf->size_sampled = ov5640_conf->ram_size - 1;
|
||||||
|
|
|
@ -153,6 +153,6 @@ void pac1720_init(void)
|
||||||
I2C_write8(PAC1720_ADDRESS, PAC1720_V_SOURCE_SAMP_CONFIG, 0xFF);
|
I2C_write8(PAC1720_ADDRESS, PAC1720_V_SOURCE_SAMP_CONFIG, 0xFF);
|
||||||
|
|
||||||
//TRACE_INFO("PAC > Init PAC1720 continuous measurement");
|
//TRACE_INFO("PAC > Init PAC1720 continuous measurement");
|
||||||
//chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(512), "PAC1720", NORMALPRIO, pac1720_thd, NULL);
|
chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(512), "PAC1720", NORMALPRIO, pac1720_thd, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *co
|
||||||
packet.max_size = 512; // TODO: replace 512 with real size
|
packet.max_size = 512; // TODO: replace 512 with real size
|
||||||
packet.mod = mod;
|
packet.mod = mod;
|
||||||
|
|
||||||
|
ax25_init(&packet);
|
||||||
ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble);
|
ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble);
|
||||||
ax25_send_byte(&packet, '/'); // Report w/ timestamp, no APRS messaging. $ = NMEA raw data
|
ax25_send_byte(&packet, '/'); // Report w/ timestamp, no APRS messaging. $ = NMEA raw data
|
||||||
|
|
||||||
|
@ -169,7 +170,7 @@ uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *co
|
||||||
/**
|
/**
|
||||||
* Transmit custom experimental packet
|
* Transmit custom experimental packet
|
||||||
*/
|
*/
|
||||||
uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod, const aprs_conf_t *config, uint8_t *data, size_t size, bool noPreamble)
|
uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod, const aprs_conf_t *config, uint8_t *data, size_t size)
|
||||||
{
|
{
|
||||||
ax25_t packet;
|
ax25_t packet;
|
||||||
packet.data = message;
|
packet.data = message;
|
||||||
|
@ -177,7 +178,8 @@ uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod,
|
||||||
packet.mod = mod;
|
packet.mod = mod;
|
||||||
|
|
||||||
// Encode APRS header
|
// Encode APRS header
|
||||||
ax25_send_header(&packet, config->callsign, config->ssid, config->path, noPreamble ? 0 : config->preamble);
|
ax25_init(&packet);
|
||||||
|
ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble);
|
||||||
ax25_send_string(&packet, "{{");
|
ax25_send_string(&packet, "{{");
|
||||||
ax25_send_byte(&packet, packetType);
|
ax25_send_byte(&packet, packetType);
|
||||||
|
|
||||||
|
@ -185,7 +187,7 @@ uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod,
|
||||||
for(uint16_t i=0; i<size; i++)
|
for(uint16_t i=0; i<size; i++)
|
||||||
ax25_send_byte(&packet, data[i]);
|
ax25_send_byte(&packet, data[i]);
|
||||||
|
|
||||||
// Send footer
|
// Encode footer
|
||||||
ax25_send_footer(&packet);
|
ax25_send_footer(&packet);
|
||||||
scramble(&packet);
|
scramble(&packet);
|
||||||
nrzi_encode(&packet);
|
nrzi_encode(&packet);
|
||||||
|
@ -193,6 +195,41 @@ uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod,
|
||||||
return packet.size;
|
return packet.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit custom data packet (the methods aprs_encode_data allow multiple APRS packets in a row without preable being sent)
|
||||||
|
*/
|
||||||
|
void aprs_encode_data_init(ax25_t* packet, uint8_t* message, mod_t mod)
|
||||||
|
{
|
||||||
|
packet->data = message;
|
||||||
|
packet->max_size = 8192; // TODO: replace 8192 with real size
|
||||||
|
packet->mod = mod;
|
||||||
|
|
||||||
|
// Encode APRS header
|
||||||
|
ax25_init(packet);
|
||||||
|
}
|
||||||
|
uint32_t aprs_encode_data_encodePacket(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
// Encode header
|
||||||
|
ax25_send_header(packet, config->callsign, config->ssid, config->path, packet->size > 0 ? 0 : config->preamble);
|
||||||
|
ax25_send_string(packet, "{{");
|
||||||
|
ax25_send_byte(packet, packetType);
|
||||||
|
|
||||||
|
// Encode message
|
||||||
|
for(uint16_t i=0; i<size; i++)
|
||||||
|
ax25_send_byte(packet, data[i]);
|
||||||
|
|
||||||
|
// Encode footer
|
||||||
|
ax25_send_footer(packet);
|
||||||
|
|
||||||
|
return packet->size;
|
||||||
|
}
|
||||||
|
uint32_t aprs_encode_data_finalize(ax25_t* packet)
|
||||||
|
{
|
||||||
|
scramble(packet);
|
||||||
|
nrzi_encode(packet);
|
||||||
|
return packet->size;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transmit message packet
|
* Transmit message packet
|
||||||
*/
|
*/
|
||||||
|
@ -205,6 +242,7 @@ uint32_t aprs_encode_message(uint8_t* message, mod_t mod, const aprs_conf_t *con
|
||||||
|
|
||||||
// Encode APRS header
|
// Encode APRS header
|
||||||
char temp[10];
|
char temp[10];
|
||||||
|
ax25_init(&packet);
|
||||||
ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble);
|
ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble);
|
||||||
ax25_send_byte(&packet, ':');
|
ax25_send_byte(&packet, ':');
|
||||||
|
|
||||||
|
@ -218,7 +256,7 @@ uint32_t aprs_encode_message(uint8_t* message, mod_t mod, const aprs_conf_t *con
|
||||||
chsnprintf(temp, sizeof(temp), "%d", ++msg_id);
|
chsnprintf(temp, sizeof(temp), "%d", ++msg_id);
|
||||||
ax25_send_string(&packet, temp);
|
ax25_send_string(&packet, temp);
|
||||||
|
|
||||||
// Send footer
|
// Encode footer
|
||||||
ax25_send_footer(&packet);
|
ax25_send_footer(&packet);
|
||||||
scramble(&packet);
|
scramble(&packet);
|
||||||
nrzi_encode(&packet);
|
nrzi_encode(&packet);
|
||||||
|
@ -237,6 +275,7 @@ uint32_t aprs_encode_telemetry_configuration(uint8_t* message, mod_t mod, const
|
||||||
packet.max_size = 512; // TODO: replace 512 with real size
|
packet.max_size = 512; // TODO: replace 512 with real size
|
||||||
packet.mod = mod;
|
packet.mod = mod;
|
||||||
|
|
||||||
|
ax25_init(&packet);
|
||||||
ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble); // Header
|
ax25_send_header(&packet, config->callsign, config->ssid, config->path, config->preamble); // Header
|
||||||
ax25_send_byte(&packet, ':'); // Message flag
|
ax25_send_byte(&packet, ':'); // Message flag
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "si4464.h"
|
#include "si4464.h"
|
||||||
#include "tracking.h"
|
#include "tracking.h"
|
||||||
|
#include "ax25.h"
|
||||||
|
|
||||||
#define GSP_FIX_OLD 0x0
|
#define GSP_FIX_OLD 0x0
|
||||||
#define GSP_FIX_CURRENT 0x1
|
#define GSP_FIX_CURRENT 0x1
|
||||||
|
@ -51,7 +52,11 @@
|
||||||
uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *config, trackPoint_t *trackPoint);
|
uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *config, trackPoint_t *trackPoint);
|
||||||
uint32_t aprs_encode_telemetry_configuration(uint8_t* message, mod_t mod, const aprs_conf_t *config, const telemetry_conf_t type);
|
uint32_t aprs_encode_telemetry_configuration(uint8_t* message, mod_t mod, const aprs_conf_t *config, const telemetry_conf_t type);
|
||||||
uint32_t aprs_encode_message(uint8_t* message, mod_t mod, const aprs_conf_t *config, const char *receiver, const char *text);
|
uint32_t aprs_encode_message(uint8_t* message, mod_t mod, const aprs_conf_t *config, const char *receiver, const char *text);
|
||||||
uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod, const aprs_conf_t *config, uint8_t *data, size_t size, bool noPreamble);
|
uint32_t aprs_encode_experimental(char packetType, uint8_t* message, mod_t mod, const aprs_conf_t *config, uint8_t *data, size_t size);
|
||||||
|
|
||||||
|
void aprs_encode_data_init(ax25_t* packet, uint8_t* message, mod_t mod);
|
||||||
|
uint32_t aprs_encode_data_encodePacket(ax25_t* packet, char packetType, const aprs_conf_t *config, uint8_t *data, size_t size);
|
||||||
|
uint32_t aprs_encode_data_finalize(ax25_t* packet);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -113,11 +113,15 @@ void ax25_send_string(ax25_t *packet, const char *string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ax25_init(ax25_t *packet)
|
||||||
|
{
|
||||||
|
packet->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ax25_send_header(ax25_t *packet, const char *callsign, uint8_t ssid, const char *path, uint16_t preamble)
|
void ax25_send_header(ax25_t *packet, const char *callsign, uint8_t ssid, const char *path, uint16_t preamble)
|
||||||
{
|
{
|
||||||
uint8_t i, j;
|
uint8_t i, j;
|
||||||
uint8_t tmp[8];
|
uint8_t tmp[8];
|
||||||
packet->size = 0;
|
|
||||||
packet->ones_in_a_row = 0;
|
packet->ones_in_a_row = 0;
|
||||||
packet->crc = 0xffff;
|
packet->crc = 0xffff;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ typedef struct {
|
||||||
mod_t mod; // Modulation type (MOD_AFSK or MOD_2GFSK)
|
mod_t mod; // Modulation type (MOD_AFSK or MOD_2GFSK)
|
||||||
} ax25_t;
|
} ax25_t;
|
||||||
|
|
||||||
|
void ax25_init(ax25_t *packet);
|
||||||
void ax25_send_header(ax25_t *packet, const char *callsign, uint8_t ssid, const char *path, uint16_t preamble);
|
void ax25_send_header(ax25_t *packet, const char *callsign, uint8_t ssid, const char *path, uint16_t preamble);
|
||||||
void ax25_send_path(ax25_t *packet, const char *callsign, uint8_t ssid, bool last);
|
void ax25_send_path(ax25_t *packet, const char *callsign, uint8_t ssid, bool last);
|
||||||
void ax25_send_byte(ax25_t *packet, char byte);
|
void ax25_send_byte(ax25_t *packet, char byte);
|
||||||
|
|
|
@ -80,21 +80,8 @@ void init2GFSK(radioMSG_t *msg) {
|
||||||
active_mod = MOD_2GFSK;
|
active_mod = MOD_2GFSK;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_reference_t feeder_ref = NULL;
|
|
||||||
thread_t *feeder_thd = NULL;
|
thread_t *feeder_thd = NULL;
|
||||||
|
|
||||||
/*
|
|
||||||
* Radio GPIO1 interrupt
|
|
||||||
*/
|
|
||||||
CH_IRQ_HANDLER(VectorE0) {
|
|
||||||
CH_IRQ_PROLOGUE();
|
|
||||||
|
|
||||||
chThdResumeS(&feeder_ref, MSG_OK);
|
|
||||||
|
|
||||||
EXTI->PR |= EXTI_PR_PR12;
|
|
||||||
CH_IRQ_EPILOGUE();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: I'd suggest re-working the FIFO handler system.
|
* TODO: I'd suggest re-working the FIFO handler system.
|
||||||
* Will give it some thought.
|
* Will give it some thought.
|
||||||
|
@ -112,19 +99,11 @@ THD_FUNCTION(si_fifo_feeder_thd, arg)
|
||||||
// Initial FIFO fill
|
// Initial FIFO fill
|
||||||
Si4464_writeFIFO(tim_msg.msg, c);
|
Si4464_writeFIFO(tim_msg.msg, c);
|
||||||
|
|
||||||
// Initialize interrupt
|
// Start transmission
|
||||||
chSysLock();
|
|
||||||
SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI12_PC;
|
|
||||||
EXTI->IMR |= EXTI_IMR_MR12; // Activate interrupt for chan12 (=>PC12)
|
|
||||||
EXTI->RTSR |= EXTI_RTSR_TR12; // Listen on rising edge
|
|
||||||
EXTI->PR |= EXTI_PR_PR12; // Clear any pending interrupt
|
|
||||||
nvicEnableVector(EXTI15_10_IRQn, 1); // Enable interrupt
|
|
||||||
chSysUnlock();
|
|
||||||
// Transmit
|
|
||||||
radioTune(tim_msg.freq, 0, tim_msg.power, all);
|
radioTune(tim_msg.freq, 0, tim_msg.power, all);
|
||||||
|
|
||||||
while(c < all) { // Do while bytes not written into FIFO completely
|
while(c < all) { // Do while bytes not written into FIFO completely
|
||||||
chThdSuspendS(&feeder_ref); // Suspend until interrupt resumes it
|
//chThdSuspendS(&feeder_ref); // Suspend until interrupt resumes it
|
||||||
|
|
||||||
// Determine free memory in Si4464-FIFO
|
// Determine free memory in Si4464-FIFO
|
||||||
uint8_t more = Si4464_freeFIFO();
|
uint8_t more = Si4464_freeFIFO();
|
||||||
|
@ -132,14 +111,14 @@ THD_FUNCTION(si_fifo_feeder_thd, arg)
|
||||||
if((more = all-c) == 0) // Calculate remainder to send
|
if((more = all-c) == 0) // Calculate remainder to send
|
||||||
break; // End if nothing left
|
break; // End if nothing left
|
||||||
}
|
}
|
||||||
//TRACE_DEBUG("fed %db %d<%d", more, c, all);
|
|
||||||
Si4464_writeFIFO(&tim_msg.msg[c], more); // Write into FIFO
|
Si4464_writeFIFO(&tim_msg.msg[c], more); // Write into FIFO
|
||||||
c += more;
|
c += more;
|
||||||
|
chThdSleepMilliseconds(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
nvicDisableVector(EXTI15_10_IRQn); // Disable interrupt
|
// Shutdown radio (and wait for Si4464 to finish transmission)
|
||||||
|
|
||||||
shutdownRadio();
|
shutdownRadio();
|
||||||
|
|
||||||
chThdExit(MSG_OK);
|
chThdExit(MSG_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,8 +126,6 @@ void send2GFSK(radioMSG_t *msg) {
|
||||||
// Copy data
|
// Copy data
|
||||||
memcpy(&tim_msg, msg, sizeof(radioMSG_t));
|
memcpy(&tim_msg, msg, sizeof(radioMSG_t));
|
||||||
|
|
||||||
if(feeder_thd != NULL) // No waiting on first use
|
|
||||||
chThdWait(feeder_thd);
|
|
||||||
// Start/re-start FIFO feeder
|
// Start/re-start FIFO feeder
|
||||||
feeder_thd = chThdCreateStatic(si_fifo_feeder_wa, sizeof(si_fifo_feeder_wa), HIGHPRIO+1, si_fifo_feeder_thd, NULL);
|
feeder_thd = chThdCreateStatic(si_fifo_feeder_wa, sizeof(si_fifo_feeder_wa), HIGHPRIO+1, si_fifo_feeder_thd, NULL);
|
||||||
|
|
||||||
|
@ -313,10 +290,7 @@ void shutdownRadio(void)
|
||||||
{
|
{
|
||||||
// Wait for PH to finish transmission for 2GFSK
|
// Wait for PH to finish transmission for 2GFSK
|
||||||
while(active_mod == MOD_2GFSK && Si4464_getState() == SI4464_STATE_TX)
|
while(active_mod == MOD_2GFSK && Si4464_getState() == SI4464_STATE_TX)
|
||||||
{
|
|
||||||
TRACE_DEBUG("Waiting for Si4464 (state=%d, free=%d)", Si4464_getState(), Si4464_freeFIFO());
|
|
||||||
chThdSleepMilliseconds(5);
|
chThdSleepMilliseconds(5);
|
||||||
}
|
|
||||||
|
|
||||||
Si4464_shutdown();
|
Si4464_shutdown();
|
||||||
active_mod = MOD_NOT_SET;
|
active_mod = MOD_NOT_SET;
|
||||||
|
@ -376,12 +350,11 @@ uint32_t getAPRSRegionFrequency(void) {
|
||||||
*/
|
*/
|
||||||
bool transmitOnRadio(radioMSG_t *msg, bool shutdown)
|
bool transmitOnRadio(radioMSG_t *msg, bool shutdown)
|
||||||
{
|
{
|
||||||
(void)shutdown;
|
(void)shutdown;
|
||||||
if(inRadioBand(msg->freq)) // Frequency in radio radio band
|
if(inRadioBand(msg->freq)) // Frequency in radio radio band
|
||||||
{
|
{
|
||||||
if(inRadioBand(msg->freq)) // Frequency in radio radio band
|
if(inRadioBand(msg->freq)) // Frequency in radio radio band
|
||||||
{
|
{
|
||||||
|
|
||||||
lockRadio(); // Lock radio
|
lockRadio(); // Lock radio
|
||||||
|
|
||||||
TRACE_INFO( "RAD > Transmit %d.%03d MHz, Pwr %d, %s, %d bits",
|
TRACE_INFO( "RAD > Transmit %d.%03d MHz, Pwr %d, %s, %d bits",
|
||||||
|
@ -462,8 +435,9 @@ void lockRadio(void)
|
||||||
{
|
{
|
||||||
chMtxLock(&radio_mtx);
|
chMtxLock(&radio_mtx);
|
||||||
|
|
||||||
while(active_mod != MOD_NOT_SET && Si4464_getState() == SI4464_STATE_TX)
|
// Wait for old feeder thread to terminate
|
||||||
chThdSleepMilliseconds(1);
|
if(feeder_thd != NULL) // No waiting on first use
|
||||||
|
chThdWait(feeder_thd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlockRadio(void)
|
void unlockRadio(void)
|
||||||
|
|
|
@ -273,7 +273,7 @@ const uint8_t noCameraFound[] = {
|
||||||
0xBD, 0xC0, 0x20, 0x00, 0x01, 0xFF, 0xD9
|
0xBD, 0xC0, 0x20, 0x00, 0x01, 0xFF, 0xD9
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t gimage_id = 0; // Global image ID (for all image threads)
|
static uint8_t gimage_id = 5; // Global image ID (for all image threads)
|
||||||
mutex_t camera_mtx;
|
mutex_t camera_mtx;
|
||||||
|
|
||||||
void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, uint8_t image_id, bool redudantTx)
|
void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf, uint8_t image_id, bool redudantTx)
|
||||||
|
@ -297,6 +297,17 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf,
|
||||||
msg.freq = getFrequency(&conf->frequency);
|
msg.freq = getFrequency(&conf->frequency);
|
||||||
msg.power = conf->power;
|
msg.power = conf->power;
|
||||||
|
|
||||||
|
//image_id = 0; // FIXME temporary
|
||||||
|
|
||||||
|
ax25_t ax25_handle;
|
||||||
|
if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK)
|
||||||
|
{
|
||||||
|
msg.mod = conf->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
|
||||||
|
msg.afsk_conf = &(conf->afsk_conf);
|
||||||
|
msg.gfsk_conf = &(conf->gfsk_conf);
|
||||||
|
aprs_encode_data_init(&ax25_handle, msg.msg, msg.mod);
|
||||||
|
}
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
conf->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
|
conf->wdg_timeout = chVTGetSystemTimeX() + S2ST(600); // TODO: Implement more sophisticated method
|
||||||
|
@ -309,8 +320,9 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf,
|
||||||
|
|
||||||
if(r <= 0)
|
if(r <= 0)
|
||||||
{
|
{
|
||||||
if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer
|
|
||||||
TRACE_ERROR("SSDV > Premature end of file");
|
TRACE_ERROR("SSDV > Premature end of file");
|
||||||
|
if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_data_finalize(&ax25_handle);
|
||||||
|
if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ssdv_enc_feed(&ssdv, b, r);
|
ssdv_enc_feed(&ssdv, b, r);
|
||||||
|
@ -318,37 +330,34 @@ void encode_ssdv(const uint8_t *image, uint32_t image_len, module_conf_t* conf,
|
||||||
|
|
||||||
if(c == SSDV_EOI)
|
if(c == SSDV_EOI)
|
||||||
{
|
{
|
||||||
if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer
|
|
||||||
TRACE_INFO("SSDV > ssdv_enc_get_packet said EOI");
|
TRACE_INFO("SSDV > ssdv_enc_get_packet said EOI");
|
||||||
|
if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_data_finalize(&ax25_handle);
|
||||||
|
if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer
|
||||||
break;
|
break;
|
||||||
} else if(c != SSDV_OK) {
|
} else if(c != SSDV_OK) {
|
||||||
if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer
|
|
||||||
TRACE_ERROR("SSDV > ssdv_enc_get_packet failed: %i", c);
|
TRACE_ERROR("SSDV > ssdv_enc_get_packet failed: %i", c);
|
||||||
|
if(conf->protocol == PROT_APRS_2GFSK || conf->protocol == PROT_APRS_AFSK) msg.bin_len = aprs_encode_data_finalize(&ax25_handle);
|
||||||
|
if(msg.bin_len > 0) transmitOnRadio(&msg, false); // Empty buffer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(conf->protocol) {
|
switch(conf->protocol) {
|
||||||
case PROT_APRS_2GFSK:
|
case PROT_APRS_2GFSK:
|
||||||
case PROT_APRS_AFSK:
|
case PROT_APRS_AFSK:
|
||||||
msg.mod = conf->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
|
|
||||||
msg.afsk_conf = &(conf->afsk_conf);
|
|
||||||
msg.gfsk_conf = &(conf->gfsk_conf);
|
|
||||||
|
|
||||||
// Deleting buffer
|
|
||||||
for(uint16_t t=0; t<256; t++)
|
|
||||||
pkt_base91[t] = 0;
|
|
||||||
|
|
||||||
// Encode packet
|
// Encode packet
|
||||||
TRACE_INFO("IMG > Encode APRS/SSDV packet");
|
TRACE_INFO("IMG > Encode APRS/SSDV packet");
|
||||||
base91_encode(&pkt[1], pkt_base91, sizeof(pkt)-37); // Sync byte, CRC and FEC of SSDV not transmitted
|
base91_encode(&pkt[1], pkt_base91, sizeof(pkt)-37); // Sync byte, CRC and FEC of SSDV not transmitted
|
||||||
msg.bin_len += 8 + aprs_encode_experimental('I', &msg.msg[msg.bin_len/8+1], msg.mod, &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91), msg.bin_len > 0);
|
msg.bin_len = aprs_encode_data_encodePacket(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91));
|
||||||
if(redudantTx)
|
if(redudantTx)
|
||||||
msg.bin_len += 8 + aprs_encode_experimental('I', &msg.msg[msg.bin_len/8+1], msg.mod, &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91), false);
|
msg.bin_len = aprs_encode_data_encodePacket(&ax25_handle, 'I', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91));
|
||||||
|
|
||||||
// Transmit
|
// Transmit
|
||||||
if(msg.bin_len >= 58000 || conf->packet_spacing) { // Transmit if buffer is full or if single packet transmission activation (packet_spacing != 0)
|
if(msg.bin_len >= 58000 || conf->packet_spacing) // Transmit if buffer is full or if single packet transmission activation (packet_spacing != 0)
|
||||||
|
{
|
||||||
|
msg.bin_len = aprs_encode_data_finalize(&ax25_handle);
|
||||||
transmitOnRadio(&msg, false);
|
transmitOnRadio(&msg, false);
|
||||||
msg.bin_len = 0;
|
msg.bin_len = 0;
|
||||||
|
chThdSleepMilliseconds(7500); // FIXME: Throttle it for my poor TH-D72. Has to be removed later.
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -400,10 +409,13 @@ THD_FUNCTION(imgThread, arg) {
|
||||||
uint32_t image_len = 0;
|
uint32_t image_len = 0;
|
||||||
uint8_t *image;
|
uint8_t *image;
|
||||||
|
|
||||||
// Lock camera
|
// Lock camera FIXME: Removed for testing
|
||||||
TRACE_INFO("IMG > Lock camera");
|
TRACE_INFO("IMG > Lock camera");
|
||||||
chMtxLock(&camera_mtx);
|
chMtxLock(&camera_mtx);
|
||||||
TRACE_INFO("IMG > Locked camera");
|
TRACE_INFO("IMG > Locked camera");
|
||||||
|
//TRACE_INFO("IMG > Lock radio");
|
||||||
|
//lockRadio(); // Lock radio because SPI and pseudo DCMI use the same DMA
|
||||||
|
//TRACE_INFO("IMG > Locked radio");
|
||||||
|
|
||||||
uint8_t tries;
|
uint8_t tries;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
|
@ -472,7 +484,10 @@ THD_FUNCTION(imgThread, arg) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock camera
|
// Unlock camera FIXME: Removed for testing
|
||||||
|
//TRACE_INFO("IMG > Unlock radio");
|
||||||
|
//unlockRadio(); // Unlock radio
|
||||||
|
//TRACE_INFO("IMG > Unlocked radio");
|
||||||
TRACE_INFO("IMG > Unlock camera");
|
TRACE_INFO("IMG > Unlock camera");
|
||||||
chMtxUnlock(&camera_mtx);
|
chMtxUnlock(&camera_mtx);
|
||||||
TRACE_INFO("IMG > Unlocked camera");
|
TRACE_INFO("IMG > Unlocked camera");
|
||||||
|
@ -502,7 +517,7 @@ void start_image_thread(module_conf_t *conf)
|
||||||
if(conf->init_delay) chThdSleepMilliseconds(conf->init_delay);
|
if(conf->init_delay) chThdSleepMilliseconds(conf->init_delay);
|
||||||
TRACE_INFO("IMG > Startup image thread");
|
TRACE_INFO("IMG > Startup image thread");
|
||||||
chsnprintf(conf->name, sizeof(conf->name), "IMG");
|
chsnprintf(conf->name, sizeof(conf->name), "IMG");
|
||||||
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(50*1024), "IMG", NORMALPRIO, imgThread, conf);
|
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(100*1024), "IMG", NORMALPRIO, imgThread, conf);
|
||||||
if(!th) {
|
if(!th) {
|
||||||
// Print startup error, do not start watchdog for this thread
|
// Print startup error, do not start watchdog for this thread
|
||||||
TRACE_ERROR("IMG > Could not startup thread (not enough memory available)");
|
TRACE_ERROR("IMG > Could not startup thread (not enough memory available)");
|
||||||
|
|
|
@ -178,7 +178,7 @@ THD_FUNCTION(logThread, arg)
|
||||||
msg.gfsk_conf = &(conf->gfsk_conf);
|
msg.gfsk_conf = &(conf->gfsk_conf);
|
||||||
|
|
||||||
base91_encode((uint8_t*)pkt, pkt_base91, sizeof(pkt)); // Encode base 91
|
base91_encode((uint8_t*)pkt, pkt_base91, sizeof(pkt)); // Encode base 91
|
||||||
msg.bin_len = aprs_encode_experimental('L', msg.msg, msg.mod, &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91), false); // Encode APRS
|
msg.bin_len = aprs_encode_experimental('L', msg.msg, msg.mod, &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); // Encode APRS
|
||||||
|
|
||||||
transmitOnRadio(&msg, true); // Transmit packet
|
transmitOnRadio(&msg, true); // Transmit packet
|
||||||
break;
|
break;
|
||||||
|
|
Ładowanie…
Reference in New Issue