--- a/Makefile Mon Aug 23 01:07:45 2010 +0300
+++ b/Makefile Sun Aug 29 22:49:32 2010 +0300
@@ -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
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 Sun Aug 29 22:49:32 2010 +0300
@@ -0,0 +1,182 @@
+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
+
+ print 'read_charblock', 'ascii', 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(
+ ("; '%s'\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
+
+ font_start = '0'
+ font_end = '9'
+
+ 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 ; '%s'\n" % (ord(font_start), font_start))
+ + (".equ FONT_8x6_END = %d ; '%s'\n" % (ord(font_end), font_end))
+ + (".equ FONT_8x6_COLS = %d\n" % (6, ))
+ + (".equ FONT_8x6_ROWS = %d\n" % (8, ))
+ + "FONT_8x6:\n"
+ "\n"
+ )
+
+ for char in xrange(ord('0'), ord('9') + 1) :
+ ascii = chr(char)
+ cols = charmap[ascii]
+
+ 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 Sun Aug 29 22:49:32 2010 +0300
@@ -0,0 +1,65 @@
+;; 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 f_render_invalid
+
+ ; test over-range
+ ldi r17, FONT_END
+ cp r17, r16
+ brlt f_render_invalid
+
+ ; Locate font char
+ ; compute offset in chars (r16)
+ subi r16, FONT_START
+
+ ; 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
+f_render_cpy:
+
+ ; copy via r17
+ lpm r17, Z+
+ st Y+, r17
+
+ dec r16
+ brne f_render_cpy
+
+f_render_invalid:
+
+ ; Done
+ ret
+
--- a/matrix.inc Mon Aug 23 01:07:45 2010 +0300
+++ b/matrix.inc Sun Aug 29 22:49:32 2010 +0300
@@ -1,5 +1,5 @@
;; LED Matrix driver
-;;
+;; vim: set ft=avr:
.dseg
;; I/O addresses
--- a/matrix.s Mon Aug 23 01:07:45 2010 +0300
+++ b/matrix.s Sun Aug 29 22:49:32 2010 +0300
@@ -1,3 +1,5 @@
+;; vim: set ft=avr:
+
.nolist
.include "m168def.inc" ; Same family as 328P
.list
@@ -38,6 +40,9 @@
;; Utils
.include "delay.inc"
+;; Font rendering
+.include "font.inc"
+
;; Scan through each pixel
Main_ScanRaw:
; init
@@ -195,6 +200,36 @@
; Load next frame, and animate
rjmp sc_next
+Main_ScanText:
+
+stxt_start:
+ ; char to render
+ ldi r24, 48 ; '0'
+
+ ; Render char
+stxt_loop:
+ ; target buffer
+ ldi YL, low(matrix_colbuf + 0)
+ ldi YH, high(matrix_colbuf + 0)
+
+ ; render r24 to Y
+ mov r16, r24
+ rcall Font_Render
+
+ ; Wait
+ ldi XH, high(10 * 1024)
+ ldi XL, low(10 * 1024)
+
+ rcall Timer_Sleep
+
+ ; Next char
+ inc r24
+ cpi r24, 57 + 1 ; '9'
+ brsh stxt_start ; start again from zero
+
+ ; render this char
+ rjmp stxt_loop
+
Main:
init:
; Stack
@@ -222,8 +257,8 @@
; Run
; rcall Main_ScanRaw
; rcall Main_ScanTest
-
- rcall Main_ScanCode
+ ; rcall Main_ScanCode
+ rcall Main_ScanText
end:
rjmp end