aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp_clock/octoclock/kk_ihex.h
diff options
context:
space:
mode:
authorNicholas Corgan <nick.corgan@ettus.com>2015-08-14 07:42:01 -0700
committerMartin Braun <martin.braun@ettus.com>2015-08-14 12:30:53 -0700
commitd35a0e28b6af67e4500b51c4739886f7544bca35 (patch)
tree64c04cd3b879d4898ecfcf4a52260ab8fa312d37 /host/lib/usrp_clock/octoclock/kk_ihex.h
parent8d6b63e1e86ae0f1ee8b084ea2db6d5b5b705179 (diff)
downloaduhd-d35a0e28b6af67e4500b51c4739886f7544bca35.tar.gz
uhd-d35a0e28b6af67e4500b51c4739886f7544bca35.tar.bz2
uhd-d35a0e28b6af67e4500b51c4739886f7544bca35.zip
octoclock: replaced Intel hex -> binary converter
Diffstat (limited to 'host/lib/usrp_clock/octoclock/kk_ihex.h')
-rw-r--r--host/lib/usrp_clock/octoclock/kk_ihex.h191
1 files changed, 191 insertions, 0 deletions
diff --git a/host/lib/usrp_clock/octoclock/kk_ihex.h b/host/lib/usrp_clock/octoclock/kk_ihex.h
new file mode 100644
index 000000000..20eba43cc
--- /dev/null
+++ b/host/lib/usrp_clock/octoclock/kk_ihex.h
@@ -0,0 +1,191 @@
+/*
+ * kk_ihex.h: A simple library for reading and writing the Intel HEX
+ * or IHEX format. Intended mainly for embedded systems, and thus
+ * somewhat optimised for size at the expense of error handling and
+ * generality.
+ *
+ * USAGE
+ * -----
+ *
+ * The library has been split into read and write parts, which use a
+ * common data structure (`struct ihex_state`), but each can be used
+ * independently. Include the header `kk_ihex_read.h` for reading, and/or
+ * the header `kk_ihex_write.h` for writing (and link with their respective
+ * object files). Both can be used simultaneously - this header defines
+ * the shared data structures and definitions.
+ *
+ *
+ * READING INTEL HEX DATA
+ * ----------------------
+ *
+ * To read data in the Intel HEX format, you must perform the actual reading
+ * of bytes using other means (e.g., stdio). The bytes read must then be
+ * passed to `ihex_read_byte` and/or `ihex_read_bytes`. The reading functions
+ * will then call `ihex_data_read`, at which stage the `struct ihex_state`
+ * structure will contain the data along with its address. See the header
+ * `kk_ihex_read.h` for details and example implementation of `ihex_data_read`.
+ *
+ * The sequence to read data in IHEX format is:
+ * struct ihex_state ihex;
+ * ihex_begin_read(&ihex);
+ * ihex_read_bytes(&ihex, my_input_bytes, length_of_my_input_bytes);
+ * ihex_end_read(&ihex);
+ *
+ *
+ * WRITING BINARY DATA AS INTEL HEX
+ * --------------------------------
+ *
+ * In order to write out data, the `ihex_write_at_address` or
+ * `ihex_write_at_segment` functions are used to set the data location,
+ * and then the binary bytes are written with `ihex_write_byte` and/or
+ * `ihex_write_bytes`. The writing functions will then call the function
+ * `ihex_flush_buffer` whenever the internal write buffer needs to be
+ * cleared - it is up to the caller to provide an implementation of
+ * `ihex_flush_buffer` to do the actual writing. See the header
+ * `kk_ihex_write.h` for details and an example implementation.
+ *
+ * See the declaration further down for an example implementation.
+ *
+ * The sequence to write data in IHEX format is:
+ * struct ihex_state ihex;
+ * ihex_init(&ihex);
+ * ihex_write_at_address(&ihex, 0);
+ * ihex_write_bytes(&ihex, my_data, length_of_my_data);
+ * ihex_end_write(&ihex);
+ *
+ * For outputs larger than 64KiB, 32-bit linear addresses are output. Normally
+ * the initial linear extended address record of zero is NOT written - it can
+ * be forced by setting `ihex->flags |= IHEX_FLAG_ADDRESS_OVERFLOW` before
+ * writing the first byte.
+ *
+ * Gaps in the data may be created by calling `ihex_write_at_address` with the
+ * new starting address without calling `ihex_end_write` in between.
+ *
+ *
+ * The same `struct ihex_state` may be used either for reading or writing,
+ * but NOT both at the same time. Furthermore, a global output buffer is
+ * used for writing, i.e., multiple threads must not write simultaneously
+ * (but multiple writes may be interleaved).
+ *
+ *
+ * CONSERVING MEMORY
+ * -----------------
+ *
+ * For memory-critical use, you can save additional memory by defining
+ * `IHEX_LINE_MAX_LENGTH` as something less than 255. Note, however, that
+ * this limit affects both reading and writing, so the resulting library
+ * will be unable to read lines with more than this number of data bytes.
+ * That said, I haven't encountered any IHEX files with more than 32
+ * data bytes per line. For write only there is no reason to define the
+ * maximum as greater than the line length you'll actually be writing,
+ * e.g., 32 or 16.
+ *
+ * If the write functionality is only occasionally used, you can provide
+ * your own buffer for the duration by defining `IHEX_EXTERNAL_WRITE_BUFFER`
+ * and providing a `char *ihex_write_buffer` which points to valid storage
+ * for at least `IHEX_WRITE_BUFFER_LENGTH` characters from before the first
+ * call to any IHEX write function to until after the last.
+ *
+ * If you are doing both reading and writing, you can define the maximum
+ * output length separately as `IHEX_MAX_OUTPUT_LINE_LENGTH` - this will
+ * decrease the write buffer size, but `struct ihex_state` will still
+ * use the larger `IHEX_LINE_MAX_LENGTH` for its data storage.
+ *
+ * You can also save a few additional bytes by disabling support for
+ * segmented addresses, by defining `IHEX_DISABLE_SEGMENTS`. Both the
+ * read and write modules need to be build with the same option, as the
+ * resulting data structures will not be compatible otherwise. To be honest,
+ * this is a fairly pointless optimisation.
+ *
+ *
+ * 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.
+ */
+
+#ifndef KK_IHEX_H
+#define KK_IHEX_H
+
+#define KK_IHEX_VERSION "2015-08-10"
+
+#include <stdint.h>
+
+#ifdef IHEX_USE_STDBOOL
+#include <stdbool.h>
+typedef bool ihex_bool_t;
+#else
+typedef uint_fast8_t ihex_bool_t;
+#endif
+
+typedef uint_least32_t ihex_address_t;
+typedef uint_least16_t ihex_segment_t;
+typedef int ihex_count_t;
+
+// Maximum number of data bytes per line (applies to both reading and
+// writing!); specify 255 to support reading all possible lengths. Less
+// can be used to limit memory footprint on embedded systems, e.g.,
+// most programs with IHEX output use 32.
+#ifndef IHEX_LINE_MAX_LENGTH
+#define IHEX_LINE_MAX_LENGTH 255
+#endif
+
+enum ihex_flags {
+ IHEX_FLAG_ADDRESS_OVERFLOW = 0x80 // 16-bit address overflow
+};
+typedef uint8_t ihex_flags_t;
+
+typedef struct ihex_state {
+ ihex_address_t address;
+#ifndef IHEX_DISABLE_SEGMENTS
+ ihex_segment_t segment;
+#endif
+ ihex_flags_t flags;
+ uint8_t line_length;
+ uint8_t length;
+ uint8_t data[IHEX_LINE_MAX_LENGTH + 1];
+} kk_ihex_t;
+
+enum ihex_record_type {
+ IHEX_DATA_RECORD,
+ IHEX_END_OF_FILE_RECORD,
+ IHEX_EXTENDED_SEGMENT_ADDRESS_RECORD,
+ IHEX_START_SEGMENT_ADDRESS_RECORD,
+ IHEX_EXTENDED_LINEAR_ADDRESS_RECORD,
+ IHEX_START_LINEAR_ADDRESS_RECORD
+};
+typedef uint8_t ihex_record_type_t;
+
+#ifndef IHEX_DISABLE_SEGMENTS
+
+// Resolve segmented address (if any). It is the author's recommendation that
+// segmented addressing not be used (and indeed the write function of this
+// library uses linear 32-bit addressing unless manually overridden).
+//
+#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address + (((ihex_address_t)((ihex)->segment)) << 4))
+//
+// Note that segmented addressing with the above macro is not strictly adherent
+// to the IHEX specification, which mandates that the lowest 16 bits of the
+// address and the index of the data byte must be added modulo 64K (i.e.,
+// at 16 bits precision with wraparound) and the segment address only added
+// afterwards.
+//
+// To implement fully correct segmented addressing, compute the address
+// of _each byte_ with its index in `data` as follows:
+//
+#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((((ihex)->address + (byte_index)) & 0xFFFFU) + (((ihex_address_t)((ihex)->segment)) << 4))
+
+#else // IHEX_DISABLE_SEGMENTS:
+
+#define IHEX_LINEAR_ADDRESS(ihex) ((ihex)->address)
+#define IHEX_BYTE_ADDRESS(ihex, byte_index) ((ihex)->address + (byte_index))
+
+#endif
+
+// The newline string (appended to every output line, e.g., "\r\n")
+#ifndef IHEX_NEWLINE_STRING
+#define IHEX_NEWLINE_STRING "\n"
+#endif
+
+// See kk_ihex_read.h and kk_ihex_write.h for function declarations!
+
+#endif // !KK_IHEX_H