diff --git a/tools/huffman/Makefile b/tools/huffman/Makefile
new file mode 100644
index 0000000..908100a
--- /dev/null
+++ b/tools/huffman/Makefile
@@ -0,0 +1,10 @@
+SHELL = sh
+OPTIMIZE = -O2
+CC = gcc
+CSTD = c99
+override CFLAGS = -pedantic -std=$(CSTD) -Wall -Wstrict-prototypes $(OPTIMIZE)
+
+all: huffman-decode huffman-encode
+
+clean:
+ rm -f huffman-decode huffman-encode bin2avrS
diff --git a/tools/huffman/huffman-decode.c b/tools/huffman/huffman-decode.c
new file mode 100644
index 0000000..eb9f99c
--- /dev/null
+++ b/tools/huffman/huffman-decode.c
@@ -0,0 +1,224 @@
+/* huffman-decode.c */
+/*
+ This file is part of the AVR-Huffman.
+ Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+
+#define V_NODE (-2)
+#define V_EOF (-1)
+
+#define PREFIX_SIZE_B 32
+
+#define ALLOC_ERROR {fprintf(stderr,"failed to alloc memory in %s @ %d !\n",__FILE__, __LINE__); exit(-1);}
+
+#define DEBUG 0
+
+typedef struct {
+ int16_t value;
+ void* left;
+ void* right;
+} node_t;
+
+node_t* tree=NULL;
+uint16_t tree_index;
+
+void prefix_increment(uint8_t* prefix){
+ uint8_t i;
+ for(i=0; i>7;
+ prefix[i]<<=1;
+ ci ^= 1;
+ prefix[i]|=c[ci];
+ }
+}
+
+uint8_t append_tree(int16_t value, uint16_t depth){
+ static uint8_t prefix[PREFIX_SIZE_B];
+ static uint8_t cdepth=0;
+ node_t* current=tree;
+ int8_t i,t;
+ for(;cdepth=0; --i){
+ t=(prefix[i/8])&(1<<(i%8));
+ if(t==0){
+ if(current->left==NULL){
+ // current->left=calloc(1, sizeof(node_t));
+ current->left=&(tree[tree_index++]);
+ ((node_t*)(current->left))->value = V_NODE;
+ }
+ current = current->left;
+ } else {
+ if(current->right==NULL){
+ // current->right=calloc(1, sizeof(node_t));
+ current->right=&(tree[tree_index++]);
+ ((node_t*)(current->right))->value = V_NODE;
+ }
+ current = current->right;
+ }
+ }
+ if(current==NULL)
+ ALLOC_ERROR
+ current->value=value;
+ prefix_increment(prefix);
+ return prefix[depth/8]&(1<<(depth%8));
+}
+
+void set_last_to_eof(void){
+ node_t* current=tree;
+ while(current->value==V_NODE)
+ current=current->right;
+ current->value=V_EOF;
+}
+
+void build_tree(FILE* f){
+ uint16_t treesize;
+ uint16_t x1, x2;
+ x1 =fgetc(f);
+ x2 =fgetc(f);
+ if(x1!=0xc0 || (x2&0xFE)!=0xde){
+ fprintf(stderr,"No magic values found!\n");
+ }
+ treesize= fgetc(f);
+ if(treesize>0xff){
+ fprintf(stderr,"You are trying to uncompress an empty file!\n");
+ exit(-3);
+ }
+ treesize = 2*(((x2&1)<<8)+treesize)-1;
+ //printf("Using treesize=%i with size of %i\n", treesize, sizeof(node_t));
+ tree = calloc(treesize, sizeof(node_t));
+ if(tree==NULL)
+ ALLOC_ERROR
+ tree->value = V_NODE;
+ tree_index=1;
+ uint16_t depth=0;
+ uint16_t count=0;
+ uint8_t v;
+ do{
+ while(count==0){
+ depth++;
+ count= fgetc(f);
+ if(count==255)
+ count += fgetc(f);
+ }
+ v = fgetc(f);
+ --count;
+ }while(!append_tree(v, depth));
+ set_last_to_eof();
+}
+
+
+void free_tree(node_t* node){
+ free(node);
+}
+
+FILE* outfile;
+FILE* infile;
+
+void write_char(uint8_t v){
+ fputc(v, outfile);
+}
+
+uint8_t read_bit(void){
+ static uint8_t buffer;
+ static uint8_t index=0;
+ uint8_t t;
+ if(index==0){
+ buffer = fgetc(infile);
+ if(feof(infile))
+ return 0xFF;
+ }
+ t=buffer>>7;
+ buffer<<=1;
+ index = (index+1)%8;
+ return t;
+}
+
+uint16_t decompress_byte(void){
+ node_t* current=tree;
+ uint8_t t;
+ while(current->value==V_NODE){
+ t=read_bit();
+ if(t==0xFF)
+ return EOF;
+ if(t==0){
+ current=current->left;
+ } else {
+ current=current->right;
+ }
+ if(current==NULL){
+ fprintf(stderr, "Tree damaged!\n");
+ exit(-4);
+ }
+ }
+ return current->value;
+}
+
+void decompress(void){
+ uint16_t t;
+ for(;;){
+ t=decompress_byte();
+ if(t==(uint16_t)EOF)
+ return;
+ write_char(t);
+ }
+}
+
+int main(int argc, char** argv){
+ int i;
+ FILE* fin;
+ FILE* fg;
+// outfile=stdout;
+ for(i=1;i.
+*/
+
+#include
+#include
+#include
+#include
+
+#define DEBUG 0
+#define XDEBUG 0
+
+typedef struct{
+ uint8_t depth;
+ uint16_t value;
+ uint32_t weight;
+ void* left;
+ void* right;
+} node_t;
+
+typedef struct{
+ uint16_t value;
+ unsigned depth;
+ void* encoding;
+} item_t;
+
+typedef struct{
+ uint8_t initialized;
+ item_t* item;
+ void* parent;
+ void* left;
+ void* right;
+} node2_t;
+
+uint32_t histogram[256];
+node_t* pool[256+1];
+unsigned poolsize;
+unsigned item_count;
+node_t* tree;
+node_t* treenodes;
+unsigned treeindex=0;
+item_t* itemlist;
+unsigned itemindex=0;
+node2_t* node2list=NULL;
+unsigned node2list_index=0;
+item_t* valueencode[256];
+item_t* eof_encoding;
+
+void reset_histogram(void){
+ memset(histogram, 0, 256*sizeof(uint32_t));
+}
+
+void build_histogram(char* fname){
+ FILE* f;
+ int t;
+ f = fopen(fname, "r");
+ while((t=fgetc(f))!=EOF){
+ histogram[(uint8_t)t&0xFF]++;
+ }
+ fclose(f);
+}
+
+
+void build_pool(void){
+ unsigned i,j;
+ memset(pool, 0, 256*sizeof(node_t*));
+ for(i=0,j=0;i<256;++i){
+ if(histogram[i]==0)
+ continue;
+ pool[j] = malloc(sizeof(node_t));
+ if(pool[j]==NULL){
+ fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
+ exit(-1);
+ }
+ pool[j]->depth = 0;
+ pool[j]->value = i;
+ pool[j]->left = NULL;
+ pool[j]->right = NULL;
+ pool[j]->weight = histogram[i];
+ j++;
+ }
+ pool[j] = malloc(sizeof(node_t));
+ if(pool[j]==NULL){
+ fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
+ exit(-1);
+ }
+ pool[j]->depth = 0;
+ pool[j]->value = 0xFFFF;
+ pool[j]->left = NULL;
+ pool[j]->right = NULL;
+ pool[j]->weight = 1;
+ j++;
+ poolsize = j;
+ item_count = j;
+}
+
+void find_lightest2(unsigned* a, unsigned* b, unsigned* depth){
+ unsigned ia=0;
+ unsigned ib=0;
+ uint32_t wa, wb;
+ unsigned i;
+ wa = wb = 0xFFFFFFFF;
+ for(i=0; i=pool[i]->weight){
+ wb = wa;
+ ib = ia;
+ wa = pool[i]->weight;
+ ia = i;
+ }else{
+ if(wb>pool[i]->weight){
+ wb = pool[i]->weight;
+ ib = i;
+ }
+ }
+ }
+ if(wb == 0xFFFFFFFF || wa == 0xFFFFFFFF){
+ fprintf(stderr, "Error while searching!\n");
+ exit(-2);
+ }
+ if(pool[ia]->depth <= pool[ib]->depth){
+ *a = ia;
+ *b = ib;
+ *depth = pool[ib]->depth;
+ } else {
+ *a = ib;
+ *b = ia;
+ *depth = pool[ia]->depth;
+ }
+}
+
+void init_tree(void){
+ treenodes = malloc((poolsize-1)*sizeof(node_t));
+ if(treenodes==NULL){
+ fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
+ exit(-1);
+ }
+#if XDEBUG
+ printf("treenodes := %p\n", (void*)treenodes);
+#endif
+}
+
+
+void update_tree(void){
+ if(poolsize<2)
+ return;
+ unsigned a,b, depth;
+ find_lightest2(&a,&b,&depth);
+#if XDEBUG
+ printf("joining %d and %d\n", a,b);
+#endif
+ treenodes[treeindex].depth = depth+1;
+ treenodes[treeindex].weight = pool[a]->weight + pool[b]->weight;
+ treenodes[treeindex].left = (pool[a]);
+ treenodes[treeindex].right = (pool[b]);
+#if XDEBUG
+ printf(" idx = %d\n self = %p\n depth = %d\n weight = %d\n"
+ " left = %p\n right = %p\n",
+ treeindex, (void*)&(treenodes[treeindex]), treenodes[treeindex].depth,
+ treenodes[treeindex].weight, treenodes[treeindex].left,
+ treenodes[treeindex].right);
+#endif
+ pool[a] = &(treenodes[treeindex]);
+ pool[b] = pool[poolsize-1];
+ pool[poolsize-1] = NULL;
+ --poolsize;
+ ++treeindex;
+}
+
+void build_tree(void){
+ while(poolsize>1){
+ update_tree();
+ }
+ tree = &(treenodes[treeindex-1]);
+}
+
+
+void free_leaf(node_t* node){
+ if(node->depth==0){
+ free(node);
+ }else{
+ free_leaf(node->left);
+ free_leaf(node->right);
+ }
+}
+
+void free_tree(void){
+ free_leaf(tree);
+ free(treenodes);
+ tree = NULL;
+}
+
+void init_itemlist(void){
+ itemlist = calloc((item_count),sizeof(item_t));
+ if(itemlist==NULL){
+ fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
+ exit(-1);
+ }
+}
+
+void update_itemlist(node_t* node, unsigned depth){
+ if(node->depth==0){
+ itemlist[itemindex].value = node->value;
+ itemlist[itemindex].depth = depth;
+ ++itemindex;
+ } else {
+ update_itemlist(node->left, depth+1);
+ update_itemlist(node->right, depth+1);
+ }
+}
+
+void build_itemlist(void){
+ update_itemlist(tree, 0);
+}
+
+int item_compare_depth(const void* a, const void* b){
+ if(((item_t*)a)->value==0xFFFF)
+ return 1;
+ if(((item_t*)b)->value==0xFFFF)
+ return -1;
+ return ((item_t*)a)->depth - ((item_t*)b)->depth;
+}
+
+void sort_itemlist(void){
+ qsort(itemlist, item_count, sizeof(item_t), item_compare_depth);
+}
+
+#define PREFIX_SIZE_B 32
+
+void prefix_increment(uint8_t* prefix){
+ uint8_t i;
+ for(i=0; i>7;
+ prefix[i]<<=1;
+ ci ^= 1;
+ prefix[i]|=c[ci];
+ }
+}
+
+void gen_itemencoding(void){
+ uint8_t prefix[PREFIX_SIZE_B];
+ memset(prefix, 0, PREFIX_SIZE_B);
+ unsigned depth=0;
+ unsigned depth_B=0;
+ unsigned i,j;
+ for(i=0; ivalue;
+// printf(" %2.2X (%c) => ", c, (c>32&&c<128)?c:' ');
+ for(i=item->depth-1; i>=0; --i){
+ t = (((uint8_t*)(item->encoding))[i/8])&(1<<(i%8));
+ if(current->initialized==0){
+ current->initialized=1;
+ current->parent = NULL;
+ current->item = NULL;
+ current->left = NULL;
+ current->right = NULL;
+ node2list_index++;
+ }
+ if(t==0){
+// putchar('0');
+ if(current->left){
+ current = current->left;
+ } else {
+ current->left = &(node2list[node2list_index++]);
+ ((node2_t*)(current->left))->parent = current;
+ current = current->left;
+ current->initialized=1;
+ current->item=NULL;
+ }
+ } else {
+// putchar('1');
+ if(current->right){
+ current = current->right;
+ } else {
+ current->right = &(node2list[node2list_index++]);
+ ((node2_t*)(current->right))->parent = current;
+ current = current->right;
+ current->initialized=1;
+ current->item=NULL;
+ }
+ }
+ }
+ current->item = item;
+ current->left = NULL;
+ current->right = NULL;
+// printf("\n");
+}
+
+void gen_tree2(void){
+ unsigned i;
+ node2list = calloc(2*item_count-1, sizeof(node2_t));
+#if XDEBUG
+ printf("item_count = %d\n", item_count);
+#endif
+ if(node2list==NULL){
+ fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
+ exit(-1);
+ }
+ for(i=0;i=0;--i){
+ bit_writer(f,data[i/8]&(1<<(i%8)),0);
+ }
+}
+
+void build_valueencode(void){
+ unsigned i;
+ memset(valueencode, 0, 256*sizeof(void*));
+ for(i=0; i>8), f);
+ fputc(item_count,f);
+ for(i=0; i=255){
+ fputc(255, f);
+ fputc(i-last-255, f);
+ } else {
+ fputc(i-last, f);
+ }
+ for(j=last; j=255){
+ fputc(255, f);
+ fputc(i-last-255, f);
+ } else {
+ fputc(i-last, f);
+ }
+ for(j=last; j32&&t<128)?t:' ');
+ exit(-3);
+ }
+ encoding_writer(fout, valueencode[t]->encoding, valueencode[t]->depth);
+ };
+ encoding_writer(fout, eof_encoding->encoding, eof_encoding->depth);
+ encoding_writer(fout, NULL, 0);
+}
+
+
+void compress_huffman(char * filename_in, char * filename_out){
+ FILE* fin;
+ FILE* fout;
+ reset_histogram();
+ build_histogram(filename_in);
+ build_pool();
+ init_tree();
+ build_tree();
+ init_itemlist();
+ build_itemlist();
+ free_tree();
+ sort_itemlist();
+ gen_itemencoding();
+ gen_tree2();
+ build_valueencode();
+ fin = fopen(filename_in, "r");
+ fout = fopen(filename_out, "w");
+ write_tree(fout);
+ compress_file(fin, fout);
+ fclose(fin);
+ fclose(fout);
+}
+
+int main(int argc, char** argv){
+ char filename_out[strlen(argv[1])+20];
+ strcpy(filename_out, argv[1]);
+ strcat(filename_out, ".hfm");
+ compress_huffman(argv[1],filename_out);
+ return 0;
+}
+
+