2025-12-15 18:37:39 +01:00

270 lines
7.1 KiB
C

/*******************************************************************
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 <stdio.h>
#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
}