diff options
Diffstat (limited to 'chip/npcx')
-rw-r--r-- | chip/npcx/cec.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/chip/npcx/cec.c b/chip/npcx/cec.c index 9b94b281d2..566e9a0ab6 100644 --- a/chip/npcx/cec.c +++ b/chip/npcx/cec.c @@ -90,6 +90,19 @@ #define DATA_LOW(data) DATA_TIME(LOW, data) /* + * Number of short pulses seen before the debounce logic goes into ignoring + * the bus for DEBOUNCE_WAIT_LONG instead of DEBOUNCE_WAIT_SHORT + */ +#define DEBOUNCE_CUTOFF 3 + +/* The limit how short a start-bit can be to trigger debounce logic */ +#define DEBOUNCE_LIMIT APB1_TICKS(200) +/* The time we ignore the bus for the first three debounce cases */ +#define DEBOUNCE_WAIT_SHORT APB1_TICKS(100) +/* The time we ignore the bus after the three initial debounce cases */ +#define DEBOUNCE_WAIT_LONG APB1_TICKS(500) + +/* * The variance in timing we allow outside of the CEC specification for * incoming signals. Our measurements aren't 100% accurate either, so this * gives some robustness. @@ -142,6 +155,7 @@ enum cec_state { CEC_STATE_INITIATOR_ACK_VERIFY, CEC_STATE_FOLLOWER_START_LOW, CEC_STATE_FOLLOWER_START_HIGH, + CEC_STATE_FOLLOWER_DEBOUNCE, CEC_STATE_FOLLOWER_HEADER_INIT_LOW, CEC_STATE_FOLLOWER_HEADER_INIT_HIGH, CEC_STATE_FOLLOWER_HEADER_DEST_LOW, @@ -203,6 +217,8 @@ struct cec_rx { * pulse duration */ int low_time; + /* Number of too short pulses seen in a row */ + int debounce_count; }; /* Transfer buffer and states */ @@ -550,9 +566,18 @@ void enter_state(enum cec_state new_state) timeout = CAP_START_LOW; break; case CEC_STATE_FOLLOWER_START_HIGH: + cec_rx.debounce_count = 0; cap_edge = CAP_EDGE_FALLING; timeout = CAP_START_HIGH; break; + case CEC_STATE_FOLLOWER_DEBOUNCE: + if (cec_rx.debounce_count >= DEBOUNCE_CUTOFF) { + timeout = DEBOUNCE_WAIT_LONG; + } else { + timeout = DEBOUNCE_WAIT_SHORT; + cec_rx.debounce_count++; + } + break; case CEC_STATE_FOLLOWER_HEADER_INIT_LOW: case CEC_STATE_FOLLOWER_HEADER_DEST_LOW: case CEC_STATE_FOLLOWER_EOM_LOW: @@ -723,6 +748,7 @@ static void cec_event_timeout(void) break; case CEC_STATE_FOLLOWER_START_LOW: case CEC_STATE_FOLLOWER_START_HIGH: + case CEC_STATE_FOLLOWER_DEBOUNCE: case CEC_STATE_FOLLOWER_HEADER_INIT_LOW: case CEC_STATE_FOLLOWER_HEADER_INIT_HIGH: case CEC_STATE_FOLLOWER_HEADER_DEST_LOW: @@ -765,6 +791,9 @@ static void cec_event_cap(void) if (VALID_LOW(START_BIT, t)) { cec_rx.low_time = t; enter_state(CEC_STATE_FOLLOWER_START_HIGH); + } else if (t < DEBOUNCE_LIMIT) { + /* Wait a bit if start-pulses are really short */ + enter_state(CEC_STATE_FOLLOWER_DEBOUNCE); } else { enter_state(CEC_STATE_IDLE); } |