]> cloudbase.mooo.com Git - avrcpm.git/blobdiff - avr/sw-uart.asm
* cpm/BIOS.MAC
[avrcpm.git] / avr / sw-uart.asm
index 8c2b33f5b7665519e4df66c89eb74e2806632fca..3216293faf3475b44d435f50d2ae237ed90912cb 100644 (file)
 ;    $Id$
 ;
 
+#ifdef  __ATmega8__
+  #error "ATmega8 is not supported (yet)! Please update this driver, or buy an ATmega88."
+#endif
+
 #define SSER_BIT_TC    (F_CPU+BAUD/2) / BAUD 
+#define SSER_CHAR_TC   (10 * 1000 / BAUD) + 2
 
 #define RXBUFMASK      RXBUFSIZE-1
 #define TXBUFMASK      TXBUFSIZE-1
@@ -32,10 +37,12 @@ srx_state:
        .byte   1
 srx_char_to:
        .byte   1
+srx_char_time:
+       .byte   1
 srx_dr:
        .byte   1
-;srx_lastedge:
-;      .byte   2
+srx_lastedge:
+       .byte   2
 stx_bitcount:
        .byte   1
 stx_dr:
@@ -70,14 +77,23 @@ uart_init:
 ; - Soft UART RX (ICP1/ICR1).
 ; - 1ms System timer is already configured at this point.
 
+
+       cbi     P_TXD-1,TXD                     ;TXD pin as input
        ldi     temp,(1<<COM1A1)|(1<<COM1A0)    ;OC1A high on compare match (UART TX)
+       ldi     temp2,(1<<FOC1A)                ;force compare match
        outm8   TCCR1A,temp
+       outm8   TCCR1C,temp2
+       sbi     P_TXD-1,TXD                     ;TXD pin now output (OC1A)
 
-       ldi     temp,(1<<ICF1)                  ;clear pending int
-       out     TIFR1,temp
-       inm8    temp,TIMSK1
+       ldi     temp,(1<<ICF1)                  ;clear pending input capture int
+       out     TIFR1,temp                      ;
+       inm8    temp,TIMSK1                     ;
        ori     temp,(1<<ICIE1)                 ;Enable input capture int.  (UART RX)
-       outm8   TIMSK1,temp
+       outm8   TIMSK1,temp                     ;
+
+       ldi     temp,SSER_CHAR_TC               ;Character TO
+       sts     srx_char_time,temp
+
        ret
        
 ;------------------------------------------------------------------
@@ -116,23 +132,23 @@ uart_init:
 
 ; State 0: Wait for start bit
 
-;      sts     srx_lastedge,zl                 ;save beginning of start bit
-;      sts     srx_lastedge+1,zh
-       movw    srx_lastedgel,zl
+       sts     srx_lastedge,zl                 ;save beginning of start bit
+       sts     srx_lastedge+1,zh
+;      movw    srx_lastedgel,zl
        sts     srx_dr,_0
        ldi     temp,1
        sts     srx_state,temp
-       ldi     temp,2
+       lds     temp,srx_char_time
        sts     srx_char_to,temp
        sbis    P_RXD-2,RXD                     ;RXD still low?
-       rjmp    srxi_end2
+       rjmp    srxi_end
        ldi     zl,(1<<ICNC1)|(1<<CS10)         ;next edge is falling edge
        outm8   TCCR1B,zl
        ldi     zh,(1<<ICF1)                    ;clear pending int
        out     TIFR1,zh
        sts     srx_state,_0
        sts     srx_char_to,_0
-       rjmp    srxi_end2
+       rjmp    srxi_end
 
 srxi_S1:
        cpi     temp,1
@@ -140,13 +156,13 @@ srxi_S1:
 
 ; State 1: Check start bit (and collect 0-bits)
 
-;      lds     temp,srx_lastedge
-;      lds     temp2,srx_lastedge+1
-;      sts     srx_lastedge,zl
-;      sts     srx_lastedge+1,zh
+       lds     temp,srx_lastedge
+       lds     temp2,srx_lastedge+1
+       sts     srx_lastedge,zl
+       sts     srx_lastedge+1,zh
 
-       movw    temp,srx_lastedgel
-       movw    srx_lastedgel,zl
+;      movw    temp,srx_lastedgel
+;      movw    srx_lastedgel,zl
 
        sub     zl,temp
        sbc     zh,temp2
