270 lines
7.1 KiB
C
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
|
|
}
|