/* * aprs_decoder.c * * Created on: Aug 25, 2019 * Author: curiousmuch */ #include "aprs_decoder.h" //#include "fcs_calc.h" //#define uint8_t unsigned int //#define uint32_t unsigned int decoder_varibles_t v; #define APRS_MAX_FRAME 256 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> 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 frame_buffer_init(uint8_t *buf, uint32_t len) { v.frame_buffer = buf; v.frame_buffer_len = len; } void aprs_decoder_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 = 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; } 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; } } decoder_output_t aprs_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 // TODO: Is this in the correct format???? 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< 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 aprs_decoder_init(); } return NORMAL; }