T3.x,T4.x LC Serial half duplex supportmain
| @@ -101,6 +101,13 @@ | |||
| #define SERIAL_8N2_TXINV 0x24 | |||
| #define SERIAL_8N2_RXINV_TXINV 0x34 | |||
| #endif | |||
| // Half duplex support | |||
| #define SERIAL_HALF_DUPLEX 0x200 | |||
| #define SERIAL_7E1_HALF_DUPLEX (SERIAL_7E1 | SERIAL_HALF_DUPLEX) | |||
| #define SERIAL_7O1_HALF_DUPLEX (SERIAL_7O1 | SERIAL_HALF_DUPLEX) | |||
| #define SERIAL_8N1_HALF_DUPLEX (SERIAL_8N1 | SERIAL_HALF_DUPLEX) | |||
| // bit0: parity, 0=even, 1=odd | |||
| // bit1: parity, 0=disable, 1=enable | |||
| // bit2: mode, 1=9bit, 0=8bit | |||
| @@ -109,6 +116,8 @@ | |||
| // bit5: txinv, 0=normal, 1=inverted | |||
| // bit6: unused | |||
| // bit7: actual data goes into 9th bit | |||
| // bit8: 2 stop bits (T3.5/3.6 and LC) | |||
| // bit9: Half duplex | |||
| #if defined(KINETISK) | |||
| @@ -101,6 +101,9 @@ static volatile uint8_t rx_buffer_tail = 0; | |||
| #endif | |||
| static uint8_t rx_pin_num = 0; | |||
| static uint8_t tx_pin_num = 1; | |||
| #if defined(KINETISL) | |||
| static uint8_t half_duplex_mode = 0; | |||
| #endif | |||
| // UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS | |||
| // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer | |||
| @@ -114,6 +117,12 @@ static uint8_t tx_pin_num = 1; | |||
| #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | |||
| #define C2_TX_INACTIVE C2_ENABLE | |||
| // BITBAND Support | |||
| #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) | |||
| #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | |||
| #define C3_TXDIR_BIT 5 | |||
| void serial_begin(uint32_t divisor) | |||
| { | |||
| SIM_SCGC4 |= SIM_SCGC4_UART0; // turn on clock, TODO: use bitband | |||
| @@ -198,6 +207,34 @@ void serial_format(uint32_t format) | |||
| UART0_BDL = bdl; // Says BDH not acted on until BDL is written | |||
| } | |||
| #endif | |||
| // process request for half duplex. | |||
| if ((format & SERIAL_HALF_DUPLEX) != 0) { | |||
| c = UART0_C1; | |||
| c |= UART_C1_LOOPS | UART_C1_RSRC; | |||
| UART0_C1 = c; | |||
| // Lets try to make use of bitband address to set the direction for ue... | |||
| #if defined(KINETISL) | |||
| switch (tx_pin_num) { | |||
| case 1: CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS ; break; | |||
| case 5: CORE_PIN5_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; break; | |||
| case 4: CORE_PIN4_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2) | PORT_PCR_PE | PORT_PCR_PS; break; | |||
| case 24: CORE_PIN24_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(4) | PORT_PCR_PE | PORT_PCR_PS; break; | |||
| } | |||
| half_duplex_mode = 1; | |||
| #else | |||
| volatile uint32_t *reg = portConfigRegister(tx_pin_num); | |||
| *reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin; | |||
| transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART0_C3, C3_TXDIR_BIT); | |||
| #endif | |||
| } else { | |||
| #if defined(KINETISL) | |||
| half_duplex_mode = 0; | |||
| #else | |||
| if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART0_C3, C3_TXDIR_BIT)) transmit_pin = NULL; | |||
| #endif | |||
| } | |||
| } | |||
| void serial_end(void) | |||
| @@ -369,6 +406,15 @@ void serial_putchar(uint32_t c) | |||
| if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return; | |||
| if (transmit_pin) transmit_assert(); | |||
| #if defined(KINETISL) | |||
| if (half_duplex_mode) { | |||
| __disable_irq(); | |||
| volatile uint32_t reg = UART0_C3; | |||
| reg |= UART_C3_TXDIR; | |||
| UART0_C3 = reg; | |||
| __enable_irq(); | |||
| } | |||
| #endif | |||
| head = tx_buffer_head; | |||
| if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0; | |||
| while (tx_buffer_tail == head) { | |||
| @@ -615,6 +661,15 @@ void uart0_status_isr(void) | |||
| if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) { | |||
| transmitting = 0; | |||
| if (transmit_pin) transmit_deassert(); | |||
| #if defined(KINETISL) | |||
| if (half_duplex_mode) { | |||
| __disable_irq(); | |||
| volatile uint32_t reg = UART0_C3; | |||
| reg &= ~UART_C3_TXDIR; | |||
| UART0_C3 = reg; | |||
| __enable_irq(); | |||
| } | |||
| #endif | |||
| UART0_C2 = C2_TX_INACTIVE; | |||
| } | |||
| } | |||
| @@ -102,6 +102,9 @@ static volatile uint8_t rx_buffer_tail = 0; | |||
| static uint8_t rx_pin_num = 9; | |||
| static uint8_t tx_pin_num = 10; | |||
| #endif | |||
| #if defined(KINETISL) | |||
| static uint8_t half_duplex_mode = 0; | |||
| #endif | |||
| // UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS | |||
| // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer | |||
| @@ -115,6 +118,11 @@ static uint8_t tx_pin_num = 10; | |||
| #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | |||
| #define C2_TX_INACTIVE C2_ENABLE | |||
| // BITBAND Support | |||
| #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) | |||
| #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | |||
| #define C3_TXDIR_BIT 5 | |||
| void serial2_begin(uint32_t divisor) | |||
| { | |||
| SIM_SCGC4 |= SIM_SCGC4_UART1; // turn on clock, TODO: use bitband | |||
| @@ -198,6 +206,30 @@ void serial2_format(uint32_t format) | |||
| UART1_BDL = bdl; // Says BDH not acted on until BDL is written | |||
| } | |||
| #endif | |||
| // process request for half duplex. | |||
| if ((format & SERIAL_HALF_DUPLEX) != 0) { | |||
| c = UART1_C1; | |||
| c |= UART_C1_LOOPS | UART_C1_RSRC; | |||
| UART1_C1 = c; | |||
| // Lets try to make use of bitband address to set the direction for ue... | |||
| #if defined(KINETISL) | |||
| //CORE_PIN10_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; | |||
| CORE_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); | |||
| half_duplex_mode = 1; | |||
| #else | |||
| volatile uint32_t *reg = portConfigRegister(tx_pin_num); | |||
| *reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin; | |||
| transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART1_C3, C3_TXDIR_BIT); | |||
| #endif | |||
| } else { | |||
| #if defined(KINETISL) | |||
| half_duplex_mode = 0; | |||
| #else | |||
| if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART1_C3, C3_TXDIR_BIT)) transmit_pin = NULL; | |||
| #endif | |||
| } | |||
| } | |||
| void serial2_end(void) | |||
| @@ -359,6 +391,15 @@ void serial2_putchar(uint32_t c) | |||
| if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; | |||
| if (transmit_pin) transmit_assert(); | |||
| #if defined(KINETISL) | |||
| if (half_duplex_mode) { | |||
| __disable_irq(); | |||
| volatile uint32_t reg = UART1_C3; | |||
| reg |= UART_C3_TXDIR; | |||
| UART1_C3 = reg; | |||
| __enable_irq(); | |||
| } | |||
| #endif | |||
| head = tx_buffer_head; | |||
| if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0; | |||
| while (tx_buffer_tail == head) { | |||
| @@ -605,6 +646,15 @@ void uart1_status_isr(void) | |||
| if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) { | |||
| transmitting = 0; | |||
| if (transmit_pin) transmit_deassert(); | |||
| #if defined(KINETISL) | |||
| if (half_duplex_mode) { | |||
| __disable_irq(); | |||
| volatile uint32_t reg = UART1_C3; | |||
| reg &= ~UART_C3_TXDIR; | |||
| UART1_C3 = reg; | |||
| __enable_irq(); | |||
| } | |||
| #endif | |||
| UART1_C2 = C2_TX_INACTIVE; | |||
| } | |||
| } | |||
| @@ -104,6 +104,10 @@ static uint8_t rx_pin_num = 7; | |||
| #endif | |||
| static uint8_t tx_pin_num = 8; | |||
| #if defined(KINETISL) | |||
| static uint8_t half_duplex_mode = 0; | |||
| #endif | |||
| // UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS | |||
| // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer | |||
| @@ -112,6 +116,11 @@ static uint8_t tx_pin_num = 8; | |||
| #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | |||
| #define C2_TX_INACTIVE C2_ENABLE | |||
| // BITBAND Support | |||
| #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) | |||
| #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | |||
| #define C3_TXDIR_BIT 5 | |||
| void serial3_begin(uint32_t divisor) | |||
| { | |||
| SIM_SCGC4 |= SIM_SCGC4_UART2; // turn on clock, TODO: use bitband | |||
| @@ -180,6 +189,33 @@ void serial3_format(uint32_t format) | |||
| UART2_BDL = bdl; // Says BDH not acted on until BDL is written | |||
| } | |||
| #endif | |||
| // process request for half duplex. | |||
| if ((format & SERIAL_HALF_DUPLEX) != 0) { | |||
| c = UART2_C1; | |||
| c |= UART_C1_LOOPS | UART_C1_RSRC; | |||
| UART2_C1 = c; | |||
| // Lets try to make use of bitband address to set the direction for ue... | |||
| #if defined(KINETISL) | |||
| switch (tx_pin_num) { | |||
| case 8: CORE_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break; | |||
| case 20: CORE_PIN20_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break; | |||
| } | |||
| half_duplex_mode = 1; | |||
| #else | |||
| volatile uint32_t *reg = portConfigRegister(tx_pin_num); | |||
| *reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin; | |||
| transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART2_C3, C3_TXDIR_BIT); | |||
| #endif | |||
| } else { | |||
| #if defined(KINETISL) | |||
| half_duplex_mode = 0; | |||
| #else | |||
| if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART2_C3, C3_TXDIR_BIT)) transmit_pin = NULL; | |||
| #endif | |||
| } | |||
| } | |||
| @@ -315,6 +351,15 @@ void serial3_putchar(uint32_t c) | |||
| if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return; | |||
| if (transmit_pin) transmit_assert(); | |||
| #if defined(KINETISL) | |||
| if (half_duplex_mode) { | |||
| __disable_irq(); | |||
| volatile uint32_t reg = UART2_C3; | |||
| reg |= UART_C3_TXDIR; | |||
| UART2_C3 = reg; | |||
| __enable_irq(); | |||
| } | |||
| #endif | |||
| head = tx_buffer_head; | |||
| if (++head >= SERIAL3_TX_BUFFER_SIZE) head = 0; | |||
| while (tx_buffer_tail == head) { | |||
| @@ -456,6 +501,16 @@ void uart2_status_isr(void) | |||
| if ((c & UART_C2_TCIE) && (UART2_S1 & UART_S1_TC)) { | |||
| transmitting = 0; | |||
| if (transmit_pin) transmit_deassert(); | |||
| #if defined(KINETISL) | |||
| if (transmit_pin) transmit_deassert(); | |||
| if (half_duplex_mode) { | |||
| __disable_irq(); | |||
| volatile uint32_t reg = UART2_C3; | |||
| reg &= ~UART_C3_TXDIR; | |||
| UART2_C3 = reg; | |||
| __enable_irq(); | |||
| } | |||
| #endif | |||
| UART2_C2 = C2_TX_INACTIVE; | |||
| } | |||
| } | |||
| @@ -102,6 +102,11 @@ static uint8_t tx_pin_num = 32; | |||
| #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | |||
| #define C2_TX_INACTIVE C2_ENABLE | |||
| // BITBAND Support | |||
| #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) | |||
| #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | |||
| #define C3_TXDIR_BIT 5 | |||
| void serial4_begin(uint32_t divisor) | |||
| { | |||
| SIM_SCGC4 |= SIM_SCGC4_UART3; // turn on clock, TODO: use bitband | |||
| @@ -158,6 +163,27 @@ void serial4_format(uint32_t format) | |||
| UART3_BDL = bdl; // Says BDH not acted on until BDL is written | |||
| } | |||
| #endif | |||
| // process request for half duplex. | |||
| if ((format & SERIAL_HALF_DUPLEX) != 0) { | |||
| UART3_C1 |= UART_C1_LOOPS | UART_C1_RSRC; | |||
| volatile uint32_t *reg = portConfigRegister(tx_pin_num); | |||
| *reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin; | |||
| // Lets try to make use of bitband address to set the direction for ue... | |||
| #if defined(KINETISL) | |||
| transmit_pin = &UART3_C3; | |||
| transmit_mask = UART_C3_TXDIR; | |||
| #else | |||
| transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART3_C3, C3_TXDIR_BIT); | |||
| #endif | |||
| } else { | |||
| #if defined(KINETISL) | |||
| if (transmit_pin == &UART3_C3) transmit_pin = NULL; | |||
| #else | |||
| if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART3_C3, C3_TXDIR_BIT)) transmit_pin = NULL; | |||
| #endif | |||
| } | |||
| } | |||
| void serial4_end(void) | |||
| @@ -101,6 +101,11 @@ static uint8_t tx_pin_num = 33; | |||
| #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | |||
| #define C2_TX_INACTIVE C2_ENABLE | |||
| // BITBAND Support | |||
| #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) | |||
| #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | |||
| #define C3_TXDIR_BIT 5 | |||
| void serial5_begin(uint32_t divisor) | |||
| { | |||
| SIM_SCGC1 |= SIM_SCGC1_UART4; // turn on clock, TODO: use bitband | |||
| @@ -149,6 +154,19 @@ void serial5_format(uint32_t format) | |||
| UART4_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud | |||
| UART4_BDL = bdl; // Says BDH not acted on until BDL is written | |||
| } | |||
| // process request for half duplex. | |||
| if ((format & SERIAL_HALF_DUPLEX) != 0) { | |||
| UART4_C1 |= UART_C1_LOOPS | UART_C1_RSRC; | |||
| volatile uint32_t *reg = portConfigRegister(tx_pin_num); | |||
| *reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin; | |||
| // Lets try to make use of bitband address to set the direction for ue... | |||
| transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART4_C3, C3_TXDIR_BIT); | |||
| } else { | |||
| if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART4_C3, C3_TXDIR_BIT)) transmit_pin = NULL; | |||
| } | |||
| } | |||
| void serial5_end(void) | |||
| @@ -101,6 +101,11 @@ static uint8_t tx_pin_num = 48; | |||
| #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | |||
| #define C2_TX_INACTIVE C2_ENABLE | |||
| // BITBAND Support | |||
| #define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) | |||
| #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | |||
| #define C3_TXDIR_BIT 5 | |||
| void serial6_begin(uint32_t divisor) | |||
| { | |||
| SIM_SCGC1 |= SIM_SCGC1_UART5; // turn on clock, TODO: use bitband | |||
| @@ -149,6 +154,18 @@ void serial6_format(uint32_t format) | |||
| UART5_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud | |||
| UART5_BDL = bdl; // Says BDH not acted on until BDL is written | |||
| } | |||
| // process request for half duplex. | |||
| if ((format & SERIAL_HALF_DUPLEX) != 0) { | |||
| UART5_C1 |= UART_C1_LOOPS | UART_C1_RSRC; | |||
| volatile uint32_t *reg = portConfigRegister(tx_pin_num); | |||
| *reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin; | |||
| // Lets try to make use of bitband address to set the direction for ue... | |||
| transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART5_C3, C3_TXDIR_BIT); | |||
| } else { | |||
| if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART5_C3, C3_TXDIR_BIT)) transmit_pin = NULL; | |||
| } | |||
| } | |||
| void serial6_end(void) | |||
| @@ -38,8 +38,15 @@ | |||
| #define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | |||
| #define BITBAND_SET_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 1) | |||
| #define BITBAND_CLR_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 0) | |||
| #define TCIE_BIT 22 | |||
| #define TIE_BIT 23 | |||
| #define CTRL_TXDIR_BIT 29 | |||
| #define CTRL_TIE_BIT 23 | |||
| #define CTRL_TCIE_BIT 22 | |||
| #define CTRL_TE_BIT 19 | |||
| #define CTRL_RE_BIT 18 | |||
| #define CTRL_LOOPS_BIT 7 | |||
| #define CTRL_RSRC_BIT 5 | |||
| //////////////////////////////////////////////////////////////// | |||
| @@ -95,9 +102,6 @@ static volatile uint8_t rx_buffer_tail = 0; | |||
| static uint8_t tx_pin_num = 48; | |||
| // UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS | |||
| // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer | |||
| void serial6_begin(uint32_t desiredBaudRate) | |||
| { | |||
| @@ -225,6 +229,21 @@ void serial6_format(uint32_t format) | |||
| // For T3.6 See about turning on 2 stop bit mode | |||
| if ( format & 0x100) LPUART0_BAUD |= LPUART_BAUD_SBNS; | |||
| // process request for half duplex. | |||
| if ((format & SERIAL_HALF_DUPLEX) != 0) { | |||
| BITBAND_SET_BIT(LPUART0_CTRL, CTRL_LOOPS_BIT); | |||
| BITBAND_SET_BIT(LPUART0_CTRL, CTRL_RSRC_BIT); | |||
| CORE_PIN48_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(5); | |||
| // Lets try to make use of bitband address to set the direction for ue... | |||
| transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(LPUART0_CTRL, CTRL_TXDIR_BIT); | |||
| } else { | |||
| if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(LPUART0_CTRL, CTRL_TXDIR_BIT)) transmit_pin = NULL; | |||
| BITBAND_CLR_BIT(LPUART0_CTRL, CTRL_LOOPS_BIT); | |||
| BITBAND_CLR_BIT(LPUART0_CTRL, CTRL_RSRC_BIT); | |||
| } | |||
| } | |||
| void serial6_end(void) | |||
| @@ -307,6 +326,7 @@ void serial6_putchar(uint32_t c) | |||
| if (!(SIM_SCGC2 & SIM_SCGC2_LPUART0)) return; | |||
| if (transmit_pin) transmit_assert(); | |||
| head = tx_buffer_head; | |||
| if (++head >= SERIAL6_TX_BUFFER_SIZE) head = 0; | |||
| while (tx_buffer_tail == head) { | |||
| @@ -329,7 +349,7 @@ void serial6_putchar(uint32_t c) | |||
| tx_buffer_head = head; | |||
| //LPUART0_CTRL |= LPUART_CTRL_TIE; // enable the transmit interrupt | |||
| BITBAND_SET_BIT(LPUART0_CTRL, TIE_BIT); | |||
| BITBAND_SET_BIT(LPUART0_CTRL, CTRL_TIE_BIT); | |||
| } | |||
| @@ -413,7 +433,6 @@ void lpuart0_status_isr(void) | |||
| { | |||
| uint32_t head, tail, n; | |||
| uint32_t c; | |||
| if (LPUART0_STAT & LPUART_STAT_RDRF) { | |||
| // if (use9Bits && (UART5_C3 & 0x80)) { | |||
| // n = UART5_D | 0x100; | |||
| @@ -440,8 +459,8 @@ void lpuart0_status_isr(void) | |||
| head = tx_buffer_head; | |||
| tail = tx_buffer_tail; | |||
| if (head == tail) { | |||
| BITBAND_CLR_BIT(LPUART0_CTRL, TIE_BIT); | |||
| BITBAND_SET_BIT(LPUART0_CTRL, TCIE_BIT); | |||
| BITBAND_CLR_BIT(LPUART0_CTRL, CTRL_TIE_BIT); | |||
| BITBAND_SET_BIT(LPUART0_CTRL, CTRL_TCIE_BIT); | |||
| //LPUART0_CTRL &= ~LPUART_CTRL_TIE; | |||
| //LPUART0_CTRL |= LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on... | |||
| } else { | |||
| @@ -455,7 +474,7 @@ void lpuart0_status_isr(void) | |||
| if ((c & LPUART_CTRL_TCIE) && (LPUART0_STAT & LPUART_STAT_TC)) { | |||
| transmitting = 0; | |||
| if (transmit_pin) transmit_deassert(); | |||
| BITBAND_CLR_BIT(LPUART0_CTRL, TCIE_BIT); | |||
| BITBAND_CLR_BIT(LPUART0_CTRL, CTRL_TCIE_BIT); | |||
| // LPUART0_CTRL &= ~LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on... | |||
| } | |||
| } | |||
| @@ -139,15 +139,23 @@ void HardwareSerial::begin(uint32_t baud, uint16_t format) | |||
| // uint32_t fastio = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3); | |||
| *(portControlRegister(hardware->rx_pins[rx_pin_index_].pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS; | |||
| *(portConfigRegister(hardware->rx_pins[rx_pin_index_].pin)) = hardware->rx_pins[rx_pin_index_].mux_val; | |||
| if (hardware->rx_pins[rx_pin_index_].select_input_register) { | |||
| *(hardware->rx_pins[rx_pin_index_].select_input_register) = hardware->rx_pins[rx_pin_index_].select_val; | |||
| } | |||
| *(portControlRegister(hardware->tx_pins[tx_pin_index_].pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3); | |||
| *(portConfigRegister(hardware->tx_pins[tx_pin_index_].pin)) = hardware->tx_pins[tx_pin_index_].mux_val; | |||
| // Maybe different pin configs if half duplex | |||
| half_duplex_mode_ = (format & SERIAL_HALF_DUPLEX) != 0; | |||
| if (!half_duplex_mode_) { | |||
| *(portControlRegister(hardware->rx_pins[rx_pin_index_].pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS; | |||
| *(portConfigRegister(hardware->rx_pins[rx_pin_index_].pin)) = hardware->rx_pins[rx_pin_index_].mux_val; | |||
| if (hardware->rx_pins[rx_pin_index_].select_input_register) { | |||
| *(hardware->rx_pins[rx_pin_index_].select_input_register) = hardware->rx_pins[rx_pin_index_].select_val; | |||
| } | |||
| *(portControlRegister(hardware->tx_pins[tx_pin_index_].pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3); | |||
| *(portConfigRegister(hardware->tx_pins[tx_pin_index_].pin)) = hardware->tx_pins[tx_pin_index_].mux_val; | |||
| } else { | |||
| // Half duplex maybe different pin pad config like PU... | |||
| *(portControlRegister(hardware->tx_pins[tx_pin_index_].pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | |||
| | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3); | |||
| *(portConfigRegister(hardware->tx_pins[tx_pin_index_].pin)) = hardware->tx_pins[tx_pin_index_].mux_val; | |||
| } | |||
| if (hardware->tx_pins[tx_pin_index_].select_input_register) { | |||
| *(hardware->tx_pins[tx_pin_index_].select_input_register) = hardware->tx_pins[tx_pin_index_].select_val; | |||
| } | |||
| @@ -187,6 +195,9 @@ void HardwareSerial::begin(uint32_t baud, uint16_t format) | |||
| // Bit 5 TXINVERT | |||
| if (format & 0x20) ctrl |= LPUART_CTRL_TXINV; // tx invert | |||
| // Now see if the user asked for Half duplex: | |||
| if (half_duplex_mode_) ctrl |= (LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC); | |||
| // write out computed CTRL | |||
| port->CTRL = ctrl; | |||
| @@ -525,6 +536,13 @@ size_t HardwareSerial::write9bit(uint32_t c) | |||
| //digitalWrite(3, HIGH); | |||
| //digitalWrite(5, HIGH); | |||
| if (transmit_pin_baseReg_) DIRECT_WRITE_HIGH(transmit_pin_baseReg_, transmit_pin_bitmask_); | |||
| if(half_duplex_mode_) { | |||
| __disable_irq(); | |||
| port->CTRL |= LPUART_CTRL_TXDIR; | |||
| __enable_irq(); | |||
| //digitalWriteFast(2, HIGH); | |||
| } | |||
| head = tx_buffer_head_; | |||
| if (++head >= tx_buffer_total_size_) head = 0; | |||
| while (tx_buffer_tail_ == head) { | |||
| @@ -639,6 +657,12 @@ void HardwareSerial::IRQHandler() | |||
| { | |||
| transmitting_ = 0; | |||
| if (transmit_pin_baseReg_) DIRECT_WRITE_LOW(transmit_pin_baseReg_, transmit_pin_bitmask_); | |||
| if(half_duplex_mode_) { | |||
| __disable_irq(); | |||
| port->CTRL &= ~LPUART_CTRL_TXDIR; | |||
| __enable_irq(); | |||
| //digitalWriteFast(2, LOW); | |||
| } | |||
| port->CTRL &= ~LPUART_CTRL_TCIE; | |||
| } | |||
| @@ -92,6 +92,13 @@ | |||
| #define SERIAL_8N2_RXINV (SERIAL_8N1_RXINV | SERIAL_2STOP_BITS) | |||
| #define SERIAL_8N2_TXINV (SERIAL_8N1_TXINV | SERIAL_2STOP_BITS) | |||
| #define SERIAL_8N2_RXINV_TXINV (SERIAL_8N1_RXINV_TXINV | SERIAL_2STOP_BITS) | |||
| // Half duplex support | |||
| #define SERIAL_HALF_DUPLEX 0x200 | |||
| #define SERIAL_7E1_HALF_DUPLEX (SERIAL_7E1 | SERIAL_HALF_DUPLEX) | |||
| #define SERIAL_7O1_HALF_DUPLEX (SERIAL_7O1 | SERIAL_HALF_DUPLEX) | |||
| #define SERIAL_8N1_HALF_DUPLEX (SERIAL_8N1 | SERIAL_HALF_DUPLEX) | |||
| // bit0: parity, 0=even, 1=odd | |||
| // bit1: parity, 0=disable, 1=enable | |||
| // bit2: mode, 1=9bit, 0=8bit | |||
| @@ -101,6 +108,8 @@ | |||
| // bit6: unused | |||
| // bit7: actual data goes into 9th bit | |||
| // bit8: 2 stop bits | |||
| // bit9: Half Duplex Mode | |||
| #ifdef __cplusplus | |||
| #include "Stream.h" | |||
| @@ -235,6 +244,7 @@ private: | |||
| const hardware_t * const hardware; | |||
| uint8_t rx_pin_index_ = 0x0; // default is always first item | |||
| uint8_t tx_pin_index_ = 0x0; | |||
| uint8_t half_duplex_mode_ = 0; // are we in half duplex mode? | |||
| volatile BUFTYPE *tx_buffer_; | |||
| volatile BUFTYPE *rx_buffer_; | |||
| @@ -57,7 +57,7 @@ const HardwareSerial::hardware_t UART6_Hardware = { | |||
| CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON), | |||
| #if defined(ARDUINO_TEENSY41) | |||
| {{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {52, 2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 0}}, | |||
| {{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 0}, {53, 2, nullptr, 0}}, | |||
| {{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {53, 2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 0}}, | |||
| #else | |||
| {{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | |||
| {{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | |||