Be doubly-certain that the incomming CDC class driver's endpoint/pipe is flushed...
[pub/USBasp.git] / Projects / AVRISP-MKII / Lib / XPROG / XPROGTarget.c
index def3499..1406428 100644 (file)
@@ -1,13 +1,13 @@
 /*\r
              LUFA Library\r
 /*\r
              LUFA Library\r
-     Copyright (C) Dean Camera, 2009.\r
+     Copyright (C) Dean Camera, 2010.\r
               \r
   dean [at] fourwalledcubicle [dot] com\r
       www.fourwalledcubicle.com\r
 */\r
 \r
 /*\r
               \r
   dean [at] fourwalledcubicle [dot] com\r
       www.fourwalledcubicle.com\r
 */\r
 \r
 /*\r
-  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
 \r
   Permission to use, copy, modify, distribute, and sell this \r
   software and its documentation for any purpose is hereby granted\r
 \r
   Permission to use, copy, modify, distribute, and sell this \r
   software and its documentation for any purpose is hereby granted\r
@@ -71,7 +71,7 @@ ISR(TIMER1_COMPA_vect, ISR_BLOCK)
                  return;\r
        \r
                /* Shift in the bit one less than the frame size in position, so that the start bit will eventually\r
                  return;\r
        \r
                /* Shift in the bit one less than the frame size in position, so that the start bit will eventually\r
-                * be discarded leaving the data to be byte-aligned for quick access */\r
+                * be discarded leaving the data to be byte-aligned for quick access (subtract 9 as we are ORing to the MSB) */\r
                if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)\r
                  ((uint8_t*)&SoftUSART_Data)[1] |= (1 << (BITS_IN_USART_FRAME - 9));\r
 \r
                if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)\r
                  ((uint8_t*)&SoftUSART_Data)[1] |= (1 << (BITS_IN_USART_FRAME - 9));\r
 \r
@@ -117,7 +117,7 @@ ISR(TIMER1_COMPB_vect, ISR_BLOCK)
                  return;\r
        \r
                /* Shift in the bit one less than the frame size in position, so that the start bit will eventually\r
                  return;\r
        \r
                /* Shift in the bit one less than the frame size in position, so that the start bit will eventually\r
-                * be discarded leaving the data to be byte-aligned for quick access */\r
+                * be discarded leaving the data to be byte-aligned for quick access (subtract 9 as we are ORing to the MSB) */\r
                if (BITBANG_TPIDATA_PIN & BITBANG_TPIDATA_MASK)\r
                 ((uint8_t*)&SoftUSART_Data)[1] |= (1 << (BITS_IN_USART_FRAME - 9));\r
 \r
                if (BITBANG_TPIDATA_PIN & BITBANG_TPIDATA_MASK)\r
                 ((uint8_t*)&SoftUSART_Data)[1] |= (1 << (BITS_IN_USART_FRAME - 9));\r
 \r
@@ -154,12 +154,11 @@ void XPROGTarget_EnableTargetPDI(void)
        \r
        /* Set DATA line high for at least 90ns to disable /RESET functionality */\r
        PORTD |= (1 << 3);\r
        \r
        /* Set DATA line high for at least 90ns to disable /RESET functionality */\r
        PORTD |= (1 << 3);\r
-       asm volatile ("NOP"::);\r
-       asm volatile ("NOP"::);\r
+       _delay_ms(1);\r
        \r
        /* Set up the synchronous USART for XMEGA communications - \r
           8 data bits, even parity, 2 stop bits */\r
        \r
        /* Set up the synchronous USART for XMEGA communications - \r
           8 data bits, even parity, 2 stop bits */\r
-       UBRR1  = (F_CPU / 1000000UL);\r
+       UBRR1  = (F_CPU / 500000UL);\r
        UCSR1B = (1 << TXEN1);\r
        UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);\r
 #else\r
        UCSR1B = (1 << TXEN1);\r
        UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);\r
 #else\r
