]> cloudbase.mooo.com Git - avrcpm.git/blobdiff - avr/timer.asm
* FAT buffer on ATmega328
[avrcpm.git] / avr / timer.asm
index 80e9fca44fafaa6077b007cc9a4d91a1ed87f9d8..5a4cc12280bfe81584629340a7a22ac06f0fc6cd 100644 (file)
 
        .dseg
 
+timer_var:
 delay_timer1:
+.equ ot_timer1 = delay_timer1-timer_var
        .byte   1
 delay_timer2:
+.equ ot_timer2 = delay_timer2-timer_var
        .byte   1
 timer_base:
 timer_ms:
+.equ ot_ms     = timer_ms-timer_var
        .byte   2
-timer_s:
+timer_sec:
+.equ ot_sec    = timer_sec-timer_var
        .byte   4
+
 ; don't change order here, clock put/get depends on it.
 cntms_out:             ; register for ms
        .byte   2
 utime_io:              ; register for uptime. 
        .byte   4       
 cnt_1ms:
+.equ ot_1ms    = cnt_1ms-timer_var
        .byte   2
 uptime:
+.equ ot_uptime = uptime-timer_var
        .byte   4
 timer_top:
 .equ timer_size        = timer_top - timer_base
@@ -47,9 +55,11 @@ timer_top:
 .equ timerofs  = cnt_1ms-timer_ms
  
 clk_out:
-       .byte   6       ;
+.equ oclk_out  = clk_out-timer_var
+       .byte   7       ;
 clock:
-       .byte   6       ;Format (bin): Y M D H M S
+.equ o_clock   = clock-timer_var
+       .byte   7       ;Format (bin): s m h D M YY
 .equ clkofs    = clock-clk_out
 
        .cseg   
@@ -60,7 +70,10 @@ clock:
 ; Timer/Counter1 Compare Match B interrupt
        
        INTERRUPT OC1Baddr
-       
+
+.if TIMER_DEBUG
+       cbi     PORTC,5
+.endif 
        push    zl
        in      zl,SREG
        push    zl
@@ -71,115 +84,124 @@ clock:
        outm8   OCR1BH,zh
        outm8   OCR1BL,zl
        
+       push    yl
+       push    yh
+       ldiw    y,timer_var
+
 #if DRAM_8BIT  /* Implies software uart */
-       lds     zl,srx_char_to
+       lds     zl,srx_char_to                  ;try to decrement character timout
        subi    zl,1
-       brcs    syscl0
-       sts     srx_char_to,zl
-       brne    syscl0
+       brcs    syscl0                          ;timer was 0 before (not running)
+       sts     srx_char_to,zl                  ;timer is running, store new value
+       brne    syscl0                          
        rcall   srx_to
 syscl0:
 #endif
-       lds     zl,delay_timer1
+       ldd     zl,y+ot_timer1
        subi    zl,1
        brcs    syscl_t1n
-       sts     delay_timer1,zl
+       std     y+ot_timer1,zl
 syscl_t1n:     
-       lds     zl,delay_timer2
+       ldd     zl,y+ot_timer2
        subi    zl,1
        brcs    syscl_t2n
-       sts     delay_timer2,zl
-syscl_t2n:     
-       lds     zl,cnt_1ms
-       lds     zh,cnt_1ms+1
+       std     y+ot_timer2,zl
+syscl_t2n:
+
+       ldd     zl,y+ot_1ms                     ;count milli seconds
+       ldd     zh,y+ot_1ms+1
        adiw    z,1
-       
-       sts     cnt_1ms,zl
-       sts     cnt_1ms+1,zh
-       cpi     zl,low(1000)
-       ldi     zl,high(1000)           ;doesn't change flags
+       std     y+ot_1ms,zl
+       std     y+ot_1ms+1,zh
+       cpi     zl,low(1000)                    ;one second ?
+       ldi     zl,high(1000)                   ;doesn't change flags
        cpc     zh,zl
-       brge    syscl_utime
-       rjmp    syscl_end
+       brlt    syscl_end
+;      brge    syscl_utime
+;      rjmp    syscl_end
 
 syscl_utime:
-       sts     cnt_1ms,_0
-       sts     cnt_1ms+1,_0
+       std     y+ot_1ms,_0
+       std     y+ot_1ms+1,_0
 
