/******************************************************************* File: touch.c Date: 9-September-2020 Author: Peter Spindler Description: Touch controller driver ********************************************************************/ #include "stm32f7xx_hal.h" #include "main.h" #include "touch.h" #include "display.h" #include #define TS_I2C_HANDLE hi2c3 extern I2C_HandleTypeDef TS_I2C_HANDLE; #define TS_I2C_ADDRESS 0x70 #define TOUCH_WIDTH 240 #define TOUCH_HEIGHT 240 uint16_t Touch_Calx1 = 20, Touch_Caly1 = 20; uint16_t Touch_Calx2 = 220, Touch_Caly2 = 220; // Default calibration values: uint16_t Touch_Calx1Raw = 33, Touch_Caly1Raw = 72; uint16_t Touch_Calx2Raw = 230, Touch_Caly2Raw = 190; static uint8_t Touch_ReadReg( uint8_t Reg ) { uint8_t DataRx = 0; HAL_I2C_Mem_Read( &TS_I2C_HANDLE, TS_I2C_ADDRESS, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, &DataRx, 1, 1000); return DataRx; } static void Touch_ReadRegMulti( uint8_t Reg, uint8_t *DataRx, uint16_t DataSize ) { HAL_I2C_Mem_Read( &TS_I2C_HANDLE, TS_I2C_ADDRESS, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, DataRx, DataSize, 1000); } static void Touch_WriteReg( uint8_t Reg, uint8_t Value ) { HAL_I2C_Mem_Write( &TS_I2C_HANDLE, TS_I2C_ADDRESS, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, &Value, 1, 1000); } uint8_t Touch_IsPressed( void ) { GPIO_PinState Pin = HAL_GPIO_ReadPin( CTP_INT_GPIO_Port, CTP_INT_Pin ); if( Pin == GPIO_PIN_RESET ) { uint8_t Status = Touch_ReadReg( 0x02 ) & 0x0f; if( Status > 0 ) { return 1; } } return 0; } uint8_t Touch_ReadPosRaw( uint16_t *x, uint16_t *y ) { uint8_t DataRx[2][4]; uint8_t Status = Touch_ReadReg( 0x02 ) & 0x0f; if( Status == 1 ) { Touch_ReadRegMulti( 0x03, DataRx[0], 4 ); } else if( Status == 2 ) { Touch_ReadRegMulti( 0x03, DataRx[0], 4 ); Touch_ReadRegMulti( 0x09, DataRx[1], 4 ); } else { *x = 0; *y = 0; return 0; } uint16_t xRaw = ((DataRx[0][0] & 0x0f) << 8) | DataRx[0][1]; uint16_t yRaw = ((DataRx[0][2] & 0x0f) << 8) | DataRx[0][3]; // Swap x-y: *x = yRaw; *y = xRaw; // Mirror x: if( *x <= TOUCH_WIDTH-1 ) { *x = TOUCH_WIDTH-1 - *x; } else { *x = 0; } return 1; } void Touch_SetCalibration( uint16_t x1Raw, uint16_t y1Raw, uint16_t x2Raw, uint16_t y2Raw ) { Touch_Calx1Raw = x1Raw; Touch_Caly1Raw = y1Raw; Touch_Calx2Raw = x2Raw; Touch_Caly2Raw = y2Raw; } void Touch_ConvertPos( uint16_t *x, uint16_t *y ) { int16_t x_, y_; x_ = (*x - Touch_Calx1Raw)*(Touch_Calx2-Touch_Calx1)/(Touch_Calx2Raw-Touch_Calx1Raw) + Touch_Calx1; y_ = (*y - Touch_Caly1Raw)*(Touch_Caly2-Touch_Caly1)/(Touch_Caly2Raw-Touch_Caly1Raw) + Touch_Caly1; if( x_ < 0 ) x_ = 0; if( x_ > TOUCH_WIDTH-1 ) x_ = TOUCH_WIDTH-1; if( y_ < 0 ) y_ = 0; if( y_ > TOUCH_HEIGHT-1 ) y_ = TOUCH_HEIGHT-1; *x = x_; *y = y_; } uint8_t Touch_ReadPos( uint16_t *x, uint16_t *y ) { uint8_t ret; ret = Touch_ReadPosRaw( x, y ); Touch_ConvertPos( x, y ); return ret; } void Touch_Calibrate( void ) { uint16_t x, y, xTouch, yTouch; uint16_t x1=0, y1=0, x2=0, y2=0; uint8_t i=0, iPressed, Pressed; Display_PrintString( 0, 150, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "Press" ); Display_PrintString( 0, 180, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "top/left"); Display_FillCircle( Touch_Calx1, Touch_Caly1, 10, LCD_COLOR_WHITE ); Pressed = 0; while( 1 ) { if( Touch_IsPressed() ) { if( Touch_ReadPosRaw( &x, &y ) ) { Display_Printf( 00, 210, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "%3d %3d ", x, y ); xTouch = x; yTouch = y; Pressed = 1; } } // Abort with user button down: if( HAL_GPIO_ReadPin( GPIOA, GPIO_PIN_0 ) == GPIO_PIN_SET ) { if( Pressed ) { x1 = xTouch; y1 = yTouch; } break; } } // Wait for user button up: while( 1 ) { HAL_Delay(50); if( HAL_GPIO_ReadPin( GPIOA, GPIO_PIN_0 ) == GPIO_PIN_RESET ) { HAL_Delay(50); break; } } Display_Clear( LCD_COLOR_BLACK ); Display_PrintString( 0, 0, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "Press" ); Display_PrintString( 0, 30, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "buttom/right"); Display_FillCircle( Touch_Calx2, Touch_Caly2, 10, LCD_COLOR_WHITE ); Pressed = 0; while( 1 ) { if( Touch_IsPressed() ) { if( Touch_ReadPosRaw( &x, &y ) ) { Display_Printf( 0, 60, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "%3d %3d ", x, y ); xTouch = x; yTouch = y; Pressed = 1; } } // Abort with user button down: if( HAL_GPIO_ReadPin( GPIOA, GPIO_PIN_0 ) == GPIO_PIN_SET ) { if( Pressed ) { x2 = xTouch; y2 = yTouch; } break; } } Display_Clear( LCD_COLOR_BLACK ); Display_PrintString( 0, 0, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "Done" ); Display_Printf( 0, 30, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "x1: %3d", x1 ); Display_Printf( 0, 60, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "y1: %3d", y1 ); Display_Printf( 0, 90, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "x2: %3d", x2 ); Display_Printf( 0, 120, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "y2: %3d", y2 ); // Stop if any calibration point not pressed: if( x1 == 0 || y1 == 0 || x2 == 0 || y2 == 0 ) { Display_PrintString( 0, 150, LCD_COLOR_WHITE, LCD_COLOR_BLACK, &FontBig, "Error!" ); while( 1 ); } // Wait for used button up: while( 1 ) { HAL_Delay(50); if( HAL_GPIO_ReadPin( GPIOA, GPIO_PIN_0 ) == GPIO_PIN_RESET ) { HAL_Delay(50); break; } } // Wait for user button down: while( 1 ) { if( HAL_GPIO_ReadPin( GPIOA, GPIO_PIN_0 ) == GPIO_PIN_SET ) { break; } } // Use calibration values and test with six buttons: Touch_SetCalibration( x1, y1, x2, y2 ); struct { uint16_t x, y; uint16_t Width, Height; } Rect[6]; x = 0; y = 0; for( i = 0; i < 6; i++ ) { Rect[i].x = x; Rect[i].y = y; Rect[i].Width = 110; Rect[i].Height = 70; x += 120; if( x+110 >= 240 ) { x = 0; y += 75; } } Display_Clear( LCD_COLOR_BLACK ); for( i = 0; i < 6; i++ ) { Display_DrawRect( Rect[i].x, Rect[i].y, Rect[i].Width, Rect[i].Height, LCD_COLOR_WHITE ); } uint8_t State = 0; while( 1 ) { if( State == 0 && Touch_ReadPos( &x, &y ) ) { iPressed = 0xff; for( i = 0; i < 6; i++ ) { if( x >= Rect[i].x && x <= Rect[i].x+Rect[i].Width && y >= Rect[i].y && y <= Rect[i].y+Rect[i].Height ) { Display_FillRect( Rect[i].x, Rect[i].y, Rect[i].Width, Rect[i].Height, LCD_COLOR_WHITE ); State = 1; iPressed = i; break; } } } else if( State == 1 && !Touch_IsPressed() ) { if( iPressed != 0xff ) { Display_FillRect( Rect[iPressed].x, Rect[iPressed].y, Rect[iPressed].Width, Rect[iPressed].Height, LCD_COLOR_BLACK ); Display_DrawRect( Rect[i].x, Rect[i].y, Rect[i].Width, Rect[i].Height, LCD_COLOR_WHITE ); } State = 0; } } while( 1 ); } void Touch_Init( void ) { uint8_t ID; ID = Touch_ReadReg(0xA8); if( ID != 0xcd ) { printf("Error: Touch ID is %x, expected %x\n", ID, 0xcd ); return; } Touch_WriteReg( 0xA4, 0 ); // Disable interrupt }