From 011600c6f75c400c7df5140123d720ed9c803f97 Mon Sep 17 00:00:00 2001 From: TheNetStriker Date: Fri, 1 Mar 2019 11:06:30 +0100 Subject: [PATCH] Added support for single wire serial ports. Added support for single wire serial ports. --- teensy3/HardwareSerial.h | 46 +++++++++++++++++++++++++++++++++++++++- teensy3/serial1.c | 28 +++++++++++++++++++++++- teensy3/serial2.c | 28 +++++++++++++++++++++++- teensy3/serial3.c | 29 ++++++++++++++++++++++--- 4 files changed, 125 insertions(+), 6 deletions(-) diff --git a/teensy3/HardwareSerial.h b/teensy3/HardwareSerial.h index 93f962335..21333498f 100644 --- a/teensy3/HardwareSerial.h +++ b/teensy3/HardwareSerial.h @@ -35,6 +35,8 @@ // Uncomment to enable 9 bit formats. These are default disabled to save memory. //#define SERIAL_9BIT_SUPPORT +// uncomment to enable Single Wire (i.e. all TX & RX communication via the TX line) +#define SERIAL_SINGLEWIRE_SUPPORT // // On Windows & Linux, this file is in Arduino's hardware/teensy/avr/cores/teensy3 // folder. The Windows installer puts Arduino in C:\Program Files (x86)\Arduino @@ -79,6 +81,47 @@ #define SERIAL_9E1_RXINV_TXINV 0xBE #define SERIAL_9O1_RXINV_TXINV 0xBF #endif +#ifdef SERIAL_SINGLEWIRE_SUPPORT +#define SERIAL_7E1_SINGLEWIRE 0x102 +#define SERIAL_7O1_SINGLEWIRE 0x103 +#define SERIAL_8N1_SINGLEWIRE 0x100 +#define SERIAL_8N2_SINGLEWIRE 0x104 +#define SERIAL_8E1_SINGLEWIRE 0x106 +#define SERIAL_8O1_SINGLEWIRE 0x107 +#define SERIAL_7E1_RXINV_SINGLEWIRE 0x112 +#define SERIAL_7O1_RXINV_SINGLEWIRE 0x113 +#define SERIAL_8N1_RXINV_SINGLEWIRE 0x110 +#define SERIAL_8N2_RXINV_SINGLEWIRE 0x114 +#define SERIAL_8E1_RXINV_SINGLEWIRE 0x116 +#define SERIAL_8O1_RXINV_SINGLEWIRE 0x117 +#define SERIAL_7E1_TXINV_SINGLEWIRE 0x122 +#define SERIAL_7O1_TXINV_SINGLEWIRE 0x123 +#define SERIAL_8N1_TXINV_SINGLEWIRE 0x120 +#define SERIAL_8N2_TXINV_SINGLEWIRE 0x124 +#define SERIAL_8E1_TXINV_SINGLEWIRE 0x126 +#define SERIAL_8O1_TXINV_SINGLEWIRE 0x127 +#define SERIAL_7E1_RXINV_TXINV_SINGLEWIRE 0x132 +#define SERIAL_7O1_RXINV_TXINV_SINGLEWIRE 0x133 +#define SERIAL_8N1_RXINV_TXINV_SINGLEWIRE 0x130 +#define SERIAL_8N2_RXINV_TXINV_SINGLEWIRE 0x134 +#define SERIAL_8E1_RXINV_TXINV_SINGLEWIRE 0x136 +#define SERIAL_8O1_RXINV_TXINV_SINGLEWIRE 0x137 +#ifdef SERIAL_9BIT_SUPPORT +#define SERIAL_9N1_SINGLEWIRE 0x184 +#define SERIAL_9E1_SINGLEWIRE 0x18E +#define SERIAL_9O1_SINGLEWIRE 0x18F +#define SERIAL_9N1_RXINV_SINGLEWIRE 0x194 +#define SERIAL_9E1_RXINV_SINGLEWIRE 0x19E +#define SERIAL_9O1_RXINV_SINGLEWIRE 0x19F +#define SERIAL_9N1_TXINV_SINGLEWIRE 0x1A4 +#define SERIAL_9E1_TXINV_SINGLEWIRE 0x1AE +#define SERIAL_9O1_TXINV_SINGLEWIRE 0x1AF +#define SERIAL_9N1_RXINV_TXINV_SINGLEWIRE 0x1B4 +#define SERIAL_9E1_RXINV_TXINV_SINGLEWIRE 0x1BE +#define SERIAL_9O1_RXINV_TXINV_SINGLEWIRE 0x1BF +#endif // SERIAL 9BIT +#define SERIAL_SINGLEWIRE_BITMASK 0x100 +#endif // SINGLEWIRE // Teensy LC and 3.5 and 3.6 Uarts have 1/2 bit stop setting #if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL) #define SERIAL_2STOP_BITS 0x100 @@ -101,6 +144,7 @@ #define SERIAL_8N2_TXINV 0x24 #define SERIAL_8N2_RXINV_TXINV 0x34 #endif + // bit0: parity, 0=even, 1=odd // bit1: parity, 0=disable, 1=enable // bit2: mode, 1=9bit, 0=8bit @@ -109,7 +153,7 @@ // bit5: txinv, 0=normal, 1=inverted // bit6: unused // bit7: actual data goes into 9th bit - +// bit8: single wire #if defined(KINETISK) #define BAUD2DIV(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud)) diff --git a/teensy3/serial1.c b/teensy3/serial1.c index ab32d3cc9..7ac527464 100644 --- a/teensy3/serial1.c +++ b/teensy3/serial1.c @@ -79,6 +79,9 @@ static volatile uint8_t transmitting = 0; #define rts_assert() *(rts_pin+8) = rts_mask; #define rts_deassert() *(rts_pin+4) = rts_mask; #endif +#ifdef SERIAL_SINGLEWIRE_SUPPORT + static volatile uint8_t single_wire=0; +#endif #if SERIAL1_TX_BUFFER_SIZE > 255 static volatile uint16_t tx_buffer_head = 0; static volatile uint16_t tx_buffer_tail = 0; @@ -170,7 +173,21 @@ void serial_format(uint32_t format) c = UART0_C1; c = (c & ~0x13) | (format & 0x03); // configure parity if (format & 0x04) c |= 0x10; // 9 bits (might include parity) - UART0_C1 = c; +#ifdef SERIAL_SINGLEWIRE_SUPPORT + c = c & ~( 0x80 ); // ToDo: Check what happens when we clear RSRC and set TXDIR + if ( format & SERIAL_SINGLEWIRE_BITMASK ) { + c = c | ( 0x80 | 0x20 ); // single wire mode - set C1[LOOPS = 7] and C1[RSRC = 5] + UART0_C1 = c; + c = UART0_C3 & ~0x20; // single wire mode also wants the C3[TXDIR = 5] to be cleared so it's listening + UART0_C3 = c; + single_wire = 1; // make sure there's a flag set so it can be toggled when necessary + } else { + UART0_C1 = c; + single_wire = 0; + } +#else + UART0_C1 = c; // save that c value from above +#endif if ((format & 0x0F) == 0x04) UART0_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1 c = UART0_S2 & ~0x10; if (format & 0x10) c |= 0x10; // rx invert @@ -363,6 +380,9 @@ void serial_putchar(uint32_t c) if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return; if (transmit_pin) transmit_assert(); +#ifdef SERIAL_SINGLEWIRE_SUPPORT + if (single_wire) UART0_C3 = UART0_C3 | 0x20; +#endif head = tx_buffer_head; if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0; while (tx_buffer_tail == head) { @@ -395,6 +415,9 @@ void serial_write(const void *buf, unsigned int count) if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return; if (transmit_pin) transmit_assert(); +#ifdef SERIAL_SINGLEWIRE_SUPPORT + if (single_wire) UART0_C3 = UART0_C3 | 0x20; +#endif while (p < end) { head = tx_buffer_head; if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0; @@ -609,6 +632,9 @@ void uart0_status_isr(void) if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) { transmitting = 0; if (transmit_pin) transmit_deassert(); +#ifdef SERIAL_SINGLEWIRE_SUPPORT + if (single_wire) UART0_C3 = UART0_C3 & ~0x20; +#endif UART0_C2 = C2_TX_INACTIVE; } } diff --git a/teensy3/serial2.c b/teensy3/serial2.c index 679d6eaa6..dcdcd9f66 100644 --- a/teensy3/serial2.c +++ b/teensy3/serial2.c @@ -78,6 +78,9 @@ static volatile uint8_t transmitting = 0; #define rts_assert() *(rts_pin+8) = rts_mask; #define rts_deassert() *(rts_pin+4) = rts_mask; #endif +#ifdef SERIAL_SINGLEWIRE_SUPPORT + static volatile uint8_t single_wire=0; +#endif #if SERIAL2_TX_BUFFER_SIZE > 255 static volatile uint16_t tx_buffer_head = 0; static volatile uint16_t tx_buffer_tail = 0; @@ -170,7 +173,21 @@ void serial2_format(uint32_t format) c = UART1_C1; c = (c & ~0x13) | (format & 0x03); // configure parity if (format & 0x04) c |= 0x10; // 9 bits (might include parity) - UART1_C1 = c; +#ifdef SERIAL_SINGLEWIRE_SUPPORT + c = c & ~( 0x80 ); // ToDo: Check what happens when we clear RSRC and set TXDIR + if ( format & SERIAL_SINGLEWIRE_BITMASK ) { + c = c | ( 0x80 | 0x20 ); // single wire mode - set C1[LOOPS = 7] and C1[RSRC = 5] + UART1_C1 = c; + c = UART1_C3 & ~0x20; // single wire mode also wants the C3[TXDIR = 5] to be cleared so it's listening + UART1_C3 = c; + single_wire = 1; // make sure there's a flag set so it can be toggled when necessary + } else { + UART1_C1 = c; + single_wire = 0; + } +#else + UART1_C1 = c; // save that c value from above +#endif if ((format & 0x0F) == 0x04) UART1_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1 c = UART1_S2 & ~0x10; if (format & 0x10) c |= 0x10; // rx invert @@ -353,6 +370,9 @@ void serial2_putchar(uint32_t c) if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; if (transmit_pin) transmit_assert(); +#ifdef SERIAL_SINGLEWIRE_SUPPORT + if (single_wire) UART1_C3 = UART1_C3 | 0x20; +#endif head = tx_buffer_head; if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0; while (tx_buffer_tail == head) { @@ -385,6 +405,9 @@ void serial2_write(const void *buf, unsigned int count) if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; if (transmit_pin) transmit_assert(); +#ifdef SERIAL_SINGLEWIRE_SUPPORT + if (single_wire) UART1_C3 = UART1_C3 | 0x20; +#endif while (p < end) { head = tx_buffer_head; if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0; @@ -599,6 +622,9 @@ void uart1_status_isr(void) if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) { transmitting = 0; if (transmit_pin) transmit_deassert(); +#ifdef SERIAL_SINGLEWIRE_SUPPORT + if (single_wire) UART1_C3 = UART1_C3 & ~0x20; +#endif UART1_C2 = C2_TX_INACTIVE; } } diff --git a/teensy3/serial3.c b/teensy3/serial3.c index f7e6c8234..c110c1326 100644 --- a/teensy3/serial3.c +++ b/teensy3/serial3.c @@ -79,6 +79,9 @@ static volatile uint8_t transmitting = 0; #define rts_assert() *(rts_pin+8) = rts_mask; #define rts_deassert() *(rts_pin+4) = rts_mask; #endif +#ifdef SERIAL_SINGLEWIRE_SUPPORT + static volatile uint8_t single_wire=0; +#endif #if SERIAL3_TX_BUFFER_SIZE > 255 static volatile uint16_t tx_buffer_head = 0; static volatile uint16_t tx_buffer_tail = 0; @@ -152,7 +155,21 @@ void serial3_format(uint32_t format) c = UART2_C1; c = (c & ~0x13) | (format & 0x03); // configure parity if (format & 0x04) c |= 0x10; // 9 bits (might include parity) - UART2_C1 = c; +#ifdef SERIAL_SINGLEWIRE_SUPPORT + c = c & ~( 0x80 ); // ToDo: Check what happens when we clear RSRC and set TXDIR + if ( format & SERIAL_SINGLEWIRE_BITMASK ) { + c = c | ( 0x80 | 0x20 ); // single wire mode - set C1[LOOPS = 7] and C1[RSRC = 5] + UART2_C1 = c; + c = UART2_C3 & ~0x20; // single wire mode also wants the C3[TXDIR = 5] to be cleared so it's listening + UART2_C3 = c; + single_wire = 1; // make sure there's a flag set so it can be toggled when necessary + } else { + UART2_C1 = c; + single_wire = 0; + } +#else + UART2_C1 = c; // save that c value from above +#endif if ((format & 0x0F) == 0x04) UART2_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1 c = UART2_S2 & ~0x10; if (format & 0x10) c |= 0x10; // rx invert @@ -195,9 +212,9 @@ void serial3_end(void) case 8: CORE_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; case 20: CORE_PIN20_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; } - #endif + #endif UART2_S1; - UART2_D; // clear leftover error status + UART2_D; // clear leftover error status rx_buffer_head = 0; rx_buffer_tail = 0; if (rts_pin) rts_deassert(); @@ -309,6 +326,9 @@ void serial3_putchar(uint32_t c) if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return; if (transmit_pin) transmit_assert(); +#ifdef SERIAL_SINGLEWIRE_SUPPORT + if (single_wire) UART2_C3 = UART2_C3 | 0x20; +#endif head = tx_buffer_head; if (++head >= SERIAL3_TX_BUFFER_SIZE) head = 0; while (tx_buffer_tail == head) { @@ -450,6 +470,9 @@ void uart2_status_isr(void) if ((c & UART_C2_TCIE) && (UART2_S1 & UART_S1_TC)) { transmitting = 0; if (transmit_pin) transmit_deassert(); +#ifdef SERIAL_SINGLEWIRE_SUPPORT + if (single_wire) UART2_C3 = UART2_C3 & ~0x20; +#endif UART2_C2 = C2_TX_INACTIVE; } }