Rev Author Line No. Line
3471 miho 1 /**
2 * \brief Size-optimized code for TPI
3 * \file tpi.s
4 * \author S³awomir Fraœ
5 */
6 #include <avr/io.h>
7 #include "tpi_defs.h"
8  
9  
10 #define TPI_CLK_PORT PORTB
11 #define TPI_CLK_DDR DDRB
12 #define TPI_CLK_BIT 5
13 #define TPI_DATAOUT_PORT PORTB
14 #define TPI_DATAOUT_DDR DDRB
15 #define TPI_DATAOUT_BIT 3
16 #ifdef TPI_WITH_OPTO
17 # define TPI_DATAIN_PIN PINB
18 # define TPI_DATAIN_DDR DDRB
19 # define TPI_DATAIN_BIT 4
20 #else
21 # define TPI_DATAIN_PIN PINB
22 # define TPI_DATAIN_BIT 3
23 #endif
24  
25 .comm tpi_dly_cnt, 2
26  
27  
28 /**
29 * TPI init
30 */
31 .global tpi_init
32 tpi_init:
33 /* CLK <= out */
34 sbi _SFR_IO_ADDR(TPI_CLK_DDR), TPI_CLK_BIT
35 #ifdef TPI_WITH_OPTO
36 /* DATAIN <= pull-up */
37 cbi _SFR_IO_ADDR(TPI_DATAIN_DDR), TPI_DATAIN_BIT
38 sbi _SFR_IO_ADDR(TPI_DATAIN_PORT), TPI_DATAIN_BIT
39 /* DATAOUT <= high */
40 sbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT
41 sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT
42 #else
43 /* DATA <= pull-up */
44 cbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT
45 sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT
46 #endif
47  
48 /* 32 bits */
49 ldi r21, 32
50 1:
51 rcall tpi_bit_h
52 dec r21
53 brne 1b
54  
55 ret
56  
57  
58 /**
59 * Update PR
60 * in: r25:r24 <= PR
61 * lost: r18-r21,r24,r30-r31
62 */
63 tpi_pr_update:
64 movw r20, r24
65 ldi r24, TPI_OP_SSTPR(0)
66 rcall tpi_send_byte
67 mov r24, r20
68 rcall tpi_send_byte
69 ldi r24, TPI_OP_SSTPR(1)
70 rcall tpi_send_byte
71 mov r24, r21
72 // rjmp tpi_send_byte
73  
74  
75 /**
76 * Send one byte
77 * in: r24 <= byte
78 * lost: r18-r19,r30-r31
79 */
80 .global tpi_send_byte
81 tpi_send_byte:
82 /* start bit */
83 rcall tpi_bit_l
84 /* 8 data bits */
85 ldi r18, 8
86 ldi r19, 0
87 1:
88 // parity
89 eor r19, r24
90 // get bit, shift
91 bst r24, 0
92 lsr r24
93 // send
94 rcall tpi_bit
95 dec r18
96 brne 1b
97 /* parity bit */
98 bst r19, 0
99 rcall tpi_bit
100 /* 2 stop bits */
101 rcall tpi_bit_h
102 // rjmp tpi_bit_h
103  
104  
105 /**
106 * Exchange of one bit
107 * in: T <= bit_in
108 * out: T => bit_out
109 * lost: r30-r31
110 */
111 tpi_bit_h:
112 set
113 tpi_bit:
114 /* TPIDATA = T */
115 #ifdef TPI_WITH_OPTO
116 // DATAOUT = high (opto should allow TPIDATA to be pulled low by external device)
117 // if(T == 0)
118 // DATAOUT = low
119 sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT
120 brts 1f
121 tpi_bit_l:
122 cbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT
123 1:
124 #else
125 // DATAOUT = pull-up
126 // if(T == 0)
127 // DATAOUT = low
128 cbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT
129 sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT
130 brts 1f
131 tpi_bit_l:
132 cbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT
133 sbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT
134 1:
135 #endif
136 /* delay(); */
137 lds r30, tpi_dly_cnt
138 lds r31, tpi_dly_cnt+1
139 1:
140 sbiw r30, 1
141 brsh 1b
142 /* TPICLK = 1 */
143 sbi _SFR_IO_ADDR(TPI_CLK_PORT), TPI_CLK_BIT
144 /* T = TPIDATA */
145 in r30, _SFR_IO_ADDR(TPI_DATAIN_PIN)
146 bst r30, TPI_DATAIN_BIT
147 /* delay(); */
148 lds r30, tpi_dly_cnt
149 lds r31, tpi_dly_cnt+1
150 1:
151 sbiw r30, 1
152 brsh 1b
153  
154 /* TPICLK = 0 */
155 cbi _SFR_IO_ADDR(TPI_CLK_PORT), TPI_CLK_BIT
156 ret
157  
158  
159 /**
160 * Receive one byte
161 * out: r24 => byte
162 * lost: r18-r19,r30-r31
163 */
164 .global tpi_recv_byte
165 tpi_recv_byte:
166 /* waitfor(start_bit, 192); */
167 ldi r18, 192
168 1:
169 rcall tpi_bit_h
170 brtc .tpi_recv_found_start
171 dec r18
172 brne 1b
173 /* no start bit: set return value */
174 .tpi_break_ret0:
175 ldi r24, 0
176 /* send 2 breaks (24++ bits) */
177 ldi r18, 26
178 1:
179 rcall tpi_bit_l
180 dec r18
181 brne 1b
182 /* send hi */
183 rjmp tpi_bit_h
184  
185 // ----
186 .tpi_recv_found_start:
187 /* recv 8bits(+calc.parity) */
188 ldi r18, 8
189 ldi r19, 0
190 1:
191 rcall tpi_bit_h
192 lsr r24
193 bld r24, 7
194 eor r19, r24
195 dec r18
196 brne 1b
197 /* recv parity */
198 rcall tpi_bit_h
199 bld r18, 7
200 eor r19, r18
201 brmi .tpi_break_ret0
202 /* recv stop bits */
203 rcall tpi_bit_h
204 rjmp tpi_bit_h
205  
206  
207 /**
208 * Read Block
209 */
210 .global tpi_read_block
211 tpi_read_block:
212 // X <= dptr
213 movw XL, r22
214 // r23 <= len
215 mov r23, r20
216 /* set PR */
217 rcall tpi_pr_update
218 /* read data */
219 .tpi_read_loop:
220 ldi r24, TPI_OP_SLD_INC
221 rcall tpi_send_byte
222 rcall tpi_recv_byte
223 st X+, r24
224 dec r23
225 brne .tpi_read_loop
226 ret
227  
228  
229 /**
230 * Write block
231 */
232 .global tpi_write_block
233 tpi_write_block:
234 // X <= sptr
235 movw XL, r22
236 // r23 <= len
237 mov r23, r20
238 /* set PR */
239 rcall tpi_pr_update
240 /* write data */
241 .tpi_write_loop:
242 ldi r24, TPI_OP_SOUT(NVMCMD)
243 rcall tpi_send_byte
244 ldi r24, NVMCMD_WORD_WRITE
245 rcall tpi_send_byte
246 ldi r24, TPI_OP_SST_INC
247 rcall tpi_send_byte
248 ld r24, X+
249 rcall tpi_send_byte
250 .tpi_nvmbsy_wait:
251 ldi r24, TPI_OP_SIN(NVMCSR)
252 rcall tpi_send_byte
253 rcall tpi_recv_byte
254 andi r24, NVMCSR_BSY
255 brne .tpi_nvmbsy_wait
256 dec r23
257 brne .tpi_write_loop
258 ret