337 lines
8.3 KiB
C
337 lines
8.3 KiB
C
/**
|
|
* @file ADCRAW.c
|
|
*/
|
|
|
|
#include "adcraw.h"
|
|
#include "esp_system.h"
|
|
#include "esp_log.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "driver/gpio.h"
|
|
#include <stddef.h>
|
|
#include "esp_idf_version.h"
|
|
#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5,0,0)
|
|
#include "rom/gpio.h"
|
|
#endif
|
|
|
|
#if CONFIG_LV_TOUCH_CONTROLLER_ADCRAW
|
|
|
|
#define TAG "ADCRAW"
|
|
#define CALIBRATIONINSET 1 // range 0 <= CALIBRATIONINSET <= 40
|
|
#define SAMPLE_CALIBRATION_POINTS 4
|
|
// use this scale factor to avoid working in floating point numbers
|
|
#define TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR 8
|
|
#define SCALE_FACTOR (1 << TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR)
|
|
#define CAL_X_INSET (((GetMaxX() + 1) * (CALIBRATIONINSET >> 1)) / 100)
|
|
#define CAL_Y_INSET (((GetMaxY() + 1) * (CALIBRATIONINSET >> 1)) / 100)
|
|
#define NUMSAMPLES 8
|
|
|
|
static void ad_touch_handler(void *arg);
|
|
|
|
static const esp_timer_create_args_t periodic_timer_args = {
|
|
.callback = &ad_touch_handler,
|
|
};
|
|
static esp_timer_handle_t periodic_timer;
|
|
|
|
// Current ADC values for X and Y channels
|
|
int16_t adcX, adcY = 0;
|
|
int16_t temp_x, temp_y, temp_z1, temp_z2;
|
|
|
|
// coefficient values
|
|
int _trA, _trB, _trC, _trD;
|
|
|
|
int16_t xRawTouch[SAMPLE_CALIBRATION_POINTS];
|
|
int16_t yRawTouch[SAMPLE_CALIBRATION_POINTS];
|
|
TOUCH_STATES state;
|
|
|
|
const gpio_num_t yu = TOUCHSCREEN_RESISTIVE_PIN_YU;
|
|
const gpio_num_t xl = TOUCHSCREEN_RESISTIVE_PIN_XL;
|
|
const gpio_num_t yd = TOUCHSCREEN_RESISTIVE_PIN_YD;
|
|
const gpio_num_t xr = TOUCHSCREEN_RESISTIVE_PIN_XR;
|
|
|
|
static const int gpio_to_adc[] = {
|
|
GPIO_TO_ADC_ELEMENT(TOUCHSCREEN_RESISTIVE_PIN_YD),
|
|
GPIO_TO_ADC_ELEMENT(TOUCHSCREEN_RESISTIVE_PIN_XR)
|
|
};
|
|
|
|
static void TouchCalculateCalPoints(void)
|
|
{
|
|
int32_t trA, trB, trC, trD; // variables for the coefficients
|
|
int32_t trAhold, trBhold, trChold, trDhold;
|
|
int32_t test1, test2; // temp variables (must be signed type)
|
|
|
|
int16_t xPoint[SAMPLE_CALIBRATION_POINTS], yPoint[SAMPLE_CALIBRATION_POINTS];
|
|
|
|
yPoint[0] = yPoint[1] = CAL_Y_INSET;
|
|
yPoint[2] = yPoint[3] = (GetMaxY() - CAL_Y_INSET);
|
|
xPoint[0] = xPoint[3] = CAL_X_INSET;
|
|
xPoint[1] = xPoint[2] = (GetMaxX() - CAL_X_INSET);
|
|
|
|
// calculate points transfer function
|
|
// based on two simultaneous equations solve for the constants
|
|
|
|
// use sample points 1 and 4
|
|
// Dy1 = aTy1 + b; Dy4 = aTy4 + b
|
|
// Dx1 = cTx1 + d; Dy4 = aTy4 + b
|
|
|
|
test1 = (int32_t)yPoint[0] - (int32_t)yPoint[3];
|
|
test2 = (int32_t)yRawTouch[0] - (int32_t)yRawTouch[3];
|
|
|
|
trA = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
|
|
trB = ((int32_t)((int32_t)yPoint[0] * SCALE_FACTOR) - (trA * (int32_t)yRawTouch[0]));
|
|
|
|
test1 = (int32_t)xPoint[0] - (int32_t)xPoint[2];
|
|
test2 = (int32_t)xRawTouch[0] - (int32_t)xRawTouch[2];
|
|
|
|
trC = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
|
|
trD = ((int32_t)((int32_t)xPoint[0] * SCALE_FACTOR) - (trC * (int32_t)xRawTouch[0]));
|
|
|
|
trAhold = trA;
|
|
trBhold = trB;
|
|
trChold = trC;
|
|
trDhold = trD;
|
|
|
|
// use sample points 2 and 3
|
|
// Dy2 = aTy2 + b; Dy3 = aTy3 + b
|
|
// Dx2 = cTx2 + d; Dy3 = aTy3 + b
|
|
|
|
test1 = (int32_t)yPoint[1] - (int32_t)yPoint[2];
|
|
test2 = (int32_t)yRawTouch[1] - (int32_t)yRawTouch[2];
|
|
|
|
trA = ((int32_t)(test1 * SCALE_FACTOR) / test2);
|
|
trB = ((int32_t)((int32_t)yPoint[1] * SCALE_FACTOR) - (trA * (int32_t)yRawTouch[1]));
|
|
|
|
test1 = (int32_t)xPoint[1] - (int32_t)xPoint[3];
|
|
test2 = (int32_t)xRawTouch[1] - (int32_t)xRawTouch[3];
|
|
|
|
trC = ((int32_t)((int32_t)test1 * SCALE_FACTOR) / test2);
|
|
trD = ((int32_t)((int32_t)xPoint[1] * SCALE_FACTOR) - (trC * (int32_t)xRawTouch[1]));
|
|
|
|
// get the average and use it
|
|
_trA = (trA + trAhold) >> 1;
|
|
_trB = (trB + trBhold) >> 1;
|
|
_trC = (trC + trChold) >> 1;
|
|
_trD = (trD + trDhold) >> 1;
|
|
}
|
|
|
|
void adcraw_init(void)
|
|
{
|
|
state = IDLE; // set the state of the state machine to start the sampling
|
|
|
|
gpio_set_drive_capability(yu, GPIO_DRIVE_CAP_3);
|
|
gpio_set_drive_capability(yd, GPIO_DRIVE_CAP_3);
|
|
gpio_set_drive_capability(xl, GPIO_DRIVE_CAP_3);
|
|
gpio_set_drive_capability(xr, GPIO_DRIVE_CAP_3);
|
|
|
|
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
|
|
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 5 * 1000)); //5ms (expressed as microseconds)
|
|
|
|
/*Load calibration data*/
|
|
xRawTouch[0] = TOUCHCAL_ULX;
|
|
yRawTouch[0] = TOUCHCAL_ULY;
|
|
xRawTouch[1] = TOUCHCAL_URX;
|
|
yRawTouch[1] = TOUCHCAL_URY;
|
|
xRawTouch[3] = TOUCHCAL_LLX;
|
|
yRawTouch[3] = TOUCHCAL_LLY;
|
|
xRawTouch[2] = TOUCHCAL_LRX;
|
|
yRawTouch[2] = TOUCHCAL_LRY;
|
|
|
|
TouchCalculateCalPoints();
|
|
}
|
|
|
|
static void setup_axis(gpio_num_t plus, gpio_num_t minus, gpio_num_t measure, gpio_num_t ignore)
|
|
{
|
|
// Set GPIOs:
|
|
// - Float "ignore" and "measure"
|
|
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,0,0)
|
|
gpio_pad_select_gpio(ignore);
|
|
#else
|
|
esp_rom_gpio_pad_select_gpio(ignore);
|
|
#endif
|
|
gpio_set_direction(ignore, GPIO_MODE_DISABLE);
|
|
gpio_set_pull_mode(ignore, GPIO_FLOATING);
|
|
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,0,0)
|
|
gpio_pad_select_gpio(measure);
|
|
#else
|
|
esp_rom_gpio_pad_select_gpio(measure);
|
|
#endif
|
|
gpio_set_direction(measure, GPIO_MODE_DISABLE);
|
|
gpio_set_pull_mode(measure, GPIO_FLOATING);
|
|
// - Set "plus" to 1, "minus" to 0
|
|
gpio_config(&(gpio_config_t) {
|
|
.mode = GPIO_MODE_OUTPUT,
|
|
.pin_bit_mask = (1ULL << plus) | (1ULL << minus)
|
|
});
|
|
gpio_set_level(plus, 1);
|
|
gpio_set_level(minus, 0);
|
|
}
|
|
|
|
static void setup_adc(gpio_num_t measure)
|
|
{
|
|
// Init ADC
|
|
adc1_channel_t channel = gpio_to_adc[measure];
|
|
adc_gpio_init(ADC_UNIT_1, channel);
|
|
adc1_config_width(ADC_WIDTH_BIT_10);
|
|
adc1_config_channel_atten(channel, ADC_ATTEN_DB_11);
|
|
}
|
|
|
|
static void insert_sort(int16_t array[], uint8_t size) {
|
|
uint8_t j;
|
|
int16_t save;
|
|
|
|
for (int i = 1; i < size; i++) {
|
|
save = array[i];
|
|
for (j = i; j >= 1 && save < array[j - 1]; j--)
|
|
array[j] = array[j - 1];
|
|
array[j] = save;
|
|
}
|
|
}
|
|
|
|
static void ad_touch_handler(void *arg)
|
|
{
|
|
(void) arg;
|
|
uint8_t i;
|
|
int16_t samples[NUMSAMPLES];
|
|
|
|
switch (state) {
|
|
case IDLE:
|
|
adcX = 0;
|
|
adcY = 0;
|
|
|
|
case SET_X :
|
|
setup_axis(yd, yu, xr, xl);
|
|
setup_adc(xr);
|
|
state = READ_X;
|
|
break;
|
|
|
|
case READ_X:
|
|
for (i = 0; i < NUMSAMPLES; i++)
|
|
samples[i] = adc1_get_raw(gpio_to_adc[xr]);
|
|
insert_sort(samples, NUMSAMPLES);
|
|
temp_x = samples[NUMSAMPLES / 2];
|
|
|
|
case SET_Y :
|
|
setup_axis(xl, xr, yd, yu);
|
|
setup_adc(yd);
|
|
state = READ_Y;
|
|
break;
|
|
|
|
case READ_Y:
|
|
for (i = 0; i < NUMSAMPLES; i++)
|
|
samples[i] = adc1_get_raw(gpio_to_adc[yd]);
|
|
insert_sort(samples, NUMSAMPLES);
|
|
temp_y = samples[NUMSAMPLES / 2];
|
|
|
|
case SET_Z1 :
|
|
setup_axis(yu, xl, yd, xr);
|
|
setup_adc(yd);
|
|
state = READ_Z1;
|
|
break;
|
|
|
|
case READ_Z1:
|
|
temp_z1 = adc1_get_raw(gpio_to_adc[yd]);
|
|
|
|
case SET_Z2 :
|
|
setup_axis(yu, xl, xr, yd);
|
|
setup_adc(yd);
|
|
state = READ_Z2;
|
|
break;
|
|
|
|
case READ_Z2:
|
|
temp_z2 = adc1_get_raw(gpio_to_adc[xr]);
|
|
|
|
if (temp_z1 < TOUCHSCREEN_RESISTIVE_PRESS_THRESHOLD) {
|
|
#if CONFIG_LV_TOUCH_XY_SWAP
|
|
adcX = temp_y;
|
|
adcY = temp_x;
|
|
#else
|
|
adcX = temp_x;
|
|
adcY = temp_y;
|
|
#endif
|
|
}
|
|
else {
|
|
adcX = -1;
|
|
adcY = -1;
|
|
}
|
|
state = SET_X;
|
|
//printf("x: %d y: %d z: %d\n", adcX, adcY, temp_z1 - temp_z2);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static int16_t TouchGetRawX(void)
|
|
{
|
|
int16_t x = adcX;
|
|
|
|
#if CONFIG_LV_TOUCH_INVERT_X
|
|
x = 1023 - x;
|
|
#endif
|
|
return x;
|
|
}
|
|
|
|
static int16_t TouchGetX(void)
|
|
{
|
|
int16_t result = TouchGetRawX();
|
|
|
|
if (result > 0) {
|
|
result = (int16_t)((((int32_t)_trC * result) + _trD) >> TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR);
|
|
}
|
|
printf("x: %d\n", result);
|
|
return (result);
|
|
}
|
|
|
|
static int16_t TouchGetRawY(void)
|
|
{
|
|
int16_t y = adcY;
|
|
|
|
#if CONFIG_LV_TOUCH_INVERT_Y
|
|
y = 1023 - y;
|
|
#endif
|
|
return y;
|
|
}
|
|
|
|
static int16_t TouchGetY(void)
|
|
{
|
|
int16_t result = TouchGetRawY();
|
|
|
|
if (result > 0) {
|
|
result = (int16_t)((((int32_t)_trA * result) + (int32_t)_trB) >> TOUCHSCREEN_RESISTIVE_CALIBRATION_SCALE_FACTOR);
|
|
}
|
|
printf("y: %d\n", result);
|
|
return (result);
|
|
}
|
|
|
|
/**
|
|
* Get the current position and state of the touchpad
|
|
* @param data store the read data here
|
|
* @return false: because no more data to be read
|
|
*/
|
|
bool adcraw_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
|
|
{
|
|
static int16_t last_x = 0;
|
|
static int16_t last_y = 0;
|
|
|
|
int16_t x, y;
|
|
|
|
x = TouchGetX();
|
|
y = TouchGetY();
|
|
|
|
if ((x > 0) && (y > 0)) {
|
|
data->point.x = x;
|
|
data->point.y = y;
|
|
last_x = data->point.x;
|
|
last_y = data->point.y;
|
|
data->state = LV_INDEV_STATE_PR;
|
|
}
|
|
else {
|
|
data->point.x = last_x;
|
|
data->point.y = last_y;
|
|
data->state = LV_INDEV_STATE_REL;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endif //CONFIG_LV_TOUCH_CONTROLLER_ADCRAW
|