@@ -174,14 +190,18 @@ srxi_1l:
 srxi_1fe:
        sts     srx_char_to,_0                  ; no stop bit --> framing error --> break
        sts     srx_state,_0
-       sbr     intstat,(1<<i_break)
-       rjmp    srxi_end2
+       sbr     intstat,(1<<i_break)            ;
+       sts     rxcount,_0                      ;clear rx buffer
+       sts     rxidx_w,_0
+       sts     rxidx_r,_0
+
+       rjmp    srxi_end
 
 srxi_1be:
        sts     srx_dr,temp
        ldi     temp,2
        sts     srx_state,temp
-       rjmp    srxi_end2
+       rjmp    srxi_end
 
 srxi_sberr:
        ldi     temp,(1<<ICNC1)|(1<<CS10)       ;next edge is falling edge
@@ -199,7 +219,7 @@ srxi_sberr:
        mov     temp,zl
        rcall   printhex
 #endif
-       rjmp    srxi_end2
+       rjmp    srxi_end
 
 srxi_S2:
        cpi     temp,2
@@ -207,13 +227,13 @@ srxi_S2:
 
 ; State 2: collect 1-bits
 
-;      lds     temp,srx_lastedge
-;      lds     temp2,srx_lastedge+1
-;      sts     srx_lastedge,zl
-;      sts     srx_lastedge+1,zh
+       lds     temp,srx_lastedge
+       lds     temp2,srx_lastedge+1
+       sts     srx_lastedge,zl
+       sts     srx_lastedge+1,zh
 
-       movw    temp,srx_lastedgel
-       movw    srx_lastedgel,zl
+;      movw    temp,srx_lastedgel
+;      movw    srx_lastedgel,zl
 
        sub     zl,temp
        sbc     zh,temp2
@@ -232,12 +252,12 @@ srxi_2l:
        sts     srx_dr,temp
        ldi     temp,3
        sts     srx_state,temp
-       rjmp    srxi_end2
+       rjmp    srxi_end
        
 srxi_complete1:
        ldi     temp2,1                 ;We are in start bit now.
        sts     srx_state,temp2
-       ldi     temp2,2
+       lds     temp2,srx_char_time
        sts     srx_char_to,temp2
        rjmp    srxi_complete
        
@@ -247,13 +267,13 @@ srxi_S3:
 
 ; State 3: collect 0-bits
 
-;      lds     temp,srx_lastedge
-;      lds     temp2,srx_lastedge+1
-;      sts     srx_lastedge,zl
-;      sts     srx_lastedge+1,zh
+       lds     temp,srx_lastedge
+       lds     temp2,srx_lastedge+1
+       sts     srx_lastedge,zl
+       sts     srx_lastedge+1,zh
 
-       movw    temp,srx_lastedgel
-       movw    srx_lastedgel,zl
+;      movw    temp,srx_lastedgel
+;      movw    srx_lastedgel,zl
 
        sub     zl,temp
        sbc     zh,temp2
@@ -272,14 +292,14 @@ srxi_3l:
        sts     srx_dr,temp
        ldi     temp,2
        sts     srx_state,temp
-       rjmp    srxi_end2
+       rjmp    srxi_end
 
 srxi_S4:
        ldi     zl,(1<<ICNC1)|(1<<CS10) ;next edge is falling edge
        outm8   TCCR1B,zl
        ldi     zl,(1<<ICF1)            ;clear pending int
        sts     srx_state,_0            ;next state
-       rjmp    srxi_end2
+       rjmp    srxi_end
 
 srxi_complete0:        
        sts     srx_char_to,_0          ;clear timeout
@@ -294,27 +314,25 @@ srxi_complete:
 
 ; Save received character in a circular buffer. Do nothing if buffer overflows.
 