@@ -169,8 +168,7 @@ void XPROGTarget_EnableTargetPDI(void)
        \r
        /* Set DATA line high for at least 90ns to disable /RESET functionality */\r
        BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;\r
        \r
        /* Set DATA line high for at least 90ns to disable /RESET functionality */\r
        BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;\r
-       asm volatile ("NOP"::);\r
-       asm volatile ("NOP"::);\r
+       _delay_ms(1);\r
 \r
        /* Fire timer compare channel A ISR to manage the software USART */\r
        OCR1A   = BITS_BETWEEN_USART_CLOCKS;\r
 \r
        /* Fire timer compare channel A ISR to manage the software USART */\r
        OCR1A   = BITS_BETWEEN_USART_CLOCKS;\r
@@ -188,20 +186,19 @@ void XPROGTarget_EnableTargetTPI(void)
 {\r
        IsSending = false;\r
 \r
 {\r
        IsSending = false;\r
 \r
-       /* Set /RESET line low for at least 90ns to enable TPI functionality */\r
-       RESET_LINE_DDR  |= RESET_LINE_MASK;\r
-       RESET_LINE_PORT &= ~RESET_LINE_MASK;\r
-       asm volatile ("NOP"::);\r
-       asm volatile ("NOP"::);\r
+       /* Set /RESET line low for at least 400ns to enable TPI functionality */\r
+       AUX_LINE_DDR  |=  AUX_LINE_MASK;\r
+       AUX_LINE_PORT &= ~AUX_LINE_MASK;\r
+       _delay_ms(1);\r
 \r
 #if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Set Tx and XCK as outputs, Rx as input */\r
        DDRD |=  (1 << 5) | (1 << 3);\r
        DDRD &= ~(1 << 2);\r
                \r
 \r
 #if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Set Tx and XCK as outputs, Rx as input */\r
        DDRD |=  (1 << 5) | (1 << 3);\r
        DDRD &= ~(1 << 2);\r
                \r
-       /* Set up the synchronous USART for XMEGA communications - \r
+       /* Set up the synchronous USART for TINY communications - \r
           8 data bits, even parity, 2 stop bits */\r
           8 data bits, even parity, 2 stop bits */\r
-       UBRR1  = (F_CPU / 1000000UL);\r
+       UBRR1  = (F_CPU / 500000UL);\r
        UCSR1B = (1 << TXEN1);\r
        UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);\r
 #else\r
        UCSR1B = (1 << TXEN1);\r
        UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);\r
 #else\r
@@ -226,7 +223,14 @@ void XPROGTarget_EnableTargetTPI(void)
 /** Disables the target's PDI interface, exits programming mode and starts the target's application. */\r
 void XPROGTarget_DisableTargetPDI(void)\r
 {\r
 /** Disables the target's PDI interface, exits programming mode and starts the target's application. */\r
 void XPROGTarget_DisableTargetPDI(void)\r
 {\r
+       /* Switch to Rx mode to ensure that all pending transmissions are complete */\r
+       XPROGTarget_SetRxMode();\r
+\r
 #if defined(XPROG_VIA_HARDWARE_USART)\r
 #if defined(XPROG_VIA_HARDWARE_USART)\r
+       /* Set /RESET high for a one millisecond to ensure target device is restarted */\r
+       PORTD |= (1 << 5);\r
+       _delay_ms(1);\r
+\r
        /* Turn off receiver and transmitter of the USART, clear settings */\r
        UCSR1A |= (1 << TXC1) | (1 << RXC1);\r
        UCSR1B  = 0;\r
        /* Turn off receiver and transmitter of the USART, clear settings */\r
        UCSR1A |= (1 << TXC1) | (1 << RXC1);\r
        UCSR1B  = 0;\r
@@ -236,6 +240,10 @@ void XPROGTarget_DisableTargetPDI(void)
        DDRD  &= ~((1 << 5) | (1 << 3));\r
        PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));\r
 #else\r
        DDRD  &= ~((1 << 5) | (1 << 3));\r
        PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));\r
 #else\r