-       lds     zl,uptime+0
-       inc     zl
-       sts     uptime+0,zl
-       brne    syscl_clk
-       lds     zl,uptime+1
-       inc     zl
-       sts     uptime+1,zl
-       brne    syscl_clk
-       lds     zl,uptime+2
-       inc     zl
-       sts     uptime+2,zl
+       ldd     zl,y+ot_uptime+0
+       ldd     zh,y+ot_uptime+1
+       adiw    z,1
+       std     y+ot_uptime+0,zl
+       std     y+ot_uptime+1,zh
        brne    syscl_clk
-       lds     zl,uptime+3
-       inc     zl
-       sts     uptime+3,zl
+       ldd     zl,y+ot_uptime+2
+       ldd     zh,y+ot_uptime+3
+       adiw    z,1
+       std     y+ot_uptime+2,zl
+       std     y+ot_uptime+3,zh
 
 syscl_clk:
-       lds     zl,clock+5              ;sec
+       ldd     zl,y+o_clock+0          ;sec
        inc     zl
-       sts     clock+5,zl
+       std     y+o_clock+0,zl
        cpi     zl,60
        brlo    syscl_end
-       sts     clock+5,_0
-       lds     zl,clock+4              ;min
+       std     y+o_clock+0,_0
+       ldd     zl,y+o_clock+1          ;min
        inc     zl
-       sts     clock+4,zl
+       std     y+o_clock+1,zl
        cpi     zl,60
        brlo    syscl_end
-       sts     clock+4,_0
-       lds     zl,clock+3              ;hour
+       std     y+o_clock+1,_0
+       ldd     zl,y+o_clock+2          ;hour
        inc     zl
-       sts     clock+3,zl
+       std     y+o_clock+2,zl
        cpi     zl,24
        brlo    syscl_end
-       sts     clock+3,_0
+
+syscl_clk_date:
+       std     y+o_clock+2,_0
        push    temp
 
        ldiw    z,dayspm_tab*2 - 1
-       lds     temp,clock+1            ;month
+       ldd     temp,y+o_clock+4                ;month
        add     zl,temp
        adc     zh,_0
        lpm     zh,z                    ;days this month
        cpi     temp,2
-       brne    syscl_clknf             ;february, may be leap year
-       lds     zl,(clock+0)            ;year
-       andi    zl,0xfc
+       brne    syscl_clknl             ;february, may be leap year
+       ldd     zl,y+o_clock+5          ;year
+       andi    zl,0x03
        brne    syscl_clknl
        inc     zh                      ;leap year 
 syscl_clknl:
-syscl_clknf:
-       lds     zl,clock+2              ;day
+       ldd     zl,y+o_clock+3          ;day
        inc     zl
-       sts     clock+2,zl
+       std     y+o_clock+3,zl
        cp      zh,zl
        brsh    syscl_clke
        ldi     zl,1
-       sts     clock+2,zl
+       std     y+o_clock+3,zl
        inc     temp                    ;month
-       sts     clock+1,temp
+       std     y+o_clock+4,temp
        cpi     temp,13
        brlo    syscl_clke
 
-       sts     clock+1,zl
-       lds     zl,clock+0              ;year
-       inc     zl
-       sts     clock+0,zl
+       std     y+o_clock+4,zl
+       ldd     zl,y+o_clock+5          ;low year
+       ldd     zh,y+o_clock+6          ;high year
+       adiw    z,1
+       std     y+o_clock+5,zl
+       std     y+o_clock+6,zh
 
 syscl_clke:
        pop     temp
 syscl_end:
+       pop     yh
+       pop     yl
        pop     zh
        pop     zl
        out     SREG,zl
        pop     zl
+.if TIMER_DEBUG
+       sbi     PORTC,5
+.endif 
        reti
 
 ; days per month
@@ -204,85 +226,334 @@ dly_loop:
 
 ; ----------------------------------------------
 ; 
-
 clockget:
-       ldi     temp,0xFF
-       subi    temp2,CLOCKPORT
-       brcs    clkget_end              ;Port number in range?
        ldiw    z,clk_out
+       tst     temp3
        breq    clkget_copy             ;lowest byte requestet, latch clock
-       cpi     temp2,6
-       brsh    clkget_end              ;Port number to high?
        
-       add     zl,temp2
+       add     zl,temp3
        adc     zh,_0
        ld      temp,z
 clkget_end:
        ret
        
