One more ISR improvement

This commit is contained in:
Vic 2021-01-05 10:42:50 +01:00
parent 2426dbf8e5
commit 11921eb928

View File

@ -49,13 +49,41 @@
Timing of an ALL OFF frame in clock cycles T=377µs, triggering on rising edge:
IDLE-2222444422224444-IDLE
*********************
* About this driver *
*********************
This driver implements the reverse engineered protocol of the FTC532 touch controller.
The protocol encodes the bitmap of touched keys in variable length pulses comprising a
fixed length frame. These frames are then sent out continuously from the FTC532 chip.
The first version of this driver was working fine on well behaved hardware. After being
released to the field and installed on crappy hardware in noisy environments it developed
a habit of random 'ghost' switchings at night, much to the chagrin of some users.
This is almost a re-write containing a lot more timing (and other) checks in order to
detect and mitigate various incarnations of noise.
If you should still experience 'ghost switching' issues a solution may be increasing
FTC532_DEBOUNCE to 2 or higher. That will enable the de-bouncing code, at the expense of
'snappiness' of touch reactions. Higher values will accumulate more samples in 50 ms steps
before actually firing the rules trigger. It will eat a few bytes off your RAM and Flash
budget, too.
Usage:
------
This driver does not actually switch anything. It is a pure "rules" driver that solely emits
{"FTC532":{"KEYS":"XX"}} JSON messages to be used in a rule or by an MQTT broker. "XX" stands
for the hexadecimal (big endian) representation of a bitmap of keys currently touched, where
e.g. "00" means "no key touched" while "03" means "keys 1 and 2 touched simultaneously".
Selecting "FTC532" on a GPIO will awake the driver. This driver can only be selected once.
\*********************************************************************************************/
#define XDRV_47 47
#define FTC532_DEBOUNCE 0 // no. of cycles, < 2 disables the code
#define FTC532_KEYS 4 // number of key pins on chip
#define FTC532_KEYS_MAX 8 // number of key slots in protocol
#define FTC532_DEBOUNCE 0 // number of consecutive cycles until key accepted
#define FTC532_STATE_WAITING 0x1
#define FTC532_STATE_READING 0x2
@ -79,15 +107,15 @@ struct FTC532 {
volatile uint16_t state; // ISR state
uint8_t keys = 0; // bitmap of active keys
uint8_t old_keys = 0; // previously active keys
bool present = false; // driver active
#if FTC532_DEBOUNCE > 1
uint8_t key_cnt = 0; // used to de-bounce
#endif // FTC532_DEBOUNCE > 1
bool present = false; // driver active
#ifdef DEBUG_FTC532
volatile uint16_t e_inv = 0; // inv. key error counter
volatile uint16_t e_inv = 0; // inverted key error counter
volatile uint16_t e_frame = 0; // frame error counter
volatile uint16_t e_noise = 0; // noise detection counter
volatile bool valid = 0; // did we ever receive valid data?
volatile bool valid = 0; // did we ever receive valid data?
#endif // DEBUG_FTC532
} Ftc532;
@ -108,37 +136,36 @@ void ICACHE_RAM_ATTR ftc532_ISR(void) { // Hardware interrupt routine, trigger
#endif // DEBUG_FTC532
}
Ftc532.state = FTC532_STATE_READING;
Ftc532.tsmp = 0;
} else {
Ftc532.state = FTC532_STATE_WAITING;
}
return;
}
// FTC532_STATE_READING starts here
// FTC532_STATE_READING starts here
if (time_diff > FTC532_LONG + FTC532_BIT) {
#ifdef DEBUG_FTC532
++Ftc532.e_frame; // frame error
++Ftc532.e_frame; // frame error
#endif // DEBUG_FTC532
Ftc532.state = FTC532_STATE_WAITING;
return;
}
if (time_diff > FTC532_SHORT + FTC532_BIT) {
Ftc532.tsmp |= (1 << Ftc532.rxbit); // LONG
} else if (time_diff < FTC532_NOISE) { // noise detector
Ftc532.tsmp |= (1 << Ftc532.rxbit); // LONG
} else if (time_diff < FTC532_NOISE) { // NOISE
#ifdef DEBUG_FTC532
++Ftc532.e_noise;
#endif // DEBUG_FTC532
Ftc532.state = FTC532_STATE_WAITING;
return;
} else {
Ftc532.tsmp &= ~(1 << Ftc532.rxbit); // SHORT
}
++Ftc532.rxbit;
if (Ftc532.rxbit == FTC532_KEYS_MAX * 2) { // frame complete
if (Ftc532.rxbit == FTC532_KEYS_MAX * 2) { // frame complete
Ftc532.state = FTC532_STATE_COMPLETE;
}
}
void ftc532_init(void) { // Initialize
void ftc532_init(void) { // Initialize
if (!PinUsed(GPIO_FTC532)) { return; }
Ftc532.state = FTC532_STATE_WAITING;
pinMode(Pin(GPIO_FTC532), INPUT_PULLUP);
@ -147,7 +174,7 @@ void ftc532_init(void) { // Initialize
Ftc532.present = true;
}
void ftc532_update(void) { // Usually called every 50 ms
void ftc532_update(void) { // Usually called every 50 ms
if ((Ftc532.sample & 0xF0F0) == ((~Ftc532.sample & 0x0F0F) << 4) && (Ftc532.sample >> 8) == 0xF0) {
Ftc532.keys = Ftc532.sample & 0xF;
if (Ftc532.keys != Ftc532.old_keys) {
@ -156,7 +183,8 @@ void ftc532_update(void) { // Usually called every 50 ms
#endif // FTC532_DEBOUNCE > 1
#ifdef DEBUG_FTC532
AddLog_P(LOG_LEVEL_DEBUG, PSTR("FTC: SAM=%04X KEY=%X OLD=%X INV=%u NOI=%u FRM=%u OK=%u TIME=%lu Pin=%u"),
Ftc532.sample, Ftc532.keys, Ftc532.old_keys, Ftc532.e_inv, Ftc532.e_noise, Ftc532.e_frame, Ftc532.valid, Ftc532.rxtime, Pin(GPIO_FTC532));
Ftc532.sample, Ftc532.keys, Ftc532.old_keys, Ftc532.e_inv, Ftc532.e_noise, Ftc532.e_frame,
Ftc532.valid, Ftc532.rxtime, Pin(GPIO_FTC532));
#endif // DEBUG_FTC532
ftc532_publish();
Ftc532.old_keys = Ftc532.keys;
@ -171,7 +199,7 @@ void ftc532_update(void) { // Usually called every 50 ms
#ifdef DEBUG_FTC532
else {
++Ftc532.e_inv;
AddLog_P(LOG_LEVEL_DEBUG, PSTR("FTC: SAM=%04X"), Ftc532.sample);
AddLog_P(LOG_LEVEL_DEBUG, PSTR("FTC: ILL SAM=%04X"), Ftc532.sample);
}
#endif // DEBUG_FTC532
}