From ef2fe4707015c05a7d1cfb7a741b6d92f69aa303 Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Wed, 21 May 2014 16:26:19 -0700 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/200829 Reviewed-by: Vincent Palatin --- board/keyborg/touch_scan.c | 105 +++++++++++++++++++++++++++++++++++++++------ board/keyborg/touch_scan.h | 6 +++ 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 -- cgit v1.2.1