1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
#include <ee108_switches.h>
typedef struct SwitchInfo {
int switchPin;
int prevSwitchValue; // raw switch value the last time the switch was checked
int debouncedSwitchValue;
unsigned int switchChangeTimeMs; // last time switch value changed or 0 if not yet set
unsigned int prevDebouncedPressTimeMs;
unsigned int prevDebouncedReleaseTimeMs;
} SwitchInfo;
unsigned int debounceMs = 20;
unsigned int longClickMs = 1000;
unsigned int veryLongClickMs = 2000;
static SwitchInfo sw1Info = { SW1, 1, 1, 0, 0, 0 };
SwitchPtr sw1 = &sw1Info; // point at information for switch1
static SwitchInfo sw2Info = { SW2, 1, 1, 0, 0, 0 };
SwitchPtr sw2 = &sw2Info; // point at information for switch1
void setSwitchDebounce(unsigned int debounceMs_) {
debounceMs = debounceMs_;
}
void setSwitchClickDurations(unsigned int longClickMs_, unsigned int veryLongClickMs_) {
longClickMs = longClickMs_;
veryLongClickMs = veryLongClickMs_;
}
/**
* debounces the specified switch (updating the switch info by side effect)
*
* NOTE: this function does *not* change any debounced time values. This is
* to allow the caller to calculate click durations etc.
*
* @param sw a SwitchPtr referring to valid switch state information
* @param timeNowMs the time at which this read is occurring
* @returns true if the debounced value has changed, false otherwise
*/
static boolean debounce(SwitchPtr sw, unsigned int timeNowMs) {
int currentSwitchValue = digitalRead(sw->switchPin);
boolean changed = false;
if (currentSwitchValue != sw->prevSwitchValue) { // has raw switch value changed?
sw->switchChangeTimeMs = timeNowMs;
sw->prevSwitchValue = currentSwitchValue;
} else { // no - raw switch value is unchanged
// is raw switch value different to debounced value, and if so
// has the raw switch value been stable for long enough to be stable/debounced?
if (currentSwitchValue != sw->debouncedSwitchValue) {
if ((timeNowMs - sw->switchChangeTimeMs) > debounceMs) {
sw->debouncedSwitchValue = currentSwitchValue;
changed = true; // debounced value has changed
}
}
}
return changed;
}
/**
* read the current switch event and optionally output times also
*/
int readSwitchEventTimes(SwitchPtr sw,
unsigned int *pClickDurationMs,
unsigned int *pTimeSincePrevClickMs) {
boolean debouncedValueChanged;
int switchEvent;
unsigned int timeNowMs;
timeNowMs = (unsigned int) millis();
debouncedValueChanged = debounce(sw, timeNowMs);
// if (timeNowMs == TIME_NOT_SET) // ensure we don't use the not set value
// timeNowMs -= 1;
if (sw->debouncedSwitchValue == SW_ACTIVE) { // is debounced switch pressed?
// if it has just changed, then we've just pressed, otherwise the switch is
// being held down
if (debouncedValueChanged) {
switchEvent = SW_PRESS;
sw->prevDebouncedPressTimeMs = timeNowMs;
} else
switchEvent = SW_KEEP_PRESSED;
} else { // no, switch is not currently being pressed
if (debouncedValueChanged) { // just released?
switchEvent = SW_RELEASE_CLICK;
if (pClickDurationMs)
*pClickDurationMs = timeNowMs - sw->prevDebouncedPressTimeMs;
if (pTimeSincePrevClickMs) {
*pTimeSincePrevClickMs = timeNowMs - sw->prevDebouncedReleaseTimeMs;
}
sw->prevDebouncedReleaseTimeMs = timeNowMs;
} else { // not-pressed for a while
switchEvent = SW_OFF;
}
}
return switchEvent;
}
int readSwitchEvent(SwitchPtr sw) {
unsigned int clickDurationMs = 0;
int ret = readSwitchEventTimes(sw, &clickDurationMs, NULL);
if (ret == SW_RELEASE_CLICK) {
if (clickDurationMs >= longClickMs) {
if (clickDurationMs >= veryLongClickMs)
ret = SW_VERY_LONG_CLICK;
else
ret = SW_LONG_CLICK;
}
}
return ret;
}
|