Skip to content

Commit 8975b99

Browse files
committed
#165 support steps in encoder, #136 support raw interrupt handling using std::function on ESP32 and STM32 boards
1 parent 3179ae3 commit 8975b99

File tree

3 files changed

+37
-26
lines changed

3 files changed

+37
-26
lines changed

examples/buttonRotaryEncoder/buttonRotaryEncoder.ino

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,23 @@
1717
const pinid_t spinwheelClickPin = 0;
1818

1919
// The pin onto which we connected the repeat button switch
20-
const pinid_t repeatButtonPin = 1;
20+
const pinid_t repeatButtonPin = PC9;
2121

2222
// The two pins where we connected the A and B pins of the encoder, the A pin must support interrupts.
23-
const pinid_t encoderAPin = 16;
24-
const pinid_t encoderBPin = 17;
23+
const pinid_t encoderAPin = PC8;
24+
const pinid_t encoderBPin = PC10;
2525

2626
// the maximum (0 based) value that we want the encoder to represent.
2727
const int maximumEncoderValue = 128;
2828

2929
// an LED that flashes as the encoder changes
30-
const int ledOutputPin = 12;
30+
const int ledOutputPin = LED_BLUE;
31+
32+
// You can change the step rate of the encoder, it defaults to 1, but can be changed during a precision change
33+
const int stepSize = 2;
34+
35+
// You can set the encoder to wrap around at min/max values, or just to stop there.
36+
const bool wrapAround = true;
3137

3238
auto boardIo = internalDigitalIo();
3339

