Skip to content

Commit

Permalink
Added: input_locked, inverted, input_type (SWITCH, MOTIONSENSOR, DOOR…
Browse files Browse the repository at this point in the history
…SENSOR)
  • Loading branch information
loetmeister committed Sep 9, 2018
1 parent 3e0ee90 commit 93e0a2b
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 64 deletions.
204 changes: 160 additions & 44 deletions libraries/HBWKey/HBWKey.cpp
@@ -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
}
}
};
49 changes: 29 additions & 20 deletions libraries/HBWKey/HBWKey.h
@@ -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

0 comments on commit 93e0a2b

Please sign in to comment.