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