added neginf inflate library

This commit is contained in:
Jannis Harder 2009-09-22 17:15:25 +02:00
parent 105575bc37
commit 4b0bec820e
7 changed files with 704 additions and 3 deletions

View File

@ -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

40
avr/usbload/inflate.c Normal file
View File

@ -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
}

28
avr/usbload/inflate.h Normal file
View File

@ -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

440
avr/usbload/neginf/neginf.c Normal file
View File

@ -0,0 +1,440 @@
/*
* neginf.c
* neginf -- embedded inflate lib
*
* inflate routines
*/
#include <assert.h>
#include <stdlib.h>
#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

View File

@ -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

View File

@ -0,0 +1,48 @@
/*
* neginf_conf.h
* neginf -- embedded inflate lib
*
* configuration header file
*/
#ifndef NEGINF_CONF_H
#define NEGINF_CONF_H
#include <stddef.h>
#include <stdint.h>
#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

View File

@ -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