summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-05-21 16:26:19 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-05-23 04:59:02 +0000
commitef2fe4707015c05a7d1cfb7a741b6d92f69aa303 (patch)
tree626dd1ad159688b872b3c5db1b9404b4ece1dbfc
parentd3d2c077f0df10d191a8d1fb11ab6f9469506d32 (diff)
downloadchrome-ec-ef2fe4707015c05a7d1cfb7a741b6d92f69aa303.tar.gz
Keyborg: implement fast scan mode
With fast scan mode, the scan rate can usually go up to 90-100 Hz. In worst case, the rate still maintains at around 50 Hz. BUG=None TEST=Manual test. Check heat map. BRANCH=None Change-Id: I2dc25028ffa5b3175b856d3437004c21b84e7df7 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/200829 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/keyborg/touch_scan.c105
-rw-r--r--board/keyborg/touch_scan.h6
2 files changed, 97 insertions, 14 deletions
diff --git a/board/keyborg/touch_scan.c b/board/keyborg/touch_scan.c
index 6441899272..2a953258ae 100644
--- a/board/keyborg/touch_scan.c
+++ b/board/keyborg/touch_scan.c
@@ -24,6 +24,13 @@
static uint8_t buf[2][ROW_COUNT * 2];
+#define SCAN_BUF_SIZE (DIV_ROUND_UP(COL_COUNT * 2, 32) + 2)
+#define GET_SCAN_NEEDED(x) (scan_needed[(x) / 32 + 1] & (1 << ((x) & 31)))
+static uint32_t scan_needed[SCAN_BUF_SIZE];
+
+#define SPAN_LENGTH (2 * COL_SPAN + 1)
+#define SPAN_MASK ((1 << SPAN_LENGTH) - 1)
+
static uint32_t mccr_list[COL_COUNT];
static uint32_t mrcr_list[ROW_COUNT];
@@ -115,6 +122,50 @@ static void enable_col(int idx, int enabled)
}
}
+static inline void set_scan_needed(int col)
+{
+ uint8_t word = (col - COL_SPAN + 32) / 32;
+ uint8_t bit = (col - COL_SPAN + 32) & 31;
+
+ scan_needed[word] |= SPAN_MASK << bit;
+ if (bit + SPAN_LENGTH > 32)
+ scan_needed[word + 1] |= SPAN_MASK >> (32 - bit);
+}
+
+int fast_scan(uint32_t *data)
+{
+ int col;
+
+ memset(data, 0, SCAN_BUF_SIZE);
+
+ STM32_PMSE_MRCR = 1 << 31;
+ for (col = 0; col < COL_COUNT * 2; ++col) {
+ if (col < COL_COUNT) {
+ enable_col(col, 1);
+ STM32_PMSE_MCCR = mccr_list[col];
+ }
+
+ if (master_slave_sync(5) != EC_SUCCESS)
+ return EC_ERROR_UNKNOWN;
+
+ start_adc_sample(0, ADC_SMPL_CPU_CYCLE);
+ while (!(STM32_ADC_SR(0) & (1 << 1)))
+ ;
+ if (ADC_DATA_WINDOW(flush_adc(0)) >= COL_THRESHOLD)
+ set_scan_needed(col);
+
+ if (master_slave_sync(5) != EC_SUCCESS)
+ return EC_ERROR_UNKNOWN;
+ if (col < COL_COUNT) {
+ enable_col(col, 0);
+ STM32_PMSE_MCCR = 0;
+ }
+ }
+ STM32_PMSE_MRCR = 0;
+
+ return EC_SUCCESS;
+}
+
void scan_column(uint8_t *data)
{
int i;
@@ -143,6 +194,12 @@ void touch_scan_slave_start(void)
int col, i, v;
struct spi_comm_packet *resp = (struct spi_comm_packet *)buf;
+ if (fast_scan(scan_needed) != EC_SUCCESS)
+ return;
+
+ /* Discharge the panel */
+ scan_column(buf[0]);
+
for (col = 0; col < COL_COUNT * 2; ++col) {
if (col < COL_COUNT) {
enable_col(col, 1);
@@ -152,23 +209,27 @@ void touch_scan_slave_start(void)
if (master_slave_sync(20) != EC_SUCCESS)
return;
- scan_column(resp->data);
- resp->cmd_sts = EC_SUCCESS;
-
- /* Reverse the scanned data */
- for (i = 0; ROW_COUNT - 1 - i > i; ++i) {
- v = resp->data[i];
- resp->data[i] = resp->data[ROW_COUNT - 1 - i];
- resp->data[ROW_COUNT - 1 - i] = v;
+ if (GET_SCAN_NEEDED(col)) {
+ scan_column(resp->data);
+
+ /* Reverse the scanned data */
+ for (i = 0; ROW_COUNT - 1 - i > i; ++i) {
+ v = resp->data[i];
+ resp->data[i] = resp->data[ROW_COUNT - 1 - i];
+ resp->data[ROW_COUNT - 1 - i] = v;
+ }
+ resp->size = ROW_COUNT;
+ } else {
+ resp->size = 0;
}
- resp->size = ROW_COUNT;
+ resp->cmd_sts = EC_SUCCESS;
/* Flush the last response */
if (col != 0)
spi_slave_send_response_flush();
- if (master_slave_sync(20) != EC_SUCCESS)
+ if (master_slave_sync(40) != EC_SUCCESS)
return;
/* Start sending the response for the current column */
@@ -198,6 +259,13 @@ int touch_scan_full_matrix(void)
return EC_ERROR_UNKNOWN;
encode_reset();
+
+ if (fast_scan(scan_needed) != EC_SUCCESS)
+ return EC_ERROR_UNKNOWN;
+
+ /* Discharge the panel */
+ scan_column(buf[0]);
+
for (col = 0; col < COL_COUNT * 2; ++col) {
if (col >= COL_COUNT) {
enable_col(col - COL_COUNT, 1);
@@ -210,18 +278,24 @@ int touch_scan_full_matrix(void)
last_dptr = dptr;
dptr = buf[col & 1];
- scan_column(dptr + ROW_COUNT);
+ if (GET_SCAN_NEEDED(col))
+ scan_column(dptr + ROW_COUNT);
+ else
+ memset(dptr + ROW_COUNT, 0, ROW_COUNT);
if (col > 0) {
/* Flush the data from the slave for the last column */
resp = spi_master_wait_response_done();
if (resp == NULL)
return EC_ERROR_UNKNOWN;
- memcpy(last_dptr, resp->data, ROW_COUNT);
+ if (resp->size)
+ memcpy(last_dptr, resp->data, ROW_COUNT);
+ else
+ memset(last_dptr, 0, ROW_COUNT);
encode_add_column(last_dptr);
}
- if (master_slave_sync(20) != EC_SUCCESS)
+ if (master_slave_sync(40) != EC_SUCCESS)
return EC_ERROR_UNKNOWN;
/* Start receiving data for the current column */
@@ -237,7 +311,10 @@ int touch_scan_full_matrix(void)
resp = spi_master_wait_response_done();
if (resp == NULL)
return EC_ERROR_UNKNOWN;
- memcpy(last_dptr, resp->data, ROW_COUNT);
+ if (resp->size)
+ memcpy(last_dptr, resp->data, ROW_COUNT);
+ else
+ memset(last_dptr, 0, ROW_COUNT);
encode_add_column(last_dptr);
master_slave_sync(20);
diff --git a/board/keyborg/touch_scan.h b/board/keyborg/touch_scan.h
index e3f694a1da..2d05ce486b 100644
--- a/board/keyborg/touch_scan.h
+++ b/board/keyborg/touch_scan.h
@@ -21,6 +21,12 @@ enum pin_type {
/* Threshold for each cell */
#define THRESHOLD 35
+/* Threshold for entire column */
+#define COL_THRESHOLD 16
+
+/* The span width of active columns */
+#define COL_SPAN 5 /* Must not exceed 15 */
+
/* ADC speed */
#define ADC_SMPR_VAL 0x2 /* 13.5 cycles */
#define ADC_SMPL_CYCLE_2 27