/* * 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; }