Implemented Si4464 packet handler

Develop
Sven Steudte 2017-09-02 05:43:13 +02:00
rodzic 1de6cd03ab
commit 9205c80327
5 zmienionych plików z 76 dodań i 59 usunięć

Wyświetl plik

@ -267,7 +267,7 @@ void start_user_modules(void)
start_position_thread(&config[4]);*/
// Module IMAGE, APRS 2m 2GFSK
config[5].power = 50; // Power 20 dBm
config[5].power = 127; // Power 20 dBm
config[5].protocol = PROT_APRS_2GFSK; // Protocol APRS SSDV, modulation 2GFSK
config[5].gfsk_conf.speed = 9600; // 2GFSK Speed
config[5].frequency.type = FREQ_STATIC; // Static frequency allocation

Wyświetl plik

@ -270,8 +270,12 @@ void setModem2GFSK(gfsk_conf_t* conf) {
Si4464_write(setup_data_rate, 7);
// Use 2GFSK from async GPIO1
uint8_t use_2gfsk[] = {0x11, 0x20, 0x01, 0x00, 0x2B};
uint8_t use_2gfsk[] = {0x11, 0x20, 0x01, 0x00, 0x23};
Si4464_write(use_2gfsk, 5);
// transmit LSB first
uint8_t use_lsb_first[] = {0x11, 0x12, 0x01, 0x06, 0x01};
Si4464_write(use_lsb_first, 5);
}
void setPowerLevel(int8_t level) {

Wyświetl plik

@ -6,8 +6,17 @@
#include "defines.h"
#include "types.h"
#define RADIO_MOD_GPIO(state) palWriteLine(LINE_RADIO_GPIO, state)
#define inRadioBand(freq) (RADIO_MIN_FREQ <= (freq) && (freq) <= RADIO_MAX_FREQ)
#define RADIO_MOD_GPIO(state) palWriteLine(LINE_RADIO_GPIO, state)
#define inRadioBand(freq) (RADIO_MIN_FREQ <= (freq) && (freq) <= RADIO_MAX_FREQ)
#define SI4464_STATE_SLEEP 1
#define SI4464_STATE_SPI_ACTIVE 2
#define SI4464_STATE_READY 3
#define SI4464_STATE_READY2 4
#define SI4464_STATE_TX_TUNE 5
#define SI4464_STATE_RX_TUNE 6
#define SI4464_STATE_TX 7
#define SI4464_STATE_RX 8
void Si4464_Init(void);
void Si4464_write(uint8_t* txData, uint32_t len);

Wyświetl plik

@ -411,7 +411,7 @@ static char ssdv_out_jpeg_int(ssdv_t *s, uint8_t rle, int value)
jpeg_encode_int(value, &intbits, &intlen);
r = jpeg_dht_lookup_symbol(s, (rle << 4) | (intlen & 0x0F), &huffbits, &hufflen);
if(r != SSDV_OK) TRACE_ERROR("jpeg_dht_lookup_symbol: %i (%i:%i)", r, value, rle);
if(r != SSDV_OK) TRACE_ERROR("SSDV > jpeg_dht_lookup_symbol: %i (%i:%i)", r, value, rle);
ssdv_outbits(s, huffbits, hufflen);
if(intlen) ssdv_outbits(s, intbits, intlen);
@ -667,7 +667,7 @@ static char ssdv_have_marker(ssdv_t *s)
case J_SOF2:
/* Don't do progressive images! */
TRACE_ERROR("Error: Progressive images not supported");
TRACE_ERROR("SSDV > Error: Progressive images not supported");
return(SSDV_ERROR);
case J_EOI:
@ -712,35 +712,35 @@ static char ssdv_have_marker_data(ssdv_t *s)
s->height = (d[1] << 8) | d[2];
/* Display information about the image... */
TRACE_INFO("Precision: %i", d[0]);
TRACE_INFO("Resolution: %ix%i", s->width, s->height);
TRACE_INFO("Components: %i", d[5]);
TRACE_INFO("SSDV > Precision: %i", d[0]);
TRACE_INFO("SSDV > Resolution: %ix%i", s->width, s->height);
TRACE_INFO("SSDV > Components: %i", d[5]);
/* The image must have a precision of 8 */
if(d[0] != 8)
{
TRACE_ERROR("Error: The image must have a precision of 8");
TRACE_ERROR("SSDV > Error: The image must have a precision of 8");
return(SSDV_ERROR);
}
/* The image must have 3 components (Y'Cb'Cr) */
if(d[5] != 3)
{
TRACE_ERROR("Error: The image must have 3 components");
TRACE_ERROR("SSDV > Error: The image must have 3 components");
return(SSDV_ERROR);
}
/* Maximum image is 4080x4080 */
if(s->width > 4080 || s->height > 4080)
{
TRACE_ERROR("Error: The image is too big. Maximum resolution is 4080x4080");
TRACE_ERROR("SSDV > Error: The image is too big. Maximum resolution is 4080x4080");
return(SSDV_ERROR);
}
/* The image dimensions must be a multiple of 16 */
if((s->width & 0x0F) || (s->height & 0x0F))
{
TRACE_ERROR("Error: The image dimensions must be a multiple of 16");
TRACE_ERROR("SSDV > Error: The image dimensions must be a multiple of 16");
return(SSDV_ERROR);
}
@ -751,11 +751,11 @@ static char ssdv_have_marker_data(ssdv_t *s)
uint8_t *dq = &d[i * 3 + 6];
if(dq[0] != i + 1)
{
TRACE_ERROR("Error: Components are not in order in the SOF0 header");
TRACE_ERROR("SSDV > Error: Components are not in order in the SOF0 header");
return(SSDV_ERROR);
}
TRACE_INFO("DQT table for component %i: %02X, Sampling factor: %ix%i", dq[0], dq[2], dq[1] & 0x0F, dq[1] >> 4);
TRACE_INFO("SSDV > DQT table for component %i: %02X, Sampling factor: %ix%i", dq[0], dq[2], dq[1] & 0x0F, dq[1] >> 4);
/* The first (Y) component must have a factor of 2x2,2x1,1x2 or 1x1 */
if(dq[0] == 1)
@ -767,13 +767,13 @@ static char ssdv_have_marker_data(ssdv_t *s)
case 0x21: s->mcu_mode = 2; s->ycparts = 2; break;
case 0x11: s->mcu_mode = 3; s->ycparts = 1; break;
default:
TRACE_ERROR("Error: Component 1 sampling factor is not supported");
TRACE_ERROR("SSDV > Error: Component 1 sampling factor is not supported");
return(SSDV_ERROR);
}
}
else if(dq[0] != 1 && dq[1] != 0x11)
{
TRACE_ERROR("Error: Component %i sampling factor must be 1x1", dq[0]);
TRACE_ERROR("SSDV > Error: Component %i sampling factor must be 1x1", dq[0]);
return(SSDV_ERROR);
}
}
@ -787,11 +787,11 @@ static char ssdv_have_marker_data(ssdv_t *s)
case 3: l = (s->width >> 3) * (s->height >> 3); break;
}
TRACE_INFO("MCU blocks: %i", (int) l);
TRACE_INFO("SSDV > MCU blocks: %i", (int) l);
if(l > 0xFFFF)
{
TRACE_ERROR("Error: Maximum number of MCU blocks is 65535");
TRACE_ERROR("SSDV > Error: Maximum number of MCU blocks is 65535");
return(SSDV_ERROR);
}
@ -800,12 +800,12 @@ static char ssdv_have_marker_data(ssdv_t *s)
break;
case J_SOS:
TRACE_INFO("Components: %i", d[0]);
TRACE_INFO("SSDV > Components: %i", d[0]);
/* The image must have 3 components (Y'Cb'Cr) */
if(d[0] != 3)
{
TRACE_ERROR("Error: The image must have 3 components");
TRACE_ERROR("SSDV > Error: The image must have 3 components");
return(SSDV_ERROR);
}
@ -814,11 +814,11 @@ static char ssdv_have_marker_data(ssdv_t *s)
uint8_t *dh = &d[i * 2 + 1];
if(dh[0] != i + 1)
{
TRACE_ERROR("Error: Components are not in order in the SOF0 header");
TRACE_ERROR("SSDV > Error: Components are not in order in the SOF0 header");
return(SSDV_ERROR);
}
TRACE_INFO("Component %i DHT: %02X", dh[0], dh[1]);
TRACE_INFO("SSDV > Component %i DHT: %02X", dh[0], dh[1]);
}
/* Do I need to look at the last three bytes of the SOS data? */
@ -827,14 +827,14 @@ static char ssdv_have_marker_data(ssdv_t *s)
/* Verify all of the DQT and DHT tables where loaded */
if(!s->sdqt[0] || !s->sdqt[1])
{
TRACE_ERROR("Error: The image is missing one or more DQT tables");
TRACE_ERROR("SSDV > Error: The image is missing one or more DQT tables");
return(SSDV_ERROR);
}
if(!s->sdht[0][0] || !s->sdht[0][1] ||
!s->sdht[1][0] || !s->sdht[1][1])
{
TRACE_ERROR("Error: The image is missing one or more DHT tables");
TRACE_ERROR("SSDV > Error: The image is missing one or more DHT tables");
return(SSDV_ERROR);
}
@ -884,7 +884,7 @@ static char ssdv_have_marker_data(ssdv_t *s)
case J_DRI:
s->dri = (d[0] << 8) + d[1];
TRACE_INFO("Reset interval: %i blocks", s->dri);
TRACE_INFO("SSDV > Reset interval: %i blocks", s->dri);
break;
}
@ -1071,7 +1071,7 @@ char ssdv_enc_get_packet(ssdv_t *s)
else if(r != SSDV_FEED_ME)
{
/* An error occured */
TRACE_ERROR("ssdv_process() failed: %i", r);
TRACE_ERROR("SSDV > ssdv_process() failed: %i", r);
return(SSDV_ERROR);
}
break;
@ -1266,12 +1266,12 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
}
/* Display information about the image */
TRACE_INFO("Callsign: %s", decode_callsign(callsign, s->callsign));
TRACE_INFO("Image ID: %02X", s->image_id);
TRACE_INFO("Resolution: %ix%i", s->width, s->height);
TRACE_INFO("MCU blocks: %i", s->mcu_count);
TRACE_INFO("Sampling factor: %s", factor);
TRACE_INFO("Quality level: %d", s->quality);
TRACE_INFO("SSDV > Callsign: %s", decode_callsign(callsign, s->callsign));
TRACE_INFO("SSDV > Image ID: %02X", s->image_id);
TRACE_INFO("SSDV > Resolution: %ix%i", s->width, s->height);
TRACE_INFO("SSDV > MCU blocks: %i", s->mcu_count);
TRACE_INFO("SSDV > Sampling factor: %s", factor);
TRACE_INFO("SSDV > Quality level: %d", s->quality);
/* Output JPEG headers and enable byte stuffing */
ssdv_out_headers(s);
@ -1282,7 +1282,7 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
if(packet_id != s->packet_id)
{
/* One or more packets have been lost! */
TRACE_ERROR("Gap detected between packets %i and %i", s->packet_id - 1, packet_id);
TRACE_ERROR("SSDV > Gap detected between packets %i and %i", s->packet_id - 1, packet_id);
/* If this packet has no new MCU, ignore */
if(s->packet_mcu_offset == 0xFF) return(SSDV_FEED_ME);
@ -1330,7 +1330,7 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
else if(r != SSDV_FEED_ME)
{
/* An error occured */
TRACE_ERROR("ssdv_process() failed: %i", r);
TRACE_ERROR("SSDV > ssdv_process() failed: %i", r);
return(SSDV_ERROR);
}
}

