diff --git a/tracker/software/config.c b/tracker/software/config.c index 9bea984..92a5f3c 100644 --- a/tracker/software/config.c +++ b/tracker/software/config.c @@ -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 diff --git a/tracker/software/drivers/si4464.c b/tracker/software/drivers/si4464.c index 1638c73..ab52fc1 100644 --- a/tracker/software/drivers/si4464.c +++ b/tracker/software/drivers/si4464.c @@ -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) { diff --git a/tracker/software/drivers/si4464.h b/tracker/software/drivers/si4464.h index d9cc835..6bcdd96 100644 --- a/tracker/software/drivers/si4464.h +++ b/tracker/software/drivers/si4464.h @@ -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); diff --git a/tracker/software/protocols/ssdv/ssdv.c b/tracker/software/protocols/ssdv/ssdv.c index ebe1e49..01a7df5 100644 --- a/tracker/software/protocols/ssdv/ssdv.c +++ b/tracker/software/protocols/ssdv/ssdv.c @@ -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); } } diff --git a/tracker/software/radio.c b/tracker/software/radio.c index 2a39b35..80e7e66 100644 --- a/tracker/software/radio.c +++ b/tracker/software/radio.c @@ -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)