T3.x,T4.x LC Serial half duplex supportteensy4-core
#define SERIAL_8N2_TXINV 0x24 | #define SERIAL_8N2_TXINV 0x24 | ||||
#define SERIAL_8N2_RXINV_TXINV 0x34 | #define SERIAL_8N2_RXINV_TXINV 0x34 | ||||
#endif | #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 | // bit0: parity, 0=even, 1=odd | ||||
// bit1: parity, 0=disable, 1=enable | // bit1: parity, 0=disable, 1=enable | ||||
// bit2: mode, 1=9bit, 0=8bit | // bit2: mode, 1=9bit, 0=8bit | ||||
// bit5: txinv, 0=normal, 1=inverted | // bit5: txinv, 0=normal, 1=inverted | ||||
// bit6: unused | // bit6: unused | ||||
// bit7: actual data goes into 9th bit | // bit7: actual data goes into 9th bit | ||||
// bit8: 2 stop bits (T3.5/3.6 and LC) | |||||
// bit9: Half duplex | |||||
#if defined(KINETISK) | #if defined(KINETISK) |
#endif | #endif | ||||
static uint8_t rx_pin_num = 0; | static uint8_t rx_pin_num = 0; | ||||
static uint8_t tx_pin_num = 1; | 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 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 | // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer | ||||
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | ||||
#define C2_TX_INACTIVE C2_ENABLE | #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) | void serial_begin(uint32_t divisor) | ||||
{ | { | ||||
SIM_SCGC4 |= SIM_SCGC4_UART0; // turn on clock, TODO: use bitband | SIM_SCGC4 |= SIM_SCGC4_UART0; // turn on clock, TODO: use bitband | ||||
UART0_BDL = bdl; // Says BDH not acted on until BDL is written | UART0_BDL = bdl; // Says BDH not acted on until BDL is written | ||||
} | } | ||||
#endif | #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) | void serial_end(void) | ||||
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return; | if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return; | ||||
if (transmit_pin) transmit_assert(); | 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; | head = tx_buffer_head; | ||||
if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0; | if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0; | ||||
while (tx_buffer_tail == head) { | while (tx_buffer_tail == head) { | ||||
if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) { | if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) { | ||||
transmitting = 0; | transmitting = 0; | ||||
if (transmit_pin) transmit_deassert(); | 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; | UART0_C2 = C2_TX_INACTIVE; | ||||
} | } | ||||
} | } |
static uint8_t rx_pin_num = 9; | static uint8_t rx_pin_num = 9; | ||||
static uint8_t tx_pin_num = 10; | static uint8_t tx_pin_num = 10; | ||||
#endif | #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 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 | // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer | ||||
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | ||||
#define C2_TX_INACTIVE C2_ENABLE | #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) | void serial2_begin(uint32_t divisor) | ||||
{ | { | ||||
SIM_SCGC4 |= SIM_SCGC4_UART1; // turn on clock, TODO: use bitband | SIM_SCGC4 |= SIM_SCGC4_UART1; // turn on clock, TODO: use bitband | ||||
UART1_BDL = bdl; // Says BDH not acted on until BDL is written | UART1_BDL = bdl; // Says BDH not acted on until BDL is written | ||||
} | } | ||||
#endif | #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) | void serial2_end(void) | ||||
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; | if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; | ||||
if (transmit_pin) transmit_assert(); | 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; | head = tx_buffer_head; | ||||
if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0; | if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0; | ||||
while (tx_buffer_tail == head) { | while (tx_buffer_tail == head) { | ||||
if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) { | if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) { | ||||
transmitting = 0; | transmitting = 0; | ||||
if (transmit_pin) transmit_deassert(); | 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; | UART1_C2 = C2_TX_INACTIVE; | ||||
} | } | ||||
} | } |
#endif | #endif | ||||
static uint8_t tx_pin_num = 8; | 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 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 | // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer | ||||
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | ||||
#define C2_TX_INACTIVE C2_ENABLE | #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) | void serial3_begin(uint32_t divisor) | ||||
{ | { | ||||
SIM_SCGC4 |= SIM_SCGC4_UART2; // turn on clock, TODO: use bitband | SIM_SCGC4 |= SIM_SCGC4_UART2; // turn on clock, TODO: use bitband | ||||
UART2_BDL = bdl; // Says BDH not acted on until BDL is written | UART2_BDL = bdl; // Says BDH not acted on until BDL is written | ||||
} | } | ||||
#endif | #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 | |||||
} | |||||
} | } | ||||
if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return; | if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return; | ||||
if (transmit_pin) transmit_assert(); | 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; | head = tx_buffer_head; | ||||
if (++head >= SERIAL3_TX_BUFFER_SIZE) head = 0; | if (++head >= SERIAL3_TX_BUFFER_SIZE) head = 0; | ||||
while (tx_buffer_tail == head) { | while (tx_buffer_tail == head) { | ||||
if ((c & UART_C2_TCIE) && (UART2_S1 & UART_S1_TC)) { | if ((c & UART_C2_TCIE) && (UART2_S1 & UART_S1_TC)) { | ||||
transmitting = 0; | transmitting = 0; | ||||
if (transmit_pin) transmit_deassert(); | 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; | UART2_C2 = C2_TX_INACTIVE; | ||||
} | } | ||||
} | } |
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | ||||
#define C2_TX_INACTIVE C2_ENABLE | #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) | void serial4_begin(uint32_t divisor) | ||||
{ | { | ||||
SIM_SCGC4 |= SIM_SCGC4_UART3; // turn on clock, TODO: use bitband | SIM_SCGC4 |= SIM_SCGC4_UART3; // turn on clock, TODO: use bitband | ||||
UART3_BDL = bdl; // Says BDH not acted on until BDL is written | UART3_BDL = bdl; // Says BDH not acted on until BDL is written | ||||
} | } | ||||
#endif | #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) | void serial4_end(void) |
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | ||||
#define C2_TX_INACTIVE C2_ENABLE | #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) | void serial5_begin(uint32_t divisor) | ||||
{ | { | ||||
SIM_SCGC1 |= SIM_SCGC1_UART4; // turn on clock, TODO: use bitband | SIM_SCGC1 |= SIM_SCGC1_UART4; // turn on clock, TODO: use bitband | ||||
UART4_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud | 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 | 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) | void serial5_end(void) |
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE | ||||
#define C2_TX_INACTIVE C2_ENABLE | #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) | void serial6_begin(uint32_t divisor) | ||||
{ | { | ||||
SIM_SCGC1 |= SIM_SCGC1_UART5; // turn on clock, TODO: use bitband | SIM_SCGC1 |= SIM_SCGC1_UART5; // turn on clock, TODO: use bitband | ||||
UART5_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud | 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 | 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) | void serial6_end(void) |
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) | #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_SET_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 1) | ||||
#define BITBAND_CLR_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 0) | #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 | |||||
//////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////// | ||||
static uint8_t tx_pin_num = 48; | 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) | void serial6_begin(uint32_t desiredBaudRate) | ||||
{ | { | ||||
// For T3.6 See about turning on 2 stop bit mode | // For T3.6 See about turning on 2 stop bit mode | ||||
if ( format & 0x100) LPUART0_BAUD |= LPUART_BAUD_SBNS; | 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) | void serial6_end(void) | ||||
if (!(SIM_SCGC2 & SIM_SCGC2_LPUART0)) return; | if (!(SIM_SCGC2 & SIM_SCGC2_LPUART0)) return; | ||||
if (transmit_pin) transmit_assert(); | if (transmit_pin) transmit_assert(); | ||||
head = tx_buffer_head; | head = tx_buffer_head; | ||||
if (++head >= SERIAL6_TX_BUFFER_SIZE) head = 0; | if (++head >= SERIAL6_TX_BUFFER_SIZE) head = 0; | ||||
while (tx_buffer_tail == head) { | while (tx_buffer_tail == head) { | ||||
tx_buffer_head = head; | tx_buffer_head = head; | ||||
//LPUART0_CTRL |= LPUART_CTRL_TIE; // enable the transmit interrupt | //LPUART0_CTRL |= LPUART_CTRL_TIE; // enable the transmit interrupt | ||||
BITBAND_SET_BIT(LPUART0_CTRL, TIE_BIT); | |||||
BITBAND_SET_BIT(LPUART0_CTRL, CTRL_TIE_BIT); | |||||
} | } | ||||
{ | { | ||||
uint32_t head, tail, n; | uint32_t head, tail, n; | ||||
uint32_t c; | uint32_t c; | ||||
if (LPUART0_STAT & LPUART_STAT_RDRF) { | if (LPUART0_STAT & LPUART_STAT_RDRF) { | ||||
// if (use9Bits && (UART5_C3 & 0x80)) { | // if (use9Bits && (UART5_C3 & 0x80)) { | ||||
// n = UART5_D | 0x100; | // n = UART5_D | 0x100; | ||||
head = tx_buffer_head; | head = tx_buffer_head; | ||||
tail = tx_buffer_tail; | tail = tx_buffer_tail; | ||||
if (head == 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_TIE; | ||||
//LPUART0_CTRL |= LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on... | //LPUART0_CTRL |= LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on... | ||||
} else { | } else { | ||||
if ((c & LPUART_CTRL_TCIE) && (LPUART0_STAT & LPUART_STAT_TC)) { | if ((c & LPUART_CTRL_TCIE) && (LPUART0_STAT & LPUART_STAT_TC)) { | ||||
transmitting = 0; | transmitting = 0; | ||||
if (transmit_pin) transmit_deassert(); | 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... | // LPUART0_CTRL &= ~LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on... | ||||
} | } | ||||
} | } |
// uint32_t fastio = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3); | // 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) { | 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; | *(hardware->tx_pins[tx_pin_index_].select_input_register) = hardware->tx_pins[tx_pin_index_].select_val; | ||||
} | } | ||||
// Bit 5 TXINVERT | // Bit 5 TXINVERT | ||||
if (format & 0x20) ctrl |= LPUART_CTRL_TXINV; // tx invert | 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 | // write out computed CTRL | ||||
port->CTRL = ctrl; | port->CTRL = ctrl; | ||||
//digitalWrite(3, HIGH); | //digitalWrite(3, HIGH); | ||||
//digitalWrite(5, HIGH); | //digitalWrite(5, HIGH); | ||||
if (transmit_pin_baseReg_) DIRECT_WRITE_HIGH(transmit_pin_baseReg_, transmit_pin_bitmask_); | 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_; | head = tx_buffer_head_; | ||||
if (++head >= tx_buffer_total_size_) head = 0; | if (++head >= tx_buffer_total_size_) head = 0; | ||||
while (tx_buffer_tail_ == head) { | while (tx_buffer_tail_ == head) { | ||||
{ | { | ||||
transmitting_ = 0; | transmitting_ = 0; | ||||
if (transmit_pin_baseReg_) DIRECT_WRITE_LOW(transmit_pin_baseReg_, transmit_pin_bitmask_); | 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; | port->CTRL &= ~LPUART_CTRL_TCIE; | ||||
} | } |
#define SERIAL_8N2_RXINV (SERIAL_8N1_RXINV | SERIAL_2STOP_BITS) | #define SERIAL_8N2_RXINV (SERIAL_8N1_RXINV | SERIAL_2STOP_BITS) | ||||
#define SERIAL_8N2_TXINV (SERIAL_8N1_TXINV | 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) | #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 | // bit0: parity, 0=even, 1=odd | ||||
// bit1: parity, 0=disable, 1=enable | // bit1: parity, 0=disable, 1=enable | ||||
// bit2: mode, 1=9bit, 0=8bit | // bit2: mode, 1=9bit, 0=8bit | ||||
// bit6: unused | // bit6: unused | ||||
// bit7: actual data goes into 9th bit | // bit7: actual data goes into 9th bit | ||||
// bit8: 2 stop bits | |||||
// bit9: Half Duplex Mode | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
#include "Stream.h" | #include "Stream.h" | ||||
const hardware_t * const hardware; | const hardware_t * const hardware; | ||||
uint8_t rx_pin_index_ = 0x0; // default is always first item | uint8_t rx_pin_index_ = 0x0; // default is always first item | ||||
uint8_t tx_pin_index_ = 0x0; | uint8_t tx_pin_index_ = 0x0; | ||||
uint8_t half_duplex_mode_ = 0; // are we in half duplex mode? | |||||
volatile BUFTYPE *tx_buffer_; | volatile BUFTYPE *tx_buffer_; | ||||
volatile BUFTYPE *rx_buffer_; | volatile BUFTYPE *rx_buffer_; |
CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON), | CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON), | ||||
#if defined(ARDUINO_TEENSY41) | #if defined(ARDUINO_TEENSY41) | ||||
{{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {52, 2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 0}}, | {{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 | #else | ||||
{{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | {{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | ||||
{{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | {{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, |