From 7eb47348efc741eab2c7dc175edb9c3273f6c475 Mon Sep 17 00:00:00 2001 From: Leo Bicknell Date: Sun, 1 Jun 2025 10:21:22 -0400 Subject: [PATCH] DIYables 3.5 TFT LCD Color Touch Screen Shield Changes necessary to make the DIYables 3.5 TFT LCD Color Touch Screen Shield work when connected to a NUCLEO-F103RB system. It has an 8-bit parallel interface using the GPIO driver. With these changes it appears to pass all tests quite well, and has a responsive touch interface that reports pressure. The vendor's page: https://diyables.io/products/3.5-tft-lcd-color-touch-screen-shield-for-arduino-uno-mega-320x480-resolution-ili9488-driver-parallel-8-bit-interface-28pin-module-with-touch Drivers/io_gpio/lcdts_io_gpio8_hal.c: - ADC_SAMPLETIME_15CYCLES is not present in my generated files. Use ADC_SAMPLETIME_1CYCLE_5 which seems to work, there are other choices that might be better. - TS_IO_DetectToch() (intentional mispelling to match code) would not detect touches. Referenced the DIYAbles code at https://github.com/DIYables/DIYables_TFT_Shield/blob/main/src/DIYables_TFT_Shield.cpp and rewrote the function. This screen detects the touch pressure, so instead of the function simply returning true (1) or false (0) it now returns the pressure. Values under 10 are returned as 0 to prevent spurious readings, although my unit pretty reliably returns 0 when there is no press. Wrap the new and old function in the TS_PRESSURE flag. Drivers/io_gpio/lcdts_io_gpio8_hal.h: - Set TS_RS_ADCCH and TS_WR_ADCCH to match the NUCLEO-F103RB ADC channels. - Ran the App/TouchCalib and generated a new TS_CINDEX value to match my device. - Add a new TS_PRESSURE flag. Drivers/lcd/ili9488.c: - The SETWINDOW and SETCURSOR functions do not need to be changed based on the ILI9488_ORIENTATION parameter with this board. Add a new #if DIYABLES_QUIRK == 1 section that always uses the standard functions. Proper operation with all 4 values of ILI9488_ORIENTATION was confirmed after this change. - In ili9488_Init() this board needs to have "ILI9488_INVON" set to get the proper colors. Also wrap this in a #if DIYABLES_QUIRK == 1. Drivers/lcd/ili9488.h: - This board has a parallel interface, so set ILI9488_INTERFACE 2. - Set the new variable DIYABLES_QUIRK to 1 to trigger the quirk handling above. --- Drivers/io_gpio/lcdts_io_gpio8_hal.c | 79 +++++++++++++++++++++------- Drivers/io_gpio/lcdts_io_gpio8_hal.h | 9 ++-- Drivers/lcd/ili9488.c | 8 +++ Drivers/lcd/ili9488.h | 4 +- 4 files changed, 78 insertions(+), 22 deletions(-) diff --git a/Drivers/io_gpio/lcdts_io_gpio8_hal.c b/Drivers/io_gpio/lcdts_io_gpio8_hal.c index d3d204e..94a1602 100644 --- a/Drivers/io_gpio/lcdts_io_gpio8_hal.c +++ b/Drivers/io_gpio/lcdts_io_gpio8_hal.c @@ -450,7 +450,7 @@ uint16_t TS_IO_GetAd(uint32_t chn) sConfig.Channel = chn; sConfig.Rank = ADC_REGULAR_RANK_1; - sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; + sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; if (HAL_ADC_ConfigChannel(&TS_AD_HANDLE, &sConfig) == HAL_OK) { TS_IO_Delay(TS_AD_DELAY); @@ -464,30 +464,73 @@ uint16_t TS_IO_GetAd(uint32_t chn) return (ret >> 2); } +#ifdef TS_PRESSURE //----------------------------------------------------------------------------- -/* return: - - 0 : touchscreen is not pressed - - 1 : touchscreen is pressed */ +/* Reads the pressure of the current touch. + * + * return: + * - uint8_t with the force of the touch, typically 0-3000. + */ uint8_t TS_IO_DetectToch(void) { - uint8_t ret; - LL_GPIO_SetPinMode(LCD_D7_GPIO_Port, LCD_D7_Pin, LL_GPIO_MODE_INPUT); /* YM = D_INPUT */ - LL_GPIO_SetPinMode(LCD_WR_GPIO_Port, LCD_WR_Pin, LL_GPIO_MODE_INPUT); /* YP = D_INPUT */ - HAL_GPIO_WritePin(LCD_RS_GPIO_Port, LCD_RS_Pin, GPIO_PIN_RESET); /* XM = 0 */ HAL_GPIO_WritePin(LCD_D6_GPIO_Port, LCD_D6_Pin, GPIO_PIN_RESET); /* XP = 0 */ - LL_GPIO_SetPinPull(LCD_WR_GPIO_Port, LCD_WR_Pin, LL_GPIO_PULL_UP); /* YP pullup resistor on */ - TS_IO_Delay(TS_AD_DELAY); - if(HAL_GPIO_ReadPin(LCD_WR_GPIO_Port, LCD_WR_Pin)) /* YP ? */ - ret = 0; /* Touchscreen is not touch */ - else - ret = 1; /* Touchscreen is touch */ - LL_GPIO_SetPinPull(LCD_WR_GPIO_Port, LCD_WR_Pin, LL_GPIO_PULL_NO); /* YP pullup resistor off */ - HAL_GPIO_WritePin(LCD_RS_GPIO_Port, LCD_RS_Pin, GPIO_PIN_SET); /* XM = 1 */ - HAL_GPIO_WritePin(LCD_D6_GPIO_Port, LCD_D6_Pin, GPIO_PIN_SET); /* XP = 1 */ - LL_GPIO_SetPinMode(LCD_D7_GPIO_Port, LCD_D7_Pin, LL_GPIO_MODE_OUTPUT);/* YM = OUT */ + HAL_GPIO_WritePin(LCD_D7_GPIO_Port, LCD_D7_Pin, GPIO_PIN_SET); /* YM = 1 */ + + LL_GPIO_SetPinMode(LCD_WR_GPIO_Port, LCD_WR_Pin, LL_GPIO_MODE_ANALOG);/* YP = AN_INPUT */ + + int z = TS_IO_GetAd(TS_RS_ADCCH); /* Ad Converter TS_RS_ADCCH */ + LL_GPIO_SetPinMode(LCD_WR_GPIO_Port, LCD_WR_Pin, LL_GPIO_MODE_OUTPUT);/* YP = OUT */ + + HAL_GPIO_WritePin(LCD_D7_GPIO_Port, LCD_RD_Pin, GPIO_PIN_SET); /* YM = 1 */ + HAL_GPIO_WritePin(LCD_D7_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); /* YM = 1 */ + + // Keep spurious touches from triggering. + if (z > 10) { + return z; + } else { + return 0; + } +} +#else +//----------------------------------------------------------------------------- +uint8_t ts_DetectTouch(uint16_t DeviceAddr) +{ + static uint8_t ret = 0; + int32_t x1, x2, y1, y2, i; + + ret = 0; + if(TS_IO_DetectToch()) + { + x1 = TS_IO_GetX(); /* Get X */ + y1 = TS_IO_GetY(); /* Get Y */ + i = TOUCH_MAXREPEAT; + while(i--) + { + x2 = TS_IO_GetX(); /* Get X */ + y2 = TS_IO_GetY(); /* Get Y */ + if((ABS(x1 - x2) < TOUCH_FILTER) && (ABS(y1 - y2) < TOUCH_FILTER)) + { + x1 = (x1 + x2) >> 1; + y1 = (y1 + y2) >> 1; + i = 0; + if(TS_IO_DetectToch()) + { + tx = x1; + ty = y1; + ret = 1; + } + } + else + { + x1 = x2; + y1 = y2; + } + } + } return ret; } +#endif //----------------------------------------------------------------------------- /* read the X position */ diff --git a/Drivers/io_gpio/lcdts_io_gpio8_hal.h b/Drivers/io_gpio/lcdts_io_gpio8_hal.h index 0014722..0c58fe3 100644 --- a/Drivers/io_gpio/lcdts_io_gpio8_hal.h +++ b/Drivers/io_gpio/lcdts_io_gpio8_hal.h @@ -80,12 +80,15 @@ #define TS_AD_DELAY 5000 +/* Touchscreen reports pressure of touch. */ +#define TS_PRESSURE 1 + /* Select the AD channels (check in the cube which AD channel is connected to the RS and WR pins */ -#define TS_RS_ADCCH ADC_CHANNEL_13 -#define TS_WR_ADCCH ADC_CHANNEL_10 +#define TS_RS_ADCCH ADC_CHANNEL_4 +#define TS_WR_ADCCH ADC_CHANNEL_1 /* these constants can be defined with the application appTouchCalib.c */ -#define TS_CINDEX {-1409179, -21, -107208, 42542238, 136441, -1509, -512509626} +#define TS_CINDEX {-266, 82209, -10704, -210366973, 231263, -29964, -591817031} /* The touch value that it still accepts as the same value */ #define TOUCH_FILTER 32 diff --git a/Drivers/lcd/ili9488.c b/Drivers/lcd/ili9488.c index 3d9e5b2..2a94529 100644 --- a/Drivers/lcd/ili9488.c +++ b/Drivers/lcd/ili9488.c @@ -171,6 +171,10 @@ static uint16_t yStart, yEnd; #define SETCURSOR(x, y) ILI9488_SETCURSOR(x, y) #elif ILI9488_INTERFACE == 2 +#if DIYABLES_QUIRK == 1 +#define SETWINDOW(x1, x2, y1, y2) ILI9488_SETWINDOW(x1, x2, y1, y2) +#define SETCURSOR(x, y) ILI9488_SETCURSOR(x, y) +#else #if ILI9488_ORIENTATION == 0 #define SETWINDOW(x1, x2, y1, y2) ILI9488_SETWINDOW(ILI9488_MAX_X - (x2), ILI9488_MAX_X - (x1), y1, y2) #define SETCURSOR(x, y) ILI9488_SETCURSOR(ILI9488_MAX_X - (x), y) @@ -185,6 +189,7 @@ static uint16_t yStart, yEnd; #define SETCURSOR(x, y) ILI9488_SETCURSOR(ILI9488_MAX_X - (x), ILI9488_MAX_Y - (y)) #endif #endif +#endif #ifndef LCD_REVERSE16 #define LCD_REVERSE16 0 @@ -323,6 +328,9 @@ void ili9488_Init(void) LCD_IO_WriteCmd8MultipleData8(ILI9488_DFUNCTR, (uint8_t *)"\x02\x02", 2); // Display Function Control RGB/MCU Interface Control LCD_IO_WriteCmd8MultipleData8(ILI9488_IMGFUNCT, (uint8_t *)"\x01", 1); // Set Image Functio (Disable 24 bit data) LCD_IO_WriteCmd8MultipleData8(ILI9488_ADJCTR3, (uint8_t *)"\xA9\x51\x2C\x82", 4); // Adjust Control (D7 stream, loose) +#if DIYABLES_QUIRK == 1 + LCD_IO_WriteCmd8MultipleData8(ILI9488_INVON, NULL, 0); +#endif LCD_Delay(5); LCD_IO_WriteCmd8MultipleData8(ILI9488_SLPOUT, NULL, 0); // Exit Sleep LCD_Delay(120); diff --git a/Drivers/lcd/ili9488.h b/Drivers/lcd/ili9488.h index bdc4890..6c5407c 100644 --- a/Drivers/lcd/ili9488.h +++ b/Drivers/lcd/ili9488.h @@ -2,7 +2,7 @@ - 0: SPI half duplex (the mosi pin is bidirectional mode) - 1: SPI full duplex (write = mosi pin, read = miso pin) - 2: paralell 8 bit interface */ -#define ILI9488_INTERFACE 1 +#define ILI9488_INTERFACE 2 /* Orientation: - 0: 320x480 micro-sd in the top (portrait) @@ -30,3 +30,5 @@ /* ILI9488 Size (physical resolution in default orientation) */ #define ILI9488_LCD_PIXEL_WIDTH 320 #define ILI9488_LCD_PIXEL_HEIGHT 480 + +#define DIYABLES_QUIRK 1