]> cloudbase.mooo.com Git - avrcpm.git/blame - avr/timer.asm
* MMC/SD Bootloader support
[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
de15c768 25timer_var:
9c15f366 26delay_timer1:
de15c768 27.equ ot_timer1 = delay_timer1-timer_var
9c15f366
L
28 .byte 1
29delay_timer2:
de15c768 30.equ ot_timer2 = delay_timer2-timer_var
9c15f366
L
31 .byte 1
32timer_base:
33timer_ms:
de15c768 34.equ ot_ms = timer_ms-timer_var
9c15f366 35 .byte 2
de15c768
L
36timer_sec:
37.equ ot_sec = timer_sec-timer_var
9c15f366 38 .byte 4
de15c768 39
9c15f366
L
40; don't change order here, clock put/get depends on it.
41cntms_out: ; register for ms
42 .byte 2
43utime_io: ; register for uptime.
44 .byte 4
45cnt_1ms:
de15c768 46.equ ot_1ms = cnt_1ms-timer_var
9c15f366
L
47 .byte 2
48uptime:
de15c768 49.equ ot_uptime = uptime-timer_var
9c15f366
L
50 .byte 4
51timer_top:
52.equ timer_size = timer_top - timer_base
53
fb050095 54.equ utofs = cnt_1ms-cntms_out
9c15f366
L
55.equ timerofs = cnt_1ms-timer_ms
56
fb050095 57clk_out:
de15c768 58.equ oclk_out = clk_out-timer_var
d8fa6a36 59 .byte 7 ;
fb050095 60clock:
de15c768 61.equ o_clock = clock-timer_var
d8fa6a36 62 .byte 7 ;Format (bin): s m h D M YY
fb050095
L
63.equ clkofs = clock-clk_out
64
9c15f366 65 .cseg
9c15f366 66
5985ce1c
L
67; ------------- system timer 1ms ---------------
68
69
4675c141
L
70; Timer/Counter1 Compare Match B interrupt
71
72 INTERRUPT OC1Baddr
de15c768
L
73
74.if TIMER_DEBUG
75 cbi PORTC,5
76.endif
9c15f366
L
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
de15c768
L
87 push yl
88 push yh
89 ldiw y,timer_var
90
9c15f366 91#if DRAM_8BIT /* Implies software uart */
d8fa6a36 92 lds zl,srx_char_to ;try to decrement character timout
9c15f366 93 subi zl,1
d8fa6a36
L
94 brcs syscl0 ;timer was 0 before (not running)
95 sts srx_char_to,zl ;timer is running, store new value
96 brne syscl0
9c15f366
L
97 rcall srx_to
98syscl0:
99#endif
de15c768 100 ldd zl,y+ot_timer1
9c15f366
L
101 subi zl,1
102 brcs syscl_t1n
de15c768 103 std y+ot_timer1,zl
9c15f366 104syscl_t1n:
de15c768 105 ldd zl,y+ot_timer2
9c15f366
L
106 subi zl,1
107 brcs syscl_t2n
de15c768 108 std y+ot_timer2,zl
d8fa6a36
L
109syscl_t2n:
110
de15c768
L
111 ldd zl,y+ot_1ms ;count milli seconds
112 ldd zh,y+ot_1ms+1
9c15f366 113 adiw z,1
de15c768
L
114 std y+ot_1ms,zl
115 std y+ot_1ms+1,zh
d8fa6a36
L
116 cpi zl,low(1000) ;one second ?
117 ldi zl,high(1000) ;doesn't change flags
9c15f366 118 cpc zh,zl
de15c768
L
119 brlt syscl_end
120; brge syscl_utime
121; rjmp syscl_end
fb050095
L
122
123syscl_utime:
de15c768
L
124 std y+ot_1ms,_0
125 std y+ot_1ms+1,_0
9c15f366 126
de15c768
L
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
fb050095 132 brne syscl_clk
de15c768
L
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
fb050095
L
138
139syscl_clk:
de15c768 140 ldd zl,y+o_clock+0 ;sec
fb050095 141 inc zl
de15c768 142 std y+o_clock+0,zl
fb050095 143 cpi zl,60
de15c768
L
144 brlo syscl_end
145 std y+o_clock+0,_0
146 ldd zl,y+o_clock+1 ;min
fb050095 147 inc zl
de15c768 148 std y+o_clock+1,zl
fb050095
L
149 cpi zl,60
150 brlo syscl_end
de15c768
L
151 std y+o_clock+1,_0
152 ldd zl,y+o_clock+2 ;hour
fb050095 153 inc zl
de15c768 154 std y+o_clock+2,zl
fb050095 155 cpi zl,24
de15c768 156 brlo syscl_end
d8fa6a36
L
157
158syscl_clk_date:
de15c768 159 std y+o_clock+2,_0
fb050095
L
160 push temp
161
162 ldiw z,dayspm_tab*2 - 1
de15c768 163 ldd temp,y+o_clock+4 ;month
fb050095
L
164 add zl,temp
165 adc zh,_0
166 lpm zh,z ;days this month
167 cpi temp,2
d8fa6a36 168 brne syscl_clknl ;february, may be leap year
de15c768 169 ldd zl,y+o_clock+5 ;year
d8fa6a36 170 andi zl,0x03
fb050095
L
171 brne syscl_clknl
172 inc zh ;leap year
173syscl_clknl:
de15c768 174 ldd zl,y+o_clock+3 ;day
fb050095 175 inc zl
de15c768 176 std y+o_clock+3,zl
fb050095
L
177 cp zh,zl
178 brsh syscl_clke
179 ldi zl,1
de15c768 180 std y+o_clock+3,zl
fb050095 181 inc temp ;month
de15c768 182 std y+o_clock+4,temp
fb050095
L
183 cpi temp,13
184 brlo syscl_clke
185
de15c768
L
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
fb050095
L
192
193syscl_clke:
194 pop temp
9c15f366 195syscl_end:
de15c768
L
196 pop yh
197 pop yl
9c15f366
L
198 pop zh
199 pop zl
200 out SREG,zl
201 pop zl
de15c768
L
202.if TIMER_DEBUG
203 sbi PORTC,5
204.endif
9c15f366
L
205 reti
206
fb050095
L
207; days per month
208
209dayspm_tab:
210 .db 31,28,31,30,31,30
211 .db 31,31,30,31,30,31
212
5985ce1c
L
213; ----------------------------------------------
214; delay
215;
9c15f366 216; wait for temp ms
5985ce1c 217;
9c15f366
L
218
219delay_ms:
220 sts delay_timer1,temp
221dly_loop:
222 lds temp,delay_timer1
223 cpi temp,0
224 brne dly_loop
225 ret
226
5985ce1c 227; ----------------------------------------------
9c15f366 228;
9c15f366 229clockget:
fb050095 230 ldiw z,clk_out
d8fa6a36 231 tst temp3
9c15f366 232 breq clkget_copy ;lowest byte requestet, latch clock
9c15f366 233
d8fa6a36 234 add zl,temp3
fb050095 235 adc zh,_0
9c15f366
L
236 ld temp,z
237clkget_end:
238 ret
239
d8fa6a36 240
9c15f366 241clkget_copy:
d8fa6a36 242 ldi temp3,7
9c15f366
L
243 cli
244clkget_l:
245 ldd temp,z+clkofs
246 st z+,temp
d8fa6a36 247 dec temp3
9c15f366
L
248 brne clkget_l
249 sei
d8fa6a36
L
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
257clkget_l2:
258 ld temp,-z
259 rcall binbcd2
260 st z,temp
261 dec temp3
262 brne clkget_l2
263
fb050095 264 lds temp,clk_out
d8fa6a36 265 ret ;req. byte in temp
9c15f366 266
d8fa6a36
L
267; ----------------------------------------------
268;
9c15f366 269clockput:
fb050095 270 ldiw z,clk_out
d8fa6a36 271 add zl,temp3
fb050095
L
272 adc zh,_0
273 st z,temp
d8fa6a36
L
274 tst temp3
275 breq clkput_copy ;lowest byte stored, latch clock
fb050095 276clkput_end:
fb050095
L
277 ret
278
d8fa6a36 279
fb050095 280clkput_copy:
d8fa6a36
L
281 ldi temp3,5
282clkput_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
fb050095
L
296 cli
297clkput_l:
d8fa6a36
L
298 ld temp,-z
299 std z+clkofs,temp
300 dec temp3
fb050095
L
301 brne clkput_l
302 sei
d8fa6a36
L
303#if I2C
304 rcall rtc_set ; set hardware clock
305#endif
fb050095
L
306 ret
307
d8fa6a36
L
308
309; ----------------------------------------------
310
311; convert binary to bcd
312; (only range 0 - 99)
313
314binbcd2:
315 push temp2
316 ldi temp2,10
317 mov _tmp0,_255
318tobcd_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
329binbcd4:
330 ldi temp3,16
623dd899 331 movw _tmp0,temp
d8fa6a36
L
332 clr temp
333 clr temp2
334binbcd4l:
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
356binbcd4e:
357 ret
358
359; convert bcd to binary
360
361bcdbin2:
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
374bcdbin4:
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
393rtc_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
79986122 410 brmi rtc_get_e ;i2c error
d8fa6a36
L
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
79986122 421 brmi rtc_get_e
d8fa6a36
L
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
432rtc_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
457rtc_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
477rtc_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
fb050095
L
540; ----------------------------------------------
541;
542
543utimeget:
544 ldi temp,0xFF
fb050095 545 ldiw z,cntms_out
de15c768
L
546 subi temp3,1
547 brcs utimget_end ;Rel. port number = 0 ? (controlport)
fb050095 548 breq utimget_copy ;lowest byte requestet, latch clock
fb050095 549
de15c768 550 add zl,temp3
fb050095
L
551 adc zh,_0
552 ld temp,z
553utimget_end:
554 ret
555
fb050095
L
556utimget_copy:
557 ldi temp2,6
558 cli
559utimget_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
569utimeput:
de15c768
L
570 subi temp3,1
571 brcc utput__1
9c15f366
L
572
573 ; clock control
574
575 cpi temp,starttimercmd
de15c768 576 breq timer_start ;timer_ms
9c15f366 577 cpi temp,quitTimerCmd
de15c768 578 breq utput_quit ;
9c15f366 579 cpi temp,printTimerCmd
de15c768 580 breq timer_print ;timer_ms
9c15f366 581 cpi temp,uptimeCmd
fb050095 582 brne utcp_ex
de15c768 583 rjmp uptime_print ;cnt_1ms
fb050095 584utcp_ex:
9c15f366
L
585 ret
586
fb050095 587utput_quit:
9c15f366
L
588 rcall timer_print
589 rjmp timer_start
590
fb050095 591utput__1:
9c15f366 592 ldiw z,cntms_out
fb050095 593 breq utput__copy ;lowest byte requestet, latch clock
9c15f366 594
de15c768
L
595 add zl,temp3
596 adc zh,_0
9c15f366 597 st z,temp
9c15f366
L
598 ret
599
fb050095 600utput__copy:
9c15f366
L
601 st z,temp
602 adiw z,5
603 ldi temp2,6
604 cli
fb050095
L
605utput__l:
606 ldd temp,z+utofs
9c15f366
L
607 st z+,temp
608 dec temp2
fb050095 609 brne utput__l
9c15f366
L
610 sei
611 ret
612
613; start/reset timer
614;
615timer_start:
616 ldiw z,timer_ms
617 ldi temp2,6
618 cli
619ts_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
631timer_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
649tp_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
686uptime_print:
9c15f366 687 ldiw z,cnt_1ms
9c15f366
L
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
5985ce1c 715; vim:set ts=8 noet nowrap
9c15f366 716