123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /*
- * aprs_decoder.c
- *
- * Created on: Aug 25, 2019
- * Author: curiousmuch
- */
- #include "aprs_decoder.h"
- /* Local Global Variables */
- static decoder_varibles_t v;
- /* Private Functions */
- static uint32_t fcs_calc(uint8_t *data, uint32_t len)
- {
- uint32_t crc, aprs_polynomial, i, j, byte_lsb, crc_lsb;
- crc = 0xFFFF;
- aprs_polynomial = 0x8408;
- for (i=0;i<len;i++)
- {
- for (j=0;j<8;j++)
- {
- byte_lsb = (data[i] >> j) & 0x01;
- crc_lsb = crc & 0x0001;
- if (crc_lsb != byte_lsb)
- crc = (crc >> 1) ^ aprs_polynomial;
- else
- crc = crc >> 1;
- }
- }
- crc = crc ^ 0xFFFF;
- return crc & 0xFFFF;
- }
- void ax25_buffer_init(uint8_t *buf, uint32_t len)
- {
- v.frame_buffer = buf;
- v.frame_buffer_len = len;
- }
- uint8_t get_rx_status(void)
- {
- if (v.packet_rx)
- return 1;
- else
- return 0;
- }
- uint8_t flag_found(void)
- {
- if (v.flag_buffer == 0x7E)
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- /* Public Functions */
- uint8_t ax25_decoder_get_cs(void)
- {
- return get_rx_status();
- }
- void ax25_decoder_reset(void)
- {
- v.decoder_state = FLAG_SEARCH;
- v.frame_buffer_index = 0;
- //v.frame_max_len = APRS_MAX_FRAME;
- v.flag_buffer = 0;
- v.flag_buffer_index = 0;
- v.byte_buffer = 0;
- v.byte_buffer_index = 0;
- v.current_nrzi_bit = 0;
- v.previous_nrzi_bit = 0;
- v.current_bit = 0;
- v.one_count = 0;
- v.skip_bit_flag = 0;
- v.packet_rx = 0;
- }
- void ax25_decoder_init(uint8_t *frame_buffer, uint32_t frame_len)
- {
- // reset state-machine variables
- ax25_decoder_reset();
- // setup frame buffer
- ax25_buffer_init(frame_buffer, frame_len);
- }
- uint32_t ax25_decoder_get_frame_len(void)
- {
- // could we have a race condition?
- return v.frame_len;
- }
- uint8_t * ax25_decoder_get_frame(void)
- {
- return v.frame_buffer;
- }
- decoder_output_t ax25_decoder_feed_bit(uint8_t nrzi_bit)
- {
- v.current_nrzi_bit = nrzi_bit;
- // decoder NRZI
- if (v.previous_nrzi_bit == v.current_nrzi_bit)
- {
- v.current_bit = 1;
- v.one_count += 1;
- }
- else
- {
- v.current_bit = 0;
- v.one_count = 0;
- }
- v.previous_nrzi_bit = v.current_nrzi_bit;
- // load bit into flag buffer
- v.flag_buffer = (v.flag_buffer >> 1) + (v.current_bit*0x80);
- switch(v.decoder_state)
- {
- case FLAG_SEARCH:
- if (flag_found())
- {
- // set state variable
- v.decoder_state = FLAG_FOUND;
- v.packet_rx = 1;
- // re-initialize buffer indexes
- v.flag_buffer_index = 0;
- v.frame_buffer_index = 0;
- }
- else
- {
- v.decoder_state = FLAG_SEARCH;
- v.packet_rx = 0;
- }
- break;
- case FLAG_FOUND:
- if (v.flag_buffer_index == 7) // check every 8 bits for flag again
- {
- if (flag_found()) // if flag is found, payload hasn't started
- {
- v.decoder_state = FLAG_FOUND;
- v.flag_buffer_index = 0;
- }
- else
- {
- v.decoder_state = FRAME_START;
- // load current bits in byte buffer and remove 0 stuffing
- uint8_t i, bit;
- v.skip_bit_flag = 0;
- v.byte_buffer = 0;
- v.byte_buffer_index = 0;
- v.one_count = 0;
- for (i=0;i<7;i++)
- {
- bit = (v.flag_buffer << i) & 0x80; // load bit
- // count ones for to remove bit stuffing
- if (bit)
- v.one_count += 1;
- else
- v.one_count = 0;
- // skip bit or store in v.byte_buffer
- if (v.skip_bit_flag)
- {
- v.skip_bit_flag = 0;
- // if "0" is not stuffed packet is invalid
- if (bit != 0)
- {
- v.decoder_state = ABORT;
- break;
- }
- }
- else
- {
- v.byte_buffer |= (bit) ? (0x80>>i): 0;
- v.byte_buffer_index += 1;
- }
- if (v.one_count == 5)
- v.skip_bit_flag = 1;
- }
- // check if byte buffer is full
- if (v.byte_buffer_index == 7)
- {
- v.frame_buffer[v.frame_buffer_index] = v.byte_buffer;
- v.byte_buffer = 0;
- v.byte_buffer_index = 0;
- v.frame_buffer_index += 1;
- }
- break;
- }
- }
- else
- {
- v.flag_buffer_index += 1;
- }
- break;
- case FRAME_START:
- // skip stuffed "0"
- if (v.skip_bit_flag == 1)
- {
- v.skip_bit_flag = 0;
- // bit will only not be stuffed properly if the HDLC flag is being received
- // indicating the end of the frame or the packet has become corrupted.
- if (v.current_bit != 0)
- {
- v.decoder_state = FRAME_BREAK;
- break;
- }
- }
- else
- {
- // load bit
- v.byte_buffer |= v.current_bit*(0x01<<v.byte_buffer_index);
- v.byte_buffer_index += 1;
- // check if byte buffer is full
- if (v.byte_buffer_index > 7)
- {
- v.frame_buffer[v.frame_buffer_index] = v.byte_buffer;
- v.byte_buffer = 0;
- v.byte_buffer_index = 0;
- v.frame_buffer_index += 1;
- // check for overflow
- if (v.frame_buffer_index >= v.frame_buffer_len)
- {
- v.decoder_state = ABORT;
- break;
- }
- }
- }
- if(v.one_count == 5)
- v.skip_bit_flag = 1;
- break;
- default:
- // we're in trouble.
- break;
- }
- if (v.decoder_state == FRAME_BREAK)
- {
- // state
- v.decoder_state = FLAG_SEARCH;
- // calculate CRC
- volatile uint32_t fcs, frame_fcs;
- if (v.frame_buffer_index < 10) // TODO: Determine minimum APRS packet
- return ERROR_PACKET_FORMAT;
- v.frame_len = v.frame_buffer_index - 2;
- fcs = fcs_calc(v.frame_buffer, v.frame_len);
- frame_fcs = (v.frame_buffer[v.frame_len+1]<<8) |
- v.frame_buffer[v.frame_len];
- if (fcs == frame_fcs)
- return FRAME_DECODED;
- else
- return ERROR_FCS_MISMATCH;
- }
- if (v.decoder_state == ABORT)
- {
- // re-initialize state machine
- ax25_decoder_reset();
- }
- return NORMAL;
- }
|