Rotary-Dial/RotaryDialer.cpp

101 lines
2.1 KiB
C++

#include "RotaryDialer.h"
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define NO_NUMBER -1
// Require DEBOUNCE_DELAY milliseconds between state changes. This value is
// noted in the class documentation.
#define DEBOUNCE_DELAY 15
RotaryDialer::RotaryDialer(int readyPin, int pulsePin) :
pinReady(readyPin), pinPulse(pulsePin), hasCompletedNumber(false),
state(WAITING)
{ }
void RotaryDialer::setup() {
pinMode(pinReady, INPUT);
pinMode(pinPulse, INPUT);
digitalWrite(pinReady, HIGH);
digitalWrite(pinPulse, HIGH);
lastStateChangeMillis = millis();
}
bool RotaryDialer::changeStateIfDebounced(enum State newState) {
unsigned long currentMillis = millis();
if (currentMillis < lastStateChangeMillis) {
// clock wrapped; ignore (but could figure it out in this case)
lastStateChangeMillis = currentMillis;
return false;
} else if (currentMillis - lastStateChangeMillis > DEBOUNCE_DELAY) {
state = newState;
lastStateChangeMillis = currentMillis;
return true;
} else {
return false;
}
}
void RotaryDialer::completeDial() {
if (!changeStateIfDebounced(WAITING)) {
return;
}
if (number > 0 && number <= 10) {
if (number == 10) {
number = 0;
}
hasCompletedNumber = true;
}
}
bool RotaryDialer::update() {
int readyStatus = digitalRead(pinReady);
int pulseStatus = digitalRead(pinPulse);
switch(state) {
case WAITING:
if (readyStatus == LOW
&& changeStateIfDebounced(LISTENING_NOPULSE))
{
hasCompletedNumber = false;
number = 0;
}
break;
case LISTENING_NOPULSE:
if (readyStatus == HIGH) {
completeDial();
} else if (pulseStatus == HIGH) {
changeStateIfDebounced(LISTENING_PULSE);
}
break;
case LISTENING_PULSE:
if (readyStatus == HIGH) {
completeDial();
} else if (pulseStatus == LOW
&& changeStateIfDebounced(LISTENING_NOPULSE))
{
number++;
}
break;
}
return hasCompletedNumber;
}
bool RotaryDialer::hasNextNumber() {
return hasCompletedNumber;
}
int RotaryDialer::getNextNumber() {
if (hasCompletedNumber) {
hasCompletedNumber = false;
return number;
} else {
return NO_NUMBER;
}
}