forked from ThorstenPferdekaemper/HBWired
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added: input_locked, inverted, input_type (SWITCH, MOTIONSENSOR, DOOR…
…SENSOR)
- Loading branch information
1 parent
3e0ee90
commit 93e0a2b
Showing
2 changed files
with
189 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,168 @@ | ||
/* | ||
* HBWKey.cpp | ||
* | ||
* Updated (www.loetmeister.de): 09.09.2018 | ||
* - Added: input_locked, n_inverted, input_type (SWITCH, MOTIONSENSOR, DOORSENSOR) | ||
* - Changes require new XML layout for config! | ||
* | ||
*/ | ||
|
||
#include "HBWKey.h" | ||
|
||
// Class HBWKey | ||
HBWKey::HBWKey(uint8_t _pin, hbw_config_key* _config) { | ||
keyPressedMillis = 0; | ||
keyPressNum = 0; | ||
pin = _pin; | ||
config = _config; | ||
pinMode(pin,INPUT_PULLUP); | ||
keyPressedMillis = 0; | ||
keyPressNum = 0; | ||
pin = _pin; | ||
config = _config; | ||
} | ||
|
||
|
||
void HBWKey::loop(HBWDevice* device, uint8_t channel) { | ||
uint32_t now = millis(); | ||
if(digitalRead(pin)){ | ||
// d.h. Taste nicht gedrueckt | ||
// "Taste war auch vorher nicht gedrueckt" kann ignoriert werden | ||
// Taste war vorher gedrueckt? | ||
if(keyPressedMillis){ | ||
// entprellen, nur senden, wenn laenger als 50ms gedrueckt | ||
// aber noch kein "long" gesendet | ||
if(now - keyPressedMillis >= 50 && !lastSentLong){ | ||
keyPressNum++; | ||
device->sendKeyEvent(channel,keyPressNum, false); | ||
}; | ||
keyPressedMillis = 0; | ||
}; | ||
}else{ | ||
// Taste gedrueckt | ||
// Taste war vorher schon gedrueckt | ||
if(keyPressedMillis){ | ||
// muessen wir ein "long" senden? | ||
if(lastSentLong) { // schon ein LONG gesendet | ||
if(now - lastSentLong >= 300){ // alle 300ms wiederholen | ||
// keyPressNum nicht erhoehen | ||
lastSentLong = now ? now : 1; // der Teufel ist ein Eichhoernchen | ||
device->sendKeyEvent(channel,keyPressNum, true); // long press | ||
}; | ||
}else if(now - keyPressedMillis >= long(config->long_press_time) * 100) { | ||
// erstes LONG | ||
keyPressNum++; | ||
lastSentLong = now ? now : 1; | ||
device->sendKeyEvent(channel,keyPressNum, true); // long press | ||
}; | ||
}else{ | ||
// Taste war vorher nicht gedrueckt | ||
keyPressedMillis = now ? now : 1; // der Teufel ist ein Eichhoernchen | ||
lastSentLong = 0; | ||
} | ||
} | ||
} | ||
void HBWKey::afterReadConfig(){ | ||
if(config->long_press_time == 0xFF) config->long_press_time = 10; | ||
pinMode(pin, config->pullup ? INPUT_PULLUP : INPUT); | ||
|
||
#ifdef DEBUG_OUTPUT | ||
hbwdebug(F("cfg KeyPin:")); | ||
hbwdebug(pin); | ||
hbwdebug(F(" type:")); | ||
hbwdebug(config->input_type); | ||
hbwdebug(F("\n")); | ||
#endif | ||
}; | ||
|
||
|
||
void HBWKey::loop(HBWDevice* device, uint8_t channel) { | ||
|
||
uint32_t now = millis(); | ||
|
||
if (config->n_input_locked) { | ||
|
||
bool buttonState = (digitalRead(pin) ^ !config->n_inverted); | ||
|
||
switch (config->input_type) { | ||
case IN_SWITCH: | ||
// sends a short KeyEvent, each time the switch changes the polarity | ||
if (buttonState) { | ||
if (!keyPressedMillis) { | ||
// Taste war vorher nicht gedrueckt | ||
keyPressedMillis = now ? now : 1; | ||
} | ||
else if (now - keyPressedMillis >= SWITCH_DEBOUNCE_TIME && !lastSentLong) { | ||
// if bus is not idle, retry next time | ||
if (device->sendKeyEvent(channel, keyPressNum, false) == 0) { | ||
keyPressNum++; | ||
lastSentLong = now ? now : 1; | ||
} | ||
} | ||
} | ||
else { | ||
if (lastSentLong) { | ||
// if bus is not idle, retry next time | ||
if (device->sendKeyEvent(channel, keyPressNum, false) == 0) { | ||
keyPressNum++; | ||
lastSentLong = 0; | ||
} | ||
} | ||
keyPressedMillis = 0; | ||
} | ||
break; | ||
|
||
case IN_PUSHBUTTON: | ||
// sends short KeyEvent on short press and (repeated) long KeyEvent on long press | ||
if (buttonState) { | ||
// d.h. Taste nicht gedrueckt | ||
// "Taste war auch vorher nicht gedrueckt" kann ignoriert werden | ||
// Taste war vorher gedrueckt? | ||
if (keyPressedMillis) { | ||
// entprellen, nur senden, wenn laenger als 50ms gedrueckt | ||
// aber noch kein "long" gesendet | ||
if (now - keyPressedMillis >= KEY_DEBOUNCE_TIME && !lastSentLong) { | ||
keyPressNum++; | ||
device->sendKeyEvent(channel, keyPressNum, false); | ||
} | ||
keyPressedMillis = 0; | ||
} | ||
} | ||
else { | ||
// Taste gedrueckt | ||
// Taste war vorher schon gedrueckt | ||
if (keyPressedMillis) { | ||
// muessen wir ein "long" senden? | ||
if (lastSentLong) { // schon ein LONG gesendet | ||
if (now - lastSentLong >= 300) { // alle 300ms wiederholen | ||
// keyPressNum nicht erhoehen | ||
lastSentLong = now ? now : 1; // der Teufel ist ein Eichhoernchen | ||
device->sendKeyEvent(channel, keyPressNum, true); // long press | ||
} | ||
} | ||
else if (now - keyPressedMillis >= long(config->long_press_time) * 100) { | ||
// erstes LONG | ||
keyPressNum++; | ||
lastSentLong = now ? now : 1; | ||
device->sendKeyEvent(channel, keyPressNum, true); // long press | ||
}; | ||
} | ||
else { | ||
// Taste war vorher nicht gedrueckt | ||
keyPressedMillis = now ? now : 1; // der Teufel ist ein Eichhoernchen | ||
lastSentLong = 0; | ||
} | ||
} | ||
break; | ||
|
||
case IN_MOTIONSENSOR: | ||
// sends a short KeyEvent for raising or falling edge - not both | ||
if (buttonState) { | ||
if (!keyPressedMillis) { | ||
// Taste war vorher nicht gedrueckt | ||
keyPressedMillis = now ? now : 1; | ||
} | ||
else if (now - keyPressedMillis >= SWITCH_DEBOUNCE_TIME && !lastSentLong) { | ||
// if bus is not idle, retry next time | ||
if (device->sendKeyEvent(channel, keyPressNum, false) == 0) { | ||
keyPressNum++; | ||
lastSentLong = now ? now : 1; | ||
} | ||
} | ||
} | ||
else { | ||
if (lastSentLong) { | ||
//keyPressNum++; | ||
lastSentLong = 0; | ||
} | ||
keyPressedMillis = 0; | ||
} | ||
break; | ||
|
||
#ifdef IN_DOORSENSOR | ||
case IN_DOORSENSOR: | ||
// sends a short KeyEvent on HIGH and long KeyEvent on LOW input level changes | ||
if (buttonState) { | ||
if (!keyPressedMillis) { | ||
// Taste war vorher nicht gedrueckt | ||
keyPressedMillis = now ? now : 1; | ||
} | ||
else if (now - keyPressedMillis >= SWITCH_DEBOUNCE_TIME && !lastSentLong) { | ||
// if bus is not idle, retry next time | ||
if (device->sendKeyEvent(channel, keyPressNum, false) == 0) { | ||
keyPressNum++; | ||
lastSentLong = now ? now : 1; | ||
} | ||
} | ||
} | ||
else { | ||
if (lastSentLong) { | ||
// if bus is not idle, retry next time | ||
if (device->sendKeyEvent(channel, keyPressNum, true) == 0) { | ||
keyPressNum++; | ||
lastSentLong = 0; | ||
} | ||
} | ||
keyPressedMillis = 0; | ||
} | ||
break; | ||
#endif | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,43 @@ | ||
|
||
#ifndef HBWKey_h | ||
#define HBWKey_h | ||
|
||
#include <inttypes.h> | ||
#include "Arduino.h" | ||
#include "HBWired.h" | ||
|
||
|
||
// +0.0 00.1 INPUT_TYPE (switch/pushbutton) | ||
// +0.1 00.1 INPUT_LOCKED | ||
// +1.0 01.0 LONG_PRESS_TIME | ||
// TODO: input_type und input_locked implementieren | ||
//#define DEBUG_OUTPUT | ||
|
||
#define KEY_DEBOUNCE_TIME 65 // ms | ||
#define SWITCH_DEBOUNCE_TIME 155 // ms | ||
|
||
#define IN_DOORSENSOR 0 // sends a short KeyEvent on HIGH and long KeyEvent on LOW input level changes | ||
#define IN_MOTIONSENSOR 1 // sends a short KeyEvent for raising or falling edge - not both | ||
#define IN_SWITCH 2 // sends a short KeyEvent, each time the input (e.g. wall switch) changes the polarity | ||
#define IN_PUSHBUTTON 3 // sends a short KeyEvent on short press and (repeated) long KeyEvent on long press | ||
|
||
|
||
struct hbw_config_key { | ||
uint8_t input_type:1; | ||
uint8_t input_locked:1; | ||
uint8_t :6; | ||
uint8_t long_press_time; // 0x0000 | ||
uint8_t n_input_locked:1; // 0x07:0 0=LOCKED, 1=UNLOCKED | ||
uint8_t n_inverted:1; // 0x07:1 0=inverted, 1=not inverted | ||
uint8_t pullup:1; // 0x07:2 // TODO: needed....? | ||
uint8_t input_type:2; // 0x07:3-4 3=PUSHBUTTON (default), 2=SWITCH, 1=MOTIONSENSOR, 0=DOORSENSOR? | ||
uint8_t :3; // 0x07:5-7 | ||
uint8_t long_press_time; // 0x08 | ||
}; | ||
|
||
|
||
// Class HBWKey | ||
class HBWKey : public HBWChannel { | ||
public: | ||
HBWKey(uint8_t _pin, hbw_config_key* _config); | ||
virtual void loop(HBWDevice*, uint8_t channel); | ||
private: | ||
uint8_t pin; // Pin | ||
uint32_t keyPressedMillis; // Zeit, zu der die Taste gedrueckt wurde (fuer's Entprellen) | ||
uint32_t lastSentLong; // Zeit, zu der das letzte Mal longPress gesendet wurde | ||
uint8_t keyPressNum; | ||
hbw_config_key* config; | ||
public: | ||
HBWKey(uint8_t _pin, hbw_config_key* _config); | ||
virtual void loop(HBWDevice*, uint8_t channel); | ||
virtual void afterReadConfig(); | ||
private: | ||
uint8_t pin; // Pin | ||
uint32_t keyPressedMillis; // Zeit, zu der die Taste gedrueckt wurde (fuer's Entprellen) | ||
uint32_t lastSentLong; // Zeit, zu der das letzte Mal longPress gesendet wurde | ||
uint8_t keyPressNum; | ||
hbw_config_key* config; | ||
}; | ||
|
||
#endif | ||
#endif |