clean out non-dmx related arudino stuff
authorTero Marttila <terom@paivola.fi>
Sat, 07 Jun 2014 13:05:33 +0300
changeset 89 1b3cea759eff
parent 88 c923295ee520
child 90 13c2deb919d1
clean out non-dmx related arudino stuff
Makefile
adc.inc
console.s
delay.inc
dip.inc
div.inc
dmx.s
font-compile.py
font.inc
font.txt
hw.S
led7seg.inc
led7seg.s
m168def.inc
macros.inc
matrix.inc
matrix.s
spi.inc
src/hello-lkm.c
src/hello.c
timer.inc
timer.s
--- a/Makefile	Mon Jun 02 18:27:08 2014 +0300
+++ b/Makefile	Sat Jun 07 13:05:33 2014 +0300
@@ -40,21 +40,10 @@
 AS = avra
 ASFLAGS = 
 
-matrix.hex: spi.inc matrix.inc timer.inc delay.inc macros.inc font.inc font.def
-led7seg.hex: spi.inc led7seg.inc adc.inc timer.inc delay.inc macros.inc
-timer.hex: timer.inc macros.inc
-
 %.hex: %.s
 	$(AS) $(ASFLAGS) $<
 	mv $<.hex $@
 
-# fonts
-font.inc: font.def
-
-font.def: font.txt font-compile.py
-	python font-compile.py $< $@ > /dev/null
-
-
 ## Flashing
 # Arduino Duemilanove
 AD_PART = m328p
