--- 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
-