summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/npcx/cec.c29
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);
}