+       /* Set /RESET high for a one millisecond to ensure target device is restarted */\r
+       BITBANG_PDICLOCK_PORT |= BITBANG_PDICLOCK_MASK;\r
+       _delay_ms(1);\r
+\r
        /* Set DATA and CLOCK lines to inputs */\r
        BITBANG_PDIDATA_DDR   &= ~BITBANG_PDIDATA_MASK;\r
        BITBANG_PDICLOCK_DDR  &= ~BITBANG_PDICLOCK_MASK;\r
        /* Set DATA and CLOCK lines to inputs */\r
        BITBANG_PDIDATA_DDR   &= ~BITBANG_PDIDATA_MASK;\r
        BITBANG_PDICLOCK_DDR  &= ~BITBANG_PDICLOCK_MASK;\r
@@ -249,6 +257,9 @@ void XPROGTarget_DisableTargetPDI(void)
 /** Disables the target's TPI interface, exits programming mode and starts the target's application. */\r
 void XPROGTarget_DisableTargetTPI(void)\r
 {\r
 /** Disables the target's TPI interface, exits programming mode and starts the target's application. */\r
 void XPROGTarget_DisableTargetTPI(void)\r
 {\r
+       /* Switch to Rx mode to ensure that all pending transmissions are complete */\r
+       XPROGTarget_SetRxMode();\r
+\r
 #if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Turn off receiver and transmitter of the USART, clear settings */\r
        UCSR1A |= (1 << TXC1) | (1 << RXC1);\r
 #if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Turn off receiver and transmitter of the USART, clear settings */\r
        UCSR1A |= (1 << TXC1) | (1 << RXC1);\r
@@ -269,8 +280,8 @@ void XPROGTarget_DisableTargetTPI(void)
 #endif\r
 \r
        /* Tristate target /RESET line */\r
 #endif\r
 \r
        /* Tristate target /RESET line */\r
-       RESET_LINE_DDR  &= ~RESET_LINE_MASK;\r
-       RESET_LINE_PORT &= ~RESET_LINE_MASK;\r
+       AUX_LINE_DDR  &= ~AUX_LINE_MASK;\r
+       AUX_LINE_PORT &= ~AUX_LINE_MASK;\r
 }\r
 \r
 /** Sends a byte via the USART.\r
 }\r
 \r
 /** Sends a byte via the USART.\r
@@ -279,38 +290,21 @@ void XPROGTarget_DisableTargetTPI(void)
  */\r
 void XPROGTarget_SendByte(const uint8_t Byte)\r
 {\r
  */\r
 void XPROGTarget_SendByte(const uint8_t Byte)\r
 {\r
-#if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Switch to Tx mode if currently in Rx mode */\r
        if (!(IsSending))\r
        /* Switch to Tx mode if currently in Rx mode */\r
        if (!(IsSending))\r
-       {\r
-               PORTD  |=  (1 << 3);\r
-               DDRD   |=  (1 << 3);\r
-\r
-               UCSR1B |=  (1 << TXEN1);\r
-               UCSR1B &= ~(1 << RXEN1);\r
-               \r
-               IsSending = true;\r
-       }\r
-       \r
+         XPROGTarget_SetTxMode();\r
+         \r
+#if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Wait until there is space in the hardware Tx buffer before writing */\r
        while (!(UCSR1A & (1 << UDRE1)));\r
        UCSR1A |= (1 << TXC1);\r
        UDR1    = Byte;\r
 #else\r
        /* Wait until there is space in the hardware Tx buffer before writing */\r
        while (!(UCSR1A & (1 << UDRE1)));\r
        UCSR1A |= (1 << TXC1);\r
        UDR1    = Byte;\r
 #else\r
-       /* Switch to Tx mode if currently in Rx mode */\r
-       if (!(IsSending))\r
-       {\r
-               BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;\r
-               BITBANG_PDIDATA_DDR  |= BITBANG_PDIDATA_MASK;\r
-\r
-               IsSending = true;\r
-       }\r
-\r
        /* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */\r
        uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | (0 << 9) | ((uint16_t)Byte << 1) | (0 << 0));\r
 \r
        /* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */\r
        /* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */\r
        uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | (0 << 9) | ((uint16_t)Byte << 1) | (0 << 0));\r
 \r
        /* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */\r
-       uint8_t ParityData    = Byte;\r
+       uint8_t ParityData = Byte;\r
        while (ParityData)\r
        {\r
                NewUSARTData ^= (1 << 9);\r
        while (ParityData)\r
        {\r
                NewUSARTData ^= (1 << 9);\r
@@ -332,37 +326,15 @@ void XPROGTarget_SendByte(const uint8_t Byte)
  */\r
 uint8_t XPROGTarget_ReceiveByte(void)\r
 {\r
  */\r
 uint8_t XPROGTarget_ReceiveByte(void)\r
 {\r
-#if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Switch to Rx mode if currently in Tx mode */\r
        if (IsSending)\r
        /* Switch to Rx mode if currently in Tx mode */\r
        if (IsSending)\r
-       {\r
-               while (!(UCSR1A & (1 << TXC1)));\r
-               UCSR1A |=  (1 << TXC1);\r
-\r
-               UCSR1B &= ~(1 << TXEN1);\r
-               UCSR1B |=  (1 << RXEN1);\r
-\r
-               DDRD   &= ~(1 << 3);\r
-               PORTD  &= ~(1 << 3);\r
-               \r
-               IsSending = false;\r
-       }\r
+         XPROGTarget_SetRxMode();\r
 \r
 \r
+#if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Wait until a byte has been received before reading */\r
        while (!(UCSR1A & (1 << RXC1)) && TimeoutMSRemaining);\r
        return UDR1;\r
 #else\r
        /* Wait until a byte has been received before reading */\r
        while (!(UCSR1A & (1 << RXC1)) && TimeoutMSRemaining);\r
        return UDR1;\r
 #else\r
-       /* Switch to Rx mode if currently in Tx mode */\r
-       if (IsSending)\r
-       {\r
-               while (SoftUSART_BitCount);\r
-\r
-               BITBANG_PDIDATA_DDR  &= ~BITBANG_PDIDATA_MASK;\r
-               BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;\r
-\r
-               IsSending = false;\r
-       }\r
-\r
        /* Wait until a byte has been received before reading */\r
        SoftUSART_BitCount = BITS_IN_USART_FRAME;\r
        while (SoftUSART_BitCount && TimeoutMSRemaining);\r
        /* Wait until a byte has been received before reading */\r
        SoftUSART_BitCount = BITS_IN_USART_FRAME;\r
        while (SoftUSART_BitCount && TimeoutMSRemaining);\r
@@ -375,19 +347,11 @@ uint8_t XPROGTarget_ReceiveByte(void)
 /** Sends a BREAK via the USART to the attached target, consisting of a full frame of idle bits. */\r
 void XPROGTarget_SendBreak(void)\r
 {\r
 /** Sends a BREAK via the USART to the attached target, consisting of a full frame of idle bits. */\r
 void XPROGTarget_SendBreak(void)\r
 {\r
-#if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Switch to Tx mode if currently in Rx mode */\r
        if (!(IsSending))\r
        /* Switch to Tx mode if currently in Rx mode */\r
        if (!(IsSending))\r
-       {\r
-               PORTD  |=  (1 << 3);\r
-               DDRD   |=  (1 << 3);\r
-\r
-               UCSR1B &= ~(1 << RXEN1);\r
-               UCSR1B |=  (1 << TXEN1);\r
-               \r
-               IsSending = true;\r
-       }\r
+         XPROGTarget_SetTxMode();\r
 \r
 \r
+#if defined(XPROG_VIA_HARDWARE_USART)\r
        /* Need to do nothing for a full frame to send a BREAK */\r
        for (uint8_t i = 0; i < BITS_IN_USART_FRAME; i++)\r
        {\r
        /* Need to do nothing for a full frame to send a BREAK */\r
        for (uint8_t i = 0; i < BITS_IN_USART_FRAME; i++)\r
        {\r
@@ -396,21 +360,81 @@ void XPROGTarget_SendBreak(void)
                while (!(PIND & (1 << 5)));\r
        }\r
 #else\r
                while (!(PIND & (1 << 5)));\r
        }\r
 #else\r
-       /* Switch to Tx mode if currently in Rx mode */\r
-       if (!(IsSending))\r
+       while (SoftUSART_BitCount);\r
+\r
+       /* Need to do nothing for a full frame to send a BREAK */\r
+       SoftUSART_Data     = 0x0FFF;\r
+       SoftUSART_BitCount = BITS_IN_USART_FRAME;\r
+#endif\r
+}\r
+\r
+static void XPROGTarget_SetTxMode(void)\r
+{\r
+#if defined(XPROG_VIA_HARDWARE_USART)\r
+       /* Wait for a full cycle of the clock */\r
+       while (PIND & (1 << 5));\r
+       while (!(PIND & (1 << 5)));\r
+\r
+       PORTD  |=  (1 << 3);\r
+       DDRD   |=  (1 << 3);\r
+\r
+       UCSR1B &= ~(1 << RXEN1);\r
+       UCSR1B |=  (1 << TXEN1);\r
+               \r
+       IsSending = true;\r
+#else\r
+       while (SoftUSART_BitCount);\r
+\r
+       /* Wait for a full cycle of the clock */\r
+       SoftUSART_Data     = 0x0001;\r
+       SoftUSART_BitCount = 1;\r
+       while (SoftUSART_BitCount);\r
+\r
+       if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)\r
        {\r
                BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;\r
                BITBANG_PDIDATA_DDR  |= BITBANG_PDIDATA_MASK;\r
        {\r
                BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;\r
                BITBANG_PDIDATA_DDR  |= BITBANG_PDIDATA_MASK;\r
-\r
-               IsSending = true;\r
        }\r
        }\r
-       \r
+       else\r
+       {\r
+               BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK;\r
+               BITBANG_TPIDATA_DDR  |= BITBANG_TPIDATA_MASK;   \r
+       }\r
+#endif\r
+\r
+       IsSending = true;\r
+}\r
+\r
+static void XPROGTarget_SetRxMode(void)\r
+{\r
+#if defined(XPROG_VIA_HARDWARE_USART)\r
+       while (!(UCSR1A & (1 << TXC1)));\r
+       UCSR1A |=  (1 << TXC1);\r
+\r
+       UCSR1B &= ~(1 << TXEN1);\r
+       UCSR1B |=  (1 << RXEN1);\r
+\r
+       DDRD   &= ~(1 << 3);\r
+       PORTD  &= ~(1 << 3);\r
+#else\r
        while (SoftUSART_BitCount);\r
 \r
        while (SoftUSART_BitCount);\r
 \r
-       /* Need to do nothing for a full frame to send a BREAK */\r
-       SoftUSART_Data     = 0x0FFF;\r
-       SoftUSART_BitCount = BITS_IN_USART_FRAME;\r
+       if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)\r
+       {\r
+               BITBANG_PDIDATA_DDR  &= ~BITBANG_PDIDATA_MASK;\r
+               BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;\r
+       }\r
+       else\r
+       {\r
+               BITBANG_TPIDATA_DDR  &= ~BITBANG_TPIDATA_MASK;\r
+               BITBANG_TPIDATA_PORT &= ~BITBANG_TPIDATA_MASK;  \r
+       }\r
+       \r
+       /* Wait until DATA line has been pulled up to idle by the target */\r
+       while (!(BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK) && TimeoutMSRemaining);\r
 #endif\r
 #endif\r
+\r
+       IsSending = false;\r
 }\r
 \r
 #endif\r
 }\r
 \r
 #endif\r