//Sollen die Arbeitsregister gerettet werden //ansonsten auskommentieren #define SAVEREGS //Soll der 4bitModus unterstüzt werden? //ansonsten auskommnetieren //#define USE4BIT //Makro zum Speichern eines Wertes an die Stelle des Y-Pointers //kann geändert werden, um hier z.B. direkt auf ein Display zu schreiben //Der Y Pointer muß danach incrementiert werden! #define FUNC_SAVE(Register) st Y+, Register //Makro zum lesen eines Wertes in ein Register an der Adresse des Z-Pointers //kan geändert werden, um die Daten z.B. direkt von einer SDKarte oder dem EEPRom zu lesen //der Z-Pointer muß danach incrementiert werden! #define FUNC_READ(Register) lpm Register, Z+ //Defines für verwendete Register #define ROOT_ENTRY r2 #define B0L r4 #define B0H r5 #define DBYTE r7 #define COUNTER r8 #define ZTL r9 #define ZTH r10 #define ZT2L r11 #define ZT2H r12 #ifdef USE4BIT #define BUFFER r16 #endif #define TEMP r17 #define BLL r18 #define BLH r19 #define BRL r20 #define BRH r21 #define C r22 //Bit definitionen #define RECORD_R 0 #define RECORD_L 1 #define WRAP_L_1 2 #define WRAP_R_1 3 #define WRAP_L_2 4 #define WRAP_R_2 5 #define E4BIT 6 #define RECORD 7 /** Huffman Dekodierungsroutine Benötigt als Parameter den Y-Pointer als ein Zeiger auf den RAM wo die dekomprimierten Daten hingespeichert werden, so den Z-Pointer als Zeiger auf den Flash wo die komprimierten Daten liegen */ huffman: #ifdef SAVEREGS push ROOT_ENTRY push B0L push B0H push DBYTE push COUNTER push ZTL push ZTH push ZT2L push ZT2H push TEMP push BLL push BLH push BRL push BRH push C #ifdef USE4BIT push BUFFER clr BUFFER #endif #endif mov ZT2L, ZL ;Startadresse sichern mov ZT2H, ZH //##### Headerlänge laden FUNC_READ(ZTH) FUNC_READ(ZTL) //lpm ZTH, Z+ //lpm ZTL, Z+ //#### Größe der Daten laden (byte 2 und 3) FUNC_READ(XH) FUNC_READ(XL) //lpm XH, Z+ //lpm XL, Z+ //#### Abbruchbedingung berechnen add XL, YL adc XH, YH //#### RootEntrytyp laden FUNC_READ(ROOT_ENTRY) //lpm ROOT_ENTRY, Z+ //#### BL berechnen ldi BLL, 5 ldi BLH, 0 add BLL, ZT2L adc BLH, ZT2H //#### BR berechnen ldi TEMP, 2 and TEMP, ROOT_ENTRY breq h_00 ;root == 0X ;root ist 1X --> +3bytes für Record ldi BRL, 8 ldi BRH, 0 rjmp h_01 h_00: ;root war 0X --> +1byte für Blatt ldi BRL, 6 ldi BRH, 0 h_01: add BRL, ZT2L adc BRH, ZT2H //#### C setzen mov C, ROOT_ENTRY //#### Basis Header Adresse in B0 speichern sbrs C, 1 ;Ist das erste ein Record? adiw Z, 1 ; Nein --> Also +1 für Blatt sbrc C, 1 ;Ist das erste ein Record? adiw Z, 3 ; Ja --> Also +3 für Record sbrs C, 0 ;Ist das zweite ein Record? adiw Z, 1 ; Nein --> Also +1 für Blatt sbrc C, 0 ;Ist das zweite ein Record? adiw Z, 3 ; Ja --> Also +3 für Record mov B0L, ZL mov B0H, ZH //#### Erstes Datenbyte laden mov ZL, ZTL ;Header überspringen mov ZH, ZTH add ZL, ZT2L adc ZH, ZT2H FUNC_READ(DBYTE) //lpm DBYTE, Z+ ;Daten laden mov ZTL, ZL ;und für später aufheben mov ZTH, ZH //#### Bitzähler initialisieren ldi TEMP, 0b10000000 mov COUNTER, TEMP rjmp h_reset //#### Loop um durch den Binärbaum zu wandern h_loop: //##### Datensatz ist ein Record ################################# FUNC_READ(C) //lpm C, Z+ ; erstes Byte Lesen, enthält Info über Daten mov TEMP, COUNTER ; Zähler in TEMP laden and TEMP, DBYTE ; & mit Datenbyte breq h_r00 ; Test auf TEMP = 0 --> Datenbit war 0 //#### Bit = 1 adiw Z, 1 ;Linken Eintrag überspringen sbrs C, RECORD_R rjmp h_load_char ;--> Kein Record Zeichen laden ;Auch ein Record FUNC_READ(TEMP) //lpm TEMP, Z+ ;Adressbyte laden mov ZL, TEMP ;Basis Adresse laden ldi ZH, 0 sbrc C, WRAP_R_1 ;trat ein Wrap Around auf? inc ZH ;dann ZH + 1 sbrc C, WRAP_R_2 ;trat ein zweiter Wrap Around auf? inc ZH ;dann ZH + 1 add ZL, B0L ;Adresse addieren adc ZH, B0H ;Carry addieren sbr C, (1< Kein Record Zeichen laden ;Doch ein Record FUNC_READ(TEMP) //lpm TEMP, Z+ ;Adressbyte laden mov ZL, TEMP ;Basis Adresse laden ldi ZH, 0 sbrc C, WRAP_L_1 ;trat ein Wrap Around auf? inc ZH ;dann ZH + 1 sbrc C, WRAP_L_2 ;trat ein zweiter Wrap Around auf? inc ZH ;dann ZH + 1 add ZL, B0L ;Adresse addieren adc ZH, B0H ;Carry addieren sbr C, (1< Datenbit war 0 //#### Bit = 1 mov ZL, BRL mov ZH, BRH sbrc C, RECORD_R ;Handelt es sich um einen Record? rjmp h_weiter ;--> Ja dann nächstes bit laden ;--> Sonst, lade das Zeichen rjmp h_load_char h_nr00: //#### Bit = 0 mov ZL, BLL mov ZH, BLH sbrc C, RECORD_L ;Handelt es sich um einen Record? rjmp h_weiter ;--> Ja dann nächstes bit laden ;--> Sonst, lade das Zeichen (h_load_char) //######################################################### //#### Das Zeichen vom Z Pointer laden ################# h_load_char: FUNC_READ(TEMP) //lpm TEMP, Z ;Wert laden #ifdef USE4BIT sbrc C, E4BIT ;4bitCodierung? rjmp h_4bit ;sonst zu 4bit springen /*cpi BUFFER, 0xF0 ;Testen ob schon was drin steht brlo h_lowpart8bit ; nein? --> Dann ist dies der LowPart temp um 4 shiften lsl TEMP lsl TEMP lsl TEMP lsl TEMP andi BUFFER, 0x0F ;Indikator ausmaskieren or TEMP, BUFFER ;und zusammensetzen rjmp h_e8bit h_lowpart8bit: mov BUFFER, TEMP ;Temp in den Buffer schreiben ori BUFFER, 0xF0 ;und das Highbyte = 1111 setzen als Indikator cbr C, (1< h_weiter cbr C, (1< Record oder Blatt? brne h_reset brne h_loop //##### diese Datenbyte ist "alle", nächstes laden mov ZT2L, ZL ;Z-Pointer retten mov ZT2H, ZH mov ZL, ZTL ;Z-DatenPointer restaurieren mov ZH, ZTH FUNC_READ(DBYTE) //lpm DBYTE, Z+ ;Neues Datenbyte laden mov ZTL, ZL ;Daten Pointer retten mov ZTH, ZH ldi TEMP, 0b10000000 ;Bitcounter für nächste Byte mov COUNTER, TEMP sbrs C, RECORD ;---> Record oder Blatt? rjmp h_reset ;Wir haben im lezten Schritt ein Zeichen geladen ;Also müssen wir jezt wieder an den Anfang des Baumes ;Insebsondere der alte Z-Pointer ist uns egal mov ZL, ZT2L ;Ansonsten den alten Z-Pointer restaurieren mov ZH, ZT2H rjmp h_loop ;Und weiter gehts //######################################### //############# 4 Bit Modus ####### #ifdef USE4BIT h_4bit: cpi BUFFER, 0xE0 ;Testen ob schon was drin steht brlo h_lowpart8bit ; nein? --> Dann ist dies der LowPart //temp um 4 shiften lsl TEMP lsl TEMP lsl TEMP lsl TEMP andi BUFFER, 0x0F ;Indikator ausmaskieren or TEMP, BUFFER ;und zusammensetzen clr BUFFER rjmp h_e8bit h_lowpart8bit: mov BUFFER, TEMP ;Temp in den Buffer schreiben ori BUFFER, 0xF0 ;und das Highbyte = 1111 setzen als Indikator cbr C, (1<