acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
ButtonConfig.h (13303B)
1 /* 2 MIT License 3 4 Copyright (c) 2018 Brian T. Park 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in all 14 copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 SOFTWARE. 23 */ 24 25 #ifndef ACE_BUTTON_BUTTON_CONFIG_H 26 #define ACE_BUTTON_BUTTON_CONFIG_H 27 28 #if !defined(RASPBERRY_PI) 29 #include <Arduino.h> 30 #else 31 #include <raspi/raspi.h> 32 #endif /* RASPBERRY_PI */ 33 34 // TODO: Verify if this is actually needed. The program size seems to be 35 // identical with or without it on the Arduino IDE (which uses gcc). 36 #define ACE_BUTTON_INLINE __attribute__((always_inline)) 37 38 namespace ace_button { 39 40 class AceButton; 41 class TimingStats; 42 43 /** 44 * Class that defines the timing parameters and event handler of an AceButton or 45 * a group of AceButton instances. It is assumed that in many cases, a group of 46 * multiple buttons will need to be assigned the same configuration parameters. 47 * For example, various timing delays and the EventHandler. Instead of storing 48 * these parameters in each instance of AceButton (which consumes static 49 * memory), we save space by collecting them into a separate ButtonConfig class. 50 * Each AceButton instance contains a pointer to an instance of ButtonConfig, 51 * and an instance of ButtonConfig will be shared among multiple AceButtons. 52 * 53 * Various timing parameters are given default values. They can be 54 * overridden by the user. 55 * 56 * A single default "System" ButtonConfig instance is created automatically and 57 * can be accessed using the ButtConfig::getSystemButtonConfig() static method. 58 * For convenience and ease of use, every instance of AceButton is attached to 59 * this "System" ButtonConfig by default. The client code can override this 60 * association by attaching another ButtonConfig instance using the 61 * AceButton(ButtonConfig*) constuctor (the recommended solution) or the 62 * AceButton::setButtonConfig() method. 63 */ 64 class ButtonConfig { 65 public: 66 // Various timing constants, in milliseconds. 67 // 68 // Note that the timing constants are stored as uint16_t (2 69 // bytes) instead of unsigned long (4 bytes) which is the type returned by 70 // the millis() system method. It turns out that we can store and perform 71 // all timing calculations using uint16_t without ill effect, as long as the 72 // polling of AceButton::check() happens more frequently than the rollover 73 // time of a uint16_t (i.e. 65.536 seconds) and certain precautions (e.g. 74 // AceButton::checkOrphanedClick()) are taken before a uint16_t rollover 75 // happens. In theory, these additional precautions would be needed even if 76 // an 'unsigned long' is used but almost no one does them because they 77 // assume that their code won't be running continuously for the rollover 78 // time of an 'unsigned long' (i.e. 49.7 days). 79 80 /** Default value returned by getDebounceDelay(). */ 81 static const uint16_t kDebounceDelay = 20; 82 83 /** Default value returned by getClickDelay(). */ 84 static const uint16_t kClickDelay = 200; 85 86 /** Default value returned by getDoubleClickDelay(). */ 87 static const uint16_t kDoubleClickDelay = 400; 88 89 /** Default value returned by getLongPressDelay(). */ 90 static const uint16_t kLongPressDelay = 1000; 91 92 /** Default value returned by getRepeatPressDelay(). */ 93 static const uint16_t kRepeatPressDelay = 1000; 94 95 /** Default value returned by getRepeatPressInterval(). */ 96 static const uint16_t kRepeatPressInterval = 200; 97 98 // Various features controlled by feature flags. 99 100 /** 101 * Type of the feature flag. It used to be a uint8_t but got changed to a 102 * uint16_t when more than 8 flags were needed. Let's define a typedef to 103 * make it easier to change this in the future. 104 */ 105 typedef uint16_t FeatureFlagType; 106 107 /** Flag to activate the AceButton::kEventClicked event. */ 108 static const FeatureFlagType kFeatureClick = 0x01; 109 110 /** 111 * Flag to activate the AceButton::kEventDoubleClicked event. 112 * Activating this automatically activates kEventClicked since there is 113 * no double-click without a click. 114 */ 115 static const FeatureFlagType kFeatureDoubleClick = 0x02; 116 117 /** Flag to activate the AceButton::kEventLongPress event. */ 118 static const FeatureFlagType kFeatureLongPress = 0x04; 119 120 /** Flag to activate the AceButton::kEventRepeatPressed event. */ 121 static const FeatureFlagType kFeatureRepeatPress = 0x08; 122 123 /** Flag to suppress kEventReleased after a kEventClicked. */ 124 static const FeatureFlagType kFeatureSuppressAfterClick = 0x10; 125 126 /** 127 * Flag to suppress kEventReleased after a kEventDoubleClicked. A 128 * kEventClicked is _always_ suppressed after a kEventDoubleClicked to 129 * prevent generating 2 double-clicks if the user performed a triple-click. 130 */ 131 static const FeatureFlagType kFeatureSuppressAfterDoubleClick = 0x20; 132 133 /** Flag to suppress kEventReleased after a kEventLongPressed. */ 134 static const FeatureFlagType kFeatureSuppressAfterLongPress = 0x40; 135 136 /** Flag to suppress kEventReleased after a kEventRepeatPressed. */ 137 static const FeatureFlagType kFeatureSuppressAfterRepeatPress = 0x80; 138 139 /** 140 * Flag to suppress kEventClicked before a kEventDoubleClicked. This causes 141 * the notification of a kEventClicked to be delayed until the delay time of 142 * getDoubleClickDelay() has passed so that we can determine if there was a 143 * kEventDoubleClicked. 144 */ 145 static const FeatureFlagType kFeatureSuppressClickBeforeDoubleClick = 0x100; 146 147 /** 148 * Convenience flag to suppress all suppressions. Calling 149 * setFeature(kFeatureSuppressAll) suppresses all and 150 * clearFeature(kFeatureSuppressAll) clears all suppression. Note however 151 * that isFeature(kFeatureSuppressAll) currently means "is ANY feature 152 * enabled?" not "are ALL features enabled?". 153 */ 154 static const FeatureFlagType kFeatureSuppressAll = 155 (kFeatureSuppressAfterClick | 156 kFeatureSuppressAfterDoubleClick | 157 kFeatureSuppressAfterLongPress | 158 kFeatureSuppressAfterRepeatPress | 159 kFeatureSuppressClickBeforeDoubleClick); 160 161 /** 162 * The event handler signature. 163 * 164 * @param button pointer to the AceButton that generated the event 165 * @param eventType the event type which trigger the call 166 * @param buttonState the state of the button that triggered the event 167 */ 168 typedef void (*EventHandler)(AceButton* button, uint8_t eventType, 169 uint8_t buttonState); 170 171 /** Constructor. */ 172 ButtonConfig() {} 173 174 // These configuration methods are virtual so that they can be overriddden. 175 // Subclasses can override at the class-level by defining a new virtual 176 // function in the subclass, or by defining an instance variable and storing 177 // the parameter with each instance of this class. 178 179 /** Milliseconds to wait for debouncing. */ 180 uint16_t getDebounceDelay() { return mDebounceDelay; } 181 182 /** Milliseconds to wait for a possible click. */ 183 uint16_t getClickDelay() { return mClickDelay; } 184 185 /** 186 * Milliseconds between the first and second click to register as a 187 * double-click. 188 */ 189 uint16_t getDoubleClickDelay() { 190 return mDoubleClickDelay; 191 } 192 193 /** Milliseconds for a long press event. */ 194 uint16_t getLongPressDelay() { 195 return mLongPressDelay; 196 } 197 198 /** 199 * Milliseconds that a button needs to be Pressed down before the start of 200 * the sequence of RepeatPressed events. The first event will fire as soon 201 * as this delay has passed. Subsequent events will fire after 202 * getRepeatPressInterval() time. 203 */ 204 uint16_t getRepeatPressDelay() { 205 return mRepeatPressDelay; 206 } 207 208 /** 209 * Milliseconds between two successive RepeatPressed events. 210 */ 211 uint16_t getRepeatPressInterval() { 212 return mRepeatPressInterval; 213 } 214 215 /** Set the debounceDelay. */ 216 void setDebounceDelay(uint16_t debounceDelay) { 217 mDebounceDelay = debounceDelay; 218 } 219 220 /** Set the clickDelay. */ 221 void setClickDelay(uint16_t clickDelay) { 222 mClickDelay = clickDelay; 223 } 224 225 /** Set the doubleClickDelay. */ 226 void setDoubleClickDelay(uint16_t doubleClickDelay) { 227 mDoubleClickDelay = doubleClickDelay; 228 } 229 230 /** Set the longPressDelay. */ 231 void setLongPressDelay(uint16_t longPressDelay) { 232 mLongPressDelay = longPressDelay; 233 } 234 235 /** Set the repeatPressDelay. */ 236 void setRepeatPressDelay(uint16_t repeatPressDelay) { 237 mRepeatPressDelay = repeatPressDelay; 238 } 239 240 /** Set the repeatPressInterval. */ 241 void setRepeatPressInterval(uint16_t repeatPressInterval) { 242 mRepeatPressInterval = repeatPressInterval; 243 } 244 245 // The getClock() and readButton() are external dependencies that normally 246 // would be injected using separate classes, but in the interest of saving 247 // RAM in an embedded environment, we expose them in this class instead. 248 249 /** 250 * Return the milliseconds of the internal clock. Override to use something 251 * other than millis(). The return type is 'unsigned long' instead of 252 * uint16_t because that's the return type of millis(). 253 */ 254 virtual unsigned long getClock() { return millis(); } 255 256 /** 257 * Return the microseconds of the internal clock. Can be overridden 258 * for testing purposes. 259 */ 260 virtual unsigned long getClockMicros() { return micros(); } 261 262 /** 263 * Return the HIGH or LOW state of the button. Override to use something 264 * other than digitalRead(). The return type is 'int' instead of uint16_t 265 * because that's the return type of digitalRead(). 266 */ 267 virtual int readButton(uint8_t pin) { 268 return digitalRead(pin); 269 } 270 271 // These methods return the various feature flags that control the 272 // functionality of the AceButton. 273 274 /** Check if the given features are enabled. */ 275 bool isFeature(FeatureFlagType features) ACE_BUTTON_INLINE { 276 return mFeatureFlags & features; 277 } 278 279 /** Enable the given features. */ 280 void setFeature(FeatureFlagType features) ACE_BUTTON_INLINE { 281 mFeatureFlags |= features; 282 } 283 284 /** Disable the given features. */ 285 void clearFeature(FeatureFlagType features) ACE_BUTTON_INLINE { 286 mFeatureFlags &= ~features; 287 } 288 289 // EventHandler 290 291 /** Return the eventHandler. */ 292 EventHandler getEventHandler() ACE_BUTTON_INLINE { 293 return mEventHandler; 294 } 295 296 /** 297 * Install the event handler. The event handler must be defined for the 298 * AceButton to be useful. 299 */ 300 void setEventHandler(EventHandler eventHandler) ACE_BUTTON_INLINE { 301 mEventHandler = eventHandler; 302 } 303 304 // TimingStats 305 306 /** Set the timing stats object. The timingStats can be nullptr. */ 307 void setTimingStats(TimingStats* timingStats) { 308 mTimingStats = timingStats; 309 } 310 311 /** Get the timing stats. Can return nullptr. */ 312 TimingStats* getTimingStats() { return mTimingStats; } 313 314 /** 315 * Return a pointer to the singleton instance of the ButtonConfig 316 * which is attached to all AceButton instances by default. 317 */ 318 static ButtonConfig* getSystemButtonConfig() ACE_BUTTON_INLINE { 319 return &sSystemButtonConfig; 320 } 321 322 protected: 323 /** 324 * Initialize to its pristine state, except for the EventHandler which is 325 * unchanged. This is intended mostly for testing purposes. 326 */ 327 virtual void init() { 328 mFeatureFlags = 0; 329 mTimingStats = nullptr; 330 } 331 332 private: 333 /** 334 * A single static instance of ButtonConfig provided by default to all 335 * AceButton instances. 336 */ 337 static ButtonConfig sSystemButtonConfig; 338 339 // Disable copy-constructor and assignment operator 340 ButtonConfig(const ButtonConfig&) = delete; 341 ButtonConfig& operator=(const ButtonConfig&) = delete; 342 343 /** The event handler for all buttons associated with this ButtonConfig. */ 344 EventHandler mEventHandler = nullptr; 345 346 /** A bit mask flag that activates certain features. */ 347 FeatureFlagType mFeatureFlags = 0; 348 349 /** The timing stats object. */ 350 TimingStats* mTimingStats = nullptr; 351 352 uint16_t mDebounceDelay = kDebounceDelay; 353 uint16_t mClickDelay = kClickDelay; 354 uint16_t mDoubleClickDelay = kDoubleClickDelay; 355 uint16_t mLongPressDelay = kLongPressDelay; 356 uint16_t mRepeatPressDelay = kRepeatPressDelay; 357 uint16_t mRepeatPressInterval = kRepeatPressInterval; 358 }; 359 360 } 361 #endif