diff --git a/tracker/software/pkt/devices/si446x.c b/tracker/software/pkt/devices/si446x.c index f1078351..3646a7d3 100644 --- a/tracker/software/pkt/devices/si446x.c +++ b/tracker/software/pkt/devices/si446x.c @@ -1254,19 +1254,37 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) { uint8_t layer0[AFSK_FEEDER_BUFFER_SIZE]; - /* TODO: Insert CRC in radio.c transmit function? */ + TRACE_INFO("SI > Packet frame bytes %i", pp->frame_len); + + /* TODO: Make this a prepare function. + * Create iterator object and complete TX frame. + * Insert CRC in radio.c transmit function? + */ uint16_t crc = calc_crc16(pp->frame_data, 0, pp->frame_len); pp->frame_data[pp->frame_len++] = crc & 0xFF; pp->frame_data[pp->frame_len++] = crc >> 8; + pp->frame_data[pp->frame_len++] = HDLC_FLAG; - tx_composer_t output = {0}; - output.pp = pp; + static tx_iterator_t output = {0}; + memset(&output, 0, sizeof(output)); + //output.pp = pp; /* TODO: get preamble count from TX packet. */ output.pre_count = 30; output.scramble = false; + output.data_buff = pp->frame_data; output.data_size = pp->frame_len; + output.out_buff = layer0; + output.out_size = sizeof(layer0); - uint32_t data = pktStreamDataForSend(&output, layer0, AFSK_FEEDER_BUFFER_SIZE); + static int32_t data = 0; + data = pktIterateSendStream(&output, sizeof(layer0)); + + TRACE_INFO("SI > Iterator data count %i", data); + + if(data < 0) { + /* Buffer overrun. */ + /* TODO: Implement handling. */ + } /* Reset TX FIFO in case some remnant unsent data is left there. */ const uint8_t reset_fifo[] = {0x15, 0x01}; @@ -1292,8 +1310,7 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) { uint16_t all = data * SAMPLES_PER_BAUD; uint16_t c = (all > free) ? free : all; - - TRACE_INFO("SI > AFSK up-sampled bytes to send %i", all); + TRACE_INFO("SI > AFSK frame bytes to send %i, upsampled %i", data, all); /* * Start transmission timeout timer. diff --git a/tracker/software/pkt/protocols/txhdlc.c b/tracker/software/pkt/protocols/txhdlc.c index 39aadf08..b911061b 100644 --- a/tracker/software/pkt/protocols/txhdlc.c +++ b/tracker/software/pkt/protocols/txhdlc.c @@ -33,93 +33,102 @@ void scramble(uint8_t *data, size_t size) { } -/* TODO: Make this a macro. */ -static bool pktGetBitAsNRZI(bool bit, bool *prior) { - if((bit & 0x1) == 0) - *prior = !*prior; - return *prior; +/* + * Write NRZI data to output buffer. + * Byte complete = true else false. + * + */ +static bool pktIteratorWriteNRZI(tx_iterator_t *iterator, uint8_t bit) { + /* If new byte clear it first. */ + if(iterator->out_index % 8 == 0) + iterator->out_buff[iterator->out_index >> 3] = 0; + + /* clean up bit. */ + bit &= 0x1; + /* Keep track of HDLC for RLL detection. */ + iterator->hdlc_data <<= 1; + iterator->hdlc_data |= bit; + + /* Remember last NRZI state (keep history for debug purposes). */ + iterator->nrzi_last <<= 1; + iterator->nrzi_last |= (bit == 0) + ? (((iterator->nrzi_last >> 1 ) ^ 0x1) & 0x1) + : 1; + + /* Write NRZI bit to current byte. */ + iterator->out_buff[iterator->out_index >> 3] |= + (iterator->nrzi_last & 0x1) << (iterator->out_index % 8); + + /* If byte is full return true. */ + return ((++iterator->out_index % 8) == 0); } /* * Create stream of bytes of encoded link level data. - * The calling function may request chunk sizes from 1 up. + * The calling function may request chunk sizes from 1 byte up. * The function returns the number of bytes encoded. - * + * When return < request there is no more to encode. + * When return is -1 then the output buffer is full. */ -uint32_t pktStreamDataForSend(tx_composer_t *composer, - uint8_t *buf, size_t size) { +int32_t pktIterateSendStream(tx_iterator_t *iterator, size_t qty) { - if(size == 0) + if(qty == 0) return 0; - size_t cnt = size; + size_t cnt = 0; /* * Output preamble bytes of specified quantity in requested chunk size. * RLL encoding is not used as these are HDLC flags. */ - while(composer->pre_count > 0) { - uint8_t i = 0, f = HDLC_FLAG; - do { - /* Shift up prior bit. */ - composer->hdlc_data <<= 1; - /* Get a data bit. */ - composer->hdlc_data |= pktGetBitAsNRZI(f & 0x1, - &composer->prior_nrz); - f <<= 1; - } while(++i < 8); - *buf++ = composer->hdlc_data; - if(--cnt == 0) - return size; - composer->pre_count--; - } + while(iterator->pre_count > 0) { + /* TODO: Check for output buffer exhausted. */ + uint8_t i; + for(i = 0; !pktIteratorWriteNRZI(iterator, (HDLC_FLAG >> i) & 0x1); i++); + iterator->pre_count--; + if(++cnt == qty) + return qty; + } /* End while. */ /* * Output frame bytes in requested chunk size. - * CRC has been added to the data already. + * CRC and closing HDLC flag must be included in the frame data. */ - while(composer->data_size > 0) { - uint8_t i = 0; + while(iterator->data_size > 0) { do { - /* Shift up prior bit (and shift in a zero). */ - composer->hdlc_data <<= 1; - /* Check RLL encoding. */ - if((composer->hdlc_data & HDLC_RLL_BIT) == HDLC_RLL_BIT) { - /* Include the inserted 0 bit in the stream count. */ - i++; - } else { - /* Get a data bit. */ - composer->hdlc_data |= pktGetBitAsNRZI( - composer->pp->frame_data[composer->bit_index >> 3] & 0x1, - &composer->prior_nrz); + /* + * RLL encoding is enabled for the packet data pay load. + * Except the last data byte which is the HDLC flag. + */ + + + if(((iterator->hdlc_data & HDLC_RLL_SEQUENCE) == HDLC_RLL_SEQUENCE) + && (iterator->data_size > 1)) { + /* Insert RLL 0 to HDLC output stream. */ + if(pktIteratorWriteNRZI(iterator, 0)) { + if(++cnt == qty) + return qty; + } } + /* Get data bit. */ + uint8_t byte = iterator->data_buff[iterator->inp_index >> 3]; + uint8_t bit = (byte >> (iterator->inp_index % 8)) & 0x1; - /* Count the added bit. */ - composer->bit_index++; - } while(++i < 8); + /* Show bit is consumed and write it to steam. */ + iterator->inp_index++; + if(pktIteratorWriteNRZI(iterator, bit)) { + if(++cnt == qty) + return qty; + } + } while((iterator->inp_index % 8) != 0); + /* Consumed an input byte. */ + --iterator->data_size; + } /* End while. */ - /* Save the HDLC byte. */ - *buf++ = composer->hdlc_data; - if(--cnt == 0) - return size; - composer->data_size--; - } + /* TODO: Put CRC and closing flag insertion in here versus in main code. */ - /* - * Output closing flag. - * RLL encoding is not used as this is an HDLC flag. - */ - uint8_t i = 0, f = HDLC_FRAME_CLOSE; - do { - /* Shift up prior bit. */ - composer->hdlc_data <<= 1; - /* Get a data bit. */ - composer->hdlc_data |= pktGetBitAsNRZI(f & 0x1, - &composer->prior_nrz); - f <<= 1; - } while(++i < 8); - *buf++ = composer->hdlc_data; - composer->bit_index += i; - return --cnt; + /* Round up for partial byte. */ + + return (++cnt); } /** @} */ diff --git a/tracker/software/pkt/protocols/txhdlc.h b/tracker/software/pkt/protocols/txhdlc.h index 9810c48e..3e3f6b3e 100644 --- a/tracker/software/pkt/protocols/txhdlc.h +++ b/tracker/software/pkt/protocols/txhdlc.h @@ -18,6 +18,8 @@ #ifndef PKT_PROTOCOLS_TXHDLC_H_ #define PKT_PROTOCOLS_TXHDLC_H_ +#define HDLC_RLL_SEQUENCE 0x1FU + #define AX25_WRITE_BIT(data, size) { \ data[size >> 3] |= (1 << (size & 7)); \ } @@ -26,17 +28,30 @@ data[size >> 3] &= ~(1 << (size & 7)); \ } +typedef enum { + ITERATE_INIT, + ITERATE_PREAMBLE, + ITERATE_FRAME, + ITERATE_CRC, + ITERATE_CLOSE +} txit_state_t; + typedef struct { - packet_t pp; + //packet_t pp; + txit_state_t state; uint16_t pre_count; + uint8_t *data_buff; uint16_t data_size; + uint8_t *out_buff; + uint16_t out_size; + uint8_t nrzi_last; uint8_t hdlc_data; - uint32_t bit_index; - uint8_t rll_count; - bool prior_nrz; + uint32_t inp_index; + uint32_t out_index; + uint16_t rll_count; bool scramble; uint32_t lfsr; -} tx_composer_t; +} tx_iterator_t; /*===========================================================================*/ /* External declarations. */ @@ -45,8 +60,7 @@ typedef struct { #ifdef __cplusplus extern "C" { #endif - uint32_t pktStreamDataForSend(tx_composer_t *composer, - uint8_t *buf, size_t size); + int32_t pktIterateSendStream(tx_iterator_t *iterator, size_t qty); #ifdef __cplusplus } #endif