Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 40 additions & 18 deletions src/ClickEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@
// ----------------------------------------------------------------------------

#include "ClickEncoder.h"
#if defined(ESP8266)
# if defined(IRAM_ATTR)
# define CLICK_ENCODER_ISR_ATTR IRAM_ATTR
# elif defined(ICACHE_RAM_ATTR)
# define CLICK_ENCODER_ISR_ATTR ICACHE_RAM_ATTR
# else
# error "ClickEncoder requires IRAM_ATTR or ICACHE_RAM_ATTR on ESP8266"
# endif
#else
# define CLICK_ENCODER_ISR_ATTR
#endif


// ----------------------------------------------------------------------------
// Button configuration (values for 1ms timer service calls)
Expand Down Expand Up @@ -112,7 +124,7 @@ AnalogButton::AnalogButton(int8_t BTN, int16_t rangeLow, int16_t rangeHigh) : Cl
// ----------------------------------------------------------------------------
// call this every 1 millisecond via timer ISR
//
void ClickEncoder::service(void)
void CLICK_ENCODER_ISR_ATTR ClickEncoder::service(void)
{
bool moved = false;

Expand Down Expand Up @@ -170,24 +182,29 @@ void ClickEncoder::service(void)
}
}
}
// handle button
//
#ifndef WITHOUT_BUTTON
#if defined(ESP8266)
if (!analogInput) {
serviceButton();
}
#else
serviceButton();
#endif
#endif

}

#ifndef WITHOUT_BUTTON
void CLICK_ENCODER_ISR_ATTR ClickEncoder::serviceButton(void)
{
unsigned long currentMillis = millis();
unsigned long millisSinceLastCheck = currentMillis - lastButtonCheck;
if ((pinBTN > 0 || (pinBTN == 0 && buttonOnPinZeroEnabled)) // check button only, if a pin has been provided
&& (millisSinceLastCheck >= ENC_BUTTONINTERVAL)) // checking button is sufficient every 10-30ms
{
if ((pinBTN > 0 || (pinBTN == 0 && buttonOnPinZeroEnabled))
&& (millisSinceLastCheck >= ENC_BUTTONINTERVAL))
{
lastButtonCheck = currentMillis;

bool pinRead = getPinState();








if (pinRead == !pinsActive) { // key is now up
if (keyDownTicks > 1) { //Make sure key was down through 1 complete tick to prevent random transients from registering as click
Expand All @@ -211,24 +228,23 @@ void ClickEncoder::service(void)

keyDownTicks = 0;
}

if (pinRead == pinsActive) { // key is down
if ((keyDownTicks > (buttonHoldTime)) && (buttonHeldEnabled)) {
button = Held;
}
keyDownTicks += millisSinceLastCheck;
}

if (doubleClickTicks > 0) {
doubleClickTicks -= (uint16_t)constrain(min(millisSinceLastCheck, (unsigned long)doubleClickTicks), 0, 65536);
if (doubleClickTicks == 0) {
button = Clicked;
}
}
}
#endif // WITHOUT_BUTTON

}
#endif

// ----------------------------------------------------------------------------

Expand Down Expand Up @@ -289,6 +305,11 @@ void ClickEncoder::resetEncoder(void)
#ifndef WITHOUT_BUTTON
ClickEncoder::Button ClickEncoder::getButton(void)
{
#if defined(ESP8266)
if (analogInput) {
serviceButton();
}
#endif
noInterrupts();
ClickEncoder::Button ret = button;
if (button != ClickEncoder::Held && ret != ClickEncoder::Open) {
Expand All @@ -299,7 +320,7 @@ ClickEncoder::Button ClickEncoder::getButton(void)
return ret;
}

bool ClickEncoder::getPinState() {
bool CLICK_ENCODER_ISR_ATTR ClickEncoder::getPinState() {
bool pinState;
if (analogInput) {
int16_t pinValue = analogRead(pinBTN);
Expand All @@ -311,3 +332,4 @@ bool ClickEncoder::getPinState() {
}

#endif
#undef CLICK_ENCODER_ISR_ATTR
1 change: 1 addition & 0 deletions src/ClickEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ class ClickEncoder
unsigned long lastButtonCheck = 0;
int16_t anlogActiveRangeLow = 0;
int16_t anlogActiveRangeHigh = 0;
void serviceButton(void);
bool getPinState();
#endif
};
Expand Down
74 changes: 74 additions & 0 deletions test/esp8266_analog_button_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <assert.h>

#include "ClickEncoder.h"

static unsigned long fakeMillis;
static int fakeAnalogValue;
static int fakeDigitalValue;
static unsigned int analogReadCalls;
static unsigned int digitalReadCalls;

unsigned long millis(void)
{
return fakeMillis;
}

int analogRead(uint8_t)
{
++analogReadCalls;
return fakeAnalogValue;
}

int digitalRead(uint8_t)
{
++digitalReadCalls;
return fakeDigitalValue;
}

void pinMode(uint8_t, uint8_t)
{
}

void noInterrupts(void)
{
}

void interrupts(void)
{
}

int main(void)
{
fakeAnalogValue = 150;
AnalogButton analogButton(1, 100, 200);

#if defined(ESP8266)
fakeMillis = 10;
assert(analogButton.getButton() == ClickEncoder::Open);
assert(analogReadCalls == 1);

fakeMillis = 20;
analogButton.service();
assert(analogReadCalls == 1);

fakeAnalogValue = 900;
assert(analogButton.getButton() == ClickEncoder::Open);
assert(analogReadCalls == 2);

fakeMillis = 410;
assert(analogButton.getButton() == ClickEncoder::Clicked);
assert(analogReadCalls == 3);

fakeDigitalValue = LOW;
DigitalButton digitalButton(1);
fakeMillis = 10;
digitalButton.service();
assert(digitalReadCalls == 1);
#else
fakeMillis = 10;
analogButton.service();
assert(analogReadCalls == 1);
#endif

return 0;
}
21 changes: 21 additions & 0 deletions test/support/Arduino.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef TEST_SUPPORT_ARDUINO_H
#define TEST_SUPPORT_ARDUINO_H

#include <stdint.h>

#define LOW 0x0
#define HIGH 0x1
#define INPUT 0x0
#define INPUT_PULLUP 0x2

unsigned long millis(void);
int analogRead(uint8_t pin);
int digitalRead(uint8_t pin);
void pinMode(uint8_t pin, uint8_t mode);
void noInterrupts(void);
void interrupts(void);

#define min(a, b) ((a) < (b) ? (a) : (b))
#define constrain(value, lower, upper) ((value) < (lower) ? (lower) : ((value) > (upper) ? (upper) : (value)))

#endif