Updated John Steggall's software USART in the XPLAINBridge project.
[pub/USBasp.git] / Projects / XPLAINBridge / Lib / SoftUART.S
index 8951387..f9a89d9 100644 (file)
@@ -2,6 +2,8 @@
 \r
        uart_soft\r
 \r
+       v0.2\r
+\r
        copyright John Steggall 2009\r
 \r
 */\r
 */\r
 \r
 #include <avr/io.h>\r
+#include "SoftUARTConf.h"\r
 \r
-/* BITLENGTH is the time for a bit cycle worked out at F_CPU / BAUD. Gives a rough but usable figure. Wouldn't like to try\r
- * anything faster than 9600! */\r
-#define BITLENGTH 833\r
 \r
 #define SFT_TX_EN 7\r
 \r
@@ -52,43 +52,59 @@ rxShifter:
        .byte   0\r
 rxBitcount:\r
        .byte   0\r
+       \r
+       .global status\r
 status:\r
        .byte   0\r
 \r
        .section        .text\r
 \r
+\r
+       .global RX_PIN_INT\r
+\r
 /*********************************************\r
  * External interrupt\r
  * \r
  * RX pin has gone low.\r
  */\r
-       .global INT0_vect\r
-\r
-INT0_vect:\r
+RX_PIN_INT:\r
        push            r16\r
        lds             r16,SREG\r
        push            r16\r
 \r
-       lds             r16,PIND\r
+#if (RXPORT>=32)\r
+       lds             r16,RXPORT\r
        sbrc            r16,0           // anti glitch\r
+\r
+#else\r
+       sbic            RXPORT,0\r
+#endif\r
+\r
        rjmp            ignore\r
        nop\r
        nop\r
        nop\r
        nop\r
-       lds             r16,PIND\r
-       sbrc            r16,0           // just make sure\r
+\r
+#if (RXPORT>=32)\r
+       lds             r16,RXPORT\r
+       sbrc            r16,0           // anti glitch\r
+\r
+#else\r
+       sbic            RXPORT,0\r
+#endif\r
+\r
        rjmp            ignore\r
 \r
        push            r17\r
 \r
        // grab timer value\r
-       lds             r16,TCNT3L              \r
-       lds             r17,TCNT3H\r
+       lds             r16,TC_COUNTL           \r
+       lds             r17,TC_COUNTH\r
        \r
        // set trigger for RX timer (will need to add a little more though)\r
-       sts             OCR3CH,r17\r
-       sts             OCR3CL,r16\r
+       sts             TC_RX_COMPH,r17\r
+       sts             TC_RX_COMPL,r16\r
        \r
        pop             r17\r
 \r
@@ -98,13 +114,15 @@ INT0_vect:
 \r
 \r
        // turn off interrupt, will get annoying.\r
-       cbi             0x1D,0\r
+       cbi             EXTI_MASK_REG,EXTI_MASK_BIT\r
 \r
        // turn on interrupt on compare match\r
-       sbi             0x18,OCF3C\r
-       lds             r16,TIMSK3\r
-       ori             r16,(1<<OCIE3C)\r
-       sts             TIMSK3,r16\r
+\r
+       sbi             TC_INTFLAG_REG,TC_RX_IF_BIT             //------------------------\r
+\r
+       lds             r16,TC_INT_MASK_REG\r
+       ori             r16,(1<<TC_RX_COMPEN)\r
+       sts             TC_INT_MASK_REG,r16\r
 \r
 ignore:\r
        pop             r16\r
@@ -136,17 +154,23 @@ TIMER3_COMPB_vect:
 \r
        lds             r16,txShifter\r
 \r
-       lds             r17, PORTD\r
-\r
+#if (TXPORT>=32)\r
+       lds             r17, TXPORT\r
        sbrs            r16,0\r
-       andi            r17,0xFD\r
+       andi            r17,~(1<<TXPIN)\r
        sbrc            r16,0\r
-       ori             r17,0x02\r
+       ori             r17,(1<<TXPIN)\r
+       sts             TXPORT,r17\r
 \r
-       sts             PORTD,r17\r
+#else\r
+       sbrs            r16,0\r
+       cbi             TXPORT,TXPIN\r
+       sbrc            r16,0\r
+       sbi             TXPORT,TXPIN\r
 \r
