]> cloudbase.mooo.com Git - avrcpm.git/blob - avr/timer.asm
* I2C Support added
[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 delay_timer1:
26 .byte 1
27 delay_timer2:
28 .byte 1
29 timer_base:
30 timer_ms:
31 .byte 2
32 timer_s:
33 .byte 4
34 ; don't change order here, clock put/get depends on it.
35 cntms_out: ; register for ms
36 .byte 2
37 utime_io: ; register for uptime.
38 .byte 4
39 cnt_1ms:
40 .byte 2
41 uptime:
42 .byte 4
43 timer_top:
44 .equ timer_size = timer_top - timer_base
45
46 .equ utofs = cnt_1ms-cntms_out
47 .equ timerofs = cnt_1ms-timer_ms
48
49 clk_out:
50 .byte 7 ;
51 clock:
52 .byte 7 ;Format (bin): s m h D M YY
53 .equ clkofs = clock-clk_out
54
55 .cseg
56
57 ; ------------- system timer 1ms ---------------
58
59
60 ; Timer/Counter1 Compare Match B interrupt
61
62 INTERRUPT OC1Baddr
63
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 */
75 lds zl,srx_char_to ;try to decrement character timout
76 subi zl,1
77 brcs syscl0 ;timer was 0 before (not running)
78 sts srx_char_to,zl ;timer is running, store new value
79 brne syscl0
80 rcall srx_to
81 syscl0:
82 #endif
83 lds zl,delay_timer1
84 subi zl,1
85 brcs syscl_t1n
86 sts delay_timer1,zl
87 syscl_t1n:
88 lds zl,delay_timer2
89 subi zl,1
90 brcs syscl_t2n
91 sts delay_timer2,zl
92 syscl_t2n:
93
94 lds zl,cnt_1ms ;count milli seconds
95 lds zh,cnt_1ms+1
96 adiw z,1
97 sts cnt_1ms,zl
98 sts cnt_1ms+1,zh
99 cpi zl,low(1000) ;one second ?
100 ldi zl,high(1000) ;doesn't change flags
101 cpc zh,zl
102 brge syscl_utime
103 rjmp syscl_end
104
105 syscl_utime:
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
112 brne syscl_clk
113 lds zl,uptime+1
114 inc zl
115 sts uptime+1,zl
116 brne syscl_clk
117 lds zl,uptime+2
118 inc zl
119 sts uptime+2,zl
120 brne syscl_clk
121 lds zl,uptime+3
122 inc zl
123 sts uptime+3,zl
124
125 syscl_clk:
126 lds zl,clock+0 ;sec
127 inc zl
128 sts clock+0,zl
129 cpi zl,60
130 brlo syscl_end
131 sts clock+0,_0
132 lds zl,clock+1 ;min
133 inc zl
134 sts clock+1,zl
135 cpi zl,60
136 brlo syscl_end
137 sts clock+1,_0
138 lds zl,clock+2 ;hour
139 inc zl
140 sts clock+2,zl
141 cpi zl,24
142 brsh syscl_clk_date
143 rjmp syscl_end
144
145 syscl_clk_date:
146 sts clock+2,_0
147 push temp
148
149 ldiw z,dayspm_tab*2 - 1
150 lds temp,clock+4 ;month
151 add zl,temp
152 adc zh,_0
153 lpm zh,z ;days this month
154 cpi temp,2
155 brne syscl_clknl ;february, may be leap year
156 lds zl,(clock+5) ;year
157 andi zl,0x03
158 brne syscl_clknl
159 inc zh ;leap year
160 syscl_clknl:
161 lds zl,clock+3 ;day
162 inc zl
163 sts clock+3,zl
164 cp zh,zl
165 brsh syscl_clke
166 ldi zl,1
167 sts clock+3,zl
168 inc temp ;month
169 sts clock+4,temp
170 cpi temp,13
171 brlo syscl_clke
172
173 sts clock+4,zl
174 lds zl,clock+5 ;low year
175 inc zl
176 sts clock+5,zl
177 brne syscl_clke
178 lds zl,clock+6 ;high year
179 inc zl
180 sts clock+6,zl
181
182 syscl_clke:
183 pop temp
184 syscl_end:
185 pop zh
186 pop zl
187 out SREG,zl
188 pop zl
189 reti
190
191 ; days per month
192
193 dayspm_tab:
194 .db 31,28,31,30,31,30
195 .db 31,31,30,31,30,31
196
197 ; ----------------------------------------------
198 ; delay
199 ;
200 ; wait for temp ms
201 ;
202
203 delay_ms:
204 sts delay_timer1,temp
205 dly_loop:
206 lds temp,delay_timer1
207 cpi temp,0
208 brne dly_loop
209 ret
210
211 ; ----------------------------------------------
212 ;
213 clockget:
214 ldiw z,clk_out
215 tst temp3
216 breq clkget_copy ;lowest byte requestet, latch clock
217
218 add zl,temp3
219 adc zh,_0
220 ld temp,z
221 clkget_end:
222 ret
223
224
225 clkget_copy:
226 ldi temp3,7
227 cli
228 clkget_l:
229 ldd temp,z+clkofs
230 st z+,temp
231 dec temp3
232 brne clkget_l
233 sei
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
241 clkget_l2:
242 ld temp,-z
243 rcall binbcd2
244 st z,temp
245 dec temp3
246 brne clkget_l2
247
248 lds temp,clk_out
249 ret ;req. byte in temp
250
251 ; ----------------------------------------------
252 ;
253 clockput:
254 ldiw z,clk_out
255 add zl,temp3
256 adc zh,_0
257 st z,temp
258 tst temp3
259 breq clkput_copy ;lowest byte stored, latch clock
260 clkput_end:
261 ret
262
263
264 clkput_copy:
265 ldi temp3,5
266 clkput_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
280 cli
281 clkput_l:
282 ld temp,-z
283 std z+clkofs,temp
284 dec temp3
285 brne clkput_l
286 sei
287 #if I2C
288 rcall rtc_set ; set hardware clock
289 #endif
290 ret
291
292
293 ; ----------------------------------------------
294
295 ; convert binary to bcd
296 ; (only range 0 - 99)
297
298 binbcd2:
299 push temp2
300 ldi temp2,10
301 mov _tmp0,_255
302 tobcd_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
313 binbcd4:
314 ldi temp3,16
315 mov _tmp0,temp
316 mov _tmp1,temp2
317 clr temp
318 clr temp2
319 binbcd4l:
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
341 binbcd4e:
342 ret
343
344 ; convert bcd to binary
345
346 bcdbin2:
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
359 bcdbin4:
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
378 rtc_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
417 rtc_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
442 rtc_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
462 rtc_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
525 ; ----------------------------------------------
526 ;
527
528 utimeget:
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
540 utimget_end:
541 ret
542
543
544
545 utimget_copy:
546 ldi temp2,6
547 cli
548 utimget_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
558 utimeput:
559 subi temp2,TIMERPORT
560 brcs utput__end ;Port number in range?
561 brne utput__1
562
563 ; clock control
564
565 cpi temp,starttimercmd
566 breq timer_start
567 cpi temp,quitTimerCmd
568 breq utput_quit
569 cpi temp,printTimerCmd
570 breq timer_print
571 cpi temp,uptimeCmd
572 brne utcp_ex
573 rjmp uptime_print
574 utcp_ex:
575 ret
576
577 utput_quit:
578 rcall timer_print
579 rjmp timer_start
580
581 utput__1:
582 dec temp2
583 ldiw z,cntms_out
584 breq utput__copy ;lowest byte requestet, latch clock
585 cpi temp2,6
586 brsh utput__end ;Port number to high?
587
588 add zl,temp2
589 brcc PC+2
590 inc zh
591 st z,temp
592 utput__end:
593 ret
594
595 utput__copy:
596 st z,temp
597 adiw z,5
598 ldi temp2,6
599 cli
600 utput__l:
601 ldd temp,z+utofs
602 st z+,temp
603 dec temp2
604 brne utput__l
605 sei
606 ret
607
608 ; start/reset timer
609 ;
610 timer_start:
611 ldiw z,timer_ms
612 ldi temp2,6
613 cli
614 ts_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
626 timer_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
644 tp_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
681 uptime_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
712 ; vim:set ts=8 noet nowrap
713