--- a/Makefile Tue Jul 26 22:43:41 2011 +0300
+++ b/Makefile Tue Jul 26 22:43:59 2011 +0300
@@ -4,7 +4,7 @@
AD_PART = m328p
AD_PROG = arduino
AD_BAUD = 57600
-AD_PORT = /dev/ttyUSB0
+AD_PORT = /dev/ttyUSB1
AD = avrdude
ADFLAGS = -p $(AD_PART) -c $(AD_PROG) -b $(AD_BAUD) -P $(AD_PORT)
@@ -13,14 +13,19 @@
all: $(PROG).hex
-matrix.hex: spi.inc matrix.inc timer.inc delay.inc macros.inc
+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
+font.inc: font.def
+
%.hex: %.s
$(AS) $(ASFLAGS) $<
mv $<.hex $@
+font.def: font.txt font-compile.py
+ python font-compile.py $< $@ > /dev/null
+
upload: $(PROG).hex
$(AD) $(ADFLAGS) -U flash:w:$<
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/font-compile.py Tue Jul 26 22:43:59 2011 +0300
@@ -0,0 +1,193 @@
+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()
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/font.inc Tue Jul 26 22:43:59 2011 +0300
@@ -0,0 +1,73 @@
+;; 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
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/font.txt Tue Jul 26 22:43:59 2011 +0300
@@ -0,0 +1,210 @@
+; \x00
+------
+-####-
+-#--#-
+-#--#-
+-#--#-
+-#--#-
+-####-
+------
+
+; \x20
+------
+------
+------
+------
+------
+------
+------
+------
+
+; !
+--##--
+--##--
+--##--
+--##--
+--##--
+------
+--##--
+--##--
+
+; 0
+-####-
+#----#
+#----#
+#----#
+#----#
+#----#
+#----#
+-####-
+
+; 1
+---#--
+--##--
+-#-#--
+#--#--
+---#--
+---#--
+---#--
+-#####
+
+; 2
+--###-
+-#---#
+-#---#
+----#-
+---#--
+--#---
+-#----
+######
+
+; 3
+-###--
+#---#-
+-----#
+----#-
+---##-
+-----#
+#---#-
+-###--
+
+; 4
+----#-
+-#--#-
+##--#-
+#---#-
+######
+----#-
+----#-
+----#-
+
+; 5
+######
+#-----
+#-----
+#####-
+-----#
+-----#
+#----#
+-####-
+
+; 6
+------
+-####-
+##---#
+#-----
+#####-
+#----#
+#----#
+-####-
+
+; 7
+-#####
+#----#
+----#-
+---#--
+--#---
+-#----
+#-----
+------
+
+; 8
+------
+-####-
+#----#
+#----#
+-####-
+#----#
+#----#
+-####-
+
+; 9
+-####-
+#----#
+#----#
+#----#
+-#####
+-----#
+-----#
+----#-
+
+; h
+#-----
+#-----
+#-----
+#-----
+#-###-
+##---#
+#----#
+#----#
+
+; e
+--##--
+-#--#-
+#----#
+######
+#-----
+#---#-
+-###--
+------
+
+; l
+--##--
+---#--
+---#--
+---#--
+---#--
+---#--
+---#--
+--###-
+
+; o
+------
+------
+------
+-####-
+#----#
+#----#
+#----#
+-####-
+
+; w
+------
+------
+------
+#---#-
+#---#-
+#---#-
+#-#-#-
+-#-#--
+
+; r
+------
+------
+#-----
+#-##--
+##----
+#-----
+#-----
+#-----
+
+; d
+----#-
+----#-
+----#-
+-####-
+#---#-
+#---#-
+#---#-
+-###--
+
+;
+------
+------
+------
+------
+------
+------
+------
+------
+
--- a/matrix.inc Tue Jul 26 22:43:41 2011 +0300
+++ b/matrix.inc Tue Jul 26 22:43:59 2011 +0300
@@ -1,19 +1,58 @@
;; 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
-.dseg
-.set MATRIX_COLS = 8 ; number of columns
+;; Matrix properties
+; Matrix width in columns
+.set MATRIX_COLS = 8 ; physical columns
-matrix_colbit: .byte 1 ; column bit
-matrix_rowbuf: .byte MATRIX_COLS ; row bitmask by column
+; 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, an set up buffers
+;; Normalize the outputs, enable the matrix, and set up buffers
Matrix_Init:
; Setup ENable port
sbi MATRIX_PORT, MATRIX_OE ; high -> disabled
@@ -35,10 +74,13 @@
ldi r16, 0b1
sts matrix_colbit, r16
+ ldi r16, 0
+ sts matrix_colshift, r16
+
ldi r16, 0
- ldi r17, MATRIX_COLS
- ldi YL, low(matrix_rowbuf)
- ldi YH, high(matrix_rowbuf)
+ ldi r17, MATRIX_BUF_COLS
+ ldi YL, low(matrix_colbuf)
+ ldi YH, high(matrix_colbuf)
m_init_mzero:
st Y+, r16
@@ -54,9 +96,13 @@
; done
ret
-;; Scan the next column
+;; 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
@@ -64,7 +110,7 @@
; start packet
cbi SPI_PORT, SPI_SS
- ; output
+ ; output single column-enable bit
out SPDR, r16
; Compute col index
@@ -82,21 +128,28 @@
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_rowbuf)
- ldi XH, high(matrix_rowbuf)
+ ldi XL, low(matrix_colbuf)
+ ldi XH, high(matrix_colbuf)
; offset
- ldi r18, 0
+ ldi r16, 0
add XL, r17
- adc XH, r18
+ adc XH, r16
; load
ld r16, X
- ; output
+ ; output full row-enable bitmask
rcall SPI_Wait
out SPDR, r16
@@ -119,13 +172,17 @@
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_rowbuf)
- ldi ZH, high(matrix_rowbuf)
+ ldi ZL, low(matrix_colbuf)
+ ldi ZH, high(matrix_colbuf)
; Column bit
ldi r25, 0
@@ -156,3 +213,211 @@
; 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
+
+ ret
+
--- a/matrix.s Tue Jul 26 22:43:41 2011 +0300
+++ b/matrix.s Tue Jul 26 22:43:59 2011 +0300
@@ -1,3 +1,5 @@
+;; vim: set ft=avr:
+
.nolist
.include "m168def.inc" ; Same family as 328P
.list
@@ -18,7 +20,8 @@
.org SPIaddr
rjmp SPI_Interrupt
-.org 0x40
+
+cseg0: .org 0x40
;; Syntax
.include "macros.inc"
@@ -37,6 +40,9 @@
;; Utils
.include "delay.inc"
+;; Font rendering
+.include "font.inc"
+
;; Scan through each pixel
Main_ScanRaw:
; init
@@ -73,15 +79,15 @@
Main_ScanTest:
; Generate pattern
; end of buffer
- ldi r17, MATRIX_COLS
- ldi XL, low(matrix_rowbuf + MATRIX_COLS)
- ldi XH, high(matrix_rowbuf + MATRIX_COLS)
+ 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
+ ; put, pre-decrement
st -X, r16
; flip
@@ -91,10 +97,128 @@
dec r17
brne st_loop
-st_scan:
- ; Scan repeatedly
- ;rcall Matrix_ScanCol
- rjmp st_scan
+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:
@@ -122,8 +246,9 @@
; Run
; rcall Main_ScanRaw
-
- rcall Main_ScanTest
+ ; rcall Main_ScanTest
+ ; rcall Main_ScanCode
+ rcall Main_ScanText
end:
rjmp end
--- a/spi.inc Tue Jul 26 22:43:41 2011 +0300
+++ b/spi.inc Tue Jul 26 22:43:59 2011 +0300
@@ -106,6 +106,7 @@
rjmp spi_sr_wait
; Read
+ ; XXX: wrong, should be head byte?
; read+store tail byte
in r1, SPDR
st -X, r1