Skip to content

Commit

Permalink
Added support for single wire serial ports.
Browse files Browse the repository at this point in the history
Added support for single wire serial ports.
  • Loading branch information
TheNetStriker committed Mar 1, 2019
1 parent d2b0b81 commit 011600c
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 6 deletions.
46 changes: 45 additions & 1 deletion teensy3/HardwareSerial.h
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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))
Expand Down
28 changes: 27 additions & 1 deletion teensy3/serial1.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down
28 changes: 27 additions & 1 deletion teensy3/serial2.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down
29 changes: 26 additions & 3 deletions teensy3/serial3.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
}
Expand Down

0 comments on commit 011600c

Please sign in to comment.