Wyświetl plik

@ -72,34 +72,33 @@ void sendAFSK(radioMSG_t *msg) {
}
void init2GFSK(radioMSG_t *msg) {
// Initialize radio and tune
// Initialize radio
Si4464_Init();
setModem2GFSK(msg->gfsk_conf);
radioTune(msg->freq, 0, msg->power, 0);
chThdSleepMilliseconds(30);
}
void send2GFSK(radioMSG_t *msg) {
// Initialize variables for timer
tim_msg = msg;
gfsk_bit = 0;
current_byte = 0;
uint16_t c = 64;
uint16_t all = (msg->bin_len+7)/8;
// Initialize variables for timer
uint32_t initial_interval = STM32_PCLK1 / msg->gfsk_conf->speed / 2;
RCC->APB1ENR |= RCC_APB1ENR_TIM7EN;
nvicEnableVector(TIM7_IRQn, 1);
TIM7->ARR = initial_interval;
TIM7->PSC = 1;
TIM7->CR1 &= ~STM32_TIM_CR1_ARPE;
TIM7->DIER |= STM32_TIM_DIER_UIE;
// Initial FIFO fill
Si4464_writeFIFO(msg->msg, c);
// Start timer
TIM7->CR1 |= STM32_TIM_CR1_CEN;
// Transmit
radioTune(msg->freq, 0, msg->power, all);
// Block execution while timer is running
while(TIM7->CR1 & STM32_TIM_CR1_CEN)
chThdSleepMilliseconds(10);
while(c < all) { // Do while bytes not written into FIFO completely
// Determine free memory in Si4464-FIFO
uint16_t more = Si4464_freeFIFO();
if(more > all-c)
more = all-c; // Last bytes in FIFO
Si4464_writeFIFO(&msg->msg[c], more); // Write into FIFO
c += more;
chThdSleepMilliseconds(1);
}
}
/**
@ -263,6 +262,10 @@ void send2FSK(radioMSG_t *msg) {
void shutdownRadio(void)
{
// Wait for PH to finish transmission for 2GFSK
while(active_mod == MOD_2GFSK && Si4464_getState() == SI4464_STATE_TX)
chThdSleepMilliseconds(5);
Si4464_shutdown();
active_mod = MOD_NOT_SET;
}
@ -325,6 +328,10 @@ bool transmitOnRadio(radioMSG_t *msg, bool shutdown) {
if(inRadioBand(msg->freq)) { // Frequency in radio radio band
// Wait for PH to finish transmission for 2GFSK
if(active_mod == MOD_2GFSK && Si4464_getState() == SI4464_STATE_TX)
chThdSleepMilliseconds(5);
// Lock interference mutex
chMtxLock(&interference_mtx);
@ -359,12 +366,9 @@ bool transmitOnRadio(radioMSG_t *msg, bool shutdown) {
break;
}
active_mod = msg->mod;
if(shutdown)
{
shutdownRadio(); // Shutdown radio for reinitialization
} else {
active_mod = msg->mod;
}
chMtxUnlock(&interference_mtx); // Heavy interference finished (HF)