--- a/adc.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-;;
-;; Basic ADC operation
-;;
-
-; Reference select
-.set ADC_REF    = 0b01      ; AVcc
-
-; Bit adjustment
-.set ADC_LAR    = 1         ; Left-adjust
-
-; Input select
-.set ADC_MUX    = 0b000     ; ADC0
-
-; Auto-trigger source
-.set ADC_ATS    = 0b011     ; TC0 OCA
-
-; Auto-trigger enable
-.set ADC_ATE    = 1
-
-; Prescaler
-.set ADC_PS     = 0b111     ; 1/128
-
-; I/O pins
-.equ ADC_DDR    = DDRC
-.equ ADC_PORT   = PORTC
-.equ ADC_PIN    = PORTC0
-        
-;; Initialize the ADC for starting conversions
-ADC_Init:
-    ; ADMUX
-        ldi         r16, (ADC_REF << REFS0) | (ADC_LAR << ADLAR) | (ADC_MUX << MUX0)
-        sts         ADMUX, r16
-    
-    ; ADCSRB
-        ldi         r16, (ADC_ATS << ADTS0)
-        sts         ADCSRB, r16
-
-    ; ADCSRA
-        ; ADSC: No need if using external auto-trigger ???
-        ; Enable interrupt
-        ldi         r16, (1 << ADEN) | (1 << ADSC) | (ADC_ATE << ADATE) | (1 << ADIE) | (ADC_PS << ADPS0)
-        sts         ADCSRA, r16
-    
-    ; Disable digital circuit for pin
-        ldi         r16, (1 << ADC_PIN)
-        sts         DIDR0, r16
-
-    ; Done
-        ret
-
-;; Interrupt handler stub for ADC_HANDLER
-ADC_Interrupt:
-        in          r0, SREG
-
-        rcall       ADC_HANDLER
-
-        out         SREG, r0
-        reti
-
-;; Read the current 8-bit ADC sample 
-; Returns value in r16
-ADC_Read8:
-    ; Copy
-        lds         r16, ADCH
-
-    ; Done
-        ret
-
--- a/console.s	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-.nolist
-.include "m168def.inc"      ; Same family as 328P
-.list
-
-.include "macros.inc"
-
-;; Load a 16-bit *word* address into the given register a a byte address
-.macro loadp_16_i
-		ldi			@0, high(2 * @2)
-		ldi			@1, low(2 * @2)
-.endm
-
-.macro load_16_i
-		ldi			@0, high(@2)
-		ldi			@1, low(@2)
-.endm
-
-;; Data
-.dseg
-buffer:	.byte 0
-
-;; Interrupt Vector
-.cseg
-.org 0x0000
-        rjmp        Main
-
-;; Libraries
-.include "div.inc"			; Division routines
-
-;; Serial
-.set SERIAL_BAUD = 103		; 9.6k @ 16Mhz
-
-;; Initialize the UART for 
-Serial_Init:
-	; Set up control registers
-		; Single-speed
-		poke		[UCSR0A, r16, (0 << U2X0)]
-
-		; Async
-		; n parity
-		; 1 stop
-		; 8 bits
-		poke		[UCSR0C, r16, (0b00 << UMSEL00) | (0b00 << UPM00) | (0 << USBS0) | (0b11 << UCSZ00)]
-
-		; Baud rate
-		poke		[UBRR0L, r16:r17, SERIAL_BAUD]
-		
-		; Enable RX
-		; Enable TX
-		; 8 bits
-		poke		[UCSR0B, r16, (1 << RXEN0) | (1 << TXEN0) | (0 << UCSZ02)]
-		
-	; Done
-		ret
-
-;; Send a single byte on serial port
-; Input byte in r16
-Serial_Send:
-	; Wait for idle
-		lds			r0, UCSR0A
-		sbrs		r0, UDRE0
-		rjmp		Serial_Send
-
-	; Copy byte to buffer
-		sts			UDR0, r16
-
-	; Done
-		ret
-
-;; Read a single byte from serial port
-; Output byte in r16
-Serial_Recv:
-	; Wait for recv
-		lds			r0, UCSR0A
-		sbrs		r0, RXC0
-		rjmp		Serial_Recv
-
-	; Copy byte from buffer
-		lds			r16, UDR0
-
-	; Done
-		ret
-
-;; Write nul-terminated string from program mem to serial port
-; Input string in Z
-Serial_pprint:
-	; Load byte to r16
-		lpm			r16, Z+
-
-	; Quit if nul
-		tst			r16
-		breq		_serial_pprint_end
-
-	; Write it
-		rcall		Serial_Send
-
-	; Continue
-		rjmp		Serial_pprint
-
-_serial_pprint_end:
-		ret
-
-;; Write nul-terminated string from sram and \r\n to serial port
-; Input string in Z
-Serial_sprintln:
-	; Load byte to r16
-		ld			r16, Z+
-
-	; Quit if nul
-		tst			r16
-		breq		_serial_sprintln_end
-
-	; Write it
-		rcall		Serial_Send
-
-	; Continue
-		rjmp		Serial_sprintln
-
-_serial_sprintln_end:
-	; \r\n
-		ldi			r16, 13
-		rcall		Serial_Send
-		ldi			r16, 10
-		rcall		Serial_Send
-
-	; Done
-		ret
-
-;; Write char to serial port
-; Input byte in r16
-Serial_bprint:
-		; ASCII offset for '0'
-		ldi			r17, 48
-		mov			r4, r17	
-	
-	; Convert
-		ldi			r17, 100
-		call		div8u
-		add			r16, r4
-		rcall		Serial_Send
-		mov			r16, r15
-
-		ldi			r17, 10
-		call		div8u
-		add			r16, r4
-		rcall		Serial_Send
-		mov			r16, r15
-
-		add			r16, r4
-		rcall		Serial_Send
-		
-	ret
-
-;; Program
-message:	.db "Hello World", 13, 10, 0
-
-Main:
-; Initialization
-	; Stack
-		poke		[SPL, r16:r17, RAMEND]
-
-    ; Enable interrupts
-        sei
-
-	; Init
-		rcall		Serial_Init
-
-; Main program
-		ldi			ZH, high(message * 2)
-		ldi			ZL, low(message * 2)
-		
-		rcall		Serial_pprint
-
-; Echo out
-		sbi			DDRB, PORTB5
-		ldi			r20, 0
-		ldi			r21, 0
-		ldi			r22, 0
-		
-		; pointer to memory buffer
-		ldi			XH, high(buffer)
-		ldi			XL, low(buffer)
-
-		st			X, r22		; '\0'
-
-Main_Echo:
-		; blink LED
-		out			PORTB, r20
-		
-		; read
-		rcall		Serial_Recv
-		push		r16
-		
-		; display
-		rcall		Serial_bprint
-		ldi			r16, 32
-		rcall		Serial_Send
-
-		pop			r16
-
-		; test for control chars
-		cpi			r16, 127	; DEL
-		breq		backspace
-
-		cpi			r16, 13		; '\r'
-		breq		cr
-
-		cpi			r16, 10		; '\n'
-		breq		Main_Echo	; ignore
-
-		rjmp		char		; buffer char
-
-; Erase last char
-backspace:
-		; ignore if already at zero
-		cpi			XL, low(buffer)
-		ldi			r23, high(buffer)
-		cpc			XH, r23
-		breq		echo
-
-		; use pre-decrement to store nul
-		st			-X, r22		; '\0'
-
-		rjmp		echo
-
-; Erase line
-cr:
-		; seek to start
-		ldi			XH, high(buffer)
-		ldi			XL, low(buffer)
-		
-		; store nul
-		st			X, r22		; '\0'
-
-		rjmp 		echo
-
-char:
-		; buffer char
-		st			X+, r16
-		st			X, r22		; '\0'
-
-echo:		
-		; running counter
-		inc			r21
-		mov			r16, r21
-		rcall		Serial_bprint
-		
-		; ' '
-		ldi			r16, 32
-		rcall		Serial_Send
-
-		; length
-		mov			r16, XL
-		rcall		Serial_bprint
-
-		; ' '
-		ldi			r16, 32
-		rcall		Serial_Send
-		
-		; output buffer
-		ldi			ZH, high(buffer)
-		ldi			ZL, low(buffer)
-		rcall		Serial_sprintln
-		
-		; toggle
-		com			r20
-		
-		; continue
-		rjmp		Main_Echo
-
--- a/delay.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-;; vim: set ft=avr:
-;;
-;; Busy-loop delays
-;;
-
-;; Delay for approx. one second
-Delay_1s:
-        ; ~16M cycles
-        ldi         r20, 82
-        rjmp        delay_init
-
-;; Delay for a variable amount of time, adjusted by r20
-; Input: r20 controls number of delay loops
-VarDelay:
-        tst         r20
-        breq        delay_out
-
-delay_init:
-        ldi         r21, 255
-
-delay_loop:
-        ; 254 * (1 + 2) + 1 * (1 + 1) = 764 cycles / loop
-        dec         r22             
-        brne        delay_loop
-
-        ; 254 * 764 + 764 = 194820 cycles / loop
-        dec         r21             ;  1 * r20 * r21
-        brne        delay_loop      ;  2 * r20 * r21
-        
-        ; r20 * 194820 + r20 * 3 = 194823 cycles / loop (r20)
-        dec         r20             ;  1 * r20 
-        brne        delay_loop      ;  2 * r20
-
-delay_out:
-        ret
-
-
--- a/dip.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-;;
-;; Reading DIP switches from SPI
-;;
-
-.set DIP_BUFFER = spi_inbuf + 1
-
-;; Read state of dip switches
-;;  Output: r16
-DIP_Read8:
-		; update
-;		rcall		SPI_SendRecv
-		
-		; get bits
-		lds			r16, DIP_BUFFER
-
-		ret
-
--- a/div.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-;*************************************************************************** 
-;* 
-;* "div8u" - 8/8 Bit Unsigned Division 
-;* 
-;* This subroutine divides the two register variables "dd8u" (dividend) and  
-;* "dv8u" (divisor). The result is placed in "dres8u" and the remainder in 
-;* "drem8u". 
-;*   
-;* Number of words	:14 
-;* Number of cycles	:97 
-;* Low registers used	:1 (drem8u) 
-;* High registers used  :3 (dres8u/dd8u,dv8u,dcnt8u) 
-;* 
-;*************************************************************************** 
- 
-;***** Subroutine Register Variables 
- 
-.def	drem8u	=r15		;remainder 
-.def	dres8u	=r16		;result 
-.def	dd8u	=r16		;dividend 
-.def	dv8u	=r17		;divisor 
-.def	dcnt8u	=r18		;loop counter 
- 
-;***** Code 
- 
-div8u:	sub	drem8u,drem8u	;clear remainder and carry 
-		ldi	dcnt8u,9		;init loop counter 
-d8u_1:	rol	dd8u			;shift left dividend 
-		dec	dcnt8u			;decrement counter 
-		brne	d8u_2		;if done 
-		ret					;    return 
-d8u_2:	rol	drem8u			;shift dividend into remainder 
-		sub	drem8u,dv8u		;remainder = remainder - divisor 
-		brcc	d8u_3		;if result negative 
-		add	drem8u,dv8u		;    restore remainder 
-		clc					;    clear carry to be shifted into result 
-		rjmp	d8u_1		;else 
-d8u_3:	sec					;    set carry to be shifted into result 
-		rjmp	d8u_1 
- 
-
--- a/dmx.s	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
-;;; vim: set ft=avr:
-
-.nolist
-.include "m168def.inc"      ; Same family as 328P
-.list
-
-.include "macros.inc"
-
-;; Interrupt Vector
-.cseg
-.org 0x0000
-        rjmp        Main
-
-
-;; CPU cycles / second: 16 Mhz
-.set CPU_CYCLES = 16 * 1000 * 1000
-
-;; Delays
-.include "delay.inc"
-
-;; DMX baud raite: 250k
-.set DMX_BAUD = 250 * 1000
-
-;; CPU cycles / bit: 64
-.set DMX_CYCLES = CPU_CYCLES / DMX_BAUD
-
-;; DMX output I/O
-.set DMX_DDR = DDRB
-.set DMX_PORT = PORTB
-.equ DMX_DATA = PORTB3
-
-;; DMX protocol timer
-; Registers
-.set DMX_TIMER_CRA = TCCR2A
-.set DMX_TIMER_CRB = TCCR2B
-.set DMX_TIMER_CNT = TCNT2
-.set DMX_TIMER_OCRA = OCR2A
-.set DMX_TIMER_OCRB = OCR2B
-.set DMX_TIMER_IMSK = TIMSK2
-.set DMX_TIMER_IFR = TIFR2
-
-; Compare output match isn't used
-.set DMX_TIMER_COMA = 0b00
-.set DMX_TIMER_COMB = 0b00
-
-; Control register, generation mode value
-.set DMX_TIMER_WGM_10 = 0b10        ; CTC
-.set DMX_TIMER_WGM_2 = 0b0
-
-; Clock select
-.set DMX_TIMER_CS_STOP = 0b000
-.set DMX_TIMER_CS = 0b001      ; 1/1
-;.set DMX_TIMER_CS = 0b111       ; 1/1024
-
-; Counted value
-.set DMX_TIMER_TOP = DMX_CYCLES     ; number of cycles for baud
-
-;; Debug LED
-.set LED_DDR = DDRB
-.set LED_PORT = PORTB
-.set LED_PIN = PINB
-.set LED_BIT = PORTB0
-
-;; Set up DMX output
-DMX_Init:
-    ; Setup output port
-        ; out
-        sbi     DMX_DDR, DMX_DATA
-
-        ; drive high
-        sbi     DMX_PORT, DMX_DATA
-
-    ; Setup timer
-        ; setup CTC mode with no output pins
-        poke        [DMX_TIMER_CRA, r16, (DMX_TIMER_COMA << COM2A0) | (DMX_TIMER_COMB << COM2B0) | (DMX_TIMER_WGM_10 << WGM20)]
-        poke        [DMX_TIMER_CRB, r16, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS_STOP << CS20)]
-
-        ; trigger threshold for CTC
-        poke        [DMX_TIMER_OCRA, r16, (DMX_TIMER_TOP)]
-		
-    ; OK
-    ret
-
-;; Start Break signal
-;;
-;; 22 bits - 1s long; then DMX_Break_Mark
-;;
-DMX_Break_Start:
-    ; Low
-        cbi         DMX_PORT, DMX_DATA
-
-    ret
-
-;; Start Mark-after-break signal
-;;
-;; 2 bits - 1s long; then DMX_Break_End
-;;
-DMX_Break_Mark:
-    ; High
-        sbi         DMX_PORT, DMX_DATA
-
-    ret
-
-;; End break; prepare for DMX_Frame
-DMX_Frame_Start:
-    ; Start timer
-        poke        [DMX_TIMER_CRB, r20, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS << CS20)]
-    
-    ret
-
-;; Do a full DMX break, using some random length
-;;
-DMX_Break:
-    ; Break
-        ; start
-        rcall       DMX_Break_Start
-
-        ; wait; about 100ms?
-        ldi         r20, 82 / 10
-        rcall       VarDelay
-
-    ; MAB
-        ; mark
-        rcall       DMX_Break_Mark
-
-        ; short wait
-        ldi         r20, 1
-        rcall       VarDelay
-
-    ; Timed frames
-        ; start frame
-        rcall       DMX_Frame_Start
-
-    ; ok
-    ret
-
-;; Bitbang one DMX bit out
-;;  uses SREG/C to send
-;
-; Uses Timer2 as a bit sync clock, sending out the next bit once we've hit 64 cycles on the timer
-DMX_Bit:
-    ; Wait for bit sync clock
-_dmx_bit_wait:
-        ; test OCA hit
-        sbic    TIFR2, OCF2A     
-        rjmp    _dmx_bit_wait   
-
-;sbi         LED_PORT, LED_BIT
-
-    ; Output bit
-        ; XXX: ugly bit-testing, can't we do this using something more nifty?
-        brcs    _dmx_bit_1
-        
-        ; bit 0
-        cbi     DMX_PORT, DMX_DATA
-        rjmp    _dmx_bit_done
-
-_dmx_bit_1:
-        ; bit 1
-        sbi     DMX_PORT, DMX_DATA
-        nop
-
-    ; Bit sent
-_dmx_bit_done:
-        ; reset OCA hit for next bit
-        cbi     TIFR2, OCF2A
-
-    ; OK, bit sync clock keeps running for next bit
-    ret
-
-;; Bitbang one DMX byte out, using DMX_Bit
-;;  r16: byte value
-;
-; Uses Timer2 as a bit sync clock; must call DMX_Frame_Start before first DMX_Frame
-DMX_Frame:
-    ; Start bit
-        clc
-        rcall       DMX_Bit
-
-    ; Data bits: 8
-        ldi         r21, 8
-        
-_dmx_frame_loop:
-        ; shift + send bit
-        lsl         r16
-        rcall       DMX_Bit
-
-        ; loop
-        dec         r21
-        brne        _dmx_frame_loop
-
-    ; Stop bits
-        sec
-        rcall       DMX_Bit
-        rcall       DMX_Bit
-    
-    ; OK
-    ret
-
-;; End of DMX frames
-DMX_Frame_End:
-    ; Keep mark from end of last frame; DMX_Break_Start starts the break
-    ; Stop the timer
-        poke        [DMX_TIMER_CRB, r20, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS_STOP << CS20)]
-
-    ; OK
-    ret
-
-;; Send one value on all frames
-;;  r17: byte value
-DMX_Flood:
-    ; Break
-        rcall       DMX_Break
-
-    ; Start code
-        ldi         r16, 0
-        rcall       DMX_Frame
-
-    ; Channels
-        ; number of channels to send
-        ldi         r22, 100
-
-_dmx_flood_channels:
-        ; restore channel value
-        mov         r16, r17
-
-        ; send channel value
-        rcall       DMX_Frame
-
-        ; loop
-        dec         r22
-        brne        _dmx_flood_channels
-
-    ; End packet
-        rcall       DMX_Frame_End
-
-
-    ret
-
-;; Program main
-Main:
-; Initialization
-    ; Debug
-        sbi         LED_DDR, LED_BIT
-sbi         LED_PORT, LED_BIT
-
-    ; Stack
-		poke		[SPL, r16:r17, RAMEND]
-
-    ; Init
-        rcall       DMX_Init
-
-cbi         LED_PORT, LED_BIT
-
-    ; Send; value
-_main_loop:
-        ldi         r17, 255
-        rcall       DMX_Flood
-
-cbi         LED_PORT, LED_BIT
-
-        ; never returns..
-        rjmp        _main_loop
-
--- a/font-compile.py	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-def read_block (fh) :
-    """
-        Yield a series of non-empty lines from the given file, ignoring any leading empty lines, and stopping after the first empty line
-    """
-
-    leading = True
-
-    for line in fh :
-        if line.strip() :
-            leading = False
-
-            # yield non-empty
-            yield line
-
-        elif leading :
-            # skip leading empty
-            continue
-
-        else :
-            # stop on empty
-            return
-
-    else :
-        # EOF
-        return
-
-def read_charblock (lines) :
-    """
-        Read in a char from the given lines, returning an
-            (ascii, rows)
-
-        tuple, or None, if there weren't any more blocks
-    """
-
-    # the ascii code as a char
-    ascii = ''
-
-    # row data as ints
-    rows = []
-
-    for line in lines :
-        line = line.strip()
-
-        if line.startswith(';') :
-            # set ascii code
-            ascii = line.replace(';', '').strip()
-
-            if not ascii :
-                print 'read_charblock', 'empty'
-
-                # skip
-                return None
-
-            elif len(ascii) == 1 :
-                print 'read_charblock', 'simplechar', ascii
-
-            else :
-                ascii = ascii.decode('string_escape')
-        
-                print 'read_charblock', 'decodechar', ascii
-
-            assert len(ascii) == 1
-        
-        else :
-            # convert
-            row = line.replace('#', '1').replace('-', '0')
-
-            print 'read_charblock', 'row', row
-
-            # 6 columns
-            assert len(row) == 6
-
-            # from binary
-            row = int(row, 2)
-
-            rows.append(row)
-    
-    # got data?
-    if ascii and rows :
-        # 8 rows
-        assert len(rows) == 8
-
-        return ascii, rows
-
-    else :
-        # nope, empty block, EOF
-        return None
-
-def read_charblocks (fh) :
-    """
-        Read in all char blocks as (ascii, rows) tuples from given file
-    """
-
-    while True :
-        out = read_charblock(read_block(fh))
-
-        if out :
-            yield out
-
-        else :
-            break
-
-def decode_rows (inrows) :
-    """
-        Decode char def data from its 6x8 row format into the format we need (6x8 col format)
-    """
-
-    outcols = [0x00] * 6
-
-    for rowidx, row in enumerate(inrows) :
-        
-        for colidx, col in enumerate(outcols) :
-            # get bit from row
-            bit = (row >> (5 - colidx)) & 1
-
-            # set bit into column
-            outcols[colidx] |= (bit << rowidx)
-
-    # ok...
-    return outcols
-
-def write_chardef (fh, ascii, cols) :
-    """
-        Write out character definition block to given .def file, using given char code and column data
-    """
-
-    fh.write(
-            ("; %r\n" % ascii)
-        +   (".db %s\n" % (', '.join(bin(col) for col in cols)))
-        +   ("\n")
-    )
-
-def compile_fonts (infh, outf) :
-    """
-        Compile char blocks from infh, writing out definitions to outf
-    """
-
-    charmap = dict()
-
-    # decode in
-    for charblock in read_charblocks(infh) :
-        # unpack
-        ascii, rows = charblock
-
-        # convert
-        cols = decode_rows(rows)
-
-        # map
-        charmap[ascii] = cols
-
-        print 'compile_fonts', 'read', ascii
-
-    # detect min/max syms
-    syms = charmap.keys()
-    font_start = min(syms)
-    font_end = max(syms)
-
-    assert(ord(font_start) < ord(font_end))
-    
-    # write out
-    outf.write(
-            ";; AUTOMATICALLY GENERATED - Do not edit!\n"
-            ";; 8x6 font, '0' - '1', rows-by-col format\n"
-        +  (".equ FONT_8x6_START = %d ; %r\n" % (ord(font_start), font_start))
-        +  (".equ FONT_8x6_END = %d ; %r\n" % (ord(font_end), font_end))
-        +  (".equ FONT_8x6_COLS = %d\n" % (6, ))
-        +  (".equ FONT_8x6_ROWS = %d\n" % (8, ))
-        +   "FONT_8x6:\n"
-            "\n"
-    )
-
-    # default symbol for unknown chars
-    defsym = charmap['\0']
-
-    for char in xrange(ord(font_start), ord(font_end) + 1) :
-        ascii = chr(char)
-        cols = charmap.get(ascii, defsym)
-
-        write_chardef(outf, ascii, cols)
-
-def main () :
-    import sys, getopt
-
-    opts, args = getopt.getopt(sys.argv[1:], '')
-
-    inpath, outpath = args
-
-    # run
-    compile_fonts(open(inpath, 'r'), open(outpath, 'w'))
-
-if __name__ == '__main__' :
-    main()
-
--- a/font.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-;; Basic LED matrix fonts
-;; vim: set ft=avr:
-
-.cseg
-
-;; Font definition
-; Defines FONT_8x6 symbol
-.include "font.def"
-
-; Font to use
-.set FONT_TABLE     = FONT_8x6
-.set FONT_START     = FONT_8x6_START
-.set FONT_END       = FONT_8x6_END
-.set FONT_COLS      = FONT_8x6_COLS
-.set FONT_ROWS      = FONT_8x6_ROWS     ; XXX: fixed to 8
-
-;; Render the given ASCII char into the given buffer
-; Input:    r16 - ASCII char code
-;           Y   - dest buf (Wx8 column data)
-Font_Render:
-    ; Test char index
-
-        ; test under-range
-        ldi     r17, FONT_START
-        cp      r16, r17
-        brlt    font_r_invalid
-
-        ; test over-range
-        ldi     r17, FONT_END
-        cp      r17, r16
-        brlt    font_r_invalid
-
-        ; compute offset in chars (r16)
-        subi    r16, FONT_START
-
-        ; ok
-        rjmp    font_r_render
-
-font_r_invalid:
-        ; use first sym
-        ldi     r16, 0
-
-    cbi         PORTD, PIND7
-
-font_r_render:
-        ; compute offset in bytes (r1:r0)
-        ldi     r17, FONT_COLS
-        mul     r16, r17
-
-        ; font table start offset from words
-        ldi     ZL, low(FONT_TABLE * 2)
-        ldi     ZH, high(FONT_TABLE * 2)
-
-        ; apply offset
-        add     ZL, r0
-        adc     ZH, r1
-
-    ; Copy column pixel data
-        ; count columns
-        ldi     r16, FONT_COLS
-font_r_cpy:
-        
-        ; copy via r17
-        lpm     r17, Z+
-        st      Y+, r17
-
-        dec     r16
-        brne    font_r_cpy
-
-
-    ; Done
-        ret
-
--- a/font.txt	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-; \x00
-------
--####-
--#--#-
--#--#-
--#--#-
--#--#-
--####-
-------
-
-; \x20
-------
-------
-------
-------
-------
-------
-------
-------
-
-; !
---##--
---##--
---##--
---##--
---##--
-------
---##--
---##--
-
-; 0
--####-
-#----#
-#----#
-#----#
-#----#
-#----#
-#----#
--####-
-
-; 1
----#--
---##--
--#-#--
-#--#--
----#--
----#--
----#--
--#####
-
-; 2
---###-
--#---#
--#---#
-----#-
----#--
---#---
--#----
-######
-
-; 3
--###--
-#---#-
------#
-----#-
----##-
------#
-#---#-
--###--
-
-; 4
-----#-
--#--#-
-##--#-
-#---#-
-######
-----#-
-----#-
-----#-
-
-; 5
-######
-#-----
-#-----
-#####-
------#
------#
-#----#
--####-
-
-; 6
-------
--####-
-##---#
-#-----
-#####-
-#----#
-#----#
--####-
-
-; 7
--#####
-#----#
-----#-
----#--
---#---
--#----
-#-----
-------
-
-; 8
-------
--####-
-#----#
-#----#
--####-
-#----#
-#----#
--####-
-
-; 9
--####-
-#----#
-#----#
-#----#
--#####
------#
------#
-----#-
-
-; h
-#-----
-#-----
-#-----
-#-----
-#-###-
-##---#
-#----#
-#----#
-
-; e
---##--
--#--#-
-#----#
-######
-#-----
-#---#-
--###--
-------
-
-; l
---##--
----#--
----#--
----#--
----#--
----#--
----#--
---###-
-
-; o
-------
-------
-------
--####-
-#----#
-#----#
-#----#
--####-
-
-; w
-------
-------
-------
-#---#-
-#---#-
-#---#-
-#-#-#-
--#-#--
-
-; r
-------
-------
-#-----
-#-##--
-##----
-#-----
-#-----
-#-----
-
-; d
-----#-
-----#-
-----#-
--####-
-#---#-
-#---#-
-#---#-
--###--
-
-; 
-------
-------
-------
-------
-------
-------
-------
-------
-
--- a/hw.S	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-.nolist
-.include "m168def.inc"      ; Same family as 328P
-.list
-
-; Interrupt vector
-.org 0x00
-        rjmp        main            ; Reset
-
-.org OC1Aaddr
-        rjmp        timer           ; Timer 1 Compare A 
-
-; Program code
-main:
-    ; Setup pins for output
-        sbi         DDRB, PORTB4        ; Out
-        sbi         DDRB, PORTB5        ; Out
-        
-    ; Flags for output
-        ldi         r16, (1 << PORTB4)
-
-    ; Setup Timer 0
-        ; Count to 64k
-        ldi         r18, HIGH(0xffff/2)
-        ldi         r19, LOW(0xffff/2)
-        sts         OCR1AH, r18
-        sts         OCR1AL, r19
- 
-        ; Normal port operation for both comperators
-        ; Bits WGM10:1 zero
-        ldi         r18,    0x00
-        sts         TCCR1A, r18
- 
-        ; CTC mode, 1/64 prescaled
-        ; the timer will start counting from now, but that shouldn't matter..
-        ldi         r18,    (1 << WGM12) | (0b011 << CS10)
-        sts         TCCR1B, r18
-       
-        ; Enable timer interrupt
-        ldi         r18, (1 << OCIE1A)
-        sts         TIMSK1, r18
-        
-        ; Setup sleep for Idle mode
-        ldi         r18, (0b000 << SM0) | (1 << SE)
-        sts         SMCR, r18
-
-        ; ...and enable interrupts
-        sei
-
-loop:
-        ; Flip
-        com         r16
-        
-        ; Output
-        out         PORTB, r16
-
-        ; Wait
-wait:   sleep
-        cpi         r20, 1
-        brne        wait
-        ldi         r20, 0
-
-        ; continue
-        rjmp loop
-
-; Counter overflow handler
-timer:
-        ; Set flag
-        ldi         r20, 1
-
-        ; Re-enable interrupts
-        reti
-
--- a/led7seg.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-;;
-;; Driving 7-segment LED displays over SPI
-;;
-
-; Output Enable control
-.equ LED7_DDR    = DDRB
-.equ LED7_PORT   = PORTB
-.equ LED7_OE     = PORTB1                ; Output Enable (Low)
-
-; Font for 7-segment display
-; Includes decimal digits 0-9, hexadecimal digits A-F, and some special chars
-LED7_Font:
-.db     0b00111111, 0b00000110      ; 0, 1
-.db     0b01011011, 0b01001111      ; 2, 3
-.db     0b01100110, 0b01101101      ; 4, 5
-.db     0b01111101, 0b00000111      ; 6, 7
-.db     0b01111111, 0b01100111      ; 8, 9
-.db     0b01110111, 0b01111100      ; A, b
-.db     0b00111001, 0b01011110      ; C, d
-.db     0b01111001, 0b01110001      ; E, f
-.db     0b10000000, 0b00000000      ; ., 
-
-.equ LED7_0     = 0
-.equ LED7_1     = 1
-.equ LED7_2     = 2
-.equ LED7_3     = 3
-.equ LED7_4     = 4
-.equ LED7_5     = 5
-.equ LED7_6     = 6
-.equ LED7_7     = 7
-.equ LED7_8     = 8
-.equ LED7_9     = 9
-.equ LED7_A     = 10
-.equ LED7_B     = 11
-.equ LED7_C     = 12
-.equ LED7_D     = 13
-.equ LED7_E     = 14
-.equ LED7_F     = 15
-.equ LED7_DOT   = 16
-.equ LED7_EMPTY = 17
-
-; LEDs are on beginning of SPI universe
-.set led7_buffer = spi_outbuf + 0
-
-;; Initialize LCD to empty, and enable
-LED7_Init:
-    ; Setup ENable port
-        sbi         LED7_PORT, LED7_OE    ; Disabled (Low)
-        sbi         LED7_DDR, LED7_OE     ; Out
-    
-    ; Initialize buffer
-        ldi         r16, 0b01000000
-        sts         led7_buffer + 0, r16
-        sts         led7_buffer + 1, r16
-
-    ; Update display
-        rcall       SPI_SendRecv
-
-    ; Enable output once the initial display has been shifted out
-        cbi         LED7_PORT, LED7_OE
-
-    ; Done
-        ret
-
-LED7_LoadChar:
-        clr         r0, 0
-
-    ; Prep address
-        ; base addr for font table
-        ldi         ZH, high(2 * LED7_Font)
-        ldi         ZL, low(2 * LED7_Font)
-        
-        ; offset
-        add         ZL, r8
-        adc         ZH, r0
-
-    ; Load char
-        lpm         r8, Z
-
-    ; Done
-        ret
-
-;; Display an 8-bit hexadecimal value on the display
-;;  Input: r16
-LED7_ShowHex:
-        ; base16
-        ldi         r17, 16 
-
-        ; 1's
-        call        div8u
-        
-        ; r16 = result, r15 = remainder
-        mov         r17, r15 
-
-    ; Continue
-        rjmp        LED7_Show
-
-;; Display an 8-bit decimal value on the display
-;;  Input: r16
-LED7_ShowDec:
-        ; base10
-        ldi         r17, 10
-
-        ; 1's
-        call        div8u
-        mov         r8, r15
-
-        ; 10's
-        call        div8u
-        mov         r9, r16         ; 100's
-        
-        ; 1's from r8
-        rcall       LED7_LoadChar
-        mov         r17, r8
-
-        ; 10's from r15
-        mov         r8, r15
-        rcall       LED7_LoadChar
-        mov         r16, r8
-           
-        ; Set dots for 100's 
-        sbrc        r9, 0
-        ori         r17, 0b10000000 ; +100
-        sbrc        r9, 1
-        ori         r16, 0b10000000 ; +200
-
-    ; Continue
-        rjmp        LED7_ShowRaw
-
-;; Display a single digit on the display
-;;  Input: r16, r17
-LED7_Show:
-        mov         r8, r16
-        rcall       LED7_LoadChar
-        mov         r16, r8
-
-        mov         r8, r17
-        rcall       LED7_LoadChar
-        mov         r17, r8
-        
-    ;; Continue
-
-;; Display a raw segment mask
-;;  Input: r16, r17
-LED7_ShowRaw:
-    ; Store buffer
-        sts         led7_buffer + 0, r16
-        sts         led7_buffer + 1, r17
-
-    ; Update display
-        rjmp        SPI_Update
-
--- a/led7seg.s	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-.nolist
-.include "m168def.inc"      ; Same family as 328P
-.list
-
-
-;; Interrupt Vector
-.org 0x00
-        rjmp        init
-
-.org OC1Aaddr
-		; Timer/Counter1 Compare Output A
-		rjmp		Timer_OC1A
-
-.org OC0Aaddr
-        ; Timer/Counter0 Compare Output A
-        rjmp        Timer_OC0A
-
-.org SPIaddr
-        rjmp        SPI_Interrupt
-
-.org ADCCaddr
-        rjmp        ADC_Interrupt
-
-.org 0x40
-
-;; Syntax
-.include "macros.inc"
-
-;; SPI
-.include "spi.inc"
-
-;; LCD
-.include "led7seg.inc"
-
-;; DIPs
-.include "dip.inc"
-
-;; ADC
-
-; ADC Interrupt handler
-On_ADC:
-    ; DEBUG
-		sbi			PIND, PORTD7
-
-    ; Check timer, from r16
-        rcall       ADC_Read8
-
-        ldi         r17, 64
-        mul         r16, r17
-        mov         XL, r0
-        mov         XH, r1 
-
-        rjmp       Timer_Update
-
-.set ADC_Handler = On_ADC
-
-.include "adc.inc"
-
-;; Timer
-.set TIMER0_CB_A = SPI_Update
-
-.include "timer.inc"
-
-;; Utils
-.include "delay.inc"
-.include "div.inc"
-
-Sleep_ADC:
-        ; delay
-        rcall       ADC_Read8 
-        ; rcall       DIP_Read8
-        
-        ; Sleep for 64 * var timer cycles
-        ldi         r17, 64
-        mul         r16, r17
-        mov         XL, r0
-        mov         XH, r1 
-
-        rjmp       Timer_Sleep
-
-;; Show value
-Main_ShowValue:
-        ; load value to r16
-        ; rcall       DIP_Read8
-        rcall       ADC_Read8
-        ; rcall       Timer0_Read8
-
-        ; display from r16
-        rcall       LED7_ShowHex
-        
-        ; wait
-        rcall       Sleep_ADC
-
-        ; ldi         XL, 0
-        ; ldi         XH, 16
-        ; rcall       Timer_Sleep
-        
-        ; rcall       ADC_Read8
-        ; mov         r20, r16
-        ; rcall       VarDelay
-
-        ; continue
-        rjmp        Main_ShowValue
-
-;; Count down from F
-; Returns once we've hit zero
-Main_Countdown:
-        ; init from F
-        ldi         r24, LED7_F
-
-_count_loop:
-        ; display
-        mov         r16, r24
-        mov         r16, r24
-        rcall       LED7_Show
-
-        ; exit if zero
-        tst         r24
-        breq        _count_end
-
-        ; count down
-        dec         r24
-
-        ; wait...
-        rcall       Sleep_ADC
-
-        ; next
-        rjmp        _count_loop
-
-_count_end:
-        ; done
-        ret
-
-;; Count up from 00 -> 255
-; Returns once done
-Main_CountUp:
-        ; init from 0
-        ldi         r24, 0
-
-_countup_loop:
-        ; display
-        mov         r16, r24
-        rcall       LED7_ShowDec
-
-        ; wait...
-        rcall       Sleep_ADC
-
-        ; exit if zero
-        cpi         r24, 255
-        breq        _countup_end
-
-        ; count up
-        inc         r24
-
-        ; continue
-        rjmp        _countup_loop
-
-_countup_end:
-        ; done
-        ret
-
-;; Blink between dot and empty
-Main_Blink:
-_blink_loop:
-        ; dot
-        ldi         r16, LED7_DOT
-        ldi         r17, LED7_EMPTY
-        rcall       LED7_Show
-
-        ; wait...
-        rcall       Sleep_ADC
-        
-        ; empty
-        ldi         r16, LED7_EMPTY
-        ldi         r17, LED7_DOT
-        rcall       LED7_Show
-        
-        ; wait... 
-        rcall       Sleep_ADC
-        
-        ; loop
-        rjmp        _blink_loop
- 
-;; Chase segments
-Main_Spin:
-_spin_init:
-        ; init from top
-        ldi         r24, 0b00000001 
-
-_spin_next:
-        ; display
-        mov         r16, r24
-        mov         r17, r24
-        com         r17
-        andi        r17, 0b00111111
-        rcall       LED7_ShowRaw
-
-        ; delay
-        rcall       Sleep_ADC
-        
-        ; next segment
-        lsl         r24
-        
-        ; go back to A if we hit G
-        sbrc        r24, 6
-        rjmp        _spin_init
-
-        rjmp        _spin_next
-
-Main:
-init:
-    ; Stack
-        ldi         r16, high(RAMEND)
-        ldi         r17, low(RAMEND)
-        out         SPH, r16
-        out         SPL, r17
-
-    ; Enable interrupts
-        sei
-
-    ; ADC (slowest to start up)
-        rcall       ADC_Init
-    
-    ; Timer
-        rcall       Timer_Init
-
-    ; SPI
-        rcall       SPI_Init
-    
-    ; LCD (requires interrupts, blocks)
-        rcall       LED7_Init    
-    
-    ; DEBUG
-        sbi         DDRD, PORTD7
-        cbi         PORTD, PORTD7
-
-    ; Run
-        rcall       Main_Countup
-        ; rcall       Main_Countdown
-        ; rcall       Main_ShowValue
-        ; rcall       Main_Spin
-        rcall       Main_Blink
-
-end:
-        rjmp        end
-
--- a/m168def.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,958 +0,0 @@
-;***** THIS IS A MACHINE GENERATED FILE - DO NOT EDIT ********************
-;***** Created: 2005-01-11 10:30 ******* Source: ATmega168.xml ***********
-;*************************************************************************
-;* A P P L I C A T I O N   N O T E   F O R   T H E   A V R   F A M I L Y
-;* 
-;* Number            : AVR000
-;* File Name         : "m168def.inc"
-;* Title             : Register/Bit Definitions for the ATmega168
-;* Date              : 2005-01-11
-;* Version           : 2.14
-;* Support E-mail    : avr@atmel.com
-;* Target MCU        : ATmega168
-;* 
-;* DESCRIPTION
-;* When including this file in the assembly program file, all I/O register 
-;* names and I/O register bit names appearing in the data book can be used.
-;* In addition, the six registers forming the three data pointers X, Y and 
-;* Z have been assigned names XL - ZH. Highest RAM address for Internal 
-;* SRAM is also defined 
-;* 
-;* The Register names are represented by their hexadecimal address.
-;* 
-;* The Register Bit names are represented by their bit number (0-7).
-;* 
-;* Please observe the difference in using the bit names with instructions
-;* such as "sbr"/"cbr" (set/clear bit in register) and "sbrs"/"sbrc"
-;* (skip if bit in register set/cleared). The following example illustrates
-;* this:
-;* 
-;* in    r16,PORTB             ;read PORTB latch
-;* sbr   r16,(1<<PB6)+(1<<PB5) ;set PB6 and PB5 (use masks, not bit#)
-;* out   PORTB,r16             ;output to PORTB
-;* 
-;* in    r16,TIFR              ;read the Timer Interrupt Flag Register
-;* sbrc  r16,TOV0              ;test the overflow flag (use bit#)
-;* rjmp  TOV0_is_set           ;jump if set
-;* ...                         ;otherwise do something else
-;*************************************************************************
-
-; #ifndef _M168DEF_INC_
-; #define _M168DEF_INC_
-
-
-; #pragma partinc 0
-
-; ***** SPECIFY DEVICE ***************************************************
-.device ATmega168
-; #pragma AVRPART ADMIN PART_NAME ATmega168
-.equ	SIGNATURE_000	= 0x1e
-.equ	SIGNATURE_001	= 0x94
-.equ	SIGNATURE_002	= 0x06
-
-; #pragma AVRPART CORE CORE_VERSION V2E
-
-
-; ***** I/O REGISTER DEFINITIONS *****************************************
-; NOTE:
-; Definitions marked "MEMORY MAPPED"are extended I/O ports
-; and cannot be used with IN/OUT instructions
-.equ	UDR0	= 0xc6	; MEMORY MAPPED
-.equ	UBRR0H	= 0xc5	; MEMORY MAPPED
-.equ	UBRR0L	= 0xc4	; MEMORY MAPPED
-.equ	UCSR0C	= 0xc2	; MEMORY MAPPED
-.equ	UCSR0B	= 0xc1	; MEMORY MAPPED
-.equ	UCSR0A	= 0xc0	; MEMORY MAPPED
-.equ	TWAMR	= 0xbd	; MEMORY MAPPED
-.equ	TWCR	= 0xbc	; MEMORY MAPPED
-.equ	TWDR	= 0xbb	; MEMORY MAPPED
-.equ	TWAR	= 0xba	; MEMORY MAPPED
-.equ	TWSR	= 0xb9	; MEMORY MAPPED
-.equ	TWBR	= 0xb8	; MEMORY MAPPED
-.equ	ASSR	= 0xb6	; MEMORY MAPPED
-.equ	OCR2B	= 0xb4	; MEMORY MAPPED
-.equ	OCR2A	= 0xb3	; MEMORY MAPPED
-.equ	TCNT2	= 0xb2	; MEMORY MAPPED
-.equ	TCCR2B	= 0xb1	; MEMORY MAPPED
-.equ	TCCR2A	= 0xb0	; MEMORY MAPPED
-.equ	OCR1BH	= 0x8b	; MEMORY MAPPED
-.equ	OCR1BL	= 0x8a	; MEMORY MAPPED
-.equ	OCR1AH	= 0x89	; MEMORY MAPPED
-.equ	OCR1AL	= 0x88	; MEMORY MAPPED
-.equ	ICR1H	= 0x87	; MEMORY MAPPED
-.equ	ICR1L	= 0x86	; MEMORY MAPPED
-.equ	TCNT1H	= 0x85	; MEMORY MAPPED
-.equ	TCNT1L	= 0x84	; MEMORY MAPPED
-.equ	TCCR1C	= 0x82	; MEMORY MAPPED
-.equ	TCCR1B	= 0x81	; MEMORY MAPPED
-.equ	TCCR1A	= 0x80	; MEMORY MAPPED
-.equ	DIDR1	= 0x7f	; MEMORY MAPPED
-.equ	DIDR0	= 0x7e	; MEMORY MAPPED
-.equ	ADMUX	= 0x7c	; MEMORY MAPPED
-.equ	ADCSRB	= 0x7b	; MEMORY MAPPED
-.equ	ADCSRA	= 0x7a	; MEMORY MAPPED
-.equ	ADCH	= 0x79	; MEMORY MAPPED
-.equ	ADCL	= 0x78	; MEMORY MAPPED
-.equ	TIMSK2	= 0x70	; MEMORY MAPPED
-.equ	TIMSK1	= 0x6f	; MEMORY MAPPED
-.equ	TIMSK0	= 0x6e	; MEMORY MAPPED
-.equ	PCMSK2	= 0x6d	; MEMORY MAPPED
-.equ	PCMSK1	= 0x6c	; MEMORY MAPPED
-.equ	PCMSK0	= 0x6b	; MEMORY MAPPED
-.equ	EICRA	= 0x69	; MEMORY MAPPED
-.equ	PCICR	= 0x68	; MEMORY MAPPED
-.equ	OSCCAL	= 0x66	; MEMORY MAPPED
-.equ	PRR	= 0x64	; MEMORY MAPPED
-.equ	CLKPR	= 0x61	; MEMORY MAPPED
-.equ	WDTCSR	= 0x60	; MEMORY MAPPED
-.equ	SREG	= 0x3f
-.equ	SPH	= 0x3e
-.equ	SPL	= 0x3d
-.equ	SPMCSR	= 0x37
-.equ	MCUCR	= 0x35
-.equ	MCUSR	= 0x34
-.equ	SMCR	= 0x33
-.equ	ACSR	= 0x30
-.equ	SPDR	= 0x2e
-.equ	SPSR	= 0x2d
-.equ	SPCR	= 0x2c
-.equ	GPIOR2	= 0x2b
-.equ	GPIOR1	= 0x2a
-.equ	OCR0B	= 0x28
-.equ	OCR0A	= 0x27
-.equ	TCNT0	= 0x26
-.equ	TCCR0B	= 0x25
-.equ	TCCR0A	= 0x24
-.equ	GTCCR	= 0x23
-.equ	EEARH	= 0x22
-.equ	EEARL	= 0x21
-.equ	EEDR	= 0x20
-.equ	EECR	= 0x1f
-.equ	GPIOR0	= 0x1e
-.equ	EIMSK	= 0x1d
-.equ	EIFR	= 0x1c
-.equ	PCIFR	= 0x1b
-.equ	TIFR2	= 0x17
-.equ	TIFR1	= 0x16
-.equ	TIFR0	= 0x15
-.equ	PORTD	= 0x0b
-.equ	DDRD	= 0x0a
-.equ	PIND	= 0x09
-.equ	PORTC	= 0x08
-.equ	DDRC	= 0x07
-.equ	PINC	= 0x06
-.equ	PORTB	= 0x05
-.equ	DDRB	= 0x04
-.equ	PINB	= 0x03
-
-
-; ***** BIT DEFINITIONS **************************************************
-
-; ***** USART0 ***********************
-; UDR0 - USART I/O Data Register
-.equ	UDR0_0	= 0	; USART I/O Data Register bit 0
-.equ	UDR0_1	= 1	; USART I/O Data Register bit 1
-.equ	UDR0_2	= 2	; USART I/O Data Register bit 2
-.equ	UDR0_3	= 3	; USART I/O Data Register bit 3
-.equ	UDR0_4	= 4	; USART I/O Data Register bit 4
-.equ	UDR0_5	= 5	; USART I/O Data Register bit 5
-.equ	UDR0_6	= 6	; USART I/O Data Register bit 6
-.equ	UDR0_7	= 7	; USART I/O Data Register bit 7
-
-; UCSR0A - USART Control and Status Register A
-.equ	MPCM0	= 0	; Multi-processor Communication Mode
-.equ	U2X0	= 1	; Double the USART transmission speed
-.equ	UPE0	= 2	; Parity Error
-.equ	DOR0	= 3	; Data overRun
-.equ	FE0	= 4	; Framing Error
-.equ	UDRE0	= 5	; USART Data Register Empty
-.equ	TXC0	= 6	; USART Transmitt Complete
-.equ	RXC0	= 7	; USART Receive Complete
-
-; UCSR0B - USART Control and Status Register B
-.equ	TXB80	= 0	; Transmit Data Bit 8
-.equ	RXB80	= 1	; Receive Data Bit 8
-.equ	UCSZ02	= 2	; Character Size
-.equ	TXEN0	= 3	; Transmitter Enable
-.equ	RXEN0	= 4	; Receiver Enable
-.equ	UDRIE0	= 5	; USART Data register Empty Interrupt Enable
-.equ	TXCIE0	= 6	; TX Complete Interrupt Enable
-.equ	RXCIE0	= 7	; RX Complete Interrupt Enable
-
-; UCSR0C - USART Control and Status Register C
-.equ	UCPOL0	= 0	; Clock Polarity
-.equ	UCSZ00	= 1	; Character Size
-.equ	UCPHA0	= UCSZ00	; For compatibility
-.equ	UCSZ01	= 2	; Character Size
-.equ	UDORD0	= UCSZ01	; For compatibility
-.equ	USBS0	= 3	; Stop Bit Select
-.equ	UPM00	= 4	; Parity Mode Bit 0
-.equ	UPM01	= 5	; Parity Mode Bit 1
-.equ	UMSEL00	= 6	; USART Mode Select
-.equ	UMSEL0	= UMSEL00	; For compatibility
-.equ	UMSEL01	= 7	; USART Mode Select
-.equ	UMSEL1	= UMSEL01	; For compatibility
-
-
-; ***** TWI **************************
-; TWAMR - TWI (Slave) Address Mask Register
-.equ	TWAM0	= 1	; 
-.equ	TWAMR0	= TWAM0	; For compatibility
-.equ	TWAM1	= 2	; 
-.equ	TWAMR1	= TWAM1	; For compatibility
-.equ	TWAM2	= 3	; 
-.equ	TWAMR2	= TWAM2	; For compatibility
-.equ	TWAM3	= 4	; 
-.equ	TWAMR3	= TWAM3	; For compatibility
-.equ	TWAM4	= 5	; 
-.equ	TWAMR4	= TWAM4	; For compatibility
-.equ	TWAM5	= 6	; 
-.equ	TWAMR5	= TWAM5	; For compatibility
-.equ	TWAM6	= 7	; 
-.equ	TWAMR6	= TWAM6	; For compatibility
-
-; TWBR - TWI Bit Rate register
-.equ	TWBR0	= 0	; 
-.equ	TWBR1	= 1	; 
-.equ	TWBR2	= 2	; 
-.equ	TWBR3	= 3	; 
-.equ	TWBR4	= 4	; 
-.equ	TWBR5	= 5	; 
-.equ	TWBR6	= 6	; 
-.equ	TWBR7	= 7	; 
-
-; TWCR - TWI Control Register
-.equ	TWIE	= 0	; TWI Interrupt Enable
-.equ	TWEN	= 2	; TWI Enable Bit
-.equ	TWWC	= 3	; TWI Write Collition Flag
-.equ	TWSTO	= 4	; TWI Stop Condition Bit
-.equ	TWSTA	= 5	; TWI Start Condition Bit
-.equ	TWEA	= 6	; TWI Enable Acknowledge Bit
-.equ	TWINT	= 7	; TWI Interrupt Flag
-
-; TWSR - TWI Status Register
-.equ	TWPS0	= 0	; TWI Prescaler
-.equ	TWPS1	= 1	; TWI Prescaler
-.equ	TWS3	= 3	; TWI Status
-.equ	TWS4	= 4	; TWI Status
-.equ	TWS5	= 5	; TWI Status
-.equ	TWS6	= 6	; TWI Status
-.equ	TWS7	= 7	; TWI Status
-
-; TWDR - TWI Data register
-.equ	TWD0	= 0	; TWI Data Register Bit 0
-.equ	TWD1	= 1	; TWI Data Register Bit 1
-.equ	TWD2	= 2	; TWI Data Register Bit 2
-.equ	TWD3	= 3	; TWI Data Register Bit 3
-.equ	TWD4	= 4	; TWI Data Register Bit 4
-.equ	TWD5	= 5	; TWI Data Register Bit 5
-.equ	TWD6	= 6	; TWI Data Register Bit 6
-.equ	TWD7	= 7	; TWI Data Register Bit 7
-
-; TWAR - TWI (Slave) Address register
-.equ	TWGCE	= 0	; TWI General Call Recognition Enable Bit
-.equ	TWA0	= 1	; TWI (Slave) Address register Bit 0
-.equ	TWA1	= 2	; TWI (Slave) Address register Bit 1
-.equ	TWA2	= 3	; TWI (Slave) Address register Bit 2
-.equ	TWA3	= 4	; TWI (Slave) Address register Bit 3
-.equ	TWA4	= 5	; TWI (Slave) Address register Bit 4
-.equ	TWA5	= 6	; TWI (Slave) Address register Bit 5
-.equ	TWA6	= 7	; TWI (Slave) Address register Bit 6
-
-
-; ***** TIMER_COUNTER_1 **************
-; TIMSK1 - Timer/Counter Interrupt Mask Register
-.equ	TOIE1	= 0	; Timer/Counter1 Overflow Interrupt Enable
-.equ	OCIE1A	= 1	; Timer/Counter1 Output CompareA Match Interrupt Enable
-.equ	OCIE1B	= 2	; Timer/Counter1 Output CompareB Match Interrupt Enable
-.equ	ICIE1	= 5	; Timer/Counter1 Input Capture Interrupt Enable
-
-; TIFR1 - Timer/Counter Interrupt Flag register
-.equ	TOV1	= 0	; Timer/Counter1 Overflow Flag
-.equ	OCF1A	= 1	; Output Compare Flag 1A
-.equ	OCF1B	= 2	; Output Compare Flag 1B
-.equ	ICF1	= 5	; Input Capture Flag 1
-
-; TCCR1A - Timer/Counter1 Control Register A
-.equ	WGM10	= 0	; Waveform Generation Mode
-.equ	WGM11	= 1	; Waveform Generation Mode
-.equ	COM1B0	= 4	; Compare Output Mode 1B, bit 0
-.equ	COM1B1	= 5	; Compare Output Mode 1B, bit 1
-.equ	COM1A0	= 6	; Comparet Ouput Mode 1A, bit 0
-.equ	COM1A1	= 7	; Compare Output Mode 1A, bit 1
-
-; TCCR1B - Timer/Counter1 Control Register B
-.equ	CS10	= 0	; Prescaler source of Timer/Counter 1
-.equ	CS11	= 1	; Prescaler source of Timer/Counter 1
-.equ	CS12	= 2	; Prescaler source of Timer/Counter 1
-.equ	WGM12	= 3	; Waveform Generation Mode
-.equ	WGM13	= 4	; Waveform Generation Mode
-.equ	ICES1	= 6	; Input Capture 1 Edge Select
-.equ	ICNC1	= 7	; Input Capture 1 Noise Canceler
-
-; TCCR1C - Timer/Counter1 Control Register C
-.equ	FOC1B	= 6	; 
-.equ	FOC1A	= 7	; 
-
-; GTCCR - General Timer/Counter Control Register
-.equ	PSRSYNC	= 0	; Prescaler Reset Timer/Counter1 and Timer/Counter0
-.equ	TSM	= 7	; Timer/Counter Synchronization Mode
-
-
-; ***** TIMER_COUNTER_2 **************
-; TIMSK2 - Timer/Counter Interrupt Mask register
-.equ	TOIE2	= 0	; Timer/Counter2 Overflow Interrupt Enable
-.equ	TOIE2A	= TOIE2	; For compatibility
-.equ	OCIE2A	= 1	; Timer/Counter2 Output Compare Match A Interrupt Enable
-.equ	OCIE2B	= 2	; Timer/Counter2 Output Compare Match B Interrupt Enable
-
-; TIFR2 - Timer/Counter Interrupt Flag Register
-.equ	TOV2	= 0	; Timer/Counter2 Overflow Flag
-.equ	OCF2A	= 1	; Output Compare Flag 2A
-.equ	OCF2B	= 2	; Output Compare Flag 2B
-
-; TCCR2A - Timer/Counter2 Control Register A
-.equ	WGM20	= 0	; Waveform Genration Mode
-.equ	WGM21	= 1	; Waveform Genration Mode
-.equ	COM2B0	= 4	; Compare Output Mode bit 0
-.equ	COM2B1	= 5	; Compare Output Mode bit 1
-.equ	COM2A0	= 6	; Compare Output Mode bit 1
-.equ	COM2A1	= 7	; Compare Output Mode bit 1
-
-; TCCR2B - Timer/Counter2 Control Register B
-.equ	CS20	= 0	; Clock Select bit 0
-.equ	CS21	= 1	; Clock Select bit 1
-.equ	CS22	= 2	; Clock Select bit 2
-.equ	WGM22	= 3	; Waveform Generation Mode
-.equ	FOC2B	= 6	; Force Output Compare B
-.equ	FOC2A	= 7	; Force Output Compare A
-
-; TCNT2 - Timer/Counter2
-.equ	TCNT2_0	= 0	; Timer/Counter 2 bit 0
-.equ	TCNT2_1	= 1	; Timer/Counter 2 bit 1
-.equ	TCNT2_2	= 2	; Timer/Counter 2 bit 2
-.equ	TCNT2_3	= 3	; Timer/Counter 2 bit 3
-.equ	TCNT2_4	= 4	; Timer/Counter 2 bit 4
-.equ	TCNT2_5	= 5	; Timer/Counter 2 bit 5
-.equ	TCNT2_6	= 6	; Timer/Counter 2 bit 6
-.equ	TCNT2_7	= 7	; Timer/Counter 2 bit 7
-
-; OCR2A - Timer/Counter2 Output Compare Register A
-.equ	OCR2_0	= 0	; Timer/Counter2 Output Compare Register Bit 0
-.equ	OCR2_1	= 1	; Timer/Counter2 Output Compare Register Bit 1
-.equ	OCR2_2	= 2	; Timer/Counter2 Output Compare Register Bit 2
-.equ	OCR2_3	= 3	; Timer/Counter2 Output Compare Register Bit 3
-.equ	OCR2_4	= 4	; Timer/Counter2 Output Compare Register Bit 4
-.equ	OCR2_5	= 5	; Timer/Counter2 Output Compare Register Bit 5
-.equ	OCR2_6	= 6	; Timer/Counter2 Output Compare Register Bit 6
-.equ	OCR2_7	= 7	; Timer/Counter2 Output Compare Register Bit 7
-
-; OCR2B - Timer/Counter2 Output Compare Register B
-;.equ	OCR2_0	= 0	; Timer/Counter2 Output Compare Register Bit 0
-;.equ	OCR2_1	= 1	; Timer/Counter2 Output Compare Register Bit 1
-;.equ	OCR2_2	= 2	; Timer/Counter2 Output Compare Register Bit 2
-;.equ	OCR2_3	= 3	; Timer/Counter2 Output Compare Register Bit 3
-;.equ	OCR2_4	= 4	; Timer/Counter2 Output Compare Register Bit 4
-;.equ	OCR2_5	= 5	; Timer/Counter2 Output Compare Register Bit 5
-;.equ	OCR2_6	= 6	; Timer/Counter2 Output Compare Register Bit 6
-;.equ	OCR2_7	= 7	; Timer/Counter2 Output Compare Register Bit 7
-
-; ASSR - Asynchronous Status Register
-.equ	TCR2BUB	= 0	; Timer/Counter Control Register2 Update Busy
-.equ	TCR2AUB	= 1	; Timer/Counter Control Register2 Update Busy
-.equ	OCR2BUB	= 2	; Output Compare Register 2 Update Busy
-.equ	OCR2AUB	= 3	; Output Compare Register2 Update Busy
-.equ	TCN2UB	= 4	; Timer/Counter2 Update Busy
-.equ	AS2	= 5	; Asynchronous Timer/Counter2
-.equ	EXCLK	= 6	; Enable External Clock Input
-
-; GTCCR - General Timer Counter Control register
-.equ	PSRASY	= 1	; Prescaler Reset Timer/Counter2
-.equ	PSR2	= PSRASY	; For compatibility
-;.equ	TSM	= 7	; Timer/Counter Synchronization Mode
-
-
-; ***** AD_CONVERTER *****************
-; ADMUX - The ADC multiplexer Selection Register
-.equ	MUX0	= 0	; Analog Channel and Gain Selection Bits
-.equ	MUX1	= 1	; Analog Channel and Gain Selection Bits
-.equ	MUX2	= 2	; Analog Channel and Gain Selection Bits
-.equ	MUX3	= 3	; Analog Channel and Gain Selection Bits
-.equ	ADLAR	= 5	; Left Adjust Result
-.equ	REFS0	= 6	; Reference Selection Bit 0
-.equ	REFS1	= 7	; Reference Selection Bit 1
-
-; ADCSRA - The ADC Control and Status register A
-.equ	ADPS0	= 0	; ADC  Prescaler Select Bits
-.equ	ADPS1	= 1	; ADC  Prescaler Select Bits
-.equ	ADPS2	= 2	; ADC  Prescaler Select Bits
-.equ	ADIE	= 3	; ADC Interrupt Enable
-.equ	ADIF	= 4	; ADC Interrupt Flag
-.equ	ADATE	= 5	; ADC  Auto Trigger Enable
-.equ	ADSC	= 6	; ADC Start Conversion
-.equ	ADEN	= 7	; ADC Enable
-
-; ADCSRB - The ADC Control and Status register B
-.equ	ADTS0	= 0	; ADC Auto Trigger Source bit 0
-.equ	ADTS1	= 1	; ADC Auto Trigger Source bit 1
-.equ	ADTS2	= 2	; ADC Auto Trigger Source bit 2
-.equ	ACME	= 6	; 
-
-; ADCH - ADC Data Register High Byte
-.equ	ADCH0	= 0	; ADC Data Register High Byte Bit 0
-.equ	ADCH1	= 1	; ADC Data Register High Byte Bit 1
-.equ	ADCH2	= 2	; ADC Data Register High Byte Bit 2
-.equ	ADCH3	= 3	; ADC Data Register High Byte Bit 3
-.equ	ADCH4	= 4	; ADC Data Register High Byte Bit 4
-.equ	ADCH5	= 5	; ADC Data Register High Byte Bit 5
-.equ	ADCH6	= 6	; ADC Data Register High Byte Bit 6
-.equ	ADCH7	= 7	; ADC Data Register High Byte Bit 7
-
-; ADCL - ADC Data Register Low Byte
-.equ	ADCL0	= 0	; ADC Data Register Low Byte Bit 0
-.equ	ADCL1	= 1	; ADC Data Register Low Byte Bit 1
-.equ	ADCL2	= 2	; ADC Data Register Low Byte Bit 2
-.equ	ADCL3	= 3	; ADC Data Register Low Byte Bit 3
-.equ	ADCL4	= 4	; ADC Data Register Low Byte Bit 4
-.equ	ADCL5	= 5	; ADC Data Register Low Byte Bit 5
-.equ	ADCL6	= 6	; ADC Data Register Low Byte Bit 6
-.equ	ADCL7	= 7	; ADC Data Register Low Byte Bit 7
-
-; DIDR0 - Digital Input Disable Register
-.equ	ADC0D	= 0	; 
-.equ	ADC1D	= 1	; 
-.equ	ADC2D	= 2	; 
-.equ	ADC3D	= 3	; 
-.equ	ADC4D	= 4	; 
-.equ	ADC5D	= 5	; 
-
-
-; ***** ANALOG_COMPARATOR ************
-; ACSR - Analog Comparator Control And Status Register
-.equ	ACIS0	= 0	; Analog Comparator Interrupt Mode Select bit 0
-.equ	ACIS1	= 1	; Analog Comparator Interrupt Mode Select bit 1
-.equ	ACIC	= 2	; 
-.equ	ACIE	= 3	; Analog Comparator Interrupt Enable
-.equ	ACI	= 4	; Analog Comparator Interrupt Flag
-.equ	ACO	= 5	; Analog Compare Output
-.equ	ACBG	= 6	; Analog Comparator Bandgap Select
-.equ	ACD	= 7	; Analog Comparator Disable
-
-; DIDR1 - Digital Input Disable Register 1
-.equ	AIN0D	= 0	; AIN0 Digital Input Disable
-.equ	AIN1D	= 1	; AIN1 Digital Input Disable
-
-
-; ***** PORTB ************************
-; PORTB - Port B Data Register
-.equ	PORTB0	= 0	; Port B Data Register bit 0
-.equ	PB0	= 0	; For compatibility
-.equ	PORTB1	= 1	; Port B Data Register bit 1
-.equ	PB1	= 1	; For compatibility
-.equ	PORTB2	= 2	; Port B Data Register bit 2
-.equ	PB2	= 2	; For compatibility
-.equ	PORTB3	= 3	; Port B Data Register bit 3
-.equ	PB3	= 3	; For compatibility
-.equ	PORTB4	= 4	; Port B Data Register bit 4
-.equ	PB4	= 4	; For compatibility
-.equ	PORTB5	= 5	; Port B Data Register bit 5
-.equ	PB5	= 5	; For compatibility
-.equ	PORTB6	= 6	; Port B Data Register bit 6
-.equ	PB6	= 6	; For compatibility
-.equ	PORTB7	= 7	; Port B Data Register bit 7
-.equ	PB7	= 7	; For compatibility
-
-; DDRB - Port B Data Direction Register
-.equ	DDB0	= 0	; Port B Data Direction Register bit 0
-.equ	DDB1	= 1	; Port B Data Direction Register bit 1
-.equ	DDB2	= 2	; Port B Data Direction Register bit 2
-.equ	DDB3	= 3	; Port B Data Direction Register bit 3
-.equ	DDB4	= 4	; Port B Data Direction Register bit 4
-.equ	DDB5	= 5	; Port B Data Direction Register bit 5
-.equ	DDB6	= 6	; Port B Data Direction Register bit 6
-.equ	DDB7	= 7	; Port B Data Direction Register bit 7
-
-; PINB - Port B Input Pins
-.equ	PINB0	= 0	; Port B Input Pins bit 0
-.equ	PINB1	= 1	; Port B Input Pins bit 1
-.equ	PINB2	= 2	; Port B Input Pins bit 2
-.equ	PINB3	= 3	; Port B Input Pins bit 3
-.equ	PINB4	= 4	; Port B Input Pins bit 4
-.equ	PINB5	= 5	; Port B Input Pins bit 5
-.equ	PINB6	= 6	; Port B Input Pins bit 6
-.equ	PINB7	= 7	; Port B Input Pins bit 7
-
-
-; ***** PORTC ************************
-; PORTC - Port C Data Register
-.equ	PORTC0	= 0	; Port C Data Register bit 0
-.equ	PC0	= 0	; For compatibility
-.equ	PORTC1	= 1	; Port C Data Register bit 1
-.equ	PC1	= 1	; For compatibility
-.equ	PORTC2	= 2	; Port C Data Register bit 2
-.equ	PC2	= 2	; For compatibility
-.equ	PORTC3	= 3	; Port C Data Register bit 3
-.equ	PC3	= 3	; For compatibility
-.equ	PORTC4	= 4	; Port C Data Register bit 4
-.equ	PC4	= 4	; For compatibility
-.equ	PORTC5	= 5	; Port C Data Register bit 5
-.equ	PC5	= 5	; For compatibility
-.equ	PORTC6	= 6	; Port C Data Register bit 6
-.equ	PC6	= 6	; For compatibility
-
-; DDRC - Port C Data Direction Register
-.equ	DDC0	= 0	; Port C Data Direction Register bit 0
-.equ	DDC1	= 1	; Port C Data Direction Register bit 1
-.equ	DDC2	= 2	; Port C Data Direction Register bit 2
-.equ	DDC3	= 3	; Port C Data Direction Register bit 3
-.equ	DDC4	= 4	; Port C Data Direction Register bit 4
-.equ	DDC5	= 5	; Port C Data Direction Register bit 5
-.equ	DDC6	= 6	; Port C Data Direction Register bit 6
-
-; PINC - Port C Input Pins
-.equ	PINC0	= 0	; Port C Input Pins bit 0
-.equ	PINC1	= 1	; Port C Input Pins bit 1
-.equ	PINC2	= 2	; Port C Input Pins bit 2
-.equ	PINC3	= 3	; Port C Input Pins bit 3
-.equ	PINC4	= 4	; Port C Input Pins bit 4
-.equ	PINC5	= 5	; Port C Input Pins bit 5
-.equ	PINC6	= 6	; Port C Input Pins bit 6
-
-
-; ***** PORTD ************************
-; PORTD - Port D Data Register
-.equ	PORTD0	= 0	; Port D Data Register bit 0
-.equ	PD0	= 0	; For compatibility
-.equ	PORTD1	= 1	; Port D Data Register bit 1
-.equ	PD1	= 1	; For compatibility
-.equ	PORTD2	= 2	; Port D Data Register bit 2
-.equ	PD2	= 2	; For compatibility
-.equ	PORTD3	= 3	; Port D Data Register bit 3
-.equ	PD3	= 3	; For compatibility
-.equ	PORTD4	= 4	; Port D Data Register bit 4
-.equ	PD4	= 4	; For compatibility
-.equ	PORTD5	= 5	; Port D Data Register bit 5
-.equ	PD5	= 5	; For compatibility
-.equ	PORTD6	= 6	; Port D Data Register bit 6
-.equ	PD6	= 6	; For compatibility
-.equ	PORTD7	= 7	; Port D Data Register bit 7
-.equ	PD7	= 7	; For compatibility
-
-; DDRD - Port D Data Direction Register
-.equ	DDD0	= 0	; Port D Data Direction Register bit 0
-.equ	DDD1	= 1	; Port D Data Direction Register bit 1
-.equ	DDD2	= 2	; Port D Data Direction Register bit 2
-.equ	DDD3	= 3	; Port D Data Direction Register bit 3
-.equ	DDD4	= 4	; Port D Data Direction Register bit 4
-.equ	DDD5	= 5	; Port D Data Direction Register bit 5
-.equ	DDD6	= 6	; Port D Data Direction Register bit 6
-.equ	DDD7	= 7	; Port D Data Direction Register bit 7
-
-; PIND - Port D Input Pins
-.equ	PIND0	= 0	; Port D Input Pins bit 0
-.equ	PIND1	= 1	; Port D Input Pins bit 1
-.equ	PIND2	= 2	; Port D Input Pins bit 2
-.equ	PIND3	= 3	; Port D Input Pins bit 3
-.equ	PIND4	= 4	; Port D Input Pins bit 4
-.equ	PIND5	= 5	; Port D Input Pins bit 5
-.equ	PIND6	= 6	; Port D Input Pins bit 6
-.equ	PIND7	= 7	; Port D Input Pins bit 7
-
-
-; ***** TIMER_COUNTER_0 **************
-; TIMSK0 - Timer/Counter0 Interrupt Mask Register
-.equ	TOIE0	= 0	; Timer/Counter0 Overflow Interrupt Enable
-.equ	OCIE0A	= 1	; Timer/Counter0 Output Compare Match A Interrupt Enable
-.equ	OCIE0B	= 2	; Timer/Counter0 Output Compare Match B Interrupt Enable
-
-; TIFR0 - Timer/Counter0 Interrupt Flag register
-.equ	TOV0	= 0	; Timer/Counter0 Overflow Flag
-.equ	OCF0A	= 1	; Timer/Counter0 Output Compare Flag 0A
-.equ	OCF0B	= 2	; Timer/Counter0 Output Compare Flag 0B
-
-; TCCR0A - Timer/Counter  Control Register A
-.equ	WGM00	= 0	; Waveform Generation Mode
-.equ	WGM01	= 1	; Waveform Generation Mode
-.equ	COM0B0	= 4	; Compare Output Mode, Fast PWm
-.equ	COM0B1	= 5	; Compare Output Mode, Fast PWm
-.equ	COM0A0	= 6	; Compare Output Mode, Phase Correct PWM Mode
-.equ	COM0A1	= 7	; Compare Output Mode, Phase Correct PWM Mode
-
-; TCCR0B - Timer/Counter Control Register B
-.equ	CS00	= 0	; Clock Select
-.equ	CS01	= 1	; Clock Select
-.equ	CS02	= 2	; Clock Select
-.equ	WGM02	= 3	; 
-.equ	FOC0B	= 6	; Force Output Compare B
-.equ	FOC0A	= 7	; Force Output Compare A
-
-; TCNT0 - Timer/Counter0
-.equ	TCNT0_0	= 0	; 
-.equ	TCNT0_1	= 1	; 
-.equ	TCNT0_2	= 2	; 
-.equ	TCNT0_3	= 3	; 
-.equ	TCNT0_4	= 4	; 
-.equ	TCNT0_5	= 5	; 
-.equ	TCNT0_6	= 6	; 
-.equ	TCNT0_7	= 7	; 
-
-; OCR0A - Timer/Counter0 Output Compare Register
-.equ	OCROA_0	= 0	; 
-.equ	OCROA_1	= 1	; 
-.equ	OCROA_2	= 2	; 
-.equ	OCROA_3	= 3	; 
-.equ	OCROA_4	= 4	; 
-.equ	OCROA_5	= 5	; 
-.equ	OCROA_6	= 6	; 
-.equ	OCROA_7	= 7	; 
-
-; OCR0B - Timer/Counter0 Output Compare Register
-.equ	OCR0B_0	= 0	; 
-.equ	OCR0B_1	= 1	; 
-.equ	OCR0B_2	= 2	; 
-.equ	OCR0B_3	= 3	; 
-.equ	OCR0B_4	= 4	; 
-.equ	OCR0B_5	= 5	; 
-.equ	OCR0B_6	= 6	; 
-.equ	OCR0B_7	= 7	; 
-
-; GTCCR - General Timer/Counter Control Register
-;.equ	PSRSYNC	= 0	; Prescaler Reset Timer/Counter1 and Timer/Counter0
-.equ	PSR10	= PSRSYNC	; For compatibility
-;.equ	TSM	= 7	; Timer/Counter Synchronization Mode
-
-
-; ***** EXTERNAL_INTERRUPT ***********
-; EICRA - External Interrupt Control Register
-.equ	ISC00	= 0	; External Interrupt Sense Control 0 Bit 0
-.equ	ISC01	= 1	; External Interrupt Sense Control 0 Bit 1
-.equ	ISC10	= 2	; External Interrupt Sense Control 1 Bit 0
-.equ	ISC11	= 3	; External Interrupt Sense Control 1 Bit 1
-
-; EIMSK - External Interrupt Mask Register
-.equ	INT0	= 0	; External Interrupt Request 0 Enable
-.equ	INT1	= 1	; External Interrupt Request 1 Enable
-
-; EIFR - External Interrupt Flag Register
-.equ	INTF0	= 0	; External Interrupt Flag 0
-.equ	INTF1	= 1	; External Interrupt Flag 1
-
-; PCMSK2 - Pin Change Mask Register 2
-.equ	PCINT16	= 0	; Pin Change Enable Mask 16
-.equ	PCINT17	= 1	; Pin Change Enable Mask 17
-.equ	PCINT18	= 2	; Pin Change Enable Mask 18
-.equ	PCINT19	= 3	; Pin Change Enable Mask 19
-.equ	PCINT20	= 4	; Pin Change Enable Mask 20
-.equ	PCINT21	= 5	; Pin Change Enable Mask 21
-.equ	PCINT22	= 6	; Pin Change Enable Mask 22
-.equ	PCINT23	= 7	; Pin Change Enable Mask 23
-
-; PCMSK1 - Pin Change Mask Register 1
-.equ	PCINT8	= 0	; Pin Change Enable Mask 8
-.equ	PCINT9	= 1	; Pin Change Enable Mask 9
-.equ	PCINT10	= 2	; Pin Change Enable Mask 10
-.equ	PCINT11	= 3	; Pin Change Enable Mask 11
-.equ	PCINT12	= 4	; Pin Change Enable Mask 12
-.equ	PCINT13	= 5	; Pin Change Enable Mask 13
-.equ	PCINT14	= 6	; Pin Change Enable Mask 14
-
-; PCMSK0 - Pin Change Mask Register 0
-.equ	PCINT0	= 0	; Pin Change Enable Mask 0
-.equ	PCINT1	= 1	; Pin Change Enable Mask 1
-.equ	PCINT2	= 2	; Pin Change Enable Mask 2
-.equ	PCINT3	= 3	; Pin Change Enable Mask 3
-.equ	PCINT4	= 4	; Pin Change Enable Mask 4
-.equ	PCINT5	= 5	; Pin Change Enable Mask 5
-.equ	PCINT6	= 6	; Pin Change Enable Mask 6
-.equ	PCINT7	= 7	; Pin Change Enable Mask 7
-
-; PCIFR - Pin Change Interrupt Flag Register
-.equ	PCIF0	= 0	; Pin Change Interrupt Flag 0
-.equ	PCIF1	= 1	; Pin Change Interrupt Flag 1
-.equ	PCIF2	= 2	; Pin Change Interrupt Flag 2
-
-
-; ***** SPI **************************
-; SPDR - SPI Data Register
-.equ	SPDR0	= 0	; SPI Data Register bit 0
-.equ	SPDR1	= 1	; SPI Data Register bit 1
-.equ	SPDR2	= 2	; SPI Data Register bit 2
-.equ	SPDR3	= 3	; SPI Data Register bit 3
-.equ	SPDR4	= 4	; SPI Data Register bit 4
-.equ	SPDR5	= 5	; SPI Data Register bit 5
-.equ	SPDR6	= 6	; SPI Data Register bit 6
-.equ	SPDR7	= 7	; SPI Data Register bit 7
-
-; SPSR - SPI Status Register
-.equ	SPI2X	= 0	; Double SPI Speed Bit
-.equ	WCOL	= 6	; Write Collision Flag
-.equ	SPIF	= 7	; SPI Interrupt Flag
-
-; SPCR - SPI Control Register
-.equ	SPR0	= 0	; SPI Clock Rate Select 0
-.equ	SPR1	= 1	; SPI Clock Rate Select 1
-.equ	CPHA	= 2	; Clock Phase
-.equ	CPOL	= 3	; Clock polarity
-.equ	MSTR	= 4	; Master/Slave Select
-.equ	DORD	= 5	; Data Order
-.equ	SPE	= 6	; SPI Enable
-.equ	SPIE	= 7	; SPI Interrupt Enable
-
-
-; ***** CPU **************************
-; SREG - Status Register
-.equ	SREG_C	= 0	; Carry Flag
-.equ	SREG_Z	= 1	; Zero Flag
-.equ	SREG_N	= 2	; Negative Flag
-.equ	SREG_V	= 3	; Two's Complement Overflow Flag
-.equ	SREG_S	= 4	; Sign Bit
-.equ	SREG_H	= 5	; Half Carry Flag
-.equ	SREG_T	= 6	; Bit Copy Storage
-.equ	SREG_I	= 7	; Global Interrupt Enable
-
-; OSCCAL - Oscillator Calibration Value
-.equ	CAL0	= 0	; Oscillator Calibration Value Bit0
-.equ	CAL1	= 1	; Oscillator Calibration Value Bit1
-.equ	CAL2	= 2	; Oscillator Calibration Value Bit2
-.equ	CAL3	= 3	; Oscillator Calibration Value Bit3
-.equ	CAL4	= 4	; Oscillator Calibration Value Bit4
-.equ	CAL5	= 5	; Oscillator Calibration Value Bit5
-.equ	CAL6	= 6	; Oscillator Calibration Value Bit6
-.equ	CAL7	= 7	; Oscillator Calibration Value Bit7
-
-; CLKPR - Clock Prescale Register
-.equ	CLKPS0	= 0	; Clock Prescaler Select Bit 0
-.equ	CLKPS1	= 1	; Clock Prescaler Select Bit 1
-.equ	CLKPS2	= 2	; Clock Prescaler Select Bit 2
-.equ	CLKPS3	= 3	; Clock Prescaler Select Bit 3
-.equ	CLKPCE	= 7	; Clock Prescaler Change Enable
-
-; SPMCSR - Store Program Memory Control Register
-.equ	SELFPRGEN	= 0	; Self Programming Enable
-.equ	PGERS	= 1	; Page Erase
-.equ	PGWRT	= 2	; Page Write
-.equ	BLBSET	= 3	; Boot Lock Bit Set
-.equ	RWWSRE	= 4	; Read-While-Write section read enable
-.equ	RWWSB	= 6	; Read-While-Write Section Busy
-.equ	SPMIE	= 7	; SPM Interrupt Enable
-
-; MCUCR - MCU Control Register
-.equ	IVCE	= 0	; 
-.equ	IVSEL	= 1	; 
-.equ	PUD	= 4	; 
-
-; MCUSR - MCU Status Register
-.equ	PORF	= 0	; Power-on reset flag
-.equ	EXTRF	= 1	; External Reset Flag
-.equ	EXTREF	= EXTRF	; For compatibility
-.equ	BORF	= 2	; Brown-out Reset Flag
-.equ	WDRF	= 3	; Watchdog Reset Flag
-
-; SMCR - 
-.equ	SE	= 0	; 
-.equ	SM0	= 1	; 
-.equ	SM1	= 2	; 
-.equ	SM2	= 3	; 
-
-; GPIOR2 - General Purpose I/O Register 2
-.equ	GPIOR20	= 0	; 
-.equ	GPIOR21	= 1	; 
-.equ	GPIOR22	= 2	; 
-.equ	GPIOR23	= 3	; 
-.equ	GPIOR24	= 4	; 
-.equ	GPIOR25	= 5	; 
-.equ	GPIOR26	= 6	; 
-.equ	GPIOR27	= 7	; 
-
-; GPIOR1 - General Purpose I/O Register 1
-.equ	GPIOR10	= 0	; 
-.equ	GPIOR11	= 1	; 
-.equ	GPIOR12	= 2	; 
-.equ	GPIOR13	= 3	; 
-.equ	GPIOR14	= 4	; 
-.equ	GPIOR15	= 5	; 
-.equ	GPIOR16	= 6	; 
-.equ	GPIOR17	= 7	; 
-
-; GPIOR0 - General Purpose I/O Register 0
-.equ	GPIOR00	= 0	; 
-.equ	GPIOR01	= 1	; 
-.equ	GPIOR02	= 2	; 
-.equ	GPIOR03	= 3	; 
-.equ	GPIOR04	= 4	; 
-.equ	GPIOR05	= 5	; 
-.equ	GPIOR06	= 6	; 
-.equ	GPIOR07	= 7	; 
-
-; PRR - Power Reduction Register
-.equ	PRADC	= 0	; Power Reduction ADC
-.equ	PRUSART0	= 1	; Power Reduction USART
-.equ	PRSPI	= 2	; Power Reduction Serial Peripheral Interface
-.equ	PRTIM1	= 3	; Power Reduction Timer/Counter1
-.equ	PRTIM0	= 5	; Power Reduction Timer/Counter0
-.equ	PRTIM2	= 6	; Power Reduction Timer/Counter2
-.equ	PRTWI	= 7	; Power Reduction TWI
-
-; PCICR - 
-.equ	PCIE0	= 0	; 
-.equ	PCIE1	= 1	; 
-.equ	PCIE2	= 2	; 
-
-
-; ***** WATCHDOG *********************
-; WDTCSR - Watchdog Timer Control Register
-.equ	WDP0	= 0	; Watch Dog Timer Prescaler bit 0
-.equ	WDP1	= 1	; Watch Dog Timer Prescaler bit 1
-.equ	WDP2	= 2	; Watch Dog Timer Prescaler bit 2
-.equ	WDE	= 3	; Watch Dog Enable
-.equ	WDCE	= 4	; Watchdog Change Enable
-.equ	WDP3	= 5	; Watchdog Timer Prescaler Bit 3
-.equ	WDIE	= 6	; Watchdog Timeout Interrupt Enable
-.equ	WDIF	= 7	; Watchdog Timeout Interrupt Flag
-
-
-; ***** EEPROM ***********************
-; EEARL - EEPROM Address Register Low Byte
-.equ	EEAR0	= 0	; EEPROM Read/Write Access Bit 0
-.equ	EEAR1	= 1	; EEPROM Read/Write Access Bit 1
-.equ	EEAR2	= 2	; EEPROM Read/Write Access Bit 2
-.equ	EEAR3	= 3	; EEPROM Read/Write Access Bit 3
-.equ	EEAR4	= 4	; EEPROM Read/Write Access Bit 4
-.equ	EEAR5	= 5	; EEPROM Read/Write Access Bit 5
-.equ	EEAR6	= 6	; EEPROM Read/Write Access Bit 6
-.equ	EEAR7	= 7	; EEPROM Read/Write Access Bit 7
-
-; EEARH - EEPROM Address Register High Byte
-.equ	EEAR8	= 0	; EEPROM Read/Write Access Bit 0
-
-; EEDR - EEPROM Data Register
-.equ	EEDR0	= 0	; EEPROM Data Register bit 0
-.equ	EEDR1	= 1	; EEPROM Data Register bit 1
-.equ	EEDR2	= 2	; EEPROM Data Register bit 2
-.equ	EEDR3	= 3	; EEPROM Data Register bit 3
-.equ	EEDR4	= 4	; EEPROM Data Register bit 4
-.equ	EEDR5	= 5	; EEPROM Data Register bit 5
-.equ	EEDR6	= 6	; EEPROM Data Register bit 6
-.equ	EEDR7	= 7	; EEPROM Data Register bit 7
-
-; EECR - EEPROM Control Register
-.equ	EERE	= 0	; EEPROM Read Enable
-.equ	EEPE	= 1	; EEPROM Write Enable
-.equ	EEMPE	= 2	; EEPROM Master Write Enable
-.equ	EERIE	= 3	; EEPROM Ready Interrupt Enable
-.equ	EEPM0	= 4	; EEPROM Programming Mode Bit 0
-.equ	EEPM1	= 5	; EEPROM Programming Mode Bit 1
-
-
-
-; ***** LOCKSBITS ********************************************************
-.equ	LB1	= 0	; Lock bit
-.equ	LB2	= 1	; Lock bit
-.equ	BLB01	= 2	; Boot Lock bit
-.equ	BLB02	= 3	; Boot Lock bit
-.equ	BLB11	= 4	; Boot lock bit
-.equ	BLB12	= 5	; Boot lock bit
-
-
-; ***** FUSES ************************************************************
-; LOW fuse bits
-.equ	CKSEL0	= 0	; Select Clock Source
-.equ	CKSEL1	= 1	; Select Clock Source
-.equ	CKSEL2	= 2	; Select Clock Source
-.equ	CKSEL3	= 3	; Select Clock Source
-.equ	SUT0	= 4	; Select start-up time
-.equ	SUT1	= 5	; Select start-up time
-.equ	CKOUT	= 6	; Clock output
-.equ	CKDIV8	= 7	; Divide clock by 8
-
-; HIGH fuse bits
-.equ	BODLEVEL0	= 0	; Brown-out Detector trigger level
-.equ	BODLEVEL1	= 1	; Brown-out Detector trigger level
-.equ	BODLEVEL2	= 2	; Brown-out Detector trigger level
-.equ	EESAVE	= 3	; EEPROM memory is preserved through chip erase
-.equ	WDTON	= 4	; Watchdog Timer Always On
-.equ	SPIEN	= 5	; Enable Serial programming and Data Downloading
-.equ	DWEN	= 6	; debugWIRE Enable
-.equ	RSTDISBL	= 7	; External reset disable
-
-; EXTENDED fuse bits
-.equ	BOOTRST	= 0	; Select reset vector
-.equ	BOOTSZ0	= 1	; Select boot size
-.equ	BOOTSZ1	= 2	; Select boot size
-
-
-
-; ***** CPU REGISTER DEFINITIONS *****************************************
-.def	XH	= r27
-.def	XL	= r26
-.def	YH	= r29
-.def	YL	= r28
-.def	ZH	= r31
-.def	ZL	= r30
-
-
-
-; ***** DATA MEMORY DECLARATIONS *****************************************
-.equ	FLASHEND	= 0x1fff	; Note: Word address
-.equ	IOEND	= 0x00ff
-.equ	SRAM_START	= 0x0100
-.equ	SRAM_SIZE	= 1024
-.equ	RAMEND	= 0x04ff
-.equ	XRAMEND	= 0x0000
-.equ	E2END	= 0x01ff
-.equ	EEPROMEND	= 0x01ff
-.equ	EEADRBITS	= 9
-; #pragma AVRPART MEMORY PROG_FLASH 16384
-; #pragma AVRPART MEMORY EEPROM 512
-; #pragma AVRPART MEMORY INT_SRAM SIZE 1024
-; #pragma AVRPART MEMORY INT_SRAM START_ADDR 0x100
-
-
-
-; ***** BOOTLOADER DECLARATIONS ******************************************
-.equ	NRWW_START_ADDR	= 0x1c00
-.equ	NRWW_STOP_ADDR	= 0x1fff
-.equ	RWW_START_ADDR	= 0x0
-.equ	RWW_STOP_ADDR	= 0x1bff
-.equ	PAGESIZE	= 64
-.equ	FIRSTBOOTSTART	= 0x1f80
-.equ	SECONDBOOTSTART	= 0x1f00
-.equ	THIRDBOOTSTART	= 0x1e00
-.equ	FOURTHBOOTSTART	= 0x1c00
-.equ	SMALLBOOTSTART	= FIRSTBOOTSTART
-.equ	LARGEBOOTSTART	= FOURTHBOOTSTART
-
-
-
-; ***** INTERRUPT VECTORS ************************************************
-.equ	INT0addr	= 0x0002	; External Interrupt Request 0
-.equ	INT1addr	= 0x0004	; External Interrupt Request 1
-.equ	PCI0addr	= 0x0006	; Pin Change Interrupt Request 0
-.equ	PCI1addr	= 0x0008	; Pin Change Interrupt Request 0
-.equ	PCI2addr	= 0x000a	; Pin Change Interrupt Request 1
-.equ	WDTaddr	= 0x000c	; Watchdog Time-out Interrupt
-.equ	OC2Aaddr	= 0x000e	; Timer/Counter2 Compare Match A
-.equ	OC2Baddr	= 0x0010	; Timer/Counter2 Compare Match A
-.equ	OVF2addr	= 0x0012	; Timer/Counter2 Overflow
-.equ	ICP1addr	= 0x0014	; Timer/Counter1 Capture Event
-.equ	OC1Aaddr	= 0x0016	; Timer/Counter1 Compare Match A
-.equ	OC1Baddr	= 0x0018	; Timer/Counter1 Compare Match B
-.equ	OVF1addr	= 0x001a	; Timer/Counter1 Overflow
-.equ	OC0Aaddr	= 0x001c	; TimerCounter0 Compare Match A
-.equ	OC0Baddr	= 0x001e	; TimerCounter0 Compare Match B
-.equ	OVF0addr	= 0x0020	; Timer/Couner0 Overflow
-.equ	SPIaddr	= 0x0022	; SPI Serial Transfer Complete
-.equ	URXCaddr	= 0x0024	; USART Rx Complete
-.equ	UDREaddr	= 0x0026	; USART, Data Register Empty
-.equ	UTXCaddr	= 0x0028	; USART Tx Complete
-.equ	ADCCaddr	= 0x002a	; ADC Conversion Complete
-.equ	ERDYaddr	= 0x002c	; EEPROM Ready
-.equ	ACIaddr	= 0x002e	; Analog Comparator
-.equ	TWIaddr	= 0x0030	; Two-wire Serial Interface
-.equ	SPMRaddr	= 0x0032	; Store Program Memory Read
-
-.equ	INT_VECTORS_SIZE	= 52	; size in words
-
-; #endif  /* _M168DEF_INC_ */
-
-; ***** END OF FILE ******************************************************
--- a/macros.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-; XXX: stupid thing won't parse, and it's right from the README example...
-; .ifndef _MACROS_INC_
-; .define _MACROS_INC_
-
-;; Store to memory address
-.macro poke
-		.message	"No parameters"
-.endm
-
-.macro poke_i_8_i
-		ldi			@1, @2
-		sts			@0, @1
-.endm
-
-.macro poke_i_16_i
-		ldi			@1, low(@3)
-		sts			@0+0, @1
-		
-		ldi			@2, high(@3)
-		sts			@0+1, @2
-.endm
-
-; .endif
--- a/matrix.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,461 +0,0 @@
-;; LED Matrix driver
-;; vim: set ft=avr:
-
-.dseg
-;; I/O addresses
-; Control port
-.set MATRIX_DDR = DDRB
-.set MATRIX_PORT = PORTB
-
-; Pin for matrix driver Output Enable
-.set MATRIX_OE = PORTB1		; Output Enable, active low, externally pulled high
-
-;; Matrix properties
-; Matrix width in columns
-.set MATRIX_COLS = 8                        ; physical columns
-
-; Framebuffer width in columns
-.set MATRIX_BUF_COLS = 16		            ; framebuffer columns
-
-;; SPI addresses
-; row drivers (8 bits)
-.set MATRIX_SPI_ROW = 0                     ; row mask source
-
-; column sinks (8 bits)
-.set MATRIX_SPI_COL = 1                     ; column scan sink
-
-;; Matrix state
-; Matrix framebuffer
-; this holds the columns data as a 1 byte bitmask of row data per column (8 bits -> 8 rows)
-matrix_colbuf:	    .byte MATRIX_BUF_COLS   ; framebuffer (row data by column)
-
-; Column scan bit
-; in the matrix refresh loop, we push out each column's row data in turn
-; this bit tracks the currently refreshing column
-matrix_colbit:	    .byte 1                 ; column scan bit
-
-; Matrix viewport offset
-; the visible matrix data is taken directly from the framebuffer, but it can be taken at an arbitrary offset
-; this determines the starting offset for the visible viewport's left edge from the start of the framebuffer in columns
-matrix_colshift:    .byte 1                 ; viewport left column offset
-
-;; Text
-; Maximum length of message
-.set TEXT_MAXLENGTH = 64
-
-; Scrolling speed (kiloticks per frame)
-.set TEXT_SPEED = 1
-
-text_buffer:        .byte TEXT_MAXLENGTH    ; display message buffer
-text_offset:        .byte 1                 ; current offset in text
-
-.cseg
-
-;; Normalize the outputs, enable the matrix, and set up buffers
-Matrix_Init:
-    ; Setup ENable port
-        sbi         MATRIX_PORT, MATRIX_OE	; high -> disabled
-        sbi         MATRIX_DDR, MATRIX_OE	; out
- 
-	; blank hardware
-		ldi			r16, 0
-
-		sts			spi_outbuf + 0, r16		; column sinks
-		sts			spi_outbuf + 1, r16		; row drivers
-
-	; write out
-		rcall		SPI_SendRecv
-
-	; enable
-		cbi			MATRIX_PORT, MATRIX_OE	; low -> enabled
-
-	; init buffers
-		ldi			r16, 0b1
-		sts			matrix_colbit, r16
-
-        ldi         r16, 0
-        sts         matrix_colshift, r16
-
-		ldi			r16, 0
-		ldi			r17, MATRIX_BUF_COLS
-		ldi			YL, low(matrix_colbuf)
-		ldi			YH, high(matrix_colbuf)
-
-m_init_mzero:
-		st			Y+, r16
-		
-		; loop until zero
-		dec			r17
-		brne		m_init_mzero
-
-	; Use Timer0, 32k cycles -> 500Hz scan rate
-		ldi			r16, 32
-		rcall		Timer0_Start
-
-	; done
-		ret
-
-;; Scan the matrix's next column from the viewport
-;;  Interrupt-driven
-Matrix_ScanCol:
-    ; Save registers
-        push        r16
-        push        r17
-
-	; Column bit
-		; load
-		lds			r16, matrix_colbit
-	
-		; start packet
-        cbi         SPI_PORT, SPI_SS
-
-		; output single column-enable bit
-		out			SPDR, r16
-
-	; Compute col index
-		ldi			r17, 0
-
-m_sc_colidx:
-		; shift
-		lsr			r16
-
-		; done if we shifted the bit out
-		brcs		m_sc_row
-
-		; count shifts
-		inc			r17
-		rjmp		m_sc_colidx
-
-m_sc_row:
-    ; Column shift
-        ; load
-        lds         r16, matrix_colshift
-
-        ; add to col index
-        add         r17, r16
-
-	; Row mask
-		; base
-		ldi			XL, low(matrix_colbuf)
-		ldi			XH, high(matrix_colbuf)
-
-		; offset
-		ldi			r16, 0
-
-		add			XL, r17
-		adc			XH, r16
-
-		; load
-		ld			r16, X
-
-		; output full row-enable bitmask
-		rcall		SPI_Wait
-		out			SPDR, r16
-
-	; Update col bit
-		lds			r16, matrix_colbit
-	
-		; shift left
-		lsl			r16
-		brcc		m_sc_colout
-
-		; overflow, take bit from C
-		rol			r16
-
-m_sc_colout:
-		; store
-		sts			matrix_colbit, r16
-
-	; End of packet
-		rcall		SPI_Wait
-        sbi         SPI_PORT, SPI_SS
-
-	; Done
-        pop         r17
-        pop         r16
-
-		ret
-
-;; Scan the matrix once in one go
-;; XXX: doesn't support colshift
-Matrix_ScanFull:
-	; Row index
-		ldi			ZL, low(matrix_colbuf)
-		ldi			ZH, high(matrix_colbuf)
-
-	; Column bit
-		ldi			r25, 0
-		sec								; set C
-		
-m_pulse_col:
-		; rotate bit left from C
-		rol			r25
-		
-		; overflow
-		brcs		m_pulse_end
-		
-		; store in output buffer
-		sts			spi_outbuf + 1, r25
-
-	; Row mask
-		ld			r16, Z+
-
-		sts			spi_outbuf + 0, r16
-
-	; Display
-		rcall		SPI_SendRecv
-
-	; Next column
-		rjmp		m_pulse_col
-
-m_pulse_end:
-	; Done
-		ret
-
-;; Reset the viewport to the start (left edge) of the framebuffer
-Matrix_ShiftZero:
-    ; Constant offset
-        ldi         r16, 0
-
-    ; Set
-        rjmp        Matrix_ShiftSet
-
-;; Shift the viewport one column to the left in the framebuffer, looping around to the end of the framebuffer
-; This moves the visible output one column to the right
-Matrix_ShiftLeft:
-    ; Decrement-loop current value
-        ; current value
-        lds         r16, matrix_colshift
-
-        ; shift window left
-        dec         r16
-
-        ; test for underflow (MSB/N set) -> don't skip reset
-        brpl        Matrix_ShiftSet
-
-        ; reset window to right edge
-        ldi         r16, MATRIX_BUF_COLS - MATRIX_COLS
-
-    ; Set
-        rjmp        Matrix_ShiftSet
-
-;; Shift the viewport one column to the right in the framebuffer, looping around to the start of the FB
-; This moves the visible output one column to the left
-Matrix_ShiftRight:
-    ; Increment-loop current value
-        ; current value
-        lds         r16, matrix_colshift
-
-        ; shift window right
-        inc         r16
-
-        ; test for overflow -> don't skip reset
-        cpi         r16, MATRIX_BUF_COLS - MATRIX_COLS
-        brlt        Matrix_ShiftSet
-
-        ; reset window to left edge
-        ldi         r16, 0
-
-    ; Set
-        rjmp        Matrix_ShiftSet
-
-;; Set the matrix viewport offset
-;; Input: r16
-Matrix_ShiftSet:
-        ; store new value
-        sts         matrix_colshift, r16
-
-        ; done
-        ret
-
-;; Rewinds the currently visible viewport to the beginning of the framebuffer
-; This copies the currently visible viewport data to the beginning of the framebuffer and resets the offset
-Matrix_ShiftRewind:
-        ; current view offset
-        ldi         XL, low(matrix_colbuf)
-        ldi         XH, high(matrix_colbuf)
-
-        ; offset
-        lds         r16, matrix_colshift
-
-        ; add
-        ldi         r17, 0
-        add         XL, r16
-        adc         XH, r17
-
-        ; start of framebuffer
-        ldi         YL, low(matrix_colbuf + 0)
-        ldi         YH, high(matrix_colbuf + 0)
-
-        ; viewport width
-        ldi         r17, MATRIX_COLS
-
-matrix_shiftrew_loop:
-        ; copy
-        ld          r16, X+
-        st          Y+, r16
-
-        ; count
-        dec         r17
-        brne        matrix_shiftrew_loop
-
-        ; done, reset offset
-        rjmp        MAtrix_ShiftZero
-
-
-;; Load a NUL-terminated ASCII string from PGM into the text buffer
-; Input:    Z       - Address of NUL-terminated ASCII string in PGM        
-Text_LoadString:
-    ; Setup
-        ; storage buffer
-        ldi         YL, low(text_buffer)
-        ldi         YH, high(text_buffer)
-
-        ; max. length
-        ldi         r18, TEXT_MAXLENGTH
-
-text_loads_loop:
-    ; Test max length
-        ; count and check for overflow
-        dec         r18
-        brne        text_loads_char
-
-    ; Load char
-        ; force NUL
-        ldi         r16, 0x00
-
-text_loads_char:
-        ; load next char
-        lpm         r16, Z+
-
-text_loads_store:
-    ; Store and test NUL
-        ; store it
-        st          Y+, r16
-
-        ; test for NUL
-        tst         r16
-        brne        text_loads_loop
-
-    ; Update scroll offset
-        ; reset offset
-        ldi         r17, 0
-        sts         text_offset, r17
-
-        ; done
-        ret
-
-;; Shows the loaded string of ASCII text on the display, scrolling it horizontally
-; Uses font.inc for rendering
-; XXX: uses blocking timer sleeps and doesn't return until done
-Text_ShowString:
-    ; Load initial char
-        ldi         XL, low(text_buffer + 0)
-        ldi         XH, high(text_buffer + 0)
-
-        ; load char
-        ld          r16, X+
-        push        XL
-        push        XH
-
-        ; one column spacing
-        ldi         YL, low(matrix_colbuf + 1)
-        ldi         YH, high(matrix_colbuf + 1)
-
-        ; render to framebuffer
-        rcall       Font_Render
-
-        ; reset viewport
-        rcall       Matrix_ShiftZero
-       
-   ; Load next char
-text_shows_next:        
-        ; next char
-        pop         XH
-        pop         XL
-        ld          r16, X+
-        push        XL
-        push        XH
-
-        ; test NUL
-        tst         r16
-        breq        text_shows_end
-
-        ; offscreen
-        ldi         YL, low(matrix_colbuf + 1 + 6 + 1)
-        ldi         YH, high(matrix_colbuf + 1 + 6 + 1)
-
-        ; render
-        rcall       Font_Render
-
-    ; Animate to next char
-        ldi         r20, 7
-        
-text_shows_animloop:
-        ; sleep
-        ldi         XH, high(TEXT_SPEED * 1024)
-        ldi         XL, low(TEXT_SPEED * 1024)
-
-        rcall       Timer_Sleep
-
-        ; shift
-        rcall       Matrix_ShiftRight
-
-        ; count
-        dec         r20
-        brne        text_shows_animloop
-
-    ; Rewind to next char
-        rcall       Matrix_ShiftRewind
-
-        sbi         PIND, PIND7
-
-        ; load next char and animate it in
-        rjmp        text_shows_next
-
-text_shows_end:
-    ; Done
-        pop         XH
-        pop         XL
-
-
-    ; Clear second frame
-        ldi         YL, low(matrix_colbuf + 16)
-        ldi         YH, high(matrix_colbuf + 16)
-        ldi         r16, MATRIX_COLS
-        ldi         r17, 0
-
-text_shows_end2:        
-        st          -Y, r17
-
-        dec         r16
-        brne        text_shows_end2
-
-    ; Blink
-text_shows_end3:        
-        ; on
-        ldi         r16, 0
-        rcall       Matrix_ShiftSet
-
-        ; sleep
-        ldi         XH, high(TEXT_SPEED * 6 * 1024)
-        ldi         XL, low(TEXT_SPEED * 6 * 1024)
-
-        rcall       Timer_Sleep
-
-        ; off        
-        ldi         r16, 8
-        rcall       Matrix_ShiftSet
-
-        ; sleep
-        ldi         XH, high(TEXT_SPEED * 6 * 1024)
-        ldi         XL, low(TEXT_SPEED * 6 * 1024)
-
-        rcall       Timer_Sleep
-
-        ; loop
-        rjmp        text_shows_end3
-
-    ; XXX: end
-        ret
-
--- a/matrix.s	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,255 +0,0 @@
-;; vim: set ft=avr:
-
-.nolist
-.include "m168def.inc"      ; Same family as 328P
-.list
-
-
-;; Interrupt Vector
-.org 0x00
-        rjmp        init
-
-.org OC1Aaddr
-		; Timer/Counter1 Compare Output A
-		rjmp		Timer_OC1A
-
-.org OC0Aaddr
-        ; Timer/Counter0 Compare Output A
-        rjmp        Timer_OC0A
-
-.org SPIaddr
-        rjmp        SPI_Interrupt
-
-
-cseg0:         .org 0x40
-
-;; Syntax
-.include "macros.inc"
-
-;; SPI
-.include "spi.inc"
-
-;; Matrix
-.include "matrix.inc"
-
-;; Timer
-.set TIMER0_CB_A = Matrix_ScanCol
-
-.include "timer.inc"
-
-;; Utils
-.include "delay.inc"
-
-;; Font rendering
-.include "font.inc"
-
-;; Scan through each pixel
-Main_ScanRaw:
-	; init
-		ldi			r18, 1
-		ldi			r19, 1
-
-scan_loop:
-	; write out to SPI
-		sts			spi_outbuf + 0, r18		; rows
-		sts			spi_outbuf + 1, r19		; columns
-
-		rcall		SPI_SendRecv
-
-	; delay
-		ldi			r20, 5					; ~4M cycles
-		rcall		VarDelay
-
-	; cols
-		lsl			r19						; next col
-		brcc		scan_loop				; refresh if we didn't overflow
-		
-		rol			r19						; shift back from C into r21.0
-
-	; rows
-		lsl			r18						; next row
-		brcc		scan_loop				; refresh if we didn't overflow
-		
-		rol			r18						; shift back from C into r20.0
-
-	; one scan completed
-		ret
-
-;; Scan with test pattern
-Main_ScanTest:
-	; Generate pattern
-		; end of buffer
-		ldi			r17, MATRIX_BUF_COLS
-		ldi			XL, low(matrix_colbuf + MATRIX_BUF_COLS)
-		ldi			XH, high(matrix_colbuf + MATRIX_BUF_COLS)
-		
-		; bit pattern
-		ldi			r16, 0b11
-
-st_loop:
-		; put, pre-decrement
-		st			-X, r16
-
-		; flip
-		rol			r16
-		
-		; loop until zero	
-		dec			r17
-		brne		st_loop
-
-st_animate:
-	; Animate
-        ; shift right
-        rcall       Matrix_ShiftLeft
-
-        ; wait for X/16th of a second
-        ldi         XH, high(8 * 1024)
-        ldi         XL, low(8 * 1024)
-
-        rcall       Timer_Sleep
-
-        ; loop
-        rjmp        st_animate
-
-
-;; Display device code memory
-Main_ScanCode:
-    ; Code start
-        ldi         ZL, low(cseg0 * 2)      ; word addr
-        ldi         ZH, high(cseg0 * 2)     ; word addr
-    
-    ; Pause refresh
-        cli
-
-    ; Load initial frame
-        ; to first frame, starting from right edge
-        ldi         r17, 8
-		ldi			XL, low(matrix_colbuf + 16)
-		ldi			XH, high(matrix_colbuf + 16)
-
-sc_load_initial:
-        ; one byte
-        lpm         r16, Z+
-        st          -X, r16
-
-        ; loop until zero
-        dec         r17
-        brne        sc_load_initial
-
-        ; the first ShiftLeft below will jump to the end of the framebuffer
-
-sc_next:
-    ; Show this frame
-        rcall       Matrix_ShiftLeft
-
-    ; Load next frame
-        ldi         r17, 8
-        ldi         XL, low(matrix_colbuf + 8)
-        ldi         XH, high(matrix_colbuf + 8)
-
-sc_load_next:
-        ; one byte
-        lpm         r16, Z+
-        st          -X, r16
-
-        ; loop until zero
-        dec         r17
-        brne        sc_load_next
-
-    ; Enable refresh
-        sei
-
-    ; Animate from this -> next frame
-        ldi         r17, 8      ; 8 columns
-
-sc_anim:
-        ; wait for X/16th of a second
-        ldi         XH, high(2 * 1024)
-        ldi         XL, low(2 * 1024)
-
-        rcall       Timer_Sleep
-
-        ; shift
-        rcall       Matrix_ShiftLeft
-
-        ; loop until zero
-        dec         r17
-        brne        sc_anim
-
-    ; Pause refresh
-        cli
-
-    ; Move next -> this
-        ldi         r17, 8
-        ldi         XL, low(matrix_colbuf + 16)
-        ldi         XH, high(matrix_colbuf + 16)
-        ldi         YL, low(matrix_colbuf + 8)
-        ldi         YH, high(matrix_colbuf + 8)
-
-sc_move_this:
-        ; one byte
-        ld          r16, -Y
-        st          -X, r16
-
-        ; loop until zero
-        dec         r17
-        brne        sc_move_this
-
-sbi         PIND, PIND7
-
-    ; Load next frame, and animate
-        rjmp        sc_next
-
-Main_ScanText:
-
-    ; Constants
-stxt_message:       ; text to render
-        .db         0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x0 ; 'hello world!'
-
-    ; Load into buffer
-        ldi         ZL, low(stxt_message * 2)
-        ldi         ZH, high(stxt_message * 2)
-
-        rcall       Text_LoadString
-
-sbi         PORTD, PIND7
-
-    ; Display
-        rcall       Text_ShowString
-
-    ; Done
-        ret
-
-Main:
-init:
-    ; Stack
-        ldi         r16, high(RAMEND)
-        ldi         r17, low(RAMEND)
-        out         SPH, r16
-        out         SPL, r17
-
-    ; Enable interrupts
-        sei
-
-; DEBUG
-sbi			DDRD, PORTD7
-cbi			PORTD, PORTD7
-
-	; Timer
-		rcall		Timer_Init
-
-    ; SPI
-        rcall       SPI_Init
-
-	; Matrix
-		rcall		Matrix_Init	
-	
-    ; Run
-		; rcall		Main_ScanRaw
-		; rcall		Main_ScanTest
-        ; rcall       Main_ScanCode
-        rcall       Main_ScanText
-
-end:
-        rjmp        end
-
--- a/spi.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-;; vim: filetype=avr
-;;
-;; SPI interface control and use
-;;
-
-;; I/O Port
-.equ SPI_DDR    = DDRB
-.equ SPI_PORT   = PORTB
-.equ SPI_SCK    = PORTB5
-.equ SPI_MISO   = PORTB4
-.equ SPI_MOSI   = PORTB3
-.equ SPI_SS     = PORTB2
-
-;; Internal status flags
-.equ SPI_FLAGS  = GPIOR0
-.equ SPI_BUSY   = 0
-
-;; Settings
-.set SPI_DORD = 0           ; word order
-.set SPI_CPOL = 0           ; clock polarity
-.set SPI_CPHA = 0           ; clock phase
-.set SPI_CLOCK  = 0b01      ; clock speed
-
-;; Internal state
-; Number of in/out bytes
-.set SPI_BUFLEN  = 2
-
-.dseg
-; Buffer for incoming frames
-spi_inbuf:  .byte SPI_BUFLEN
-
-; Buffer for outgoing frames
-spi_outbuf: .byte SPI_BUFLEN
-
-.cseg
-
-;; Initialize SPI subsystem for master operation
-SPI_Init:
-    ; Set modes
-        sbi         SPI_DDR, SPI_SCK        ; Out
-        sbi         SPI_DDR, SPI_MOSI       ; Out
-        sbi         SPI_DDR, SPI_SS         ; Out
-
-    ; Drive SS high (off)
-        sbi         SPI_PORT, SPI_SS
-
-    ; Set control mode
-        ; XXX: Enable interrupt
-        ; Enable SPI
-        ; MSB first
-        ; Master mode
-        ; Polarity/phase: Mode 0 (sample on rising edge)
-        ; Clock rate 1/16
-        ldi         r16, (0 << SPIE) | (1 << SPE) | (SPI_DORD << DORD) | (1 << MSTR) | (SPI_CPOL << CPOL) | (SPI_CPHA << CPHA) | (SPI_CLOCK << SPR0)
-        out         SPCR, r16
-    
-    ; Flags
-        clr         r0
-        out         SPI_FLAGS, r0
-
-    ; Start update timer
-    ; XXX: also used for ADC
-;        ldi         r16, 64         ; every 64k cycles
-;        rcall       Timer0_Start
-    
-    ; Done
-        ret
-
-;; Triggered by Timer0, updates the spi_bufs
-;;  Run from timer interrupt context
-SPI_Update:
-        ; skip if updating
-        sbic        SPI_FLAGS, SPI_BUSY
-        ret
-
-    ;; Continue
-    ; XXX: blocks too much?
-
-;; Send/Recv from/to SPI buffers
-SPI_SendRecv:
-    ; Flag
-        sbi         SPI_FLAGS, SPI_BUSY
-
-    ; Start of packet
-        cbi         SPI_PORT, SPI_SS
-    
-    ; Init buffers
-        ldi         r16, SPI_BUFLEN
-        
-        ; send/recv in reverse order
-        ldi         XL, low(spi_inbuf + SPI_BUFLEN)
-        ldi         XH, high(spi_inbuf + SPI_BUFLEN)
-        ldi         YL, low(spi_outbuf + SPI_BUFLEN)
-        ldi         YH, high(spi_outbuf + SPI_BUFLEN)
-    
-    ; Write
-spi_sr_next:
-        ; load+send tail byte
-        ld          r1, -Y
-        out         SPDR, r1
-
-    ; Wait
-spi_sr_wait:        
-        in          r1, SPSR
-        sbrs        r1, SPIF
-        rjmp        spi_sr_wait
-
-    ; Read
-        ; XXX: wrong, should be head byte?
-        ; read+store tail byte
-        in          r1, SPDR
-        st          -X, r1
- 
-    ; Done?
-        dec         r16
-        brne        spi_sr_next         ; if nonzero
-    
-    ; End of packet
-        sbi         SPI_PORT, SPI_SS
-        
-        cbi         SPI_FLAGS, SPI_BUSY
-
-    ; Done
-        ret
-
-;; Wait for SPI to be ready for send
-SPI_Wait:
-    ; Test
-        in          r1, SPSR
-        sbrs        r1, SPIF
-        rjmp        SPI_Wait
-    
-    ; Read SPDR to clear SPIF
-        in          r10, SPDR
-
-    ; Done
-        ret
-
-;; Service SPI interrupt
-SPI_Interrupt:
-    ; XXX: disabled
-        reti
-
-
--- a/src/hello-lkm.c	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,484 +0,0 @@
-/*
- * Control the JY-LKM1638 LED display module.
- */
-
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "stdlib.h"
-
-// XXX
-#include "timer.c"
-
-#define LKM_DDR     DDRC
-#define LKM_PORT    PORTC
-#define LKM_PIN     PINC
-#define LKM_CLK     0
-#define LKM_DIO     1
-#define LKM_STB     2
-
-enum lkm_cmd {
-    LKM_CMD_DATA    = 0b01000000,
-    LKM_CMD_CONTROL = 0b10000000,
-    LKM_CMD_ADDRESS = 0b11000000,
-
-    LKM_DATA_WRITE          = 0b00000000,
-    LKM_DATA_READ           = 0b00000010,
-
-    LKM_DATA_ADDR_AUTO      = 0b00000000,
-    LKM_DATA_ADDR_FIXED     = 0b00000100,
-
-    LKM_DATA_TEST_NORMAL    = 0b00000000,
-    LKM_DATA_TEST_TEST      = 0b00001000,
-
-    LKM_ADDRESS             = 0b00001111,
-    
-    LKM_CONTROL_INTENSITY       = 0b00000111,
-    LKM_CONTROL_INTENSITY_MIN   = 0b00000000,
-    LKM_CONTROL_INTENSITY_MAX   = 0b00000111,
-
-    LKM_CONTROL_DISPLAY_OFF = 0b00000000,
-    LKM_CONTROL_DISPLAY_ON  = 0b00001000,
-};
-
-static const uint8_t LKM_DISPLAY_FONT[] = {
-    0b00111111,	// 0
-    0b00000110,	// 1
-    0b01011011,	// 2
-    0b01001111,	// 3
-    0b01100110,	// 4
-    0b01101101,	// 5
-    0b01111101,	// 6
-    0b00000111,	// 7
-    0b01111111,	// 8
-    0b01100111,	// 9
-    0b01110111,	// A
-    0b01111100,	// B
-    0b00111001,	// C
-    0b01011110,	// D
-    0b01111001,	// E
-    0b01110001,	// F
-};
-
-enum {
-    LKM_DISPLAY_DECIMAL = 0b10000000,
-};
-
-/*
- * XXX: RED/GREEN somehow swapped vs reference; bug in our write code?
- */
-enum {
-    LKM_LED_OFF     = 0b00,
-    LKM_LED_GREEN   = 0b01,
-    LKM_LED_RED     = 0b10,
-    LKM_LED_ORANGE  = 0b11,
-};
-
-/*
- * Button bitfields.
- *
- * The JY-LKM1638 uses K3
- */
-enum {
-    LKM_BUTTON_K1L  = 0b00000100,
-    LKM_BUTTON_K2L  = 0b00000010,
-    LKM_BUTTON_K3L  = 0b00000001,
-    
-    LKM_BUTTON_K1H  = 0b01000000,
-    LKM_BUTTON_K2H  = 0b00100000,
-    LKM_BUTTON_K3H  = 0b00010000,
-};
-
-void lkm_init ()
-{
-    // strobe off: high output
-    // XXX: should use an external pull-up resistor?
-    sbi(&LKM_PORT, LKM_STB);
-    sbi(&LKM_DDR, LKM_STB);
-
-    // clock low
-    sbi(&LKM_DDR, LKM_CLK);
-    cbi(&LKM_PORT, LKM_CLK);
-
-    // data tri-state
-    cbi(&LKM_DDR, LKM_DIO);
-    cbi(&LKM_DDR, LKM_DIO);
-}
-
-/*
- * Select the LKM for write.
- */
-void lkm_out ()
-{
-    // clock low
-    cbi(&LKM_PORT, LKM_CLK);
-
-    // data out
-    sbi(&LKM_DDR, LKM_DIO);
-
-    // select on: low
-    cbi(&LKM_PORT, LKM_STB);
-}
-
-/*
- * Select the LKM for read.
- */
-void lkm_in ()
-{
-    // data in
-    cbi(&LKM_DDR, LKM_DIO);
-    cbi(&LKM_PORT, LKM_DIO);
-
-    // select on: low
-    cbi(&LKM_PORT, LKM_STB);
-
-    // clock high
-    sbi(&LKM_PORT, LKM_CLK);
-
-    // pause
-    _delay_us(1);
-}
-
-/*
- * Write out one byte
- */
-void lkm_write (byte b)
-{
-    char i;
-
-    for (i = 0; i < 8; i++) {
-        // clock read: low
-        cbi(&LKM_PORT, LKM_CLK);
-
-        // set output
-        if (b & 1)
-            sbi(&LKM_PORT, LKM_DIO);
-        else 
-            cbi(&LKM_PORT, LKM_DIO);
-        
-        // clock write: high
-        sbi(&LKM_PORT, LKM_CLK);
-        
-        // next bit
-        b >>= 1;
-    }
-}
-
-/*
- * Read in one byte.
- */
-byte lkm_read ()
-{
-    byte b = 0;
-    char i;
-
-    // XXX: this loop is timing-critical; we must allow the signal to settle betwen clocks
-    for (i = 0; i < 8; i++) {
-        // next bit
-        b >>= 1;
-
-        // clock read: low
-        cbi(&LKM_PORT, LKM_CLK);
-    
-        // pause
-        _delay_us(1);
-
-        // read input
-        if (tbi(&LKM_PIN, LKM_DIO))
-            b |= 0x80;
-        
-        // pause
-        _delay_us(1);
-
-        // clock write: high
-        sbi(&LKM_PORT, LKM_CLK);
-        
-        // pause
-        _delay_us(1);
-    }
-
-    return b;
-}
-
-/*
- * End command.
- */
-void lkm_end ()
-{
-    // select off: high
-    sbi(&LKM_PORT, LKM_STB);
-
-    // tristate data
-    cbi(&LKM_DDR, LKM_DIO);
-}
-
-void lkm_cmd (byte cmd)
-{
-    lkm_out();
-    lkm_write(cmd);
-    lkm_end();
-}
-
-void lkm_cmd1 (byte cmd, byte arg)
-{
-    lkm_out();
-    lkm_write(cmd);
-    lkm_write(arg);
-    lkm_end();
-}
-
-static inline void lkm_control (byte display, byte intensity)
-{
-    lkm_cmd(LKM_CMD_CONTROL
-        |   (display ? LKM_CONTROL_DISPLAY_ON : LKM_CONTROL_DISPLAY_OFF)
-        |   (intensity & LKM_CONTROL_INTENSITY)
-    );
-}
-
-/*
- * Blank display/LEDs
- */
-static void lkm_clear ()
-{
-    char i;
-
-    lkm_cmd(LKM_CMD_DATA
-        |   LKM_DATA_TEST_NORMAL
-        |   LKM_DATA_ADDR_AUTO
-        |   LKM_DATA_WRITE
-    );
-    
-    // write out all 16 bytes of 0x00
-    lkm_out();
-    lkm_write(LKM_CMD_ADDRESS | (0x0) & LKM_ADDRESS);
-    for (i = 0; i < 16; i++) {
-        lkm_write(0x00);
-    }
-    lkm_end();
-
-}
-
-/*
- * Set raw output mask for given display 0..7
- */
-static inline void lkm_display (byte display, byte value)
-{
-    lkm_cmd(LKM_CMD_DATA
-        |   LKM_DATA_TEST_NORMAL
-        |   LKM_DATA_ADDR_AUTO
-        |   LKM_DATA_WRITE
-    );
-    lkm_cmd1(LKM_CMD_ADDRESS | ((display * 2 + 0) & LKM_ADDRESS),
-        value
-    );
-}
-
-/*
- * Set raw output mask for given led 0..7
- */
-static inline void lkm_led (byte led, byte value)
-{
-    lkm_cmd(LKM_CMD_DATA
-        |   LKM_DATA_TEST_NORMAL
-        |   LKM_DATA_ADDR_AUTO
-        |   LKM_DATA_WRITE
-    );
-    lkm_cmd1(LKM_CMD_ADDRESS | ((led * 2 + 1) & LKM_ADDRESS),
-        value
-    );
-}
-
-/*
- * Set 4-bit hexadecimal output for given display 0..7
- */
-static inline void lkm_display_hex (byte display, byte hex)
-{
-    lkm_display(display, LKM_DISPLAY_FONT[hex]);
-}
-
-static inline void lkm_display_dec (byte display, byte dec, byte decimal)
-{
-    byte raw;
-
-    if (dec < 10)
-        raw = LKM_DISPLAY_FONT[dec];
-    else
-        raw = 0x00;
-
-    if (decimal)
-        raw |= LKM_DISPLAY_DECIMAL;
-
-    lkm_display(display, raw);
-}
-
-/*
- * Read the 8-bit key states
- */
-byte lkm_buttons ()
-{
-    byte k3 = 0;
-    char i;
-
-    lkm_out();
-    lkm_write(LKM_CMD_DATA
-        |   LKM_DATA_TEST_NORMAL
-        |   LKM_DATA_ADDR_AUTO
-        |   LKM_DATA_READ
-    );
-    lkm_in();
-    for (i = 0; i < 4; i++) {
-        /*
-         * The ordering of keys used is weird; it seems to go 04 15 26 37
-         */
-        k3 |= lkm_read() << i;
-        
-        /*
-        k3 >>= 1;
-
-        byte b = lkm_read();
-
-        if (b & LKM_BUTTON_K3L)
-            k3 |= 0b00001000;
-
-        if (b & LKM_BUTTON_K3H)
-            k3 |= 0b10000000;
-        */
-    }
-    lkm_end();
-
-    return k3;
-}
-
-/*
- * Set 8-bit hexadecimal output on displays n..n+1
- */
-void lkm_display_hh (byte display, byte hex)
-{
-    lkm_display_hex(display + 0, ((hex >> 4) & 0xF));
-    lkm_display_hex(display + 1, ((hex >> 0) & 0xF));
-}
-
-/*
- * Set 16-bit hexadecimal output on displays 4..7
- */
-void lkm_display_hhhh (short hex)
-{
-    lkm_display_hex(7, ((hex >> 0) & 0xF));
-    lkm_display_hex(6, ((hex >> 4) & 0xF));
-    lkm_display_hex(5, ((hex >> 8) & 0xF));
-    lkm_display_hex(4, ((hex >> 12) & 0xF));
-}
-
-/*
- * Set 2-digit decimal output on displays n..n+1
- */
-void lkm_display_dd (byte display, byte dec)
-{
-    byte d = dec / 10;
-    byte u = dec % 10;
-
-    byte c = d / 10;
-    d = d % 10;
-
-    lkm_display_dec(display + 0, d, c > 1);
-    lkm_display_dec(display + 1, u, c > 0);
-}
-
-// debug
-#define DEBUG_DDR   DDRB
-#define DEBUG_PORT  PORTB
-#define DEBUG_LED   0
-
-int main (void)
-{
-    // led_init();
-    sbi(&DEBUG_DDR, DEBUG_LED);
-
-    timer_init();
-    lkm_init();
-
-    sei();
-
-    // setup display
-    lkm_clear();
-    lkm_control(LKM_CONTROL_DISPLAY_ON, LKM_CONTROL_INTENSITY_MAX);
-
-/*
-    // test
-    lkm_led(0, LKM_LED_OFF);
-    lkm_led(1, LKM_LED_RED);
-    lkm_led(2, LKM_LED_GREEN);
-    lkm_led(3, LKM_LED_ORANGE);
-
-    return 0;
-*/
-
-    // start
-    byte channels[4] = { };
-    enum channel_state {
-        CHANNEL_IDLE    = 0,
-        CHANNEL_INC,
-        CHANNEL_DEC,
-    } channel_state[4] = { };
-    byte channel_count[4] = { };
-    char c;
-        
-    while (true) {
-        // scan input
-        byte buttons = lkm_buttons();
-        
-        for (c = 0; c < 4; c++) {
-            enum channel_state state = channel_state[c], next;
-            byte count = channel_count[c];
-
-            // decode buttons -> state
-            if (buttons & 0b1) {
-                next = CHANNEL_INC;
-            } else if (buttons & 0b10) {
-                next = CHANNEL_DEC;
-            } else {
-                next = CHANNEL_IDLE;
-            }
-            
-            buttons >>= 2;
-            
-            // feedback
-            if (state == CHANNEL_INC || next == CHANNEL_INC)
-                lkm_led(c * 2 + 0, LKM_LED_GREEN);
-            else if (state == CHANNEL_DEC && next == CHANNEL_DEC)
-                lkm_led(c * 2 + 0, LKM_LED_RED);
-            else
-                lkm_led(c * 2 + 0, LKM_LED_OFF);
-
-            if (state == CHANNEL_DEC || next == CHANNEL_DEC)
-                lkm_led(c * 2 + 1, LKM_LED_RED);
-            else if (state == CHANNEL_INC && next == CHANNEL_INC)
-                lkm_led(c * 2 + 1, LKM_LED_GREEN);
-            else
-                lkm_led(c * 2 + 1, LKM_LED_OFF);
-
-            // counts
-            if ((channel_state[c] = next) != state)
-                channel_count[c] = 0;
-            else
-                count = ++channel_count[c];
-
-            // state transitions
-            if (next == CHANNEL_INC && count > 0) {
-                channels[c] += count;
-            } else if (next == CHANNEL_DEC && count > 0) {
-                channels[c] -= count;
-            } else if (state == CHANNEL_INC && !count) {
-                channels[c] = 0xff;
-            } else if (state == CHANNEL_DEC && !count) {
-                channels[c] = 0x00;
-            }
-
-            lkm_display_hh(c * 2, channels[c]);
-        
-            xbi(&DEBUG_PORT, DEBUG_LED);
-        }
-
-        timer_sleep(8000);
-    }
-}
--- a/src/hello.c	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-#include <avr/io.h>
-
-#include "stdlib.h"
-
-// XXX
-#include "timer.c"
-#include "serial.c"
-#include "spi.c"
-#include "led7.c"
-
-static enum state {
-    START       = '\n',
-    CMD_SET     = 's',
-    CMD_INC     = '+',
-    CMD_DEC     = '-',
-    CMD_READ    = 'r',
-    ARG_CHAR    = '0',
-    ERROR       = '!',
-} state = START, cmd = 0;
-
-static enum {
-    CMD_LED_1   = 0,
-} cmd_led = 0;
-
-static char arg_char;
-
-static unsigned char led_state = 0;
-
-int command (enum state cmd)
-{
-    switch (cmd) {
-        case CMD_SET:
-            led_state = arg_char;
-
-            return 0;
-
-        case CMD_INC:
-            if (led_state == 0xff)
-                return 1;
-
-            led_state++;
-            return 0;
-
-        case CMD_DEC:
-            if (!led_state)
-                return 1;
-
-            led_state--;
-            return 0;
-
-        case CMD_READ:
-            led_state = spi_rx[1]; // XXX
-            return 0;
-
-        default:
-            return 1;
-    }
-}
-
-char input (char c)
-{
-    if (c == '\r') {
-        char ret = '?';
-
-        // command state
-        switch (state) {
-            case START:
-                cmd = 0;
-                break;
-
-            case CMD_SET:
-            case CMD_INC:
-            case CMD_DEC:
-                break;
-
-            case ARG_CHAR:
-                break;
-
-            case ERROR:
-                cmd = 0;
-                break;
-        }
-
-        // command
-        if (!cmd) {
-            ret = ' ';
-        } else if (command(cmd)) {
-            ret = '!';
-        } else {
-            ret = '\n';
-        }
-        
-        // return to START with response
-        state = START;
-        return ret;
-
-    } else if (31 < c && c < 128) {
-        // process input char
-        switch (state) {
-            case START:
-                if (c == 's') {
-                    cmd = CMD_SET;
-                    state = ARG_CHAR;
-                    arg_char = 0;
-                } else if (c == 'S') {
-                    cmd = state = CMD_SET;
-                    arg_char = 255;
-                } else if (c == '+') {
-                    cmd = state = CMD_INC;
-                } else if (c == '-') {
-                    cmd = state = CMD_DEC;
-                } else if (c == 'r') {
-                    cmd = state = CMD_READ;
-                } else {
-                    break;
-                }
-                
-                return state;
-            break;
-
-            /* 
-            case CMD_SET:
-                if (c == '1') {
-                    cmd_led = CMD_LED_1;
-                    state = ARG_CHAR;
-                    arg_char = 0;
-                } else {
-                    state = ERROR;
-                }
-
-                break;
-            */
-            case ARG_CHAR:
-                if (c >= '0' && c <= '9') {
-                    arg_char *= 10;
-                    arg_char += (c - '0');
-                } else {
-                    break;
-                }
-                    
-                return c;
-            break;
-        }
-
-        // reject
-        state = ERROR;
-        return ERROR;
-
-    } else {
-        // ignore
-        return ' ';
-    }
-}
-
-
-#define DEBUG_DDR   DDRB
-#define DEBUG_PORT  PORTB
-#define DEBUG_LED   0
-
-int main (void)
-{
-    led7_init();
-    timer_init();
-    serial_init();
-    spi_init();
-
-    // led_init();
-    sbi(&DEBUG_DDR, DEBUG_LED);
-
-    sei();
-
-    // start
-    char c;
-    unsigned short timeout = 0;
-        
-    serial_write(state);
-
-    while (true) {
-        // TODO: SPI timer
-        led7_update(led_state);
-        spi_update();
-
-        // toggle
-        if (led_state == 0) {
-            timeout = 0;
-            cbi(&DEBUG_PORT, DEBUG_LED);
-
-        } else if (led_state == 255) {
-            timeout = 0;
-            sbi(&DEBUG_PORT, DEBUG_LED);
-
-        } else {
-            // as Hz
-            timeout = (16000 / led_state);
-            xbi(&DEBUG_PORT, DEBUG_LED);
-        }
-        
-        // sleep
-        if (timer_sleep(timeout)) {
-            c = '.';
-
-        } else if ((c = serial_read())) {
-            // got serial data
-            c = input(c);
-
-        } else {
-            c = '?';
-        }
-        
-        // output...
-        serial_write(c);
-    }
-}
--- a/timer.inc	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-;; vim: filetype=avr
-;;
-;; Timer unit control and use
-;;
-
-.equ TIMER_FLAGS = GPIOR0
-
-;; Timer0
-; Compare output mode
-.set TIMER0_COMA = 0b00			; null
-.set TIMER0_COMB = 0b00			; null
-
-; Waveform Generation Mode (triplet low/high)
-.set TIMER0_WGML = 0b10			; CTC
-.set TIMER0_WGMH = 0b0			; CTC
-
-; Clock Source
-.set TIMER0_CS = 0b101			; 1/1024
-
-;; Timer1
-; Waveform Generation Mode (nibble low/high)
-.set TIMER1_WGML = 0b00			; CTC
-.set TIMER1_WGMH = 0b01			; CTC
-
-; Clock Source
-.set TIMER1_CS = 0b101			; 1/1024
-
-; Flags
-.equ TIMER1_BUSY = 1
-
-.set SLEEP_MODE = 0b000			; Idle
-
-Timer_Init:
-Timer0_Init:
-		; OC0A/B disconnected from output
-		; No PWM mode
-		ldi			r16, (TIMER0_COMA << COM0A0) | (TIMER0_COMB << COM0B0) | (TIMER0_WGML << WGM00)
-		out			TCCR0A, r16
-
-		; Clear
-		ldi			r16, 0
-		out			OCR0A, r16
-		out			OCR0B, r16
-		out			TCCR0B, r16
-
-		; Enable compare interrupt
-		ldi			r16, (1 << OCIE0A)
-		sts			TIMSK0, r16
-
-Timer1_Init:
-		; OC1A/B disconnected from output
-		; No PWM mode
-		poke		[TCCR1A, r16, (0b00 << COM1A0) | (0b00 << COM1B0) | (TIMER1_WGML << WGM10)]
-
-		; Clear
-		poke		[TCCR1B, r16, 0]
-		poke		[TCCR1C, r16, 0]
-
-		; Enable compare interrupt
-		poke		[TIMSK1, r16, (1 << OCIE1A)]
-
-Sleep_init:
-		; Select sleep mode
-		; Enable `sleep`
-		poke		[SMCR, r16, (SLEEP_MODE << SM0) | (1 << SE)]
-
-		; Disable ADC
-		poke		[SMCR, r16, (1 << PRTWI) | (1 << PRUSART0) | (1 << PRADC)]
-
-		ret
-
-;; Timer0 is recurring; this starts it running, and it keeps hitting OC0A periodically
-;;  Input: r16 (period, in 1k-cycles)
-Timer0_Start:
-	; Initialize timer
-		; set CTC trigger from r16
-		out			OCR0A, r16
-
-		; clear counter
-		ldi			r16, 0
-		out			TCNT0, r16
-
-	; Start
-		; WGM
-		; Clock Source
-		ldi			r16, (TIMER0_WGMH << WGM02) | (TIMER0_CS << CS00)
-		out			TCCR0B, r16
-
-		ret
-
-Timer0_Read8:
-		in			r16, TCNT0
-
-		ret
-
-;; Timer0 Compare A interrupt handler
-Timer_OC0A:
-		in			r0, SREG
-
-		; Run callback
-		rcall		TIMER0_CB_A
-
-		out			SREG, r0
-		reti
-
-;; Timer1 is one-shot; this starts it running, and it is then stopped once it hits OC1A
-Timer1_Start:
-	; Initialize timer
-		poke		[TCNT1H, r16, high(0)]
-		poke		[TCNT1L, r16, low(0)]
-
-	; Set flag
-		sbi			TIMER_FLAGS, TIMER1_BUSY
-	
-	; Start
-		; WGM
-		; Clock Source
-		poke		[TCCR1B, r16, (TIMER1_WGMH << WGM12) | (TIMER1_CS << CS10)]
-
-		ret
-
-Timer1_Stop:
-		; WGM
-		; Clock off
-		poke		[TCCR1B, r16, (TIMER1_WGMH << WGM12) | (0b00 << CS10)]
-		
-	; Clear flag
-		cbi			TIMER_FLAGS, TIMER1_BUSY
-
-		ret
-
-;; Timer1 Compare A interrupt handler
-Timer_OC1A:
-		in			r0, SREG
-	
-	; Stop timer
-		rcall		Timer1_Stop
-
-		out			SREG, r0
-		reti
-
-;; Prime the timer and sleep for 1s
-Timer_Sleep_1s:
-	; Initialize counter to 16k cycles
-		ldi			XH, high(16 * 1024)
-		ldi			XL, low(16 * 1024)
-
-	;; Continue
-
-;; Count to X
-Timer_Sleep:
-	; Set TOP
-		sts			OCR1AH, XH
-		sts			OCR1AL, XL
-
-	; Start timer
-		rcall		Timer1_Start
-
-	; Wait for timer to complete
-_timer1_sleep:
-		sleep
-		
-		sbic		TIMER_FLAGS, TIMER1_BUSY
-		rjmp		_timer1_sleep
-
-	; Done
-		ret
-
-;; Update timer for given timeout
-Timer_Update:
-	; Set TOP
-		sts			OCR1AH, XH
-		sts			OCR1AL, XL
-	
-	; Check timer
-		lds			YL, TCNT1L
-		lds			YH, TCNT1H
-		
-		cp			YL, XL
-		cpc			YH, XH
-
-		brlo		timer_up_out
-
-	; Update
-	; XXX: figure out a better way to do this...
-		ldi			r16, 0
-		subi		XL, 2
-		sbc			XH, r16
-
-		sts			TCNT1L, XL
-		sts			TCNT1H, XH
-
-timer_up_out:
-	; Done
-		ret
-
--- a/timer.s	Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-.nolist
-.include "m168def.inc"      ; Same family as 328P
-.list
-
-;; Interrupt Vector
-.org 0x00
-        rjmp        init
-
-.org OC1Aaddr
-		; Timer/Counter1 Compare Output A
-		rjmp		Timer_OC1A
-
-.org OC0Aaddr
-        ; Timer/Counter0 Compare Output A
-        rjmp        Timer_OC0A
-
-.org 0x40
-
-;; Syntax
-.include "macros.inc"
-
-;; Timer0 Compare A handler
-Tick:
-	; Toggle
-		sbi			PIND, PORTD7
-
-		ret
-
-;; Timer
-.set TIMER0_CB_A = Tick
-.include "timer.inc"
-
-Main:
-init:
-    ; Stack
-        ldi         r16, high(RAMEND)
-        ldi         r17, low(RAMEND)
-        out         SPH, r16
-        out         SPL, r17
-
-    ; Enable interrupts
-        sei
-
-	; Turn off LED7
-		sbi			DDRB, PORTB1
-		sbi			PORTB, PORTB1
-
-
-	; DEBUG
-		sbi			DDRD, PORTD7
-		cbi			PORTD, PORTD7
-
-		sbi			DDRD, PORTD6
-		sbi			DDRD, PORTD5
-		
-
-    ; Timer
-		; setup
-        rcall       Timer0_Init
-		
-		; run with 255k cycles
-		ldi			r16, 255
-		rcall		Timer0_Start	
-
-loop:
-	; Run timer
-		rjmp		loop
-