diff --git a/README.md b/README.md index 3a82d4fa..7cae5e20 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ The scope of modifications is limited to adding support for DWIN T5UID1 touchscreens (except for the addition of a `--warn` CLI option, which sets the logging level to WARNING). -The touchscreen feature is only available for AVR/LPC176X micro-controllers and -it needs to be configured before compilation. +The touchscreen feature is only available for AVR/LPC176X/STM32 +micro-controllers and it needs to be configured before compilation. The touchscreen firmware compatible with this fork is available in [this repository](https://github.com/Desuuuu/DGUS-reloaded-Klipper). diff --git a/src/stm32/Kconfig b/src/stm32/Kconfig index 98e5aed8..48004559 100644 --- a/src/stm32/Kconfig +++ b/src/stm32/Kconfig @@ -229,4 +229,33 @@ config SERIAL_PORT default 2 if STM32_SERIAL_USART2 || STM32_SERIAL_USART2_ALT default 1 +config T5UID1_SERIAL + bool "Enable DGUS T5UID1 screen" + default n +choice + depends on T5UID1_SERIAL + prompt "Screen Serial Port" if LOW_LEVEL_OPTIONS + default STM32_T5UID1_SERIAL_USART2 if !STM32_SERIAL_USART2 && !STM32_SERIAL_USART2_ALT + default STM32_T5UID1_SERIAL_USART1 + help + Select the serial device to use for the touchscreen. + config STM32_T5UID1_SERIAL_USART1 + bool "USART1" if !STM32_SERIAL_USART1 + config STM32_T5UID1_SERIAL_USART2 + bool "USART2 (on PA3/PA2)" if !STM32_SERIAL_USART2 && !STM32_SERIAL_USART2_ALT + config STM32_T5UID1_SERIAL_USART2_ALT + bool "USART2 (on PA15/PA14)" if MACH_STM32F0 && !STM32_SERIAL_USART2 && !STM32_SERIAL_USART2_ALT + config STM32_T5UID1_SERIAL_USART3 + bool "USART3" if !STM32_SERIAL_USART3 && !STM32_SERIAL_USART3_ALT + config STM32_T5UID1_SERIAL_USART3_ALT + bool "USART3 (on PD9/PD8)" if MACH_STM32F4 && !STM32_SERIAL_USART3 && !STM32_SERIAL_USART3_ALT +endchoice +config T5UID1_SERIAL_PORT + int + default 3 if STM32_T5UID1_SERIAL_USART3 || STM32_T5UID1_SERIAL_USART3_ALT + default 2 if STM32_T5UID1_SERIAL_USART2 || STM32_T5UID1_SERIAL_USART2_ALT + default 1 if STM32_T5UID1_SERIAL_USART1 + default 2 if !STM32_SERIAL_USART2 && !STM32_SERIAL_USART2_ALT + default 1 + endif diff --git a/src/stm32/Makefile b/src/stm32/Makefile index bd5017f2..d543d537 100644 --- a/src/stm32/Makefile +++ b/src/stm32/Makefile @@ -48,6 +48,9 @@ serial-src-$(CONFIG_MACH_STM32F0) := stm32/stm32f0_serial.c src-$(CONFIG_SERIAL) += $(serial-src-y) generic/serial_irq.c can-src-$(CONFIG_CANSERIAL) += stm32/can.c ../lib/fast-hash/fasthash.c src-$(CONFIG_CANSERIAL) += $(can-src-y) generic/serial_irq.c +t5uid1-src-y := stm32/serial_t5uid1.c +t5uid1-src-$(CONFIG_MACH_STM32F0) := stm32/stm32f0_serial_t5uid1.c +src-$(CONFIG_T5UID1_SERIAL) += $(t5uid1-src-y) generic/t5uid1_irq.c dirs-$(CONFIG_CANSERIAL) += lib/fast-hash diff --git a/src/stm32/serial_t5uid1.c b/src/stm32/serial_t5uid1.c new file mode 100644 index 00000000..4bcfd344 --- /dev/null +++ b/src/stm32/serial_t5uid1.c @@ -0,0 +1,83 @@ +// STM32 serial +// +// Copyright (C) 2019 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "autoconf.h" // CONFIG_T5UID1_SERIAL_PORT +#include "board/armcm_boot.h" // armcm_enable_irq +#include "board/t5uid1_irq.h" // t5uid1_rx_byte +#include "command.h" // DECL_CONSTANT_STR +#include "internal.h" // enable_pclock + +#if CONFIG_SERIAL && CONFIG_T5UID1_SERIAL_PORT == CONFIG_SERIAL_PORT + #error "The serial port selected for the T5UID1 screen is already used" +#endif + +// Select the configured serial port +#if CONFIG_T5UID1_SERIAL_PORT == 1 + DECL_CONSTANT_STR("RESERVE_PINS_t5uid1", "PA10,PA9"); + #define GPIO_Rx GPIO('A', 10) + #define GPIO_Tx GPIO('A', 9) + #define USARTx USART1 + #define USARTx_IRQn USART1_IRQn +#elif CONFIG_T5UID1_SERIAL_PORT == 2 + DECL_CONSTANT_STR("RESERVE_PINS_t5uid1", "PA3,PA2"); + #define GPIO_Rx GPIO('A', 3) + #define GPIO_Tx GPIO('A', 2) + #define USARTx USART2 + #define USARTx_IRQn USART2_IRQn +#elif CONFIG_T5UID1_SERIAL_PORT == 3 + #if CONFIG_T5UID1_STM32_SERIAL_USART3_ALT + DECL_CONSTANT_STR("RESERVE_PINS_t5uid1", "PD9,PD8"); + #define GPIO_Rx GPIO('D', 9) + #define GPIO_Tx GPIO('D', 8) + #else + DECL_CONSTANT_STR("RESERVE_PINS_t5uid1", "PB11,PB10"); + #define GPIO_Rx GPIO('B', 11) + #define GPIO_Tx GPIO('B', 10) + #endif + #define USARTx USART3 + #define USARTx_IRQn USART3_IRQn +#endif + +#define CR1_FLAGS (USART_CR1_UE | USART_CR1_RE | USART_CR1_TE \ + | USART_CR1_RXNEIE) + +void +USARTx_IRQHandler(void) +{ + uint32_t sr = USARTx->SR; + if (sr & (USART_SR_RXNE | USART_SR_ORE)) + t5uid1_rx_byte(USARTx->DR); + if (sr & USART_SR_TXE && USARTx->CR1 & USART_CR1_TXEIE) { + uint8_t data; + int ret = t5uid1_get_tx_byte(&data); + if (ret) + USARTx->CR1 = CR1_FLAGS; + else + USARTx->DR = data; + } +} + +void +t5uid1_enable_tx_irq(void) +{ + USARTx->CR1 = CR1_FLAGS | USART_CR1_TXEIE; +} + +void +t5uid1_init(uint32_t baud) +{ + enable_pclock((uint32_t)USARTx); + + uint32_t pclk = get_pclock_frequency((uint32_t)USARTx); + uint32_t div = DIV_ROUND_CLOSEST(pclk, baud); + USARTx->BRR = (((div / 16) << USART_BRR_DIV_Mantissa_Pos) + | ((div % 16) << USART_BRR_DIV_Fraction_Pos)); + USARTx->CR1 = CR1_FLAGS; + armcm_enable_irq(USARTx_IRQHandler, USARTx_IRQn, 0); + + gpio_peripheral(GPIO_Rx, GPIO_FUNCTION(7), 1); + gpio_peripheral(GPIO_Tx, GPIO_FUNCTION(7), 0); +} diff --git a/src/stm32/stm32f0_serial_t5uid1.c b/src/stm32/stm32f0_serial_t5uid1.c new file mode 100644 index 00000000..9aea8fc7 --- /dev/null +++ b/src/stm32/stm32f0_serial_t5uid1.c @@ -0,0 +1,77 @@ +// STM32F0 serial +// +// Copyright (C) 2019 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "autoconf.h" // CONFIG_T5UID1_SERIAL_PORT +#include "board/armcm_boot.h" // armcm_enable_irq +#include "board/t5uid1_irq.h" // t5uid1_rx_byte +#include "command.h" // DECL_CONSTANT_STR +#include "internal.h" // enable_pclock + +#if CONFIG_SERIAL && CONFIG_T5UID1_SERIAL_PORT == CONFIG_SERIAL_PORT + #error "The serial port selected for the T5UID1 screen is already used" +#endif + +// Select the configured serial port +#if CONFIG_T5UID1_SERIAL_PORT == 1 + DECL_CONSTANT_STR("RESERVE_PINS_t5uid1", "PA10,PA9"); + #define GPIO_Rx GPIO('A', 10) + #define GPIO_Tx GPIO('A', 9) + #define USARTx USART1 + #define USARTx_IRQn USART1_IRQn +#elif CONFIG_T5UID1_SERIAL_PORT == 2 + #if CONFIG_T5UID1_STM32_SERIAL_USART2_ALT + DECL_CONSTANT_STR("RESERVE_PINS_t5uid1", "PA15,PA14"); + #define GPIO_Rx GPIO('A', 15) + #define GPIO_Tx GPIO('A', 14) + #else + DECL_CONSTANT_STR("RESERVE_PINS_t5uid1", "PA3,PA2"); + #define GPIO_Rx GPIO('A', 3) + #define GPIO_Tx GPIO('A', 2) + #endif + #define USARTx USART2 + #define USARTx_IRQn USART2_IRQn +#endif + +#define CR1_FLAGS (USART_CR1_UE | USART_CR1_RE | USART_CR1_TE \ + | USART_CR1_RXNEIE) + +void +USARTx_IRQHandler(void) +{ + uint32_t sr = USARTx->ISR; + if (sr & (USART_ISR_RXNE | USART_ISR_ORE)) + t5uid1_rx_byte(USARTx->RDR); + if (sr & USART_ISR_TXE && USARTx->CR1 & USART_CR1_TXEIE) { + uint8_t data; + int ret = t5uid1_get_tx_byte(&data); + if (ret) + USARTx->CR1 = CR1_FLAGS; + else + USARTx->TDR = data; + } +} + +void +t5uid1_enable_tx_irq(void) +{ + USARTx->CR1 = CR1_FLAGS | USART_CR1_TXEIE; +} + +void +t5uid1_init(uint32_t baud) +{ + enable_pclock((uint32_t)USARTx); + + uint32_t pclk = get_pclock_frequency((uint32_t)USARTx); + uint32_t div = DIV_ROUND_CLOSEST(pclk, baud); + USARTx->BRR = (((div / 16) << USART_BRR_DIV_MANTISSA_Pos) + | ((div % 16) << USART_BRR_DIV_FRACTION_Pos)); + USARTx->CR1 = CR1_FLAGS; + armcm_enable_irq(USARTx_IRQHandler, USARTx_IRQn, 0); + + gpio_peripheral(GPIO_Rx, GPIO_FUNCTION(1), 1); + gpio_peripheral(GPIO_Tx, GPIO_FUNCTION(1), 0); +} diff --git a/src/stm32/stm32f1.c b/src/stm32/stm32f1.c index 886b7b91..24252cd6 100644 --- a/src/stm32/stm32f1.c +++ b/src/stm32/stm32f1.c @@ -124,10 +124,43 @@ gpio_peripheral(uint32_t gpio, uint32_t mode, int pullup) // way from other STM32s. // Code below is emulating a few mappings to work like an STM32F4 uint32_t func = (mode >> 4) & 0xf; - if(( gpio == GPIO('B', 8) || gpio == GPIO('B', 9)) && - func == 9) { // CAN - stm32f1_alternative_remap(AFIO_MAPR_CAN_REMAP_Msk, - AFIO_MAPR_CAN_REMAP_REMAP2); + switch (func) { + case 7: // USART + if (gpio == GPIO('A', 9) || gpio == GPIO('A', 10)) { + stm32f1_alternative_remap(AFIO_MAPR_USART1_REMAP_Msk, + 0); + } else if (gpio == GPIO('B', 6) || gpio == GPIO('B', 7)) { + stm32f1_alternative_remap(AFIO_MAPR_USART1_REMAP_Msk, + AFIO_MAPR_USART1_REMAP); + } else if (gpio == GPIO('A', 2) || gpio == GPIO('A', 3)) { + stm32f1_alternative_remap(AFIO_MAPR_USART2_REMAP_Msk, + 0); + } else if (gpio == GPIO('D', 5) || gpio == GPIO('D', 6)) { + stm32f1_alternative_remap(AFIO_MAPR_USART2_REMAP_Msk, + AFIO_MAPR_USART2_REMAP); + } else if (gpio == GPIO('B', 10) || gpio == GPIO('B', 11)) { + stm32f1_alternative_remap(AFIO_MAPR_USART3_REMAP_Msk, + AFIO_MAPR_USART3_REMAP_NOREMAP); + } else if (gpio == GPIO('C', 10) || gpio == GPIO('C', 11)) { + stm32f1_alternative_remap(AFIO_MAPR_USART3_REMAP_Msk, + AFIO_MAPR_USART3_REMAP_PARTIALREMAP); + } else if (gpio == GPIO('D', 8) || gpio == GPIO('D', 9)) { + stm32f1_alternative_remap(AFIO_MAPR_USART3_REMAP_Msk, + AFIO_MAPR_USART3_REMAP_FULLREMAP); + } + break; + case 9: // CAN + if (gpio == GPIO('A', 11) || gpio == GPIO('A', 12)) { + stm32f1_alternative_remap(AFIO_MAPR_CAN_REMAP_Msk, + AFIO_MAPR_CAN_REMAP_REMAP1); + } else if (gpio == GPIO('B', 8) || gpio == GPIO('B', 9)) { + stm32f1_alternative_remap(AFIO_MAPR_CAN_REMAP_Msk, + AFIO_MAPR_CAN_REMAP_REMAP2); + } else if (gpio == GPIO('D', 0) || gpio == GPIO('D', 1)) { + stm32f1_alternative_remap(AFIO_MAPR_CAN_REMAP_Msk, + AFIO_MAPR_CAN_REMAP_REMAP3); + } + break; } // Add more as needed }