From 4b0bec820e90292dc5e350dc90e8fba0f2c45e4d Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 22 Sep 2009 17:15:25 +0200 Subject: [PATCH] added neginf inflate library --- avr/usbload/Makefile | 6 +- avr/usbload/inflate.c | 40 +++ avr/usbload/inflate.h | 28 ++ avr/usbload/neginf/neginf.c | 440 +++++++++++++++++++++++++++++++ avr/usbload/neginf/neginf.h | 43 +++ avr/usbload/neginf/neginf_conf.h | 48 ++++ avr/usbload/neginf/neginf_priv.h | 102 +++++++ 7 files changed, 704 insertions(+), 3 deletions(-) create mode 100644 avr/usbload/inflate.c create mode 100644 avr/usbload/inflate.h create mode 100644 avr/usbload/neginf/neginf.c create mode 100644 avr/usbload/neginf/neginf.h create mode 100644 avr/usbload/neginf/neginf_conf.h create mode 100644 avr/usbload/neginf/neginf_priv.h diff --git a/avr/usbload/Makefile b/avr/usbload/Makefile index ac14318..2150633 100644 --- a/avr/usbload/Makefile +++ b/avr/usbload/Makefile @@ -33,13 +33,13 @@ ifeq ($(DEBUG),1) OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o \ main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o \ dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o \ - pwm.o util.o shell.o irq.o command.o testing.o + pwm.o util.o shell.o irq.o command.o testing.o inflate.o neginf/neginf.o else LDFLAGS =-Wl,-u CFLAGS =-Iusbdrv -I. -DDEBUG_LEVEL=0 -DNO_DEBUG -DNO_INFO OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o \ uart.o fifo.o sram.o crc.o debug.o dump.o timer.o watchdog.o rle.c loader.o \ - pwm.o uril.o shell.o info.o shared_memory.o command.o irq.o + pwm.o uril.o shell.o info.o shared_memory.o command.o irq.o inflate.o neginf/neginf.o endif COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE) @@ -105,4 +105,4 @@ cpp: $(COMPILE) -E main.c clean: - rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s + rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s neginf/*.o diff --git a/avr/usbload/inflate.c b/avr/usbload/inflate.c new file mode 100644 index 0000000..a2ad6d1 --- /dev/null +++ b/avr/usbload/inflate.c @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * ________ .__ __ ________ ____ ________ + * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/ + * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \ + * / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \ + * \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ / + * \__> \/ \/ \/ \/ \/ + * + * www.optixx.org + * + * + * Version: 1.0 + * Created: 09/22/2009 + * Author: jannis@harderweb.de + * + * ===================================================================================== + */ + +#include "neginf/neginf.h" + +#include "inflate.h" + +char inflate_done = 0; + +void neginf_cb_completed() +{ + inflate_done = 1; +} + +void neginf_cb_seq_byte(nbyte byte) +{ + // TODO: implement this +} + +void neginf_cb_copy(nsize from, nsize to, nint length) +{ + // TODO: implement this +} diff --git a/avr/usbload/inflate.h b/avr/usbload/inflate.h new file mode 100644 index 0000000..86ada78 --- /dev/null +++ b/avr/usbload/inflate.h @@ -0,0 +1,28 @@ +/* + * ===================================================================================== + * + * ________ .__ __ ________ ____ ________ + * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/ + * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \ + * / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \ + * \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ / + * \__> \/ \/ \/ \/ \/ + * + * www.optixx.org + * + * + * Version: 1.0 + * Created: 09/22/2009 + * Author: jannis@harderweb.de + * + * ===================================================================================== + */ + + + +#ifndef __INFLATE_H__ +#define __INFLATE_H__ + +extern char inflate_done; + +#endif diff --git a/avr/usbload/neginf/neginf.c b/avr/usbload/neginf/neginf.c new file mode 100644 index 0000000..2f7b53c --- /dev/null +++ b/avr/usbload/neginf/neginf.c @@ -0,0 +1,440 @@ +/* + * neginf.c + * neginf -- embedded inflate lib + * + * inflate routines + */ + +#include +#include + +#include "neginf.h" +#include "neginf_priv.h" + +typedef void(*mode_fun)() ; + +static neginf_state state; +static const mode_fun mode_tab[mode_count] = { + &await_block, + &raw_block_begin, + &raw_block_begin2, + &raw_block, + &fixed_block_begin, + &huff_block, + &huff_len_addbits, + &huff_dist, + &huff_dist_addbits, + &dynamic_block_begin, + &dynamic_read_lc, + &dynamic_read_lit_len, + &dynamic_read_dist +}; + +void neginf_init(nsize start_pos) +{ + state.queue_size = 0; + state.mode = mode_await_block; + state.last_block = 0; +#ifdef NEGINF_POS_TRACKING + state.output_pos = start_pos; +#endif +} + + +void neginf_process_byte(nbyte byte) +{ + assert(state.queue_size <= 16); + state.input_queue |= (byte << state.queue_size); + state.queue_size += 8; + while(state.queue_size >= 16) + { + mode_tab[state.mode](); + } +} + +#ifdef NEGINF_POS_TRACKING +nsize neginf_output_position() +{ + return state.output_pos; +} +#endif + +nint lookahead() +{ + return state.input_queue; +} + +void consume(ntiny amount) +{ + assert(state.queue_size > amount); + state.input_queue >>= amount; + state.queue_size -= amount; +} + +void await_block() +{ + if(state.last_block) + { + neginf_cb_completed(); + consume(16); + } + else + { + nint la = lookahead(); + state.last_block = la & 1; + consume(3); + switch(la & 6) + { + case 0: // 00 uncompressed + consume((state.queue_size) & 7); // align to byte + state.mode = mode_raw_block_begin; + break; + case 2: // 01 fixed huffman + state.mode = mode_fixed_block_begin; + break; + case 4: // 10 dynamic huffman + state.mode = mode_dynamic_block_begin; + break; + default: + assert(0); + } + } +} + +void raw_block_begin() +{ + state.raw_size = lookahead() & 0xFFFF; // size of raw block + consume(16); + state.mode = mode_raw_block_begin2; +} + +void raw_block_begin2() +{ + consume(16); // we ignore the inverted size + state.mode = mode_raw_block; +} + +void raw_block() +{ + if(state.raw_size == 0) + { + state.mode = mode_await_block; + } + else + { + state.raw_size--; + neginf_cb_seq_byte(lookahead() & 0xFF); +#ifdef NEGINF_POS_TRACKING + state.output_pos++; +#endif + consume(8); + } +} + +void fixed_block_begin() +{ + nint i = 0; + for(; i < 144; i++) + state.lit_len_lengths[i] = 8; + for(; i < 256; i++) + state.lit_len_lengths[i] = 9; + for(; i < 280; i++) + state.lit_len_lengths[i] = 7; + for(; i < 288; i++) + state.lit_len_lengths[i] = 8; + + ntiny j; + for(j = 0; i < 32; i++) + state.dist_lengths[i] = 5; + + compute_begins(); + state.mode = mode_huff_block; +} + +void huff_block() +{ + nint code = lit_len_read(); + if(code == 256) + { + state.mode = mode_await_block; + } + else if(code < 256) + { + neginf_cb_seq_byte(code); +#ifdef NEGINF_POS_TRACKING + state.output_pos++; +#endif + } + else + { + state.code = code; + state.mode = mode_huff_len_addbits; + } +} + +void huff_len_addbits() +{ + nint len; + nint code = state.code; + nint la = lookahead(); + if(code < 265) + len = code - 257 + 3; + else if(code < 269) + { + len = (code - 265) * 2 + 11 + (la & 1); + consume(1); + } + else if(code < 273) + { + len = (code - 269) * 4 + 19 + (la & 3); + consume(2); + } + else if(code < 277) + { + len = (code - 273) * 8 + 35 + (la & 7); + consume(3); + } + else if(code < 281) + { + len = (code - 277) * 16 + 67 + (la & 15); + consume(4); + } + else if(code < 285) + { + len = (code - 281) * 32 + 131 + (la & 31); + consume(5); + } + else + { + len = 258; + } + state.match_len = len; + state.mode = mode_huff_dist; +} + +void huff_dist() +{ + state.tcode = dist_read(); + state.mode = mode_huff_dist_addbits; +} + +void huff_dist_addbits() +{ + nint dist; + ntiny code = state.tcode; + + if(code < 4) + { + dist = code+1; + } + else if(code > 29) + { + assert(0); + } + else + { + nint la = lookahead(); + ntiny len = (code - 2) / 2; + dist = ((2 + (code & 1)) << len) + 1 + (((1 << len) - 1) & la); + consume(len); + } + neginf_cb_rel_copy(dist, state.match_len); +#ifdef NEGINF_POS_TRACKING + state.output_pos += state.match_len; +#endif + + state.mode = mode_huff_block; +} + +void dynamic_block_begin() +{ + nint j; + ntiny i; + for(j = 0; j < 288; j++) + state.lit_len_lengths[j] = 0; + for(i = 0; i < 32; i++) + state.dist_lengths[i] = 0; + for(i = 0; i < 19; i++) + state.hc_lengths[i] = 0; + + nint la = lookahead(); + state.hlit = (la & 31) + 257; + state.hdist = ((la >> 5) & 31) + 1; + state.hclen = ((la >> 10) & 15) + 4; + state.torder = 0; + consume(5+5+4); + state.mode = mode_dynamic_read_lc; +} + +void dynamic_read_lc() +{ + if(state.hclen == 0) + { + compute_begin(state.hc_lengths, state.hc_begins, 19); + state.mode = mode_dynamic_read_lit_len; + state.order = 0; + } + else + { + static const ntiny order[19] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + }; + ntiny i = lookahead() & 7; + state.hc_lengths[order[state.torder]] = i; + consume(3); + + state.torder++; + state.hclen--; + } +} + +void dynamic_read_lit_len() +{ + if(state.hlit == 0) + { + state.mode = mode_dynamic_read_dist; + state.order = 0; + } + else + { + state.hlit -= lc_read(state.lit_len_lengths); + } +} + +void dynamic_read_dist() +{ + if(state.hdist == 0) + { + compute_begins(); + state.mode = mode_huff_block; + } + else + { + state.hdist -= lc_read(state.dist_lengths); + } +} + +ntiny lc_read(ntiny * lenghts) +{ + ntiny code = huff_read(state.hc_lengths, state.hc_begins, 19); + // this reads 7 bits max so we still have 9 bits left in the buffer + if(code < 16) + { + lenghts[state.order] = code; + state.order++; + return 1; + } + else if(code == 16) + { + ntiny i; + ntiny copy = (lookahead() & 3) + 3; + consume(2); + for(i = 0; i < copy; i++) + lenghts[state.order + i] = lenghts[state.order - 1]; + state.order += copy; + return copy; + } + else + { + ntiny fill; + ntiny i; + + if(code == 17) + { + fill = (lookahead() & 7) + 3; + consume(3); + } + else + { + fill = (lookahead() & 127) + 11; + consume(7); + } + for(i = 0; i < fill; i++) + { + lenghts[state.order] = 0; + state.order++; + } + return fill; + } +} + + +void compute_begins() +{ + compute_begin(state.lit_len_lengths, state.lit_len_begins, 288); + compute_begin(state.dist_lengths, state.dist_begins, 32); +} + + +void compute_begin(ntiny * lengths, nint * begins, nint size) +{ + ntiny j; + nint i; + for(j = 0; j < 14; j++) + begins[j] = 0; + for(i = 0; i < size; i++) + { + nint len = lengths[i]; + if(len != 0 && len != 15) + begins[len-1] += 1 << (15 - len); + } + nint acc = 0; + for(j = 0; j < 14; j++) + { + nint val = begins[j]; + acc += val; + begins[j] = acc; + } +} + +nint lit_len_read() +{ + return huff_read(state.lit_len_lengths, state.lit_len_begins, 288); +} + +nint dist_read() +{ + return huff_read(state.dist_lengths, state.dist_begins, 32); +} + +nint huff_read(ntiny * lenghts, nint * begins, nint size) +{ + nint code = 0; + ntiny i; + for(i = 1; i < 16; i++) + { + + code |= (lookahead() & 1) << (15-i); + consume(1); + if(i == 15 || code < begins[i-1]) + break; + } + code -= begins[i-2]; + code >>= (15-i); + nint j; + for(j = 0; j < size; j++) + { + if(lenghts[j] == i) + { + if(code == 0) + return j; + code--; + } + } + assert(0); + return 0; // silent warning +} + +#ifndef NEGINF_USE_SEQ_WRITES +void neginf_cb_seq_byte(nbyte byte) +{ + neginf_cb_byte(state.output_pos, byte); +} +#endif + +#ifndef NEGINF_USE_REL_COPY +void neginf_cb_rel_copy(nint distance, nint length) +{ + neginf_cb_copy(state.output_pos - distance, state.output_pos, length); +} +#endif diff --git a/avr/usbload/neginf/neginf.h b/avr/usbload/neginf/neginf.h new file mode 100644 index 0000000..0e9c71d --- /dev/null +++ b/avr/usbload/neginf/neginf.h @@ -0,0 +1,43 @@ +/* + * neginf.h + * neginf -- embedded inflate lib + * + * public header file + */ + +#ifndef NEGINF_H +#define NEGINF_H + +#include "neginf_conf.h" + +#if defined(NEGINF_USE_SEQ_WRITES) && defined(NEGINF_USE_REL_COPY) +#else +#ifndef NEGINF_POS_TRACKING +#define NEGINF_POS_TRACKING +#endif +#endif + +void neginf_init(nsize start_pos); +void neginf_process_byte(nbyte byte); + +#ifdef NEGINF_POS_TRACKING +nsize neginf_output_position(); +#endif + +// callbacks + +#ifdef NEGINF_USE_SEQ_WRITES +void neginf_cb_seq_byte(nbyte byte); +#else +void neginf_cb_byte(nsize pos, nbyte byte); +#endif + +#ifdef NEGINF_USE_REL_COPY +void neginf_cb_rel_copy(nint distance, nint length); +#else +void neginf_cb_copy(nsize from, nsize to, nint length); +#endif + +void neginf_cb_completed(); + +#endif diff --git a/avr/usbload/neginf/neginf_conf.h b/avr/usbload/neginf/neginf_conf.h new file mode 100644 index 0000000..acb8558 --- /dev/null +++ b/avr/usbload/neginf/neginf_conf.h @@ -0,0 +1,48 @@ +/* + * neginf_conf.h + * neginf -- embedded inflate lib + * + * configuration header file + */ + +#ifndef NEGINF_CONF_H +#define NEGINF_CONF_H + +#include +#include + + +#define NEGINF_USE_SEQ_WRITES +//#define NEGINF_USE_REL_COPY +//#define NEGINF_POS_TRACKING + +#define NEGINF_8BIT +#define NEGINF_PACKED_STATE + + +#ifdef NEGINF_8BIT + +typedef char nbool; +typedef uint8_t nbyte; +typedef uint8_t ntiny; +typedef uint16_t nint; +typedef uint32_t nbuf; + +typedef uint32_t nsize; + +#else + +typedef int nbool; // boolean +typedef uint8_t nbyte; // has to be exaclty 8 bit, unsigned +typedef unsigned int ntiny; // has to be at least 8 bit, unsigned +typedef unsigned int nint; // has to be at least 16 bit, unsigned +typedef unsigned int nbuf; // has to be at least 24 bit, unsigned + + +typedef size_t nsize; // has be at least 24 bit, unsigned + +#endif + + + +#endif diff --git a/avr/usbload/neginf/neginf_priv.h b/avr/usbload/neginf/neginf_priv.h new file mode 100644 index 0000000..f393cdb --- /dev/null +++ b/avr/usbload/neginf/neginf_priv.h @@ -0,0 +1,102 @@ +/* + * neginf_priv.h + * neginf -- embedded inflate lib + * + * internal header file + */ + +#ifndef NEGINF_PRIV_H +#define NEGINF_PRIV_H + +typedef struct neginf_state_s neginf_state; +struct neginf_state_s { + ntiny queue_size; // 0 .. 24 + ntiny mode; + nbool last_block; +#ifdef NEGINF_POS_TRACKING + nsize output_pos; +#endif + // can be left uninitialized + nbuf input_queue; // three input bytes + + ntiny raw_size; + ntiny tcode; + nint code; + nint match_len; + + nint order; + ntiny torder; + nint hlit; + ntiny hdist; + ntiny hclen; + + ntiny lit_len_lengths[288]; + nint lit_len_begins[14]; + + ntiny dist_lengths[32]; + nint dist_begins[14]; + + ntiny hc_lengths[19]; + nint hc_begins[14]; + // what could be saved by limiting this to 7 + // will be lost due to the extra code i guess + + +} +#ifdef NEGINF_PACKED_STATE +__attribute__((__packed__)) +#endif +; + +enum neginf_mode { + mode_await_block = 0, + mode_raw_block_begin, + mode_raw_block_begin2, + mode_raw_block, + mode_fixed_block_begin, + mode_huff_block, + mode_huff_len_addbits, + mode_huff_dist, + mode_huff_dist_addbits, + mode_dynamic_block_begin, + mode_dynamic_read_lc, + mode_dynamic_read_lit_len, + mode_dynamic_read_dist, + mode_count +}; + +static void await_block(); +static void raw_block_begin(); +static void raw_block_begin2(); +static void raw_block(); +static void fixed_block_begin(); +static void huff_block(); +static void huff_len_addbits(); +static void huff_dist(); +static void huff_dist_addbits(); +static void dynamic_block_begin(); +static void dynamic_read_lc(); +static void dynamic_read_lit_len(); +static void dynamic_read_dist(); + +static void compute_begins(); +static void compute_begin(ntiny * lengths, nint * begins, nint size); +static nint lit_len_read(); +static nint dist_read(); +static nint huff_read(ntiny * lengths, nint * begins, nint size); +static ntiny lc_read(ntiny * lengths); + +static nint lookahead(); +static void consume(ntiny amount); + +#ifndef NEGINF_USE_SEQ_WRITES +static void neginf_cb_seq_byte(nbyte byte); +#endif + +#ifndef NEGINF_USE_REL_COPY +void neginf_cb_rel_copy(nint distance, nint length); +#endif + +#endif + +