33
|
1 |
;; LED Matrix driver
|
|
2 |
;;
|
|
3 |
|
|
4 |
.set MATRIX_DDR = DDRB
|
|
5 |
.set MATRIX_PORT = PORTB
|
|
6 |
.set MATRIX_OE = PORTB1 ; Output Enable, active low, externally pulled high
|
|
7 |
|
|
8 |
.dseg
|
|
9 |
.set MATRIX_COLS = 8 ; number of columns
|
|
10 |
|
|
11 |
matrix_colbit: .byte 1 ; column bit
|
|
12 |
matrix_rowbuf: .byte MATRIX_COLS ; row bitmask by column
|
|
13 |
|
|
14 |
.cseg
|
|
15 |
|
|
16 |
;; Normalize the outputs, enable the matrix, an set up buffers
|
|
17 |
Matrix_Init:
|
|
18 |
; Setup ENable port
|
|
19 |
sbi MATRIX_PORT, MATRIX_OE ; high -> disabled
|
|
20 |
sbi MATRIX_DDR, MATRIX_OE ; out
|
|
21 |
|
|
22 |
; blank hardware
|
|
23 |
ldi r16, 0
|
|
24 |
|
|
25 |
sts spi_outbuf + 0, r16 ; column sinks
|
|
26 |
sts spi_outbuf + 1, r16 ; row drivers
|
|
27 |
|
|
28 |
; write out
|
|
29 |
rcall SPI_SendRecv
|
|
30 |
|
|
31 |
; enable
|
|
32 |
cbi MATRIX_PORT, MATRIX_OE ; low -> enabled
|
|
33 |
|
|
34 |
; init buffers
|
|
35 |
ldi r16, 0b1
|
|
36 |
sts matrix_colbit, r16
|
|
37 |
|
|
38 |
ldi r16, 0
|
|
39 |
ldi r17, MATRIX_COLS
|
|
40 |
ldi YL, low(matrix_rowbuf)
|
|
41 |
ldi YH, high(matrix_rowbuf)
|
|
42 |
|
|
43 |
m_init_mzero:
|
|
44 |
st Y+, r16
|
|
45 |
|
|
46 |
; loop until zero
|
|
47 |
dec r17
|
|
48 |
brne m_init_mzero
|
|
49 |
|
|
50 |
; Use Timer0, 32k cycles -> 500Hz scan rate
|
|
51 |
ldi r16, 32
|
|
52 |
rcall Timer0_Start
|
|
53 |
|
|
54 |
; done
|
|
55 |
ret
|
|
56 |
|
|
57 |
;; Scan the next column
|
|
58 |
;; Interrupt-driven
|
|
59 |
Matrix_ScanCol:
|
|
60 |
; Column bit
|
|
61 |
; load
|
|
62 |
lds r16, matrix_colbit
|
|
63 |
|
|
64 |
; start packet
|
|
65 |
cbi SPI_PORT, SPI_SS
|
|
66 |
|
|
67 |
; output
|
|
68 |
out SPDR, r16
|
|
69 |
|
|
70 |
; Compute col index
|
|
71 |
ldi r17, 0
|
|
72 |
|
|
73 |
m_sc_colidx:
|
|
74 |
; shift
|
|
75 |
lsr r16
|
|
76 |
|
|
77 |
; done if we shifted the bit out
|
|
78 |
brcs m_sc_row
|
|
79 |
|
|
80 |
; count shifts
|
|
81 |
inc r17
|
|
82 |
rjmp m_sc_colidx
|
|
83 |
|
|
84 |
m_sc_row:
|
|
85 |
; Row mask
|
|
86 |
; base
|
|
87 |
ldi XL, low(matrix_rowbuf)
|
|
88 |
ldi XH, high(matrix_rowbuf)
|
|
89 |
|
|
90 |
; offset
|
|
91 |
ldi r18, 0
|
|
92 |
|
|
93 |
add XL, r17
|
|
94 |
adc XH, r18
|
|
95 |
|
|
96 |
; load
|
|
97 |
ld r16, X
|
|
98 |
|
|
99 |
; output
|
|
100 |
rcall SPI_Wait
|
|
101 |
out SPDR, r16
|
|
102 |
|
|
103 |
; Update col bit
|
|
104 |
lds r16, matrix_colbit
|
|
105 |
|
|
106 |
; shift left
|
|
107 |
lsl r16
|
|
108 |
brcc m_sc_colout
|
|
109 |
|
|
110 |
; overflow, take bit from C
|
|
111 |
rol r16
|
|
112 |
|
|
113 |
m_sc_colout:
|
|
114 |
; store
|
|
115 |
sts matrix_colbit, r16
|
|
116 |
|
|
117 |
; End of packet
|
|
118 |
rcall SPI_Wait
|
|
119 |
sbi SPI_PORT, SPI_SS
|
|
120 |
|
|
121 |
; Done
|
|
122 |
ret
|
|
123 |
|
|
124 |
;; Scan the matrix once in one go
|
|
125 |
Matrix_ScanFull:
|
|
126 |
; Row index
|
|
127 |
ldi ZL, low(matrix_rowbuf)
|
|
128 |
ldi ZH, high(matrix_rowbuf)
|
|
129 |
|
|
130 |
; Column bit
|
|
131 |
ldi r25, 0
|
|
132 |
sec ; set C
|
|
133 |
|
|
134 |
m_pulse_col:
|
|
135 |
; rotate bit left from C
|
|
136 |
rol r25
|
|
137 |
|
|
138 |
; overflow
|
|
139 |
brcs m_pulse_end
|
|
140 |
|
|
141 |
; store in output buffer
|
|
142 |
sts spi_outbuf + 1, r25
|
|
143 |
|
|
144 |
; Row mask
|
|
145 |
ld r16, Z+
|
|
146 |
|
|
147 |
sts spi_outbuf + 0, r16
|
|
148 |
|
|
149 |
; Display
|
|
150 |
rcall SPI_SendRecv
|
|
151 |
|
|
152 |
; Next column
|
|
153 |
rjmp m_pulse_col
|
|
154 |
|
|
155 |
m_pulse_end:
|
|
156 |
; Done
|
|
157 |
ret
|
|
158 |
|