-                       
+
 clkget_copy:
-       ldi     temp2,6
+       ldi     temp3,7
        cli
 clkget_l:
        ldd     temp,z+clkofs
        st      z+,temp
-       dec     temp2
+       dec     temp3
        brne    clkget_l
        sei
+
+       ld      temp2,-z
+       ld      temp, -z
+       rcall   binbcd4
+       std     z+0,temp
+       std     z+1,temp2
+       ldi     temp3,5
+clkget_l2:
+       ld      temp,-z 
+       rcall   binbcd2
+       st      z,temp
+       dec     temp3
+       brne    clkget_l2
+
        lds     temp,clk_out
-                                       ;req. byte in temp
-       ret
+       ret                             ;req. byte in temp
 
+; ----------------------------------------------
+; 
 clockput:
-       subi    temp2,CLOCKPORT
-       brcs    clkput_end              ;Port number in range?
-
        ldiw    z,clk_out
-       breq    clkput_copy             ;lowest byte requestet, latch clock
-       cpi     temp2,6
-       brsh    clkput_end              ;Port number to high?
-       
-       add     zl,temp2
+       add     zl,temp3
        adc     zh,_0
        st      z,temp
+       tst     temp3
+       breq    clkput_copy             ;lowest byte stored, latch clock
 clkput_end:
-       ldiw    z,clk_out
        ret
                
+
 clkput_copy:
-       st      z,temp
-       ldi     temp2,6
+       ldi     temp3,5
+clkput_l2:
+       ld      temp,z  
+       rcall   bcdbin2
+       st      z+,temp
+       dec     temp3
+       brne    clkput_l2
+
+       ldd     temp,z+0
+       ldd     temp2,z+1
+       rcall   bcdbin4
+       st      z+,temp
+       st      z+,temp2
+
+       ldi     temp3,7
        cli
 clkput_l:
-       ld      temp,z+
-       std     z+clkofs-1,temp
-       dec     temp2
+       ld      temp,-z
+       std     z+clkofs,temp
+       dec     temp3
        brne    clkput_l
        sei
-       ldiw    z,clk_out
+#if I2C_SUPPORT
+       rcall   rtc_set                 ; set hardware clock
+#endif
+       ret
+
+
+; ----------------------------------------------
+
+; convert binary to bcd
+; (only range 0 - 99)
+
+binbcd2:
+       push    temp2
+       ldi     temp2,10
+       mov     _tmp0,_255
+tobcd_l:
+       inc     _tmp0
+       sub     temp,temp2
+       brcc    tobcd_l
+       add     temp,temp2
+       swap    _tmp0
+       add     temp,_tmp0
+       pop     temp2
+       ret
+       
+
+binbcd4:
+       ldi     temp3,16
+       movw    _tmp0,temp
+       clr     temp
+       clr     temp2
+binbcd4l:
+       lsl     _tmp0
+       rol     _tmp1
+       rol     temp
+       rol     temp2
+       dec     temp3
+       breq    binbcd4e
+
+       subi    temp2,-0x03
+       sbrs    temp2,3
+       subi    temp2,0x03
+       subi    temp2,-0x30
+       sbrs    temp2,7
+       subi    temp2,0x30
+       subi    temp,-0x03
+       sbrs    temp,3
+       subi    temp,0x03
+       subi    temp,-0x30
+       sbrs    temp,7
+       subi    temp,0x30
+       rjmp    binbcd4l
+
+binbcd4e:
+       ret
+
+; convert bcd to binary
+
+bcdbin2:
+       push    temp2
+       mov     temp2,temp              ;temp2 = high digit
+       swap    temp2
+       andi    temp2,0x0f
+       andi    temp,0x0f               ;temp  = low digit
+       mov     r0,temp2
+       ldi     temp2,10
+       mul     temp2,r0                ;high digit * 10
+       add     temp,r0                 ;high digit * 10 + low digit
+       pop     temp2
+       ret
+
+bcdbin4:
+       rcall   bcdbin2
+       push    temp
+       mov     temp,temp2
+       rcall   bcdbin2
+       ldi     temp2,100
+       mul     temp,temp2
+       pop     temp
+       mov     temp2,r1
+       add     temp,r0
+       adc     temp2,_0
+       ret
+
+
+#if I2C_SUPPORT
+
+; ----------------------------------------------
+; Set software clock from hardware clock
+
+rtc_get:
+       push    _0                      ;Placeholder for month/weekday
+       push    _0                      ;day/year
+       push    _0                      ;hours
+       push    _0                      ;minutes
+       ldi     temp,0x10               ;register address
+       push    temp                    ;save reg adr/placeholder for sec
+       in      zh,sph
+       in      zl,spl
+       ldi     temp,0xA0               ;PCF8583 slave address
+       push    temp
+
+       ldi     temp2,2
+       rcall   i2c_write
+       ldi     temp2,3
+       rcall   i2c_read                ;get year (stored in RTC-RAM addr. 10h)
+       tst     temp
+       brmi    rtc_get_e               ;i2c error
+
+       ldd     temp3,z+1               ;save year
+       ldd     xl,   z+2
+
+       ldi     temp2,2                 ;register pointer. 2 = secs
+       std     z+1,temp2
+       rcall   i2c_write
+       ldi     temp2,6
+       rcall   i2c_read
+       tst     temp
+       brmi    rtc_get_e
+
+       mov     temp2,xl                ;year century
+       ldd     temp,z+4                ;get year
+       rol     temp
+       rol     temp
+       rol     temp
+       eor     temp,temp3
+       andi    temp,0x03
+       breq    rtc_get_1
+       subi    temp3, low(-1)  
+       sbci    temp2, high(-1)
+rtc_get_1:
+       ldiw    x,clock
+       cli
+
+       ldd     temp,z+1                ;get seconds
+       rcall   bcdbin2
+       st      x+,temp
+       ldd     temp,z+2                ;get minutes
+       rcall   bcdbin2
+       st      x+,temp
+       ldd     temp,z+3                ;get hours
+       rcall   bcdbin2
+       st      x+,temp
+       ldd     temp,z+4                ;get day
+       andi    temp,0x3f
+       rcall   bcdbin2
+       st      x+,temp
+       ldd     temp,z+5                ;get months
+       andi    temp,0x1f
+       rcall   bcdbin2
+       st      x+,temp                 ;store month
+       st      x+,temp3                ;store year
+       st      x+,temp2                ;store year century
+       sei
+
+rtc_get_e:
+       pop     temp
+       pop     temp
+       pop     temp
+       pop     temp
+       pop     temp
+       pop     temp
+       ret
+
+;----------------------------------------------
+; Set hardware clock from software clock
+; 
+; Register:    temp2:  s
+;              temp3:  m
+;              xh:     h
+;              xl:     D
+;              temp:   M
+;              yl:     Yl
+;              yh:     Yh
+
+rtc_set:
+       ldiw    z,clock
+       cli
+       ldd     temp2,z+0               ;sec
+       ldd     temp3,z+1               ;min
+       ldd     xh,z+2                  ;hours
+       ldd     xl,z+3                  ;day
+       ldd     temp,z+4                ;month
+       ldd     yl,z+5                  ;yearl
+       ldd     yh,z+6                  ;yearh
+       sei
+       rcall   binbcd2
+       push    temp                    ;-1 save month
+       mov     temp,xl
+       rcall   binbcd2
+       mov     xl,yl                   ;   least significant 2 bits of year
+       swap    xl
+       lsl     xl
+       lsl     xl
+       andi    xl,0xc0
+       or      temp,xl                 ;   combine with day
+       push    temp                    ;-2 save year/day
+       mov     temp,xh
+       rcall   binbcd2
+       push    temp                    ;-3 save hours
+       mov     temp,temp3
+       rcall   binbcd2
+       push    temp                    ;-4 save min
+       mov     temp,temp2
+       rcall   binbcd2
+       push    temp                    ;-5 save sec
+
+       push    _0                      ;-6 1/10s, 1/100s
+       ldi     temp,0x84               ;   stop count, alarm enable
+       push    temp                    ;-7
+       push    _0                      ;-8 register address
+       in      zh,sph
+       in      zl,spl
+       ldi     temp,0xA0               ;   PCF8583 slave address
+       push    temp                    ;(-9)
+
+       ldi     temp2,9
+       rcall   i2c_write
+       ldi     temp,0x04               ;enable counting
+       std     z+2,temp
+       ldi     temp2,3
+       rcall   i2c_write
+       std     z+3,yh                  ;store year in RTC RAM
+       std     z+2,yl
+       ldi     temp,0x10
+       std     z+1,temp
+       ldi     temp2,4
+       rcall   i2c_write
+
+       addiw   z,8                     ;remove buffer from stack
+       cli
+       out     spl,zl
+       sei
+       out     sph,zh
+
        ret
+#endif /* I2C_SUPPORT */
 
 ; ----------------------------------------------
 ; 
 
 utimeget:
        ldi     temp,0xFF
-       subi    temp2,TIMER_MSECS
-       brcs    utimget_end             ;Port number in range?
        ldiw    z,cntms_out
+       subi    temp3,1
+       brcs    utimget_end             ;Rel. port number = 0 ? (controlport)
        breq    utimget_copy            ;lowest byte requestet, latch clock
-       cpi     temp2,6
-       brsh    utimget_end             ;Port number to high?
        
-       add     zl,temp2
+       add     zl,temp3
        adc     zh,_0
        ld      temp,z
 utimget_end:
        ret
        
-       
-               
 utimget_copy:
        ldi     temp2,6
        cli
@@ -297,21 +568,20 @@ utimget_l:
        ret
 
 utimeput:
-       subi    temp2,TIMERPORT
-       brcs    utput__end              ;Port number in range?
-       brne    utput__1
+       subi    temp3,1
+       brcc    utput__1
        
        ; clock control
 
        cpi     temp,starttimercmd
-       breq    timer_start
+       breq    timer_start             ;timer_ms
        cpi     temp,quitTimerCmd
-       breq    utput_quit
+       breq    utput_quit              ;
        cpi     temp,printTimerCmd
-       breq    timer_print
+       breq    timer_print             ;timer_ms
        cpi     temp,uptimeCmd
        brne    utcp_ex
-       rjmp    uptime_print
+       rjmp    uptime_print            ;cnt_1ms
 utcp_ex:
        ret     
        
@@ -320,17 +590,12 @@ utput_quit:
        rjmp    timer_start
 
 utput__1:
-       dec     temp2
        ldiw    z,cntms_out
        breq    utput__copy             ;lowest byte requestet, latch clock
-       cpi     temp2,6
-       brsh    utput__end              ;Port number to high?
        
-       add     zl,temp2
-        brcc   PC+2
-       inc     zh
+       add     zl,temp3
+       adc     zh,_0
        st      z,temp
-utput__end:
        ret
                
 utput__copy:
@@ -365,6 +630,8 @@ ts_loop:
 ;
        
 timer_print:
+       push    r15             ;
+       push    r14             ;
        push    yh
        push    yl
        ldiw    z,timer_ms
@@ -394,14 +661,14 @@ tp_s:
        ld      yh,z+
        sbc     temp2,yh
 
-       ldd     temp3,z+timerofs
+       ldd     r14,z+timerofs
        ld      yl,z+
-       sbc     temp3,yl
+       sbc     r14,yl
 
        sei
-       ldd     temp4,z+timerofs
+       ldd     r15,z+timerofs
        ld      yh,z+
-       sbc     temp4,yh
+       sbc     r15,yh
        
        printnewline
        printstring "Timer running. Elapsed: "
@@ -410,19 +677,21 @@ tp_s:
        printstring "."
        pop     temp
        pop     temp2
-       ldi     temp3,0
-       ldi     temp4,0
+       clr     r14
+       clr     r15
        rcall   print_ultoa
        printstring "s."
 
        pop     yl
        pop     yh
+       pop     r14
+       pop     r15
        ret
        
 uptime_print:
-
+       push    r15
+       push    r14
        ldiw    z,cnt_1ms
-       
        cli
        ld      temp,z+
        push    temp
@@ -431,9 +700,9 @@ uptime_print:
        
        ld      temp,z+
        ld      temp2,z+
-       ld      temp3,z+
+       ld      r14,z+
        sei
-       ld      temp4,z+
+       ld      r15,z+
        
        printnewline
        printstring "Uptime: "
@@ -441,13 +710,15 @@ uptime_print:
        rcall   print_ultoa
        printstring ","
 
-       ldi     temp3,0
-       ldi     temp4,0
+       clr     r14
+       clr     r15
        pop     temp2
        pop     temp
        rcall print_ultoa
        printstring "s."
 
+       pop     r14
+       pop     r15
        ret
 
 ; vim:set ts=8 noet nowrap