Initial commit
This commit is contained in:
135
libs/stmpe610/include/stmpe610.h
Normal file
135
libs/stmpe610/include/stmpe610.h
Normal file
@ -0,0 +1,135 @@
|
||||
/***************************************************
|
||||
This is a library for the Adafruit STMPE610 Resistive
|
||||
touch screen controller breakout
|
||||
----> http://www.adafruit.com/products/1571
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These breakouts use SPI or I2C to communicate
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
MIT license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
/* Adapted for native Mongoose OS by Pim van Pelt <pim@ipng.nl */
|
||||
|
||||
#ifndef __STMPE610H_
|
||||
#define __STMPE610H_
|
||||
|
||||
#define STMPE_ADDR 0x41
|
||||
|
||||
#define STMPE_SYS_CTRL1 0x03
|
||||
#define STMPE_SYS_CTRL1_RESET 0x02
|
||||
#define STMPE_SYS_CTRL2 0x04
|
||||
|
||||
#define STMPE_TSC_CTRL 0x40
|
||||
#define STMPE_TSC_CTRL_EN 0x01
|
||||
#define STMPE_TSC_CTRL_XYZ 0x00
|
||||
#define STMPE_TSC_CTRL_XY 0x02
|
||||
|
||||
#define STMPE_INT_CTRL 0x09
|
||||
#define STMPE_INT_CTRL_POL_HIGH 0x04
|
||||
#define STMPE_INT_CTRL_POL_LOW 0x00
|
||||
#define STMPE_INT_CTRL_EDGE 0x02
|
||||
#define STMPE_INT_CTRL_LEVEL 0x00
|
||||
#define STMPE_INT_CTRL_ENABLE 0x01
|
||||
#define STMPE_INT_CTRL_DISABLE 0x00
|
||||
|
||||
#define STMPE_INT_EN 0x0A
|
||||
#define STMPE_INT_EN_TOUCHDET 0x01
|
||||
#define STMPE_INT_EN_FIFOTH 0x02
|
||||
#define STMPE_INT_EN_FIFOOF 0x04
|
||||
#define STMPE_INT_EN_FIFOFULL 0x08
|
||||
#define STMPE_INT_EN_FIFOEMPTY 0x10
|
||||
#define STMPE_INT_EN_ADC 0x40
|
||||
#define STMPE_INT_EN_GPIO 0x80
|
||||
|
||||
#define STMPE_INT_STA 0x0B
|
||||
#define STMPE_INT_STA_TOUCHDET 0x01
|
||||
|
||||
#define STMPE_ADC_CTRL1 0x20
|
||||
#define STMPE_ADC_CTRL1_12BIT 0x08
|
||||
#define STMPE_ADC_CTRL1_10BIT 0x00
|
||||
|
||||
#define STMPE_ADC_CTRL2 0x21
|
||||
#define STMPE_ADC_CTRL2_1_625MHZ 0x00
|
||||
#define STMPE_ADC_CTRL2_3_25MHZ 0x01
|
||||
#define STMPE_ADC_CTRL2_6_5MHZ 0x02
|
||||
|
||||
#define STMPE_TSC_CFG 0x41
|
||||
#define STMPE_TSC_CFG_1SAMPLE 0x00
|
||||
#define STMPE_TSC_CFG_2SAMPLE 0x40
|
||||
#define STMPE_TSC_CFG_4SAMPLE 0x80
|
||||
#define STMPE_TSC_CFG_8SAMPLE 0xC0
|
||||
#define STMPE_TSC_CFG_DELAY_10US 0x00
|
||||
#define STMPE_TSC_CFG_DELAY_50US 0x08
|
||||
#define STMPE_TSC_CFG_DELAY_100US 0x10
|
||||
#define STMPE_TSC_CFG_DELAY_500US 0x18
|
||||
#define STMPE_TSC_CFG_DELAY_1MS 0x20
|
||||
#define STMPE_TSC_CFG_DELAY_5MS 0x28
|
||||
#define STMPE_TSC_CFG_DELAY_10MS 0x30
|
||||
#define STMPE_TSC_CFG_DELAY_50MS 0x38
|
||||
#define STMPE_TSC_CFG_SETTLE_10US 0x00
|
||||
#define STMPE_TSC_CFG_SETTLE_100US 0x01
|
||||
#define STMPE_TSC_CFG_SETTLE_500US 0x02
|
||||
#define STMPE_TSC_CFG_SETTLE_1MS 0x03
|
||||
#define STMPE_TSC_CFG_SETTLE_5MS 0x04
|
||||
#define STMPE_TSC_CFG_SETTLE_10MS 0x05
|
||||
#define STMPE_TSC_CFG_SETTLE_50MS 0x06
|
||||
#define STMPE_TSC_CFG_SETTLE_100MS 0x07
|
||||
|
||||
#define STMPE_FIFO_TH 0x4A
|
||||
|
||||
#define STMPE_FIFO_SIZE 0x4C
|
||||
|
||||
#define STMPE_FIFO_STA 0x4B
|
||||
#define STMPE_FIFO_STA_RESET 0x01
|
||||
#define STMPE_FIFO_STA_OFLOW 0x80
|
||||
#define STMPE_FIFO_STA_FULL 0x40
|
||||
#define STMPE_FIFO_STA_EMPTY 0x20
|
||||
#define STMPE_FIFO_STA_THTRIG 0x10
|
||||
|
||||
#define STMPE_TSC_I_DRIVE 0x58
|
||||
#define STMPE_TSC_I_DRIVE_20MA 0x00
|
||||
#define STMPE_TSC_I_DRIVE_50MA 0x01
|
||||
|
||||
#define STMPE_TSC_DATA_X 0x4D
|
||||
#define STMPE_TSC_DATA_Y 0x4F
|
||||
#define STMPE_TSC_FRACTION_Z 0x56
|
||||
|
||||
#define STMPE_GPIO_SET_PIN 0x10
|
||||
#define STMPE_GPIO_CLR_PIN 0x11
|
||||
#define STMPE_GPIO_DIR 0x13
|
||||
#define STMPE_GPIO_ALT_FUNCT 0x17
|
||||
|
||||
// === Screen orientation constants ===
|
||||
enum mgos_stmpe610_rotation_t {
|
||||
STMPE610_PORTRAIT = 0,
|
||||
STMPE610_LANDSCAPE = 1,
|
||||
STMPE610_PORTRAIT_FLIP = 2,
|
||||
STMPE610_LANDSCAPE_FLIP = 3,
|
||||
};
|
||||
|
||||
enum mgos_stmpe610_touch_t {
|
||||
TOUCH_DOWN = 0,
|
||||
TOUCH_UP = 1,
|
||||
};
|
||||
|
||||
struct mgos_stmpe610_event_data {
|
||||
enum mgos_stmpe610_touch_t direction;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint8_t z;
|
||||
uint8_t length; // Amount of time the TOUCH_DOWN event lasted (always set to 1 for TOUCH_UP)
|
||||
};
|
||||
|
||||
bool mgos_stmpe610_init(void);
|
||||
|
||||
typedef void (*mgos_stmpe610_event_t)(struct mgos_stmpe610_event_data *);
|
||||
void mgos_stmpe610_set_handler(mgos_stmpe610_event_t handler);
|
||||
void mgos_stmpe610_set_rotation(enum mgos_stmpe610_rotation_t rotation);
|
||||
|
||||
#endif // __STMPE610H_
|
26
libs/stmpe610/mos.yml
Normal file
26
libs/stmpe610/mos.yml
Normal file
@ -0,0 +1,26 @@
|
||||
author: Pim van Pelt <pim@ipng.nl>
|
||||
type: lib
|
||||
description: Mongoose-OS STMPE610 for ESP32
|
||||
platforms: [ esp32 ]
|
||||
version: 1.0
|
||||
|
||||
sources:
|
||||
- src
|
||||
|
||||
includes:
|
||||
- include
|
||||
|
||||
config_schema:
|
||||
- ["stmpe610", "o", {title: "TouchScreen settings"}]
|
||||
- ["stmpe610.irq_pin", "i", 23, {title: "Touch IRQ pin"}]
|
||||
- ["stmpe610.cs_pin", "i", 32, {title: "Touch CS pin"}]
|
||||
|
||||
libs:
|
||||
- origin: libs/lobo-spi
|
||||
|
||||
tags:
|
||||
- c
|
||||
- spi
|
||||
- hw
|
||||
|
||||
manifest_version: 2017-09-29
|
263
libs/stmpe610/src/stmpe610.c
Normal file
263
libs/stmpe610/src/stmpe610.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Author: LoBo (loboris@gmail.com, loboris.github)
|
||||
*
|
||||
* Module supporting STMPE touch screen controller.
|
||||
*
|
||||
* HIGH SPEED LOW LEVEL DISPLAY FUNCTIONS
|
||||
* USING DIRECT or DMA SPI TRANSFER MODEs
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mgos.h"
|
||||
#include "lobo_spi.h"
|
||||
#include "stmpe610.h"
|
||||
|
||||
#define SPI_BUS VSPI_HOST
|
||||
#define STMPE_SPI_MODE 1
|
||||
|
||||
static spi_lobo_device_handle_t s_stmpe610_spi = NULL;
|
||||
static mgos_stmpe610_event_t s_event_handler = NULL;
|
||||
static enum mgos_stmpe610_rotation_t s_rotation = STMPE610_PORTRAIT;
|
||||
|
||||
static void IRAM_ATTR _spi_transfer_start(spi_lobo_device_handle_t spi_dev, int wrbits, int rdbits) {
|
||||
// Load send buffer
|
||||
spi_dev->host->hw->user.usr_mosi_highpart = 0;
|
||||
spi_dev->host->hw->mosi_dlen.usr_mosi_dbitlen = wrbits-1;
|
||||
spi_dev->host->hw->user.usr_mosi = 1;
|
||||
if (rdbits) {
|
||||
spi_dev->host->hw->miso_dlen.usr_miso_dbitlen = rdbits;
|
||||
spi_dev->host->hw->user.usr_miso = 1;
|
||||
}
|
||||
else {
|
||||
spi_dev->host->hw->miso_dlen.usr_miso_dbitlen = 0;
|
||||
spi_dev->host->hw->user.usr_miso = 0;
|
||||
}
|
||||
// Start transfer
|
||||
spi_dev->host->hw->cmd.usr = 1;
|
||||
// Wait for SPI bus ready
|
||||
while (spi_dev->host->hw->cmd.usr);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR stmpe610_write_reg(uint8_t reg, uint8_t val) {
|
||||
|
||||
spi_lobo_device_select(s_stmpe610_spi, 0);
|
||||
|
||||
s_stmpe610_spi->host->hw->data_buf[0] = (val << 8) | reg;
|
||||
_spi_transfer_start(s_stmpe610_spi, 16, 0);
|
||||
|
||||
spi_lobo_device_deselect(s_stmpe610_spi);
|
||||
}
|
||||
|
||||
static uint8_t IRAM_ATTR stmpe610_read_byte(uint8_t reg) {
|
||||
spi_lobo_device_select(s_stmpe610_spi, 0);
|
||||
|
||||
s_stmpe610_spi->host->hw->data_buf[0] = (reg << 8) | (reg | 0x80);
|
||||
_spi_transfer_start(s_stmpe610_spi, 16, 16);
|
||||
uint8_t res = s_stmpe610_spi->host->hw->data_buf[0] >> 8;
|
||||
|
||||
spi_lobo_device_deselect(s_stmpe610_spi);
|
||||
return res;
|
||||
}
|
||||
|
||||
static uint16_t IRAM_ATTR stmpe610_read_word(uint8_t reg) {
|
||||
spi_lobo_device_select(s_stmpe610_spi, 0);
|
||||
|
||||
s_stmpe610_spi->host->hw->data_buf[0] = ((((reg+1) << 8) | ((reg+1) | 0x80)) << 16) | (reg << 8) | (reg | 0x80);
|
||||
_spi_transfer_start(s_stmpe610_spi, 32, 32);
|
||||
uint16_t res = (uint16_t)(s_stmpe610_spi->host->hw->data_buf[0] & 0xFF00);
|
||||
res |= (uint16_t)(s_stmpe610_spi->host->hw->data_buf[0] >> 24);
|
||||
|
||||
spi_lobo_device_deselect(s_stmpe610_spi);
|
||||
return res;
|
||||
}
|
||||
|
||||
static uint32_t stmpe610_getID()
|
||||
{
|
||||
uint16_t tid = stmpe610_read_word(0);
|
||||
uint8_t tver = stmpe610_read_byte(2);
|
||||
return (tid << 8) | tver;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t stmpe610_bufferLength(void) {
|
||||
return stmpe610_read_byte(STMPE_FIFO_SIZE);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t stmpe610_readData(uint16_t *x, uint16_t *y, uint8_t *z) {
|
||||
uint8_t samples, cnt;
|
||||
uint32_t sum_sample_x = 0, sum_sample_y = 0;
|
||||
uint16_t sum_sample_z = 0;
|
||||
|
||||
samples = cnt = stmpe610_bufferLength();
|
||||
LOG(LL_DEBUG, ("Touch sensed with %d samples", samples));
|
||||
if (samples == 0)
|
||||
return 0;
|
||||
|
||||
while (cnt>0) {
|
||||
uint16_t sample_x, sample_y;
|
||||
uint8_t sample_z;
|
||||
|
||||
sample_x = stmpe610_read_word(0x4D);
|
||||
sample_y = stmpe610_read_word(0x4F);
|
||||
sample_z = stmpe610_read_byte(0x51);
|
||||
|
||||
sum_sample_x += sample_x;
|
||||
sum_sample_y += sample_y;
|
||||
sum_sample_z += sample_z;
|
||||
LOG(LL_DEBUG, ("Sample at (%d,%d) pressure=%d, bufferLength=%d", sample_x, sample_y, sample_z, stmpe610_bufferLength()));
|
||||
cnt--;
|
||||
}
|
||||
*x = sum_sample_x / samples;
|
||||
*y = sum_sample_y / samples;
|
||||
*z = sum_sample_z / samples;
|
||||
|
||||
stmpe610_write_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET); // clear FIFO
|
||||
stmpe610_write_reg(STMPE_FIFO_STA, 0); // unreset
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
static long map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||
{
|
||||
if (x<in_min) x=in_min;
|
||||
if (x>in_max) x=in_max;
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
static void stmpe610_map_rotation(uint16_t x, uint16_t y, uint16_t *x_out, uint16_t *y_out) {
|
||||
switch(s_rotation) {
|
||||
case STMPE610_LANDSCAPE:
|
||||
*x_out = map(y, 150, 3800, 0, 4095);
|
||||
*y_out = map(x, 250, 3700, 0, 4095);
|
||||
break;
|
||||
case STMPE610_PORTRAIT_FLIP:
|
||||
*x_out = map(x, 250, 3800, 0, 4095);
|
||||
*y_out = 4095-map(y, 150, 3700, 0, 4095);
|
||||
break;
|
||||
case STMPE610_LANDSCAPE_FLIP:
|
||||
*x_out = 4095-map(y, 150, 3800, 0, 4095);
|
||||
*y_out = 4095-map(x, 250, 3700, 0, 4095);
|
||||
break;
|
||||
default: // STMPE610_PORTRAIT
|
||||
*x_out = 4095-map(x, 250, 3800, 0, 4095);
|
||||
*y_out = map(y, 150, 3700, 0, 4095);
|
||||
}
|
||||
}
|
||||
|
||||
static void stmpe610_irq(int pin, void *arg) {
|
||||
struct mgos_stmpe610_event_data ed;
|
||||
uint16_t x, y;
|
||||
uint8_t z;
|
||||
|
||||
if (stmpe610_bufferLength()==0) {
|
||||
uint8_t i;
|
||||
LOG(LL_DEBUG, ("Touch DOWN"));
|
||||
for (i=0; i<10; i++) {
|
||||
mgos_msleep(5);
|
||||
if (stmpe610_bufferLength()>0) {
|
||||
|
||||
stmpe610_readData(&x, &y, &z);
|
||||
LOG(LL_DEBUG, ("Touch DOWN at (%d,%d) pressure=%d, length=%d, iteration=%d", x, y, z, ed.length, i));
|
||||
|
||||
ed.length=1;
|
||||
ed.direction = TOUCH_DOWN;
|
||||
stmpe610_map_rotation(x, y, &ed.x, &ed.y);
|
||||
ed.z = z;
|
||||
if (s_event_handler)
|
||||
s_event_handler(&ed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
stmpe610_write_reg(STMPE_INT_STA, 0xFF); // reset all ints
|
||||
return;
|
||||
}
|
||||
|
||||
ed.length = stmpe610_readData(&x, &y, &z);
|
||||
LOG(LL_DEBUG, ("Touch UP at (%d,%d) pressure=%d, length=%d", x, y, z, ed.length));
|
||||
ed.direction = TOUCH_UP;
|
||||
stmpe610_map_rotation(x, y, &ed.x, &ed.y);
|
||||
ed.z = z;
|
||||
if (s_event_handler)
|
||||
s_event_handler(&ed);
|
||||
|
||||
stmpe610_write_reg(STMPE_INT_STA, 0xFF); // reset all ints
|
||||
(void) pin;
|
||||
(void) arg;
|
||||
}
|
||||
|
||||
void mgos_stmpe610_set_handler(mgos_stmpe610_event_t handler) {
|
||||
s_event_handler = handler;
|
||||
}
|
||||
|
||||
void mgos_stmpe610_set_rotation(enum mgos_stmpe610_rotation_t rotation) {
|
||||
s_rotation = rotation;
|
||||
}
|
||||
|
||||
|
||||
bool mgos_stmpe610_init(void) {
|
||||
esp_err_t ret;
|
||||
|
||||
gpio_pad_select_gpio(mgos_sys_config_get_stmpe610_cs_pin());
|
||||
gpio_set_direction(mgos_sys_config_get_stmpe610_cs_pin(), GPIO_MODE_OUTPUT);
|
||||
|
||||
spi_lobo_bus_config_t buscfg={
|
||||
.miso_io_num=mgos_sys_config_get_spi_miso(),
|
||||
.mosi_io_num=mgos_sys_config_get_spi_mosi(),
|
||||
.sclk_io_num=mgos_sys_config_get_spi_sck(),
|
||||
.quadwp_io_num=-1,
|
||||
.quadhd_io_num=-1,
|
||||
.max_transfer_sz = 6*1024,
|
||||
};
|
||||
|
||||
spi_lobo_device_interface_config_t tsdevcfg={
|
||||
.clock_speed_hz=1000000,
|
||||
.mode=STMPE_SPI_MODE,
|
||||
.spics_io_num=mgos_sys_config_get_stmpe610_cs_pin(), //Touch CS pin
|
||||
.spics_ext_io_num=-1, //Not using the external CS
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
ret=spi_lobo_bus_add_device(SPI_BUS, &buscfg, &tsdevcfg, &s_stmpe610_spi);
|
||||
assert(ret==ESP_OK);
|
||||
|
||||
ret = spi_lobo_device_select(s_stmpe610_spi, 1);
|
||||
assert(ret==ESP_OK);
|
||||
ret = spi_lobo_device_deselect(s_stmpe610_spi);
|
||||
assert(ret==ESP_OK);
|
||||
|
||||
uint32_t tver = stmpe610_getID();
|
||||
if (tver >> 8 != 0x0811) {
|
||||
LOG(LL_ERROR, ("STMPE SPI init failed, disabling"));
|
||||
return true;
|
||||
}
|
||||
LOG(LL_INFO, ("SPI init ok (cs=%d, speed=%u, ver=%04x, rev=%02x); irq=%d", mgos_sys_config_get_stmpe610_cs_pin(), spi_lobo_get_speed(s_stmpe610_spi),
|
||||
tver>>8, tver&0xFF, mgos_sys_config_get_stmpe610_irq_pin()));
|
||||
|
||||
stmpe610_write_reg(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET);
|
||||
mgos_msleep(10);
|
||||
|
||||
for (uint8_t i=0; i<65; i++)
|
||||
stmpe610_read_byte(i);
|
||||
|
||||
stmpe610_write_reg(STMPE_SYS_CTRL2, 0x0); // turn on clocks!
|
||||
stmpe610_write_reg(STMPE_INT_EN, STMPE_INT_EN_TOUCHDET);
|
||||
stmpe610_write_reg(STMPE_ADC_CTRL1, STMPE_ADC_CTRL1_10BIT | (0x6 << 4)); // 96 clocks per conversion
|
||||
stmpe610_write_reg(STMPE_ADC_CTRL2, STMPE_ADC_CTRL2_6_5MHZ);
|
||||
stmpe610_write_reg(STMPE_TSC_CFG, STMPE_TSC_CFG_4SAMPLE | STMPE_TSC_CFG_DELAY_1MS | STMPE_TSC_CFG_SETTLE_5MS);
|
||||
stmpe610_write_reg(STMPE_TSC_FRACTION_Z, 0x6);
|
||||
stmpe610_write_reg(STMPE_FIFO_TH, 1);
|
||||
stmpe610_write_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET);
|
||||
stmpe610_write_reg(STMPE_FIFO_STA, 0); // unreset
|
||||
stmpe610_write_reg(STMPE_TSC_I_DRIVE, STMPE_TSC_I_DRIVE_50MA);
|
||||
stmpe610_write_reg(STMPE_TSC_CTRL, 0x30); // X&Y&Z, 16 reading window
|
||||
stmpe610_write_reg(STMPE_TSC_CTRL, 0x31); // X&Y&Z, 16 reading window, TSC enable
|
||||
stmpe610_write_reg(STMPE_INT_STA, 0xFF); // reset all ints
|
||||
stmpe610_write_reg(STMPE_INT_CTRL, STMPE_INT_CTRL_POL_LOW | STMPE_INT_CTRL_EDGE | STMPE_INT_CTRL_ENABLE);
|
||||
|
||||
mgos_gpio_set_mode(mgos_sys_config_get_stmpe610_irq_pin(), MGOS_GPIO_MODE_INPUT);
|
||||
mgos_gpio_set_pull(mgos_sys_config_get_stmpe610_irq_pin(), MGOS_GPIO_PULL_UP);
|
||||
mgos_gpio_set_int_handler(mgos_sys_config_get_stmpe610_irq_pin(), MGOS_GPIO_INT_EDGE_NEG, stmpe610_irq, NULL);
|
||||
mgos_gpio_enable_int(mgos_sys_config_get_stmpe610_irq_pin());
|
||||
return true;
|
||||
}
|
Reference in New Issue
Block a user