]> cloudbase.mooo.com Git - avrcpm.git/blob - avr/timer.asm
* MMC/SD Bootloader support
[avrcpm.git] / avr / timer.asm
1 ; Timer module
2 ;
3 ; Copyright (C) 2010 Leo C.
4 ;
5 ; This file is part of avrcpm.
6 ;
7 ; avrcpm is free software: you can redistribute it and/or modify it
8 ; under the terms of the GNU General Public License as published by
9 ; the Free Software Foundation, either version 3 of the License, or
10 ; (at your option) any later version.
11 ;
12 ; avrcpm is distributed in the hope that it will be useful,
13 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ; GNU General Public License for more details.
16 ;
17 ; You should have received a copy of the GNU General Public License
18 ; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
19 ;
20 ; $Id$
21 ;
22
23 .dseg
24
25 timer_var:
26 delay_timer1:
27 .equ ot_timer1 = delay_timer1-timer_var
28 .byte 1
29 delay_timer2:
30 .equ ot_timer2 = delay_timer2-timer_var
31 .byte 1
32 timer_base:
33 timer_ms:
34 .equ ot_ms = timer_ms-timer_var
35 .byte 2
36 timer_sec:
37 .equ ot_sec = timer_sec-timer_var
38 .byte 4
39
40 ; don't change order here, clock put/get depends on it.
41 cntms_out: ; register for ms
42 .byte 2
43 utime_io: ; register for uptime.
44 .byte 4
45 cnt_1ms:
46 .equ ot_1ms = cnt_1ms-timer_var
47 .byte 2
48 uptime:
49 .equ ot_uptime = uptime-timer_var
50 .byte 4
51 timer_top:
52 .equ timer_size = timer_top - timer_base
53
54 .equ utofs = cnt_1ms-cntms_out
55 .equ timerofs = cnt_1ms-timer_ms
56
57 clk_out:
58 .equ oclk_out = clk_out-timer_var
59 .byte 7 ;
60 clock:
61 .equ o_clock = clock-timer_var
62 .byte 7 ;Format (bin): s m h D M YY
63 .equ clkofs = clock-clk_out
64
65 .cseg
66
67 ; ------------- system timer 1ms ---------------
68
69
70 ; Timer/Counter1 Compare Match B interrupt
71
72 INTERRUPT OC1Baddr
73
74 .if TIMER_DEBUG
75 cbi PORTC,5
76 .endif
77 push zl
78 in zl,SREG
79 push zl
80 push zh
81 inm8 zl,OCR1BL
82 inm8 zh,OCR1BH
83 addiw z,F_CPU/1000
84 outm8 OCR1BH,zh
85 outm8 OCR1BL,zl
86
87 push yl
88 push yh
89 ldiw y,timer_var
90
91 #if DRAM_8BIT /* Implies software uart */
92 lds zl,srx_char_to ;try to decrement character timout
93 subi zl,1
94 brcs syscl0 ;timer was 0 before (not running)
95 sts srx_char_to,zl ;timer is running, store new value
96 brne syscl0
97 rcall srx_to
98 syscl0:
99 #endif
100 ldd zl,y+ot_timer1
101 subi zl,1
102 brcs syscl_t1n
103 std y+ot_timer1,zl
104 syscl_t1n:
105 ldd zl,y+ot_timer2
106 subi zl,1
107 brcs syscl_t2n
108 std y+ot_timer2,zl
109 syscl_t2n:
110
111 ldd zl,y+ot_1ms ;count milli seconds
112 ldd zh,y+ot_1ms+1
113 adiw z,1
114 std y+ot_1ms,zl
115 std y+ot_1ms+1,zh
116 cpi zl,low(1000) ;one second ?
117 ldi zl,high(1000) ;doesn't change flags
118 cpc zh,zl
119 brlt syscl_end
120 ; brge syscl_utime
121 ; rjmp syscl_end
122
123 syscl_utime:
124 std y+ot_1ms,_0
125 std y+ot_1ms+1,_0
126
127 ldd zl,y+ot_uptime+0
128 ldd zh,y+ot_uptime+1
129 adiw z,1
130 std y+ot_uptime+0,zl
131 std y+ot_uptime+1,zh
132 brne syscl_clk
133 ldd zl,y+ot_uptime+2
134 ldd zh,y+ot_uptime+3
135 adiw z,1
136 std y+ot_uptime+2,zl
137 std y+ot_uptime+3,zh
138
139 syscl_clk:
140 ldd zl,y+o_clock+0 ;sec
141 inc zl
142 std y+o_clock+0,zl
143 cpi zl,60
144 brlo syscl_end
145 std y+o_clock+0,_0
146 ldd zl,y+o_clock+1 ;min
147 inc zl
148 std y+o_clock+1,zl
149 cpi zl,60
150 brlo syscl_end
151 std y+o_clock+1,_0
152 ldd zl,y+o_clock+2 ;hour
153 inc zl
154 std y+o_clock+2,zl
155 cpi zl,24
156 brlo syscl_end
157
158 syscl_clk_date:
159 std y+o_clock+2,_0
160 push temp
161
162 ldiw z,dayspm_tab*2 - 1
163 ldd temp,y+o_clock+4 ;month
164 add zl,temp
165 adc zh,_0
166 lpm zh,z ;days this month
167 cpi temp,2
168 brne syscl_clknl ;february, may be leap year
169 ldd zl,y+o_clock+5 ;year
170 andi zl,0x03
171 brne syscl_clknl
172 inc zh ;leap year
173 syscl_clknl:
174 ldd zl,y+o_clock+3 ;day
175 inc zl
176 std y+o_clock+3,zl
177 cp zh,zl
178 brsh syscl_clke
179 ldi zl,1
180 std y+o_clock+3,zl
181 inc temp ;month
182 std y+o_clock+4,temp
183 cpi temp,13
184 brlo syscl_clke
185
186 std y+o_clock+4,zl
187 ldd zl,y+o_clock+5 ;low year
188 ldd zh,y+o_clock+6 ;high year
189 adiw z,1
190 std y+o_clock+5,zl
191 std y+o_clock+6,zh
192
193 syscl_clke:
194 pop temp
195 syscl_end:
196 pop yh
197 pop yl
198 pop zh
199 pop zl
200 out SREG,zl
201 pop zl
202 .if TIMER_DEBUG
203 sbi PORTC,5
204 .endif
205 reti
206
207 ; days per month
208
209 dayspm_tab:
210 .db 31,28,31,30,31,30
211 .db 31,31,30,31,30,31
212
213 ; ----------------------------------------------
214 ; delay
215 ;
216 ; wait for temp ms
217 ;
218
219 delay_ms:
220 sts delay_timer1,temp
221 dly_loop:
222 lds temp,delay_timer1
223 cpi temp,0
224 brne dly_loop
225 ret
226
227 ; ----------------------------------------------
228 ;
229 clockget:
230 ldiw z,clk_out
231 tst temp3
232 breq clkget_copy ;lowest byte requestet, latch clock
233
234 add zl,temp3
235 adc zh,_0
236 ld temp,z
237 clkget_end:
238 ret
239
240
241 clkget_copy:
242 ldi temp3,7
243 cli
244 clkget_l:
245 ldd temp,z+clkofs
246 st z+,temp
247 dec temp3
248 brne clkget_l
249 sei
250
251 ld temp2,-z
252 ld temp, -z
253 rcall binbcd4
254 std z+0,temp
255 std z+1,temp2
256 ldi temp3,5
257 clkget_l2:
258 ld temp,-z
259 rcall binbcd2
260 st z,temp
261 dec temp3
262 brne clkget_l2
263
264 lds temp,clk_out
265 ret ;req. byte in temp
266
267 ; ----------------------------------------------
268 ;
269 clockput:
270 ldiw z,clk_out
271 add zl,temp3
272 adc zh,_0
273 st z,temp
274 tst temp3
275 breq clkput_copy ;lowest byte stored, latch clock
276 clkput_end:
277 ret
278
279
280 clkput_copy:
281 ldi temp3,5
282 clkput_l2:
283 ld temp,z
284 rcall bcdbin2
285 st z+,temp
286 dec temp3
287 brne clkput_l2
288
289 ldd temp,z+0
290 ldd temp2,z+1
291 rcall bcdbin4
292 st z+,temp
293 st z+,temp2
294
295 ldi temp3,7
296 cli
297 clkput_l:
298 ld temp,-z
299 std z+clkofs,temp
300 dec temp3
301 brne clkput_l
302 sei
303 #if I2C
304 rcall rtc_set ; set hardware clock
305 #endif
306 ret
307
308
309 ; ----------------------------------------------
310
311 ; convert binary to bcd
312 ; (only range 0 - 99)
313
314 binbcd2:
315 push temp2
316 ldi temp2,10
317 mov _tmp0,_255
318 tobcd_l:
319 inc _tmp0
320 sub temp,temp2
321 brcc tobcd_l
322 add temp,temp2
323 swap _tmp0
324 add temp,_tmp0
325 pop temp2
326 ret
327
328
329 binbcd4:
330 ldi temp3,16
331 movw _tmp0,temp
332 clr temp
333 clr temp2
334 binbcd4l:
335 lsl _tmp0
336 rol _tmp1
337 rol temp
338 rol temp2
339 dec temp3
340 breq binbcd4e
341
342 subi temp2,-0x03
343 sbrs temp2,3
344 subi temp2,0x03
345 subi temp2,-0x30
346 sbrs temp2,7
347 subi temp2,0x30
348 subi temp,-0x03
349 sbrs temp,3
350 subi temp,0x03
351 subi temp,-0x30
352 sbrs temp,7
353 subi temp,0x30
354 rjmp binbcd4l
355
356 binbcd4e:
357 ret
358
359 ; convert bcd to binary
360
361 bcdbin2:
362 push temp2
363 mov temp2,temp ;temp2 = high digit
364 swap temp2
365 andi temp2,0x0f
366 andi temp,0x0f ;temp = low digit
367 mov _tmp0,temp2
368 ldi temp2,10
369 mul temp2,_tmp0 ;high digit * 10
370 add temp,_tmp0 ;high digit * 10 + low digit
371 pop temp2
372 ret
373
374 bcdbin4:
375 rcall bcdbin2
376 push temp
377 mov temp,temp2
378 rcall bcdbin2
379 ldi temp2,100
380 mul temp,temp2
381 pop temp
382 mov temp2,_tmp1
383 add temp,_tmp0
384 adc temp2,_0
385 ret
386
387
388 #if I2C
389
390 ; ----------------------------------------------
391 ; Set software clock from hardware clock
392
393 rtc_get:
394 push _0 ;Placeholder for month/weekday
395 push _0 ;day/year
396 push _0 ;hours
397 push _0 ;minutes
398 ldi temp,0x10 ;register address
399 push temp ;save reg adr/placeholder for sec
400 in zh,sph
401 in zl,spl
402 ldi temp,0xA0 ;PCF8583 slave address
403 push temp
404
405 ldi temp2,2
406 rcall i2c_write
407 ldi temp2,3
408 rcall i2c_read ;get year (stored in RTC-RAM addr. 10h)
409 tst temp
410 brmi rtc_get_e ;i2c error
411
412 ldd temp3,z+1 ;save year
413 ldd temp4,z+2
414
415 ldi temp2,2 ;register pointer. 2 = secs
416 std z+1,temp2
417 rcall i2c_write
418 ldi temp2,6
419 rcall i2c_read
420 tst temp
421 brmi rtc_get_e
422
423 ldd temp,z+4 ;get year
424 rol temp
425 rol temp
426 rol temp
427 eor temp,temp3
428 andi temp,0x03
429 breq rtc_get_1
430 inc temp3
431 adc temp4,_0
432 rtc_get_1:
433 ldiw x,clock
434 cli
435
436 ldd temp,z+1 ;get seconds
437 rcall bcdbin2
438 st x+,temp
439 ldd temp,z+2 ;get minutes
440 rcall bcdbin2
441 st x+,temp
442 ldd temp,z+3 ;get hours
443 rcall bcdbin2
444 st x+,temp
445 ldd temp,z+4 ;get day
446 andi temp,0x3f
447 rcall bcdbin2
448 st x+,temp
449 ldd temp,z+5 ;get months
450 andi temp,0x1f
451 rcall bcdbin2
452 st x+,temp ;store month
453 st x+,temp3 ;store year
454 st x+,temp4 ;store year century
455 sei
456
457 rtc_get_e:
458 pop temp
459 pop temp
460 pop temp
461 pop temp
462 pop temp
463 pop temp
464 ret
465
466 ;----------------------------------------------
467 ; Set hardware clock from software clock
468 ;
469 ; Register: temp2: s
470 ; temp3: m
471 ; temp4: h
472 ; xl: D
473 ; temp: M
474 ; yl: Yl
475 ; yh: Yh
476
477 rtc_set:
478 ldiw z,clock
479 cli
480 ldd temp2,z+0 ;sec
481 ldd temp3,z+1 ;min
482 ldd temp4,z+2 ;hours
483 ldd xl,z+3 ;day
484 ldd temp,z+4 ;month
485 ldd yl,z+5 ;yearl
486 ldd yh,z+6 ;yearh
487 sei
488 rcall binbcd2
489 push temp ;-1 save month
490 mov temp,xl
491 rcall binbcd2
492 mov xl,yl ; least significant 2 bits of year
493 swap xl
494 lsl xl
495 lsl xl
496 andi xl,0xc0
497 or temp,xl ; combine with day
498 push temp ;-2 save year/day
499 mov temp,temp4
500 rcall binbcd2
501 push temp ;-3 save hours
502 mov temp,temp3
503 rcall binbcd2
504 push temp ;-4 save min
505 mov temp,temp2
506 rcall binbcd2
507 push temp ;-5 save sec
508
509 push _0 ;-6 1/10s, 1/100s
510 ldi temp,0x84 ; stop count, alarm enable
511 push temp ;-7
512 push _0 ;-8 register address
513 in zh,sph
514 in zl,spl
515 ldi temp,0xA0 ; PCF8583 slave address
516 push temp ;(-9)
517
518 ldi temp2,9
519 rcall i2c_write
520 ldi temp,0x04 ;enable counting
521 std z+2,temp
522 ldi temp2,3
523 rcall i2c_write
524 std z+3,yh ;store year in RTC RAM
525 std z+2,yl
526 ldi temp,0x10
527 std z+1,temp
528 ldi temp2,4
529 rcall i2c_write
530
531 addiw z,8 ;remove buffer from stack
532 cli
533 out spl,zl
534 sei
535 out sph,zh
536
537 ret
538 #endif
539
540 ; ----------------------------------------------
541 ;
542
543 utimeget:
544 ldi temp,0xFF
545 ldiw z,cntms_out
546 subi temp3,1
547 brcs utimget_end ;Rel. port number = 0 ? (controlport)
548 breq utimget_copy ;lowest byte requestet, latch clock
549
550 add zl,temp3
551 adc zh,_0
552 ld temp,z
553 utimget_end:
554 ret
555
556 utimget_copy:
557 ldi temp2,6
558 cli
559 utimget_l:
560 ldd temp,z+utofs
561 st z+,temp
562 dec temp2
563 brne utimget_l
564 sei
565 lds temp,cntms_out
566 ;req. byte in temp
567 ret
568
569 utimeput:
570 subi temp3,1
571 brcc utput__1
572
573 ; clock control
574
575 cpi temp,starttimercmd
576 breq timer_start ;timer_ms
577 cpi temp,quitTimerCmd
578 breq utput_quit ;
579 cpi temp,printTimerCmd
580 breq timer_print ;timer_ms
581 cpi temp,uptimeCmd
582 brne utcp_ex
583 rjmp uptime_print ;cnt_1ms
584 utcp_ex:
585 ret
586
587 utput_quit:
588 rcall timer_print
589 rjmp timer_start
590
591 utput__1:
592 ldiw z,cntms_out
593 breq utput__copy ;lowest byte requestet, latch clock
594
595 add zl,temp3
596 adc zh,_0
597 st z,temp
598 ret
599
600 utput__copy:
601 st z,temp
602 adiw z,5
603 ldi temp2,6
604 cli
605 utput__l:
606 ldd temp,z+utofs
607 st z+,temp
608 dec temp2
609 brne utput__l
610 sei
611 ret
612
613 ; start/reset timer
614 ;
615 timer_start:
616 ldiw z,timer_ms
617 ldi temp2,6
618 cli
619 ts_loop:
620 ldd temp,z+timerofs
621 st z+,temp
622 dec temp2
623 brne ts_loop
624 sei
625 ret
626
627
628 ; print timer
629 ;
630
631 timer_print:
632 push yh
633 push yl
634 ldiw z,timer_ms
635
636 ; put ms on stack (16 bit)
637
638 cli
639 ldd yl,z+timerofs
640 ld temp2,z+
641 sub yl,temp2
642 ldd yh,z+timerofs
643 ld temp2,z+
644 sbc yh,temp2
645 brsh tp_s
646
647 addiw y,1000
648 sec
649 tp_s:
650 push yh
651 push yl
652
653 ldd temp,z+timerofs
654 ld yl,z+
655 sbc temp,yl
656
657 ldd temp2,z+timerofs
658 ld yh,z+
659 sbc temp2,yh
660
661 ldd temp3,z+timerofs
662 ld yl,z+
663 sbc temp3,yl
664
665 sei
666 ldd temp4,z+timerofs
667 ld yh,z+
668 sbc temp4,yh
669
670 printnewline
671 printstring "Timer running. Elapsed: "
672 rcall print_ultoa
673
674 printstring "."
675 pop temp
676 pop temp2
677 ldi temp3,0
678 ldi temp4,0
679 rcall print_ultoa
680 printstring "s."
681
682 pop yl
683 pop yh
684 ret
685
686 uptime_print:
687 ldiw z,cnt_1ms
688 cli
689 ld temp,z+
690 push temp
691 ld temp,z+
692 push temp
693
694 ld temp,z+
695 ld temp2,z+
696 ld temp3,z+
697 sei
698 ld temp4,z+
699
700 printnewline
701 printstring "Uptime: "
702
703 rcall print_ultoa
704 printstring ","
705
706 ldi temp3,0
707 ldi temp4,0
708 pop temp2
709 pop temp
710 rcall print_ultoa
711 printstring "s."
712
713 ret
714
715 ; vim:set ts=8 noet nowrap
716