|
| 1 | +/* |
| 2 | + * Copyright 2024 Google LLC |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | +#include "drivers/touch/touch_sensor.h" |
| 17 | +#include "board/board.h" |
| 18 | +#include "drivers/exti.h" |
| 19 | +#include "drivers/gpio.h" |
| 20 | +#include "drivers/i2c.h" |
| 21 | +#include "drivers/rtc.h" |
| 22 | +#include "drivers/ioexp.h" |
| 23 | +#include "kernel/events.h" |
| 24 | +#include "kernel/util/delay.h" |
| 25 | +#include "os/tick.h" |
| 26 | +#include "services/common/touch/touch.h" |
| 27 | +#include "system/logging.h" |
| 28 | +#include "system/passert.h" |
| 29 | +#include "util/attributes.h" |
| 30 | +#include "util/net.h" |
| 31 | +#include <stdint.h> |
| 32 | + |
| 33 | + |
| 34 | +//////////////////////////////////////////////////////////////////////////////// |
| 35 | +#define TOUCH_EVENT_UP (0x01) |
| 36 | +#define TOUCH_EVENT_DOWN (0x02) |
| 37 | +#define TOUCH_EVENT_MOVE (0x03) |
| 38 | +typedef struct touch_message { |
| 39 | + GPoint point; |
| 40 | + uint8_t event; |
| 41 | +}touch_message_t ; |
| 42 | + |
| 43 | + |
| 44 | +//////////////////////////////////////////////////////////////////////////////// |
| 45 | +static bool s_callback_scheduled = false; |
| 46 | + |
| 47 | +static void cst816x_data_write(uint8_t reg, const uint8_t *data, uint32_t len) { |
| 48 | + i2c_use(BOARD_CONFIG_TOUCH->i2c); |
| 49 | + i2c_write_register_block(BOARD_CONFIG_TOUCH->i2c, reg, len, data); |
| 50 | + i2c_release(BOARD_CONFIG_TOUCH->i2c); |
| 51 | +} |
| 52 | + |
| 53 | +static void cst816x_data_read(uint8_t reg, uint8_t *p_data, uint32_t len) { |
| 54 | + i2c_use(BOARD_CONFIG_TOUCH->i2c); |
| 55 | + i2c_read_register_block(BOARD_CONFIG_TOUCH->i2c, reg, len, p_data); |
| 56 | + i2c_release(BOARD_CONFIG_TOUCH->i2c); |
| 57 | +} |
| 58 | + |
| 59 | +static void cst816x_register_write(uint8_t reg, uint8_t data) |
| 60 | +{ |
| 61 | + i2c_use(BOARD_CONFIG_TOUCH->i2c); |
| 62 | + i2c_write_register_block(BOARD_CONFIG_TOUCH->i2c, reg, sizeof(data), &data); |
| 63 | + i2c_release(BOARD_CONFIG_TOUCH->i2c); |
| 64 | +} |
| 65 | + |
| 66 | +static uint8_t cst816x_register_read(uint8_t reg) |
| 67 | +{ |
| 68 | + uint8_t data = 0; |
| 69 | + i2c_use(BOARD_CONFIG_TOUCH->i2c); |
| 70 | + i2c_read_register_block(BOARD_CONFIG_TOUCH->i2c, reg, sizeof(data), &data); |
| 71 | + i2c_release(BOARD_CONFIG_TOUCH->i2c); |
| 72 | + return data; |
| 73 | +} |
| 74 | + |
| 75 | +static void cst816x_read_point(touch_message_t* p_msg) { |
| 76 | + uint8_t rbuf[5] = {0}; |
| 77 | + cst816x_data_read(0x02, rbuf, 5); |
| 78 | + |
| 79 | + uint8_t press = rbuf[0] & 0x0F; |
| 80 | + if (press == 0x01) { |
| 81 | + p_msg->event = TOUCH_EVENT_DOWN; |
| 82 | + } else { |
| 83 | + p_msg->event = TOUCH_EVENT_UP; |
| 84 | + } |
| 85 | + p_msg->point.x = (((uint16_t)(rbuf[1] & 0x0F)) << 8) | rbuf[2]; |
| 86 | + p_msg->point.y = (((uint16_t)(rbuf[3] & 0X0F)) << 8) | rbuf[4]; |
| 87 | +} |
| 88 | + |
| 89 | + |
| 90 | +static void touch_cst816x_int_callback_function(void *context) { |
| 91 | + s_callback_scheduled = false; |
| 92 | + |
| 93 | + touch_message_t msg; |
| 94 | + uint64_t now_ms = ticks_to_milliseconds(rtc_get_ticks()); |
| 95 | + memset(&msg, 0, sizeof(msg)); |
| 96 | + cst816x_read_point(&msg); |
| 97 | + if (msg.event == TOUCH_EVENT_DOWN) { |
| 98 | + touch_handle_update(0, TouchState_FingerDown, &msg.point, 0, now_ms); |
| 99 | + } else if (msg.event == TOUCH_EVENT_UP) { |
| 100 | + touch_handle_update(0, TouchState_FingerUp, NULL, 0, now_ms); |
| 101 | + } else { |
| 102 | + |
| 103 | + } |
| 104 | +} |
| 105 | + |
| 106 | +// @brief int function |
| 107 | +static void touch_cst816x_int_handle(bool *should_context_switch) { |
| 108 | + if (s_callback_scheduled) { |
| 109 | + return; |
| 110 | + } |
| 111 | + PebbleEvent e = { |
| 112 | + .type = PEBBLE_CALLBACK_EVENT, |
| 113 | + .callback.callback = touch_cst816x_int_callback_function |
| 114 | + }; |
| 115 | + *should_context_switch = event_put_isr(&e); |
| 116 | + s_callback_scheduled = true; |
| 117 | +} |
| 118 | + |
| 119 | +// @brief Initialization |
| 120 | +void touch_sensor_init(void) { |
| 121 | +#if 0 |
| 122 | + gpio_input_init_pull_up_down(&BOARD_CONFIG_TOUCH->int_gpio, GPIO_PuPd_UP); |
| 123 | + |
| 124 | + // reset |
| 125 | + // 拉高 1ms |
| 126 | + ioexp_pin_set(IOEXP_CH02, IOEXP_HIGH); |
| 127 | + delay_us(1*1000); |
| 128 | + // 拉低 10ms |
| 129 | + ioexp_pin_set(IOEXP_CH02, IOEXP_LOW); |
| 130 | + delay_us(10*1000); |
| 131 | + // 拉高 |
| 132 | + ioexp_pin_set(IOEXP_CH02, IOEXP_HIGH); |
| 133 | + delay_us(50*1000); |
| 134 | + |
| 135 | + // check |
| 136 | + uint8_t whoami; |
| 137 | + for (int i=0; i<5; ++i) { |
| 138 | + whoami = cst816x_register_read(0xA7); |
| 139 | + PBL_LOG(LOG_LEVEL_ALWAYS, "cst816x read chipid. chipid=0x%02x", whoami); |
| 140 | + if (whoami == 0x11) { |
| 141 | + break; |
| 142 | + } |
| 143 | + delay_us(10*1000); |
| 144 | + } |
| 145 | + |
| 146 | + // initialize exti |
| 147 | + exti_configure_pin(BOARD_CONFIG_TOUCH->int_exti, ExtiTrigger_Falling, touch_cst816x_int_handle); |
| 148 | + exti_enable(BOARD_CONFIG_TOUCH->int_exti); |
| 149 | + PBL_LOG(LOG_LEVEL_DEBUG, "Initialized CST816 touch controller"); |
| 150 | +#endif |
| 151 | +} |
| 152 | + |
0 commit comments