diff options
Diffstat (limited to 'host/lib/usrp_clock/octoclock/kk_ihex_read.c')
-rw-r--r-- | host/lib/usrp_clock/octoclock/kk_ihex_read.c | 261 |
1 files changed, 0 insertions, 261 deletions
diff --git a/host/lib/usrp_clock/octoclock/kk_ihex_read.c b/host/lib/usrp_clock/octoclock/kk_ihex_read.c deleted file mode 100644 index 964cdd165..000000000 --- a/host/lib/usrp_clock/octoclock/kk_ihex_read.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * kk_ihex_read.c: A simple library for reading the Intel HEX (IHEX) format. - * - * See the header `kk_ihex.h` for instructions. - * - * Copyright (c) 2013-2015 Kimmo Kulovesi, http://arkku.com/ - * Provided with absolutely no warranty, use at your own risk only. - * Use and distribute freely, mark modified copies as such. - * - * Modifications Copyright (c) 2015 National Instruments Corp. - */ - -#include "kk_ihex_read.h" - -#include <stdio.h> -#include <stdlib.h> - -#define IHEX_START ':' - -#define AUTODETECT_ADDRESS (~0UL) - -#define ADDRESS_HIGH_MASK ((ihex_address_t) 0xFFFF0000U) - -enum ihex_read_state { - READ_WAIT_FOR_START = 0, - READ_COUNT_HIGH = 1, - READ_COUNT_LOW, - READ_ADDRESS_MSB_HIGH, - READ_ADDRESS_MSB_LOW, - READ_ADDRESS_LSB_HIGH, - READ_ADDRESS_LSB_LOW, - READ_RECORD_TYPE_HIGH, - READ_RECORD_TYPE_LOW, - READ_DATA_HIGH, - READ_DATA_LOW -}; - -#define IHEX_READ_RECORD_TYPE_MASK 0x07 -#define IHEX_READ_STATE_MASK 0x78 -#define IHEX_READ_STATE_OFFSET 3 - -void -ihex_begin_read (struct ihex_state * const ihex) { - ihex->address = 0; -#ifndef IHEX_DISABLE_SEGMENTS - ihex->segment = 0; -#endif - ihex->flags = 0; - ihex->line_length = 0; - ihex->length = 0; -} - -void -ihex_read_at_address (struct ihex_state * const ihex, ihex_address_t address) { - ihex_begin_read(ihex); - ihex->address = address; -} - -#ifndef IHEX_DISABLE_SEGMENTS -void -ihex_read_at_segment (struct ihex_state * const ihex, ihex_segment_t segment) { - ihex_begin_read(ihex); - ihex->segment = segment; -} -#endif - -void -ihex_end_read (struct ihex_state * const ihex, FILE* outfile) { - uint_fast8_t type = ihex->flags & IHEX_READ_RECORD_TYPE_MASK; - uint_fast8_t sum; - if ((sum = ihex->length) == 0 && type == IHEX_DATA_RECORD) { - return; - } - { - // compute and validate checksum - const uint8_t * const eptr = ihex->data + sum; - const uint8_t *r = ihex->data; - sum += type + (ihex->address & 0xFFU) + ((ihex->address >> 8) & 0xFFU); - while (r != eptr) { - sum += *r++; - } - sum = (~sum + 1U) ^ *eptr; // *eptr is the received checksum - } - if (ihex_data_read(ihex, type, sum, outfile)) { - if (type == IHEX_EXTENDED_LINEAR_ADDRESS_RECORD) { - ihex->address &= 0xFFFFU; - ihex->address |= (((ihex_address_t) ihex->data[0]) << 24) | - (((ihex_address_t) ihex->data[1]) << 16); -#ifndef IHEX_DISABLE_SEGMENTS - } else if (type == IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD) { - ihex->segment = (ihex_segment_t) ((ihex->data[0] << 8) | ihex->data[1]); -#endif - } - } - ihex->length = 0; - ihex->flags = 0; -} - -void -ihex_read_byte (struct ihex_state * const ihex, const char byte, FILE* outfile) { - uint_fast8_t b = (uint_fast8_t) byte; - uint_fast8_t len = ihex->length; - uint_fast8_t state = (ihex->flags & IHEX_READ_STATE_MASK); - ihex->flags ^= state; // turn off the old state - state >>= IHEX_READ_STATE_OFFSET; - - if (b >= '0' && b <= '9') { - b -= '0'; - } else if (b >= 'A' && b <= 'F') { - b -= 'A' - 10; - } else if (b >= 'a' && b <= 'f') { - b -= 'a' - 10; - } else if (b == IHEX_START) { - // sync to a new record at any state - state = READ_COUNT_HIGH; - goto end_read; - } else { - // ignore unknown characters (e.g., extra whitespace) - goto save_read_state; - } - - if (!(++state & 1)) { - // high nybble, store temporarily at end of data: - b <<= 4; - ihex->data[len] = b; - } else { - // low nybble, combine with stored high nybble: - b = (ihex->data[len] |= b); - switch (state >> 1) { - default: - // remain in initial state while waiting for : - return; - case (READ_COUNT_LOW >> 1): - // data length - ihex->line_length = b; -#if IHEX_LINE_MAX_LENGTH < 255 - if (b > IHEX_LINE_MAX_LENGTH) { - ihex_end_read(ihex); - return; - } -#endif - break; - case (READ_ADDRESS_MSB_LOW >> 1): - // high byte of 16-bit address - ihex->address &= ADDRESS_HIGH_MASK; // clear the 16-bit address - ihex->address |= ((ihex_address_t) b) << 8U; - break; - case (READ_ADDRESS_LSB_LOW >> 1): - // low byte of 16-bit address - ihex->address |= (ihex_address_t) b; - break; - case (READ_RECORD_TYPE_LOW >> 1): - // record type - if (b & ~IHEX_READ_RECORD_TYPE_MASK) { - // skip unknown record types silently - return; - } - ihex->flags = (ihex->flags & ~IHEX_READ_RECORD_TYPE_MASK) | b; - break; - case (READ_DATA_LOW >> 1): - if (len < ihex->line_length) { - // data byte - ihex->length = len + 1; - state = READ_DATA_HIGH; - goto save_read_state; - } - // end of line (last "data" byte is checksum) - state = READ_WAIT_FOR_START; - end_read: - ihex_end_read(ihex, outfile); - } - } -save_read_state: - ihex->flags |= state << IHEX_READ_STATE_OFFSET; -} - -void -ihex_read_bytes (struct ihex_state * ihex, - const char * data, - ihex_count_t count, - FILE* outfile) { - while (count > 0) { - ihex_read_byte(ihex, *data++, outfile); - --count; - } -} - -ihex_bool_t -ihex_data_read (struct ihex_state *ihex, - ihex_record_type_t type, - ihex_bool_t error, - FILE* outfile) { - unsigned long line_number = 1L; - unsigned long file_position = 0L; - unsigned long address_offset = 0L; - bool debug_enabled = false; - - if (error) { - (void) fprintf(stderr, "Checksum error on line %lu\n", line_number); - return false; - } - if ((error = (ihex->length < ihex->line_length))) { - (void) fprintf(stderr, "Line length error on line %lu\n", line_number); - return false; - } - if (!outfile) { - (void) fprintf(stderr, "Excess data after end of file record\n"); - return false; - } - if (type == IHEX_DATA_RECORD) { - unsigned long address = (unsigned long) IHEX_LINEAR_ADDRESS(ihex); - if (address < address_offset) { - if (address_offset == AUTODETECT_ADDRESS) { - // autodetect initial address - address_offset = address; - if (debug_enabled) { - (void) fprintf(stderr, "Address offset: 0x%lx\n", - address_offset); - } - } else { - (void) fprintf(stderr, "Address underflow on line %lu\n", - line_number); - return false; - } - } - address -= address_offset; - if (address != file_position) { - if (debug_enabled) { - (void) fprintf(stderr, - "Seeking from 0x%lx to 0x%lx on line %lu\n", - file_position, address, line_number); - } - if (outfile == stdout || fseek(outfile, (long) address, SEEK_SET)) { - if (file_position < address) { - // "seek" forward in stdout by writing NUL bytes - do { - (void) fputc('\0', outfile); - } while (++file_position < address); - } else { - perror("fseek"); - return false; - } - } - file_position = address; - } - if (!fwrite(ihex->data, ihex->length, 1, outfile)) { - perror("fwrite"); - return false; - } - file_position += ihex->length; - } else if (type == IHEX_END_OF_FILE_RECORD) { - if (debug_enabled) { - (void) fprintf(stderr, "%lu bytes written\n", file_position); - } - if (outfile != stdout) { - (void) fclose(outfile); - } - outfile = NULL; - } - return true; -} |