@@ -69,7 +75,7 @@ void setup() {
6975
// our next task is to initialise swtiches, do this BEFORE doing anything else with switches.
7076
// We choose to initialise in poll everything (requires no interrupts), but there are other modes too:
7177
// (SWITCHES_NO_POLLING - interrupt only) or (SWITCHES_POLL_KEYS_ONLY - encoders on interrupt)
72-
switches.init(boardIo, SWITCHES_POLL_EVERYTHING, true);
78+
switches.init(boardIo, SWITCHES_POLL_KEYS_ONLY, true);
7379

7480
// now we add the switches, we don't want the spin-wheel button to repeat, so leave off the last parameter
7581
// which is the repeat interval (millis / 20 basically) Repeat button does repeat as we can see.
@@ -80,7 +86,7 @@ void setup() {
8086
// we give the encoder a max value of 128, always minimum of 0.
8187
auto hwEncoder = new HardwareRotaryEncoder(encoderAPin, encoderBPin, onEncoderChange);
8288
switches.setEncoder(0, hwEncoder);
83-
hwEncoder->changePrecision(maximumEncoderValue, 100);
89+
hwEncoder->changePrecision(maximumEncoderValue, 100, wrapAround, stepSize);
8490
}
8591

8692
void loop() {

src/SwitchInput.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -225,15 +225,15 @@ void SwitchInput::pushSwitch(pinid_t pin, bool held) {
225225
keys.getByKey(pin)->trigger(held);
226226
}
227227

228-
void SwitchInput::changeEncoderPrecision(uint8_t slot, uint16_t precision, uint16_t currentValue, bool rollover) {
228+
void SwitchInput::changeEncoderPrecision(uint8_t slot, uint16_t precision, uint16_t currentValue, bool rollover, int step) {
229229
if (slot < MAX_ROTARY_ENCODERS && encoder[slot] != nullptr) {
230-
encoder[slot]->changePrecision(precision, currentValue, rollover);
230+
encoder[slot]->changePrecision(precision, (int)currentValue, rollover, step);
231231
}
232232
}
233233

234-
void SwitchInput::setEncoder(uint8_t slot, RotaryEncoder* encoder) {
234+
void SwitchInput::setEncoder(uint8_t slot, RotaryEncoder* enc) {
235235
if (slot < MAX_ROTARY_ENCODERS) {
236-
this->encoder[slot] = encoder;
236+
this->encoder[slot] = enc;
237237
}
238238
}
239239

@@ -276,15 +276,17 @@ RotaryEncoder::RotaryEncoder(EncoderListener* listener) : notify{} {
276276
this->notify.encoderListener = listener;
277277
this->currentReading = 0;
278278
this->maximumValue = 0;
279+
this->stepSize = 1;
279280
this->flags = 0U;
280281
bitWrite(flags, LAST_SYNC_STATUS, 1);
281282
bitWrite(flags, OO_LISTENER_CALLBACK, 1);
282283
this->intent = CHANGE_VALUE;
283284
}
284285

285-
void RotaryEncoder::changePrecision(uint16_t maxValue, int currentValue, bool rolloverOnMax) {
286+
void RotaryEncoder::changePrecision(uint16_t maxValue, int currentValue, bool rolloverOnMax, int step) {
286287
this->maximumValue = maxValue;
287288
this->currentReading = currentValue;
289+
this->stepSize = step;
288290
bitWrite(flags, WRAP_AROUND_MODE, rolloverOnMax);
289291
if(maxValue == 0U && currentValue == 0) intent = DIRECTION_ONLY;
290292
runCallback((int)currentReading);
@@ -387,22 +389,21 @@ void onSwitchesInterrupt(__attribute__((unused)) pinid_t pin) {
387389
}
388390

389391
int HardwareRotaryEncoder::amountFromChange(unsigned long change) {
390-
if(change > 250000 || maximumValue < ONE_TURN_OF_ENCODER) return 1;
392+
if(change > 250000 || maximumValue < ONE_TURN_OF_ENCODER) return stepSize;
391393

392394
if(accelerationMode == HWACCEL_NONE) {
393-
return 1;
395+
return stepSize;
394396
}
395397
else if(accelerationMode == HWACCEL_REGULAR) {
396-
if(change > 120000) return 2;
397-
else if (change > 70000) return 4;
398-
else if (change > 30000) return 6;
399-
else return 10;
398+
if(change > 120000) return stepSize + stepSize;
399+
else if (change > 70000) return stepSize << 2;
400+
else if (change > 30000) return stepSize << 3;
401+
else return stepSize << 4;
400402
}
401403
else { // slower, very slight acceleration..
402-
403-
if(change > 100000) return 2;
404-
else if (change > 30000) return 3;
405-
else return 4;
404+
if(change > 100000) return stepSize + stepSize;
405+
else if (change > 30000) return stepSize + stepSize + stepSize;
406+
else return stepSize << 2;
406407
}
407408

408409
}
@@ -452,10 +453,10 @@ EncoderUpDownButtons::EncoderUpDownButtons(pinid_t pinUp, pinid_t pinDown, Encod
452453

453454
void EncoderUpDownButtons::onPressed(pinid_t pin, bool held) {
454455
if(pin == upPin) {
455-
int8_t dir = (switches.getEncoder()->getUserIntention() == SCROLL_THROUGH_ITEMS) ? -1 : 1;
456+
int8_t dir = (switches.getEncoder()->getUserIntention() == SCROLL_THROUGH_ITEMS) ? -stepSize : stepSize;
456457
increment(dir);
457458
} else if(pin == downPin) {
458-
int8_t dir = (switches.getEncoder()->getUserIntention() == SCROLL_THROUGH_ITEMS) ? 1 : -1;
459+
int8_t dir = (switches.getEncoder()->getUserIntention() == SCROLL_THROUGH_ITEMS) ? stepSize : -stepSize;
459460
increment(dir);
460461
}
461462
}

src/SwitchInput.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ class RotaryEncoder {
184184
enum EncoderFlagBits { LAST_SYNC_STATUS=0, WRAP_AROUND_MODE, OO_LISTENER_CALLBACK };
185185
uint16_t maximumValue;
186186
uint16_t currentReading;
187+
uint8_t stepSize;
187188
union {
188189
EncoderCallbackFn callback;
189190
EncoderListener* encoderListener;
@@ -202,7 +203,7 @@ class RotaryEncoder {
202203
* @param maxValue the largest value allowed or zero for direction only mode
203204
* @param currentValue the current value (zero for direction mode)
204205
*/
205-
void changePrecision(uint16_t maxValue, int currentValue, bool rolloverOnMax = false);
206+
void changePrecision(uint16_t maxValue, int currentValue, bool rolloverOnMax = false, int step = 1);
206207

207208
/**
208209
* Change the callback that will be used to notify of changes in the encoder value, this must never be null.
@@ -480,8 +481,9 @@ class SwitchInput {
480481
* maximum value that can be represented and also the current value of the encoder.
481482
* @param precision the maximum value to be set
482483
* @param currentValue the current value to be set.
484+
* @param step the size of each step of the encoder, default is 1
483485
*/
484-
void changeEncoderPrecision(uint16_t precision, uint16_t currentValue) { changeEncoderPrecision(0, precision, currentValue); }
486+
void changeEncoderPrecision(uint16_t precision, uint16_t currentValue, int step=1) { changeEncoderPrecision(0, precision, currentValue, step); }
485487

486488
/**
487489
* Use this version of changeEncoderPrecision if you are working with more than one rotary encoder.
@@ -490,8 +492,10 @@ class SwitchInput {
490492
* @param slot the index of the desired encoder, zero based
491493
* @param precision the maximum value to be set
492494
* @param currentValue the current value to be set.
495+
* @param rollover if the encoder should wrap around at min/max values or stop
496+
* @param step the size of each step of the encoder, default is 1
493497
*/
494-
void changeEncoderPrecision(uint8_t slot, uint16_t precision, uint16_t currentValue, bool rollover = false);
498+
void changeEncoderPrecision(uint8_t slot, uint16_t precision, uint16_t currentValue, bool rollover = false, int step = 1);
495499

496500
/**
497501
* Simulates a switch press by calling the callback directly without changing the internal state

0 commit comments

Comments
 (0)