summaryrefslogtreecommitdiff
path: root/fw/fe310/eos/dev/gt911.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/fe310/eos/dev/gt911.c')
-rw-r--r--fw/fe310/eos/dev/gt911.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/fw/fe310/eos/dev/gt911.c b/fw/fe310/eos/dev/gt911.c
new file mode 100644
index 0000000..6fc2e1f
--- /dev/null
+++ b/fw/fe310/eos/dev/gt911.c
@@ -0,0 +1,278 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "platform.h"
+#include "board.h"
+
+#include "eos.h"
+#include "event.h"
+
+#include "soc/interrupt.h"
+#include "soc/timer.h"
+#include "soc/i2c.h"
+#include "soc/i2s.h"
+
+#include "dev/eve.h"
+
+#include "eve/eve.h"
+#include "eve/eve_touch_engine.h"
+
+#include "gt911.h"
+
+#define CMD_SLEEP 0x05
+
+#define REG_CMD 0x8040
+#define REG_CMD2 0x8046
+
+#define REG_STATUS 0x814E
+#define REG_POINTS 0x814F
+
+#define REG_CFG 0x8047
+#define REG_CHKSUM 0x80FF
+
+#define REG_X_THR 0x8057
+#define REG_Y_THR 0x8058
+
+#define REG_PRODID 0x8140
+
+#define SIZE_POINT_BUF 8
+#define MAX_POINTS 5
+
+static int clear_tag0 = 0;
+
+static void handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+ uint8_t status;
+ uint8_t points[SIZE_POINT_BUF * MAX_POINTS];
+ int i, num_points;
+ int rv;
+
+ if (!eos_gt911_intr_enabled()) return;
+
+ rv = eos_i2c_read16(GT911_ADDR, REG_STATUS, &status, 1);
+ if (rv) goto handle_evt_fin1;
+
+ if (!(status & 0x80)) goto handle_evt_fin1;
+
+ num_points = status & 0xf;
+ if (num_points > 5) goto handle_evt_fin1;
+
+ rv = eos_spi_select(EOS_SPI_DEV_EVE);
+ if (rv) goto handle_evt_fin0;
+ while (!eve_touch_ehost_ready());
+
+ if (num_points) {
+ if (clear_tag0) {
+ eve_touch_clear_tag0();
+ clear_tag0 = 0;
+ }
+ rv = eos_i2c_read16(GT911_ADDR, REG_POINTS, points, SIZE_POINT_BUF * num_points);
+ if (rv) goto handle_evt_fin0;
+
+ for (i=0; i<num_points; i++) {
+ uint8_t *point_buf;
+ uint8_t point_id;
+ uint16_t point_x;
+ uint16_t point_y;
+
+ point_buf = points + SIZE_POINT_BUF * i;
+ point_id = point_buf[0];
+ point_x = point_buf[1] | (point_buf[2] << 8);
+ point_y = point_buf[3] | (point_buf[4] << 8);
+ eve_touch_ehost_enter(point_id, point_x, point_y);
+ }
+ } else {
+ eve_touch_ehost_enter(0, 0x8000, 0x8000);
+ clear_tag0 = 1;
+ }
+
+ eve_touch_ehost_end();
+ eos_spi_deselect();
+
+ if (!eos_eve_intr_enabled()) {
+ eos_eve_poll();
+ }
+
+handle_evt_fin0:
+ status = 0;
+ rv = eos_i2c_write16(GT911_ADDR, REG_STATUS, &status, 1);
+
+handle_evt_fin1:
+ GPIO_REG(GPIO_RISE_IE) |= (1 << CTP_PIN_INT);
+}
+
+static void handle_intr(void) {
+ GPIO_REG(GPIO_RISE_IE) &= ~(1 << CTP_PIN_INT);
+ GPIO_REG(GPIO_RISE_IP) = (1 << CTP_PIN_INT);
+ eos_evtq_push_isr(EOS_EVT_CTP | CTP_ETYPE_INTR, NULL, 0);
+}
+
+int g911_command(uint8_t command) {
+ int rv;
+
+ if (command > 0x07) {
+ rv = eos_i2c_write16(GT911_ADDR, REG_CMD2, &command, 1);
+ if (rv) return rv;
+ }
+
+ rv = eos_i2c_write16(GT911_ADDR, REG_CMD, &command, 1);
+ if (rv) return rv;
+
+ return EOS_OK;
+}
+
+static uint8_t gt911_chksum(uint8_t *buf, uint8_t len) {
+ int i;
+ uint8_t csum = 0;
+
+ for(i=0; i<len; i++) {
+ csum += buf[i];
+ }
+
+ //csum %= 256;
+ csum = (~csum) + 1;
+
+ return csum;
+}
+
+static int gt911_chip_id(char *buf) {
+ int rv;
+
+ rv = eos_i2c_read16(GT911_ADDR, REG_PRODID, buf, 4);
+ return rv;
+}
+
+void eos_gt911_init(void) {
+ eos_intr_set_handler(INT_GPIO_BASE + CTP_PIN_INT, handle_intr);
+ eos_intr_set_priority(INT_GPIO_BASE + CTP_PIN_INT, IRQ_PRIORITY_CTP);
+ eos_evtq_set_handler(EOS_EVT_CTP, handle_evt);
+}
+
+void eos_gt911_intr_enable(void) {
+ GPIO_REG(GPIO_INPUT_EN) |= (1 << CTP_PIN_INT);
+ GPIO_REG(GPIO_RISE_IE) |= (1 << CTP_PIN_INT);
+ eos_intr_enable(INT_GPIO_BASE + CTP_PIN_INT);
+}
+
+void eos_gt911_intr_disable(void) {
+ eos_intr_disable(INT_GPIO_BASE + CTP_PIN_INT);
+ GPIO_REG(GPIO_RISE_IE) &= ~(1 << CTP_PIN_INT);
+ GPIO_REG(GPIO_INPUT_EN) &= ~(1 << CTP_PIN_INT);
+}
+
+int eos_gt911_intr_enabled(void) {
+ return !!(GPIO_REG(GPIO_INPUT_EN) & (1 << CTP_PIN_INT));
+}
+
+void eos_gt911_reset(void) {
+ eos_gt911_intr_disable();
+
+ /* INT and RST output and low */
+ GPIO_REG(GPIO_OUTPUT_VAL) &= ~((1 << CTP_PIN_INT) | (1 << CTP_PIN_RST));
+ GPIO_REG(GPIO_OUTPUT_EN) |= ((1 << CTP_PIN_INT) | (1 << CTP_PIN_RST));
+
+ /* T2: > 10ms */
+ eos_time_sleep(12);
+
+ /* high: 0x28/0x29 (0x14 7bit), low: 0xBA/0xBB (0x5D 7bit) */
+ if (GT911_ADDR == 0x14) {
+ GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << CTP_PIN_INT);
+ }
+
+ /* T3: > 100us */
+ eos_time_sleep(1);
+ GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << CTP_PIN_RST);
+
+ /* T4: > 5ms */
+ eos_time_sleep(6);
+ GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << CTP_PIN_INT);
+ /* end select I2C slave addr */
+
+ /* T5: > 50ms */
+ eos_time_sleep(51);
+
+ /* set INT as input */
+ GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << CTP_PIN_INT);
+ eos_gt911_intr_enable();
+}
+
+void eos_gt911_sleep(void) {
+ eos_gt911_intr_disable();
+
+ GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << CTP_PIN_INT);
+ GPIO_REG(GPIO_OUTPUT_EN) |= (1 << CTP_PIN_INT);
+
+ g911_command(CMD_SLEEP);
+}
+
+void eos_gt911_wake(void) {
+ /* in case of wake from mcu sleep */
+ GPIO_REG(GPIO_OUTPUT_EN) |= (1 << CTP_PIN_INT);
+ GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << CTP_PIN_INT);
+
+ eos_time_sleep(5);
+ GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << CTP_PIN_INT);
+ GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << CTP_PIN_INT);
+
+ eos_gt911_intr_enable();
+}
+
+int eos_gt911_cfg_read(uint8_t *cfg_buf) {
+ int rv;
+
+ rv = eos_i2c_read16(GT911_ADDR, REG_CFG, cfg_buf, GT911_SIZE_CFG);
+ return rv;
+}
+
+int eos_gt911_cfg_write(uint8_t *cfg_buf) {
+ int rv;
+
+ cfg_buf[GT911_SIZE_CFG - 2] = gt911_chksum(cfg_buf, GT911_SIZE_CFG - 2);
+ cfg_buf[GT911_SIZE_CFG - 1] = 1;
+
+ rv = eos_i2c_write16(GT911_ADDR, REG_CFG, cfg_buf, GT911_SIZE_CFG);
+ return rv;
+}
+
+int eos_gt911_cfg_print(void) {
+ int i, rv;
+ uint8_t cfg_buf[GT911_SIZE_CFG];
+
+ rv = eos_gt911_cfg_read(cfg_buf);
+ if (rv) return rv;
+
+ printf("GT911 CFG:\n");
+ for (i=0; i<GT911_SIZE_CFG-2; i++) {
+ printf("%.2X", cfg_buf[i]);
+ if (i % 8 == 7) {
+ printf("\n");
+ } else {
+ printf(" ");
+ }
+ }
+
+ return EOS_OK;
+}
+
+void eos_gt911_set_reg(uint8_t *cfg_buf, uint16_t reg, uint8_t val) {
+ cfg_buf[reg - REG_CFG] = val;
+}
+
+uint8_t eos_gt911_get_reg(uint8_t *cfg_buf, uint16_t reg) {
+ return cfg_buf[reg - REG_CFG];
+}
+
+int eos_gt911_set_threshold(void) {
+ int rv;
+ uint8_t cfg_buf[GT911_SIZE_CFG];
+
+ rv = eos_gt911_cfg_read(cfg_buf);
+ if (rv) return rv;
+
+ eos_gt911_set_reg(cfg_buf, REG_X_THR, 1);
+ eos_gt911_set_reg(cfg_buf, REG_Y_THR, 1);
+
+ rv = eos_gt911_cfg_write(cfg_buf);
+ return rv;
+}