-       lsr             r16\r
-       ori             r16,0x80\r
+#endif\r
+       sec\r
+       ror             r16\r
 \r
 txout:\r
        sts             txShifter,r16\r
@@ -164,9 +188,9 @@ lastBitTX:
        ori             r17,SF_UART_TX          // set TXC/DRE flag\r
        sts             status,r17\r
 \r
-       lds             r16,TIMSK3\r
-       andi            r16,~(1<<OCIE3B)\r
-       sts             TIMSK3,r16\r
+       lds             r16,TC_INT_MASK_REG\r
+       andi            r16,~(1<<TC_TX_COMPEN)\r
+       sts             TC_INT_MASK_REG,r16\r
 \r
        rjmp            lastBitOut              // over and out\r
 \r
@@ -199,11 +223,27 @@ TIMER3_COMPC_vect:
        ldi             r18,3                   // set counter to 3\r
        ldi             r17,0\r
 \r
-//     cbi             0x0B,1                  // marker\r
+#ifdef DEBUG\r
+\r
+#if RXPORT>64\r
+       lds             r16,RXPORT\r
+       andi            r16,~(1<<TXPIN)\r
+       sts             TXPORT,r16\r
+#else\r
+       cbi             TXPORT,TXPIN                    // marker\r
+#endif\r
+#endif\r
 \r
 loopGetBit:\r
-       lds             r16,PIND                        \r
-       sbrc            r16,0\r
+\r
+#if (RXPORT>=32)\r
+       lds             r16,RXPORT\r
+       sbrs            r16,RXPIN\r
+#else                  \r
+       sbic            RXPORT,RXPIN\r
+\r
+#endif\r
+\r
        inc             r17\r
        dec             r18\r
        nop\r
@@ -212,7 +252,19 @@ loopGetBit:
        nop\r
        brne            loopGetBit\r
 \r
-//     sbi             0x0B,1                  // marker\r
+#ifdef DEBUG\r
+\r
+#if RXPORT>64\r
+       lds             r16,RXPORT\r
+       ori             r16,1<<TXPIN\r
+       sts             r16\r
+\r
+#else\r
+       sbi             TXPORT,TXPIN                    // marker\r
+\r
+#endif\r
+#endif\r
+\r
 \r
        lds             r16,rxShifter\r
        lsr             r16\r
@@ -226,8 +278,16 @@ skipBitSet:
 \r
 lastBitRX:\r
        lds             r17,status              // store status\r
-       lds             r16,PIND                        // get status of stop bit\r
-       sbrc            r16,0\r
+\r
+#if (RXPORT>=32)\r
+       lds             r16,RXPORT\r
+       sbrc            r16,RXPIN\r
+\r
+#else\r
+       sbic            RXPORT,RXPIN    \r
+\r
+#endif\r
+\r
        ori             r17,0x02                        // set flag if stop bit was high\r
        sts             status,r17\r
 \r
@@ -237,19 +297,19 @@ lastBitRX:
 \r
        // switch interrupt back on to get another go\r
 \r
-       sbi             0x1C,0                  // clear interrupt flag\r
-       sbi             0x1D,0                  // enable external interrupt 0 (RX)\r
+       sbi             EXTI_FLAG_REG,EXTI_MASK_BIT     // clear interrupt flag\r
+       sbi             EXTI_MASK_REG,EXTI_MASK_BIT     // enable external interrupt 0 (RX)\r
 \r
        // switch off rx bit timer\r
-       lds             r16,TIMSK3\r
-       andi            r16,~(1<<OCIE3C)\r
-       sts             TIMSK3,r16\r
+       lds             r16,TC_INT_MASK_REG\r
+       andi            r16,~(1<<TC_RX_COMPEN)\r
+       sts             TC_INT_MASK_REG,r16\r
 \r
        rjmp            lastBitOut              // loud and clear\r
 \r
 rx1stbit:\r
-       lds             r16,TCNT3L\r
-       lds             r17,TCNT3H\r
+       lds             r16,TC_COUNTL\r
+       lds             r17,TC_COUNTH\r
 \r
        subi            r16,lo8(BITLENGTH / 2)\r
        sbci            r17,hi8(BITLENGTH / 2)\r
@@ -259,8 +319,8 @@ rx1stbit:
        sbci            r17,hi8(0xFFFF - BITLENGTH)\r
 \r
 skipOverflow:\r
-       sts             OCR3CH,r17\r
-       sts             OCR3CL,r17\r
+       sts             TC_RX_COMPH,r17\r
+       sts             TC_RX_COMPL,r17\r
        rjmp            lastBitOut\r
 \r
                        \r
@@ -273,12 +333,20 @@ skipOverflow:
 \r
 SoftUART_Init:\r
 \r
-       lds             r18,PORTD\r
+#if (TXPORT>=32)\r
+       lds             r18,TXPORT\r
        ori             r18,0x02\r
-       sts             PORTD,r18\r
-       lds             r18,DDRD\r
+       sts             TXPORT,r18\r
+\r
+       lds             r18,TXDIR_REG\r
        ori             r18,0x02\r
-       sts             DDRD,r18\r
+       sts             TXDIR_REG,r18\r
+\r
+#else\r
+       sbi             TXPORT,TXPIN\r
+       sbi             TXDIR_REG,TXPIN\r
+\r
+#endif\r
 \r
        ldi             r18,(1<<SFT_TX_EN)|SF_UART_TX\r
        sts             status,r18\r
@@ -290,17 +358,17 @@ SoftUART_Init:
 \r
        // Start timer 3\r
        ldi             r18,0b00001001                  // ctc count mode, clock div 1\r
-       sts             TCCR3B,r18\r
+       sts             TC_CTRLB,r18\r
 \r
-       // Interrupt on low level INT0\r
-       sbi             0x1C,0\r
-       sbi             0x1D,0\r
+       // Interrupt on pin change INT0\r
+       sbi             EXTI_FLAG_REG,EXTI_MASK_BIT\r
+       sbi             EXTI_MASK_REG,EXTI_MASK_BIT\r
 \r
        ret\r
 \r
 \r
 /*********************************************\r
- * char SoftUART_TxByte(char)\r
+ * char SoftUART_RxByte(char)\r
  *\r
  * starts a byte send and returns the byte to be sent\r
  */\r
@@ -309,7 +377,7 @@ SoftUART_Init:
 SoftUART_TxByte:\r
        lds             r18,status\r
        sbrs            r18,SFT_TX_EN\r
-       rjmp            uart_putchar_end\r
+       rjmp            SoftUART_TxByte_end\r
 \r
        andi            r18,0xFE                                                // clear tx empty flag\r
        sts             status,r18\r
@@ -320,28 +388,35 @@ SoftUART_TxByte:
        sts             txBitcount,r18\r
 \r
        // grab timer value\r
-\r
-       lds             r18,TCNT3L\r
-       lds             r19,TCNT3H\r
+       cli                                                                     // Atomic section start\r
+       lds             r18,TC_COUNTL\r
+       lds             r19,TC_COUNTH\r
 \r
        // drop down tx line for start bit\r
-       lds             r20, PORTD\r
-       andi            r20,0xFD\r
-       sts             PORTD,r20\r
-       \r
+\r
+#if (TXPORT>=32)\r
+       lds             r20, TXPORT\r
+       andi            r20,~(1<<TXPIN)\r
+       sts             TXPORT,r20\r
+\r
+#else\r
+       cbi             TXPORT,TXPIN\r
+#endif\r
+\r
        // set trigger for tx timer\r
-       cli\r
-       sts             OCR3BH,r19\r
-       sts             OCR3BL,r18\r
-       sei\r
+       sts             TC_TX_COMPH,r19\r
+       sts             TC_TX_COMPL,r18\r
+       sei                                                                     // Atomic section end\r
 \r
        // clear interrupt flag and enable tx interrupt\r
-       sbi             0x18,OCF3B\r
-       lds             r18,TIMSK3\r
-       ori             r18,(1<<OCIE3B)\r
-       sts             TIMSK3,r18\r
 \r
-uart_putchar_end:\r
+       sbi             TC_INTFLAG_REG,TC_TX_IF_BIT\r
+\r
+       lds             r18,TC_INT_MASK_REG\r
+       ori             r18,(1<<TC_TX_COMPEN)\r
+       sts             TC_INT_MASK_REG,r18\r
+\r
+SoftUART_TxByte_end:\r
        ret\r
 \r
 \r