123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /*
- * aprs_decoder.c
- *
- * Created on: Aug 25, 2019
- * Author: curiousmuch
- */
- typedef enum {
- NORMAL,
- FRAME_DECODED,
- ERROR_FCS_MISMATCH,
- ERROR_PACKET_FORMAT,
- ERROR_BUFFER_OVERFLOW
- } decoder_output_t;
- typedef enum {
- NONE,
- BUFFER_OVERFLOW,
- BIT_STUFFING_FAILURE,
- FCS_MISMATCH,
- } decoder_error_t;
- typedef enum {
- FLAG_SEARCH,
- FLAG_FOUND,
- FRAME_START,
- PACKET_END,
- FRAME_END,
- ABORT,
- } decoder_state_t;
- typedef struct {
- decoder_state_t decoder_state;
- uint8_t *frame_buffer;
- uint8_t frame_buffer_index;
- uint8_t frame_buffer_len;
- uint8_t flag_buffer;
- uint8_t flag_buffer_index;
- uint8_t byte_buffer;
- uint8_t current_nrzi_bit;
- uint8_t previous_nrzi_bit;
- uint8_t current_bit;
- uint8_t one_count;
- uint32_t byte_buffer_index;
- uint8_t skip_bit_flag;
- } decoder_varibles_t;
- decoder_varibles_t v;
- #define APRS_MAX_FRAME 256
- void frame_buffer_init(uint8_t *buf, uint8_t len)
- {
- v.frame_buffer = buf;
- v.frame_buffer_len = len;
- }
- void aprs_decode_init(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_index = 0;
- v.byte_buffer = 0;
- v.current_nrzi_bit = 0;
- v.previous_nrzi_bit = 0;
- v.current_bit = 0;
- v.one_count = 0;
- v.skip_bit_flag = 0;
- }
- uint8_t flag_found(void)
- {
- if (v.flag_buffer == 0x7E)
- return 1;
- else
- return 0;
- }
- decoder_output_t aprs_decode_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;
- // re-initialize buffer indexes
- v.flag_buffer_index = 0;
- v.frame_buffer_index = 0;
- }
- else
- {
- v.decoder_state = FLAG_SEARCH;
- }
- 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_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;
- }
- else
- {
- v.byte_buffer |= bit*(0x8>>i);
- 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;
- }
- }
- 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 = PACKET_END;
- break;
- }
- }
- else
- {
- // load bit
- v.byte_buffer |= v.current_bit*(0x8>>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_END)
- {
- // calculate CRC
- // re-initialize state machine
- return FRAME_DECODED;
- }
- if (v.decoder_state == ABORT)
- {
- // re-initialize state machine
- aprs_decoder_init();
- }
- return NORMAL;
- }
|