-       lds     zh,rxcount              ;if rxcount < RXBUFSIZE
-       cpi     zh,RXBUFSIZE            ;   (room for at least 1 char?)
-       brsh    srxi_ov                 ; 
-       inc     zh                      ;
-       sts     rxcount,zh              ;   rxcount++
-
-       ldi     zl,low(rxfifo)          ;  
-       lds     zh,rxidx_w              ;
-       add     zl,zh                   ;
-       inc     zh                      ;
-       andi    zh,RXBUFMASK            ;
-       sts     rxidx_w,zh              ;   rxidx_w = ++rxidx_w % RXBUFSIZE
-       ldi     zh,high(rxfifo)         ;
-       brcc    PC+2                    ;
-       inc     zh                      ;
-       st      z,temp                  ;   rxfifo[rxidx_w] = char
-srxi_ov:                                       ;endif
-
-srxi_end2:
+       lds     zh,rxcount                      ;2   if rxcount < RXBUFSIZE
+       cpi     zh,RXBUFSIZE                    ;1      (room for at least 1 char?)
+       brsh    srxi_ov                         ;1 
+       inc     zh                              ;1
+       sts     rxcount,zh                      ;2      rxcount++
+
+       ldi     zl,low(rxfifo)                  ;1  
+       lds     zh,rxidx_w                      ;2
+       add     zl,zh                           ;1
+       inc     zh                              ;1
+       andi    zh,RXBUFMASK                    ;1
+       sts     rxidx_w,zh                      ;2      rxidx_w = ++rxidx_w % RXBUFSIZE
+       ldi     zh,high(rxfifo)                 ;1
+       adc     zh,_0                           ;1
+       st      z,temp                          ;2      rxfifo[rxidx_w] = char
+srxi_ov:                                       ;=19     endif
+
+srxi_end:
        pop     temp2
-srxi_end: 
        pop     zl
        pop     zh
        pop     temp
@@ -331,82 +349,76 @@ srxi_end:
        
        INTERRUPT OC1Aaddr
        
-       push    temp
-       in      temp,sreg
-       push    temp
+       push    zl
+       in      zl,sreg
+       push    zl
        push    zh
 
-       inm8    temp,OCR1AL
+       inm8    zl,OCR1AL
        inm8    zh,OCR1AH
-       subi    temp,low(-SSER_BIT_TC)
+       subi    zl,low(-SSER_BIT_TC)
        sbci    zh,high(-SSER_BIT_TC)
        outm8   OCR1AH,zh
-       outm8   OCR1AL,temp
-       lds     temp,stx_bitcount
-       tst     temp
-       breq    stxi_nxtchar
+       outm8   OCR1AL,zl
+
+       lds     zl,stx_bitcount
+       dec     zl
+       brpl    stxi_nextbit
        
-       dec     temp
-       sts     stx_bitcount,temp
-       ldi     zh,9                            ;Start bit?
-       cp      temp,zh
-       ldi     zh,(1<<COM1A1)
-       breq    stxi_0
-       lds     temp,stx_dr
-       sbrs    temp,0
-       ldi     zh,(1<<COM1A1)|(1<<COM1A0)
-       lsr     temp
-       sts     stx_dr,temp
-stxi_0:
-       outm8   TCCR1A,zh
-       pop     zh
-       pop     temp
-       out     sreg,temp
-       pop     temp
-       reti
+; bit counter was 0, more characters?
 
-; more characters?
 stxi_nxtchar:
-       lds     temp,txcount            ;if txcount != 0
-       tst     temp                    ;
-       breq    stxi_dis
+       lds     zl,txcount              ;if txcount != 0
+       dec     zl
+       brmi    stxi_dis
+
 ; get next char
-       push    zl
-       dec     temp                    ;
-       sts     txcount,temp            ;   --txcount
+       sts     txcount,zl              ;   --txcount
+       push    temp                    ;
        ldi     zl,low(txfifo)          ;  
        ldi     zh,high(txfifo)         ;
        lds     temp,txidx_r            ;
        add     zl,temp                 ;
-       brcc    PC+2                    ;
-       inc     zh                      ;
+       adc     zh,_0
        inc     temp                    ;
        andi    temp,TXBUFMASK          ;
        sts     txidx_r,temp            ;
        ld      temp,z
        com     temp
        sts     stx_dr,temp
-       ldi     temp,10
+       ldi     temp,9
        sts     stx_bitcount,temp
-       pop     zl
-       pop     zh
-       pop     temp
-       out     sreg,temp
        pop     temp
-       reti
+
+       ldi     zh,(1<<COM1A1)
+       rjmp    stxi_ex
 
 ; disable transmitter
 stxi_dis:
-       ldi     temp,(1<<COM1A1)|(1<<COM1A0)
-       outm8   TCCR1A,temp
-       inm8    temp,TIMSK1
-       andi    temp,~(1<<OCIE1A)
-       outm8   TIMSK1,temp
+       inm8    zl,TIMSK1
+       andi    zl,~(1<<OCIE1A)
+       outm8   TIMSK1,zl
+
+       ldi     zh,(1<<COM1A1)|(1<<COM1A0)
+       rjmp    stxi_ex
+
+stxi_nextbit:
+       sts     stx_bitcount,zl
+
+       ldi     zh,(1<<COM1A1)
+       lds     zl,stx_dr
+       sbrs    zl,0
+       ldi     zh,(1<<COM1A1)|(1<<COM1A0)
+       lsr     zl
+       sts     stx_dr,zl
+stxi_ex:
+       outm8   TCCR1A,zh
        pop     zh
-       pop     temp
-       out     sreg,temp
-       pop     temp
+       pop     zl
+       out     sreg,zl
+       pop     zl
        reti
+
 ;------------------------------------------------------------------
 
 srx_to:
@@ -424,9 +436,12 @@ srx_to:
        rcall   uartputc
 #endif
        lds     temp,srx_dr             ;only 0 if timeout after leading edge of start bit.
-       tst     temp
+       tst     temp                    ; --> break
        brne    srxto_store
        sbr     intstat,(1<<i_break)
+       sts     rxcount,_0              ;clear rx buffer
+       sts     rxidx_w,_0
+       sts     rxidx_r,_0
        rjmp    srxto_ov
 
 srxto_store:
@@ -465,27 +480,34 @@ srxto_ov:                                 ;endif
 ;Fetches a char from the buffer to temp. If none available, waits till one is.
 
 uartgetc:
+       push    zh
+       push    zl
+       push    temp2
+ugetc_w:
        lds     temp,rxcount            ;Number of characters in buffer
        tst     temp
-       breq    uartgetc                ;Wait for char
+       breq    ugetc_w                 ;Wait for char
        
-       push    zh
-       push    zl
        ldi     zl,low(rxfifo)
        ldi     zh,high(rxfifo)
-       lds     temp,rxidx_r
-       add     zl,temp
-       brcc    PC+2
-       inc     zh
-       inc     temp
-       andi    temp,RXBUFMASK
-       sts     rxidx_r,temp
+       lds     temp2,rxidx_r
+       add     zl,temp2
+       adc     zh,_0
+       inc     temp2
+       andi    temp2,RXBUFMASK
        cli
        lds     temp,rxcount
-       dec     temp
+       subi    temp,1
+       brcc    ugetc_fin
+       sei
+       rjmp    ugetc_w
+
+ugetc_fin:
        sts     rxcount,temp
+       sts     rxidx_r,temp2
        sei
        ld      temp,z          ;don't forget to get the char
+       pop     temp2
        pop     zl
        pop     zh
        ret
@@ -507,8 +529,7 @@ sputc_l:
        ldi     zh,high(txfifo)         ;
        lds     temp,txidx_w            ;
        add     zl,temp                 ;
-       brcc    PC+2                    ;
-       inc     zh                      ;
+       adc     zh,_0                   ;
        inc     temp                    ;
        andi    temp,TXBUFMASK          ;
        sts     txidx_w,temp            ;   txidx_w = ++txidx_w % TXBUFSIZE
@@ -518,12 +539,23 @@ sputc_l:
        lds     zh,txcount
        inc     zh
        sts     txcount,zh
-       dec     zh
+       cpi     zh,1
        brne    sputc_e
 ; Enable transmitter
        inm8    zh,TIMSK1
+       sbrc    zh,OCIE1A
+       rjmp    sputc_e
        ori     zh,(1<<OCIE1A)
        outm8   TIMSK1,zh
+
+       inm8    zl,TCNT1L               ;
+       inm8    zh,TCNT1H               ;
+       adiw    zl,30                   ;
+       outm8   OCR1AH,zh               ;
+       outm8   OCR1AL,zl               ;
+       ldi     zl,(1<<OCF1A)
+       outm8   TIFR1,zl
+
 sputc_e:
        pop     zl
        out     sreg,zl