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