--- a/Makefile Sun Aug 29 22:49:32 2010 +0300
+++ b/Makefile Mon Aug 30 00:45:38 2010 +0300
@@ -13,7 +13,7 @@
all: $(PROG).hex
-matrix.hex: spi.inc matrix.inc timer.inc delay.inc macros.inc font.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
--- a/font-compile.py Sun Aug 29 22:49:32 2010 +0300
+++ b/font-compile.py Mon Aug 30 00:45:38 2010 +0300
@@ -50,8 +50,14 @@
# skip
return None
+
+ elif len(ascii) == 1 :
+ print 'read_charblock', 'simplechar', ascii
+
+ else :
+ ascii = ascii.decode('string_escape')
- print 'read_charblock', 'ascii', ascii
+ print 'read_charblock', 'decodechar', ascii
assert len(ascii) == 1
@@ -119,7 +125,7 @@
"""
fh.write(
- ("; '%s'\n" % ascii)
+ ("; %r\n" % ascii)
+ (".db %s\n" % (', '.join(bin(col) for col in cols)))
+ ("\n")
)
@@ -143,9 +149,11 @@
charmap[ascii] = cols
print 'compile_fonts', 'read', ascii
-
- font_start = '0'
- font_end = '9'
+
+ # detect min/max syms
+ syms = charmap.keys()
+ font_start = min(syms)
+ font_end = max(syms)
assert(ord(font_start) < ord(font_end))
@@ -153,17 +161,20 @@
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_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"
)
- for char in xrange(ord('0'), ord('9') + 1) :
+ # default symbol for unknown chars
+ defsym = charmap['\0']
+
+ for char in xrange(ord(font_start), ord(font_end) + 1) :
ascii = chr(char)
- cols = charmap[ascii]
+ cols = charmap.get(ascii, defsym)
write_chardef(outf, ascii, cols)
--- a/font.inc Sun Aug 29 22:49:32 2010 +0300
+++ b/font.inc Mon Aug 30 00:45:38 2010 +0300
@@ -23,17 +23,26 @@
; test under-range
ldi r17, FONT_START
cp r16, r17
- brlt f_render_invalid
+ brlt font_r_invalid
; test over-range
ldi r17, FONT_END
cp r17, r16
- brlt f_render_invalid
+ brlt font_r_invalid
- ; Locate font char
; 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
@@ -49,16 +58,15 @@
; Copy column pixel data
; count columns
ldi r16, FONT_COLS
-f_render_cpy:
+font_r_cpy:
; copy via r17
lpm r17, Z+
st Y+, r17
dec r16
- brne f_render_cpy
+ brne font_r_cpy
-f_render_invalid:
; Done
ret
--- a/font.txt Sun Aug 29 22:49:32 2010 +0300
+++ b/font.txt Mon Aug 30 00:45:38 2010 +0300
@@ -1,3 +1,33 @@
+; \x00
+------
+-####-
+-#--#-
+-#--#-
+-#--#-
+-#--#-
+-####-
+------
+
+; \x20
+------
+------
+------
+------
+------
+------
+------
+------
+
+; !
+--##--
+--##--
+--##--
+--##--
+--##--
+------
+--##--
+--##--
+
; 0
-####-
#----#
@@ -98,6 +128,76 @@
-----#
----#-
+; h
+#-----
+#-----
+#-----
+#-----
+#-###-
+##---#
+#----#
+#----#
+
+; e
+--##--
+-#--#-
+#----#
+######
+#-----
+#---#-
+-###--
+------
+
+; l
+--##--
+---#--
+---#--
+---#--
+---#--
+---#--
+---#--
+--###-
+
+; o
+------
+------
+------
+-####-
+#----#
+#----#
+#----#
+-####-
+
+; w
+------
+------
+------
+#---#-
+#---#-
+#---#-
+#-#-#-
+-#-#--
+
+; r
+------
+------
+#-----
+#-##--
+##----
+#-----
+#-----
+#-----
+
+; d
+----#-
+----#-
+----#-
+-####-
+#---#-
+#---#-
+#---#-
+-###--
+
;
------
------
--- a/matrix.inc Sun Aug 29 22:49:32 2010 +0300
+++ b/matrix.inc Mon Aug 30 00:45:38 2010 +0300
@@ -39,6 +39,17 @@
; 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
@@ -258,3 +269,155 @@
; 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 Sun Aug 29 22:49:32 2010 +0300
+++ b/matrix.s Mon Aug 30 00:45:38 2010 +0300
@@ -202,33 +202,23 @@
Main_ScanText:
-stxt_start:
- ; char to render
- ldi r24, 48 ; '0'
+ ; Constants
+stxt_message: ; text to render
+ .db 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x0 ; 'hello world!'
- ; 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
+ ; Load into buffer
+ ldi ZL, low(stxt_message * 2)
+ ldi ZH, high(stxt_message * 2)
- ; Wait
- ldi XH, high(10 * 1024)
- ldi XL, low(10 * 1024)
-
- rcall Timer_Sleep
+ rcall Text_LoadString
- ; Next char
- inc r24
- cpi r24, 57 + 1 ; '9'
- brsh stxt_start ; start again from zero
+sbi PORTD, PIND7
- ; render this char
- rjmp stxt_loop
+ ; Display
+ rcall Text_ShowString
+
+ ; Done
+ ret
Main:
init: