Factor out all the ISP related code into a seperate ISPProtocol set of files in the...
[pub/USBasp.git] / Projects / XPLAINBridge / Lib / SoftUART.S
1 /*
2
3 uart_soft
4
5 v0.2
6
7 copyright John Steggall 2009
8
9 */
10
11
12 /*
13 Copyright 2009 John Steggall (steggall.j@gmail.com)
14
15 Permission to use, copy, modify, and distribute this software
16 and its documentation for any purpose and without fee is hereby
17 granted, provided that the above copyright notice appear in all
18 copies and that both that the copyright notice and this
19 permission notice and warranty disclaimer appear in supporting
20 documentation, and that the name of the author not be used in
21 advertising or publicity pertaining to distribution of the
22 software without specific, written prior permission.
23
24 The author disclaim all warranties with regard to this
25 software, including all implied warranties of merchantability
26 and fitness. In no event shall the author be liable for any
27 special, indirect or consequential damages or any damages
28 whatsoever resulting from loss of use, data or profits, whether
29 in an action of contract, negligence or other tortious action,
30 arising out of or in connection with the use or performance of
31 this software.
32 */
33
34 #include <avr/io.h>
35 #include "SoftUARTConf.h"
36
37
38 #define SFT_TX_EN 7
39
40 #define SF_UART_TX 1
41 #define SF_UART_RX 2
42
43 .section .data
44
45 rxdata:
46 .byte 0
47 txShifter:
48 .byte 0
49 txBitcount:
50 .byte 0
51 rxShifter:
52 .byte 0
53 rxBitcount:
54 .byte 0
55
56 .global status
57 status:
58 .byte 0
59
60 .section .text
61
62
63 .global RX_PIN_INT
64
65 /*********************************************
66 * External interrupt
67 *
68 * RX pin has gone low.
69 */
70 RX_PIN_INT:
71 push r16
72 lds r16,SREG
73 push r16
74
75 #if (RXPORT>=32)
76 lds r16,RXPORT
77 sbrc r16,0 // anti glitch
78
79 #else
80 sbic RXPORT,0
81 #endif
82
83 rjmp ignore
84 nop
85 nop
86 nop
87 nop
88
89 #if (RXPORT>=32)
90 lds r16,RXPORT
91 sbrc r16,0 // anti glitch
92
93 #else
94 sbic RXPORT,0
95 #endif
96
97 rjmp ignore
98
99 push r17
100
101 // grab timer value
102 lds r16,TC_COUNTL
103 lds r17,TC_COUNTH
104
105 // set trigger for RX timer (will need to add a little more though)
106 sts TC_RX_COMPH,r17
107 sts TC_RX_COMPL,r16
108
109 pop r17
110
111 // set bitcount to 0
112 ldi r16,0
113 sts rxBitcount,r16
114
115
116 // turn off interrupt, will get annoying.
117 cbi EXTI_MASK_REG,EXTI_MASK_BIT
118
119 // turn on interrupt on compare match
120
121 sbi TC_INTFLAG_REG,TC_RX_IF_BIT
122
123 lds r16,TC_INT_MASK_REG
124 ori r16,(1<<TC_RX_COMPEN)
125 sts TC_INT_MASK_REG,r16
126
127 ignore:
128 pop r16
129 sts SREG,r16
130 pop r16
131 reti
132
133
134 /*********************************************
135 * interrupt routine, timer compare match.
136 *
137 * TX bit rate timing
138 */
139 .global TIMER3_COMPB_vect
140
141 TIMER3_COMPB_vect:
142 push r16
143 lds r16,SREG
144 push r16
145 push r17
146 push r18
147
148 // check if the last bit was sent
149 lds r17,txBitcount
150 inc r17
151 cpi r17,0x0A
152 sts txBitcount,r17
153 breq lastBitTX
154
155 lds r16,txShifter
156
157 #if (TXPORT>=32)
158 lds r17, TXPORT
159 sbrs r16,0
160 andi r17,~(1<<TXPIN)
161 sbrc r16,0
162 ori r17,(1<<TXPIN)
163 sts TXPORT,r17
164
165 #else
166 sbrs r16,0
167 cbi TXPORT,TXPIN
168 sbrc r16,0
169 sbi TXPORT,TXPIN
170
171 #endif
172 sec
173 ror r16
174
175 txout:
176 sts txShifter,r16
177 lastBitOut:
178 pop r18
179 pop r17
180 pop r16
181 sts SREG,r16
182 pop r16
183 reti
184
185 // section handles the last bit (stop bit sent/received and sets the flag to say done //
186 lastBitTX:
187 lds r17,status // get status
188 ori r17,SF_UART_TX // set TXC/DRE flag
189 sts status,r17
190
191 lds r16,TC_INT_MASK_REG
192 andi r16,~(1<<TC_TX_COMPEN)
193 sts TC_INT_MASK_REG,r16
194
195 rjmp lastBitOut // over and out
196
197
198
199 /*********************************************
200 * interrupt routine, timer compare match.
201 *
202 * RX bit rate timing
203 */
204 .global TIMER3_COMPC_vect
205
206 TIMER3_COMPC_vect:
207 push r16
208 lds r16,SREG
209 push r16
210 push r17
211 push r18
212
213 // check if the last bit has been recieved
214 lds r17,rxBitcount
215 inc r17
216 cpi r17,0x0A
217 sts rxBitcount,r17
218 breq lastBitRX
219
220 cpi r17,0x01
221 breq rx1stbit
222
223 ldi r18,3 // set counter to 3
224 ldi r17,0
225
226 #ifdef DEBUG
227
228 #if RXPORT>64
229 lds r16,RXPORT
230 andi r16,~(1<<TXPIN)
231 sts TXPORT,r16
232 #else
233 cbi TXPORT,TXPIN // marker
234 #endif
235 #endif
236
237 loopGetBit:
238
239 #if (RXPORT>=32)
240 lds r16,RXPORT
241 sbrs r16,RXPIN
242 #else
243 sbic RXPORT,RXPIN
244
245 #endif
246
247 inc r17
248 dec r18
249 nop
250 nop
251 nop
252 nop
253 brne loopGetBit
254
255 #ifdef DEBUG
256
257 #if RXPORT>64
258 lds r16,RXPORT
259 ori r16,1<<TXPIN
260 sts r16
261
262 #else
263 sbi TXPORT,TXPIN // marker
264
265 #endif
266 #endif
267
268
269 lds r16,rxShifter
270 lsr r16
271
272 cpi r17,2
273 brlo skipBitSet
274 ori r16,0x80
275 skipBitSet:
276 sts rxShifter,r16
277 rjmp lastBitOut
278
279 lastBitRX:
280 lds r17,status // store status
281
282 #if (RXPORT>=32)
283 lds r16,RXPORT
284 sbrc r16,RXPIN
285
286 #else
287 sbic RXPORT,RXPIN
288
289 #endif
290
291 ori r17,0x02 // set flag if stop bit was high
292 sts status,r17
293
294 lds r16,rxShifter // get contents of shifter
295 sbrc r17,1 // check if we just received a valid byte
296 sts rxdata,r16 // if valid rxdata = shifter
297
298 // switch interrupt back on to get another go
299
300 sbi EXTI_FLAG_REG,EXTI_MASK_BIT // clear interrupt flag
301 sbi EXTI_MASK_REG,EXTI_MASK_BIT // enable external interrupt 0 (RX)
302
303 // switch off rx bit timer
304 lds r16,TC_INT_MASK_REG
305 andi r16,~(1<<TC_RX_COMPEN)
306 sts TC_INT_MASK_REG,r16
307
308 rjmp lastBitOut // loud and clear
309
310 rx1stbit:
311 lds r16,TC_COUNTL
312 lds r17,TC_COUNTH
313
314 subi r16,lo8(BITLENGTH / 2)
315 sbci r17,hi8(BITLENGTH / 2)
316 brcc skipOverflow
317
318 subi r16,lo8(0xFFFF - BITLENGTH)
319 sbci r17,hi8(0xFFFF - BITLENGTH)
320
321 skipOverflow:
322 sts TC_RX_COMPH,r17
323 sts TC_RX_COMPL,r17
324 rjmp lastBitOut
325
326
327 /*********************************************
328 * void SoftUART_Init(void)
329 *
330 * initialises software uart and enables transmit
331 */
332 .global SoftUART_Init
333
334 SoftUART_Init:
335
336 #if (TXPORT>=32)
337 lds r18,TXPORT
338 ori r18,0x02
339 sts TXPORT,r18
340
341 lds r18,TXDIR_REG
342 ori r18,0x02
343 sts TXDIR_REG,r18
344
345 #else
346 sbi TXPORT,TXPIN
347 sbi TXDIR_REG,TXPIN
348
349 #endif
350
351 ldi r18,(1<<SFT_TX_EN)|SF_UART_TX
352 sts status,r18
353
354 ldi r18,lo8(BITLENGTH)
355 ldi r19,hi8(BITLENGTH)
356 sts OCR3AH,r19
357 sts OCR3AL,r18
358
359 // Start timer 3
360 ldi r18,0b00001001 // ctc count mode, clock div 1
361 sts TC_CTRLB,r18
362
363 // Interrupt on pin change INT0
364 sbi EXTI_FLAG_REG,EXTI_MASK_BIT
365 sbi EXTI_MASK_REG,EXTI_MASK_BIT
366
367 ret
368
369
370 /*********************************************
371 * char SoftUART_RxByte(char)
372 *
373 * starts a byte send and returns the byte to be sent
374 */
375 .global SoftUART_TxByte
376
377 SoftUART_TxByte:
378 lds r18,status
379 sbrs r18,SFT_TX_EN
380 rjmp SoftUART_TxByte_end
381
382 andi r18,0xFE // clear tx empty flag
383 sts status,r18
384
385 sts txShifter,r24
386
387 ldi r18,0
388 sts txBitcount,r18
389
390 // grab timer value
391 cli // Atomic section start
392 lds r18,TC_COUNTL
393 lds r19,TC_COUNTH
394
395 // drop down tx line for start bit
396
397 #if (TXPORT>=32)
398 lds r20, TXPORT
399 andi r20,~(1<<TXPIN)
400 sts TXPORT,r20
401
402 #else
403 cbi TXPORT,TXPIN
404 #endif
405
406 // set trigger for tx timer
407 sts TC_TX_COMPH,r19
408 sts TC_TX_COMPL,r18
409 sei // Atomic section end
410
411 // clear interrupt flag and enable tx interrupt
412
413 sbi TC_INTFLAG_REG,TC_TX_IF_BIT
414
415 lds r18,TC_INT_MASK_REG
416 ori r18,(1<<TC_TX_COMPEN)
417 sts TC_INT_MASK_REG,r18
418
419 SoftUART_TxByte_end:
420 ret
421
422
423 /*********************************************
424 * char SoftUART_RxByte(void)
425 *
426 * returns the received byte
427 */
428 .global SoftUART_RxByte
429
430 SoftUART_RxByte:
431 lds r24,rxdata
432 lds r18,status
433 andi r18,0xFD
434 sts status,r18
435 ret
436
437
438 /*********************************************
439 * char SoftUART_IsReceived(void)
440 *
441 * checks if there is a byte in the receive buffer
442 */
443 .global SoftUART_IsReceived
444
445 SoftUART_IsReceived:
446 lds r24,status
447 andi r24,SF_UART_RX
448 lsr r24
449 ret
450
451
452 /*********************************************
453 * char SoftUART_IsReady(void)
454 *
455 * Simulates polling UDRE to see if tx buffer is empty and ready
456 *
457 * returns 1 if empty 0 if not
458 */
459 .global SoftUART_IsReady
460
461 SoftUART_IsReady:
462 lds r24,status
463 andi r24,SF_UART_TX
464 ret