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 |
AceButtonTest.ino (58698B)
1 #line 2 "AceButtonTest.ino" 2 /* 3 MIT License 4 5 Copyright (c) 2018 Brian T. Park 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy 8 of this software and associated documentation files (the "Software"), to deal 9 in the Software without restriction, including without limitation the rights 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 copies of the Software, and to permit persons to whom the Software is 12 furnished to do so, subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in all 15 copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 SOFTWARE. 24 */ 25 26 /* 27 * Using Multiple Cpp Files: 28 * 29 * I tried to spread the tests of this .ino file into 6 .cpp files (and one 30 * .h file), matching the 6 logical sections indicated below. Unfortunately, 31 * on the AVR platform (Arduino Nano), the flash memory consumption increased 32 * from 26768 (87%) to 28630 (93%), a difference of 1862 bytes. Since an Arduino 33 * Nano has only 32720 bytes in flash, the difference of 1862 bytes (5.7%) is 34 * signficant. I'm not sure where the flash consumption is coming from. Maybe 35 * the compiler is includeing debugging information to the 6 additional .cpp 36 * file names, or maybe the compiler/linker is using 4-bytes references to 37 * various global variables instead of 2-bytes? For now, let's leave all the 38 * tests in this single .ino file. I also noticed that changing from "const int 39 * PIN = 13" to "#define PIN 13" (and the same with BUTTON_ID) in the .h header 40 * file, the #define saved 210 bytes. 41 * 42 * On the Teensy-ARM platform (Teensy LC), using 6 separate .cpp files instead 43 * of one giant .ino file caused the flash memory to *decrease* from 31408 to 44 * 31204 bytes(!). And on the ARM platform, there was no difference in flash 45 * memory size between "const int PIN = 13" and "#define PIN 13". 46 * 47 * Conclusion, this seems to be a problem with the avr-gcc compiler, or a 48 * suboptimal compiler flags set by the Arduino IDE. 49 */ 50 51 #define USE_AUNIT 1 52 53 #if USE_AUNIT == 1 54 #include <AUnit.h> 55 #else 56 #include <ArduinoUnit.h> 57 #endif 58 59 #include <AceButton.h> 60 #include <ace_button/testing/TestableButtonConfig.h> 61 #include <ace_button/testing/EventTracker.h> 62 #include <ace_button/testing/TestHelper.h> 63 64 using namespace ace_button; 65 using namespace ace_button::testing; 66 67 const uint8_t PIN = 13; 68 const uint8_t BUTTON_ID = 1; 69 70 ButtonConfig buttonConfig; 71 72 TestableButtonConfig testableConfig; 73 AceButton button(&testableConfig); 74 EventTracker eventTracker; 75 TestHelper helper(&testableConfig, &button, &eventTracker); 76 77 // The event handler takes the arguments sent with the event and stored them 78 // into the EventTracker circular buffer. 79 void handleEvent(AceButton* /* button */, uint8_t eventType, 80 uint8_t buttonState) { 81 eventTracker.addEvent(eventType, buttonState); 82 } 83 84 void setup() { 85 delay(1000); // Wait for stability on some boards, otherwise garage on Serial 86 Serial.begin(115200); // ESP8266 default 74880 not supported on Linux 87 while (!Serial); // for the Arduino Leonardo/Micro only 88 89 testableConfig.setEventHandler(handleEvent); 90 91 // The default was 50 ms (not the current 20 ms) when these tests were written 92 // and some of the timing delays are hardcoded to assume that, so we have to 93 // revert back to the old value. 94 testableConfig.setDebounceDelay(50); 95 96 Serial.print(F("sizeof(AceButton): ")); 97 Serial.println(sizeof(AceButton)); 98 Serial.print(F("sizeof(ButtonConfig): ")); 99 Serial.println(sizeof(ButtonConfig)); 100 Serial.print(F("sizeof(TestableButtonConfig): ")); 101 Serial.println(sizeof(TestableButtonConfig)); 102 103 /* 104 aunit::TestRunner::exclude("*"); 105 aunit::TestRunner::include("suppress_click_before_double_click"); 106 */ 107 } 108 109 void loop() { 110 #if USE_AUNIT == 1 111 aunit::TestRunner::run(); 112 #else 113 Test::run(); 114 #endif 115 } 116 117 // ------------------------------------------------------------------ 118 // Basic tests 119 // ------------------------------------------------------------------ 120 121 // Test that the pin is properly set and retrieved. 122 test(pin) { 123 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 124 125 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 126 assertEqual(PIN, button.getPin()); 127 } 128 129 // Test that the custom id is properly set and retrieved. 130 test(custom_id) { 131 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 132 133 // reset the button 134 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 135 assertEqual(BUTTON_ID, button.getId()); 136 } 137 138 // Test that the getLastButtonPressed() returns BUTTON_STATE_UKNOWN initially. 139 test(button_state_unknown) { 140 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 141 142 // reset the button 143 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 144 145 uint8_t expected = AceButton::kButtonStateUnknown; 146 assertEqual(expected, button.getLastButtonState()); 147 } 148 149 test(feature_flags_off_by_default) { 150 assertFalse(buttonConfig.isFeature(ButtonConfig::kFeatureClick)); 151 assertFalse(buttonConfig.isFeature(ButtonConfig::kFeatureDoubleClick)); 152 assertFalse(buttonConfig.isFeature(ButtonConfig::kFeatureLongPress)); 153 assertFalse(buttonConfig.isFeature(ButtonConfig::kFeatureRepeatPress)); 154 155 assertFalse(buttonConfig.isFeature( 156 ButtonConfig::kFeatureSuppressAfterClick)); 157 assertFalse(buttonConfig.isFeature( 158 ButtonConfig::kFeatureSuppressAfterDoubleClick)); 159 assertFalse(buttonConfig.isFeature( 160 ButtonConfig::kFeatureSuppressAfterLongPress)); 161 assertFalse(buttonConfig.isFeature( 162 ButtonConfig::kFeatureSuppressAfterRepeatPress)); 163 } 164 165 // Test that the button transitions out of the kButtonStateUnknown after 166 // getDebounceDelay() time. 167 test(init_while_released) { 168 uint8_t expected; 169 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 170 171 // reset the button 172 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 173 174 // button is released when the board is rebooted, should trigger an immediate 175 // debouncing 176 helper.releaseButton(0); 177 assertEqual(0, eventTracker.getNumEvents()); 178 expected = AceButton::kButtonStateUnknown; 179 assertEqual(expected, button.getLastButtonState()); 180 181 // button is bouncing pressed/released, but must wait to debounce 182 helper.pressButton(40); 183 assertEqual(0, eventTracker.getNumEvents()); 184 expected = AceButton::kButtonStateUnknown; 185 assertEqual(expected, button.getLastButtonState()); 186 187 // button is bouncing pressed/released, but must wait to debounce 188 helper.releaseButton(45); 189 assertEqual(0, eventTracker.getNumEvents()); 190 expected = AceButton::kButtonStateUnknown; 191 assertEqual(expected, button.getLastButtonState()); 192 193 // finally button is known to be released, this doesn't not trigger event 194 helper.releaseButton(60); 195 assertEqual(0, eventTracker.getNumEvents()); 196 assertEqual(HIGH, button.getLastButtonState()); 197 } 198 199 // Test that the button transitions out of the kButtonStateUnknown when 200 // rebooted with the button pressed. 201 test(init_while_pressed) { 202 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 203 // reset the button 204 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 205 uint8_t expected; 206 207 // button is pressed when the board is rebooted, should trigger an immediate 208 // debouncing 209 helper.pressButton(0); 210 assertEqual(0, eventTracker.getNumEvents()); 211 expected = AceButton::kButtonStateUnknown; 212 assertEqual(expected, button.getLastButtonState()); 213 214 // button is bouncing pressed/released, but must wait to debounce 215 helper.releaseButton(40); 216 assertEqual(0, eventTracker.getNumEvents()); 217 expected = AceButton::kButtonStateUnknown; 218 assertEqual(expected, button.getLastButtonState()); 219 220 // button is bouncing pressed/released, but must wait to debounce 221 helper.pressButton(45); 222 assertEqual(0, eventTracker.getNumEvents()); 223 expected = AceButton::kButtonStateUnknown; 224 assertEqual(expected, button.getLastButtonState()); 225 226 // finally button is known to be released, this doesn't not trigger event 227 helper.pressButton(60); 228 assertEqual(0, eventTracker.getNumEvents()); 229 assertEqual(LOW, button.getLastButtonState()); 230 } 231 232 // Test that the TestableButtonConfig overrides the corresponding 233 // parameters on AceButton properly. 234 test(testable_config) { 235 testableConfig.setClock(0); 236 assertEqual(0UL, button.getButtonConfig()->getClock()); 237 238 testableConfig.setClock(40); 239 assertEqual(40UL, button.getButtonConfig()->getClock()); 240 241 testableConfig.setButtonState(HIGH); 242 assertEqual(HIGH, button.getButtonConfig()->readButton(0)); 243 244 testableConfig.setButtonState(LOW); 245 assertEqual(LOW, button.getButtonConfig()->readButton(0)); 246 } 247 248 // Test that the ButtonConfig parameters are mutable, just like the 249 // original AdjustableButtonConfig. 250 test(adjustable_config) { 251 buttonConfig.setDebounceDelay(1); 252 assertEqual((uint16_t)1, buttonConfig.getDebounceDelay()); 253 254 buttonConfig.setClickDelay(2); 255 assertEqual((uint16_t)2, buttonConfig.getClickDelay()); 256 257 buttonConfig.setDoubleClickDelay(3); 258 assertEqual((uint16_t)3, buttonConfig.getDoubleClickDelay()); 259 260 buttonConfig.setLongPressDelay(4); 261 assertEqual((uint16_t)4, buttonConfig.getLongPressDelay()); 262 263 buttonConfig.setRepeatPressDelay(5); 264 assertEqual((uint16_t)5, buttonConfig.getRepeatPressDelay()); 265 266 buttonConfig.setRepeatPressInterval(6); 267 assertEqual((uint16_t)6, buttonConfig.getRepeatPressInterval()); 268 } 269 270 // Detect if a button is pressed while the device is booted. 271 test(is_released_raw) { 272 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 273 button.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 274 testableConfig.init(); 275 276 testableConfig.setButtonState(HIGH); 277 assertFalse(button.isPressedRaw()); 278 279 testableConfig.setButtonState(LOW); 280 assertTrue(button.isPressedRaw()); 281 } 282 283 // ------------------------------------------------------------------ 284 // Press and Release tests 285 // ------------------------------------------------------------------ 286 287 // We assume this will be the common case because of the Aruino boards provide 288 // internal pullup resistors on the digital input pins. 289 test(press_and_release_pullup) { 290 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 291 uint8_t expected; 292 293 // reset the button 294 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 295 296 // initial button state 297 helper.releaseButton(0); 298 assertEqual(0, eventTracker.getNumEvents()); 299 300 // must wait until the initial debouncing 301 helper.releaseButton(50); 302 assertEqual(0, eventTracker.getNumEvents()); 303 304 // button pressed, but must wait to debounce 305 helper.pressButton(100); 306 assertEqual(0, eventTracker.getNumEvents()); 307 308 // still in debouncing period, so no event yet 309 helper.releaseButton(110); 310 assertEqual(0, eventTracker.getNumEvents()); 311 312 // after more than 50 ms, we should get an event 313 helper.pressButton(190); 314 assertEqual(1, eventTracker.getNumEvents()); 315 expected = AceButton::kEventPressed; 316 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 317 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 318 319 // release the button 320 helper.releaseButton(1000); 321 assertEqual(0, eventTracker.getNumEvents()); 322 323 // wait more than 50 ms 324 helper.releaseButton(1060); 325 assertEqual(1, eventTracker.getNumEvents()); 326 expected = AceButton::kEventReleased; 327 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 328 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 329 } 330 331 // Do the same test as press_and_release_pullup, but using 332 // the logic levels of an external pulldown resistor. 333 test(press_and_release_pulldown) { 334 const uint8_t DEFAULT_RELEASED_STATE = LOW; 335 uint8_t expected; 336 337 // reset the button 338 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 339 340 // initial button state 341 helper.releaseButton(0); 342 assertEqual(0, eventTracker.getNumEvents()); 343 344 // must wait until the initial debouncing 345 helper.releaseButton(50); 346 assertEqual(0, eventTracker.getNumEvents()); 347 348 // button pressed, but must wait to debounce 349 helper.pressButton(100); 350 assertEqual(0, eventTracker.getNumEvents()); 351 352 // still in debouncing period, so no event yet 353 helper.pressButton(110); 354 assertEqual(0, eventTracker.getNumEvents()); 355 356 // after more than 50 ms, we should get an event 357 helper.pressButton(190); 358 assertEqual(1, eventTracker.getNumEvents()); 359 expected = AceButton::kEventPressed; 360 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 361 362 // release the button 363 helper.releaseButton(1000); 364 assertEqual(0, eventTracker.getNumEvents()); 365 366 // wait more than 50 ms 367 helper.releaseButton(1060); 368 assertEqual(1, eventTracker.getNumEvents()); 369 expected = AceButton::kEventReleased; 370 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 371 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 372 } 373 374 // The AceButton class uses 16-bit timer variables for memory efficiency. 375 // Verify that we can rollover those variables without affecting the logic. 376 test(clock_rollover) { 377 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 378 const unsigned long BASE_TIME = 65500; // rolls over in 36 milliseconds 379 uint8_t expected; 380 381 // reset the button 382 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 383 384 // initial button state 385 helper.releaseButton(BASE_TIME + 0); 386 assertEqual(0, eventTracker.getNumEvents()); 387 388 // initialization phase, so no event yet 389 helper.releaseButton(BASE_TIME + 60); 390 assertEqual(0, eventTracker.getNumEvents()); 391 392 // press after the initialization phase, no event, must wait for debouncing 393 helper.pressButton(BASE_TIME + 100); 394 assertEqual(0, eventTracker.getNumEvents()); 395 396 // after more than 50 ms, we should get an event 397 helper.pressButton(BASE_TIME + 190); 398 assertEqual(1, eventTracker.getNumEvents()); 399 expected = AceButton::kEventPressed; 400 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 401 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 402 403 // release the button 404 helper.releaseButton(BASE_TIME + 1000); 405 assertEqual(0, eventTracker.getNumEvents()); 406 407 // wait more than 50 ms 408 helper.releaseButton(BASE_TIME + 1060); 409 assertEqual(1, eventTracker.getNumEvents()); 410 expected = AceButton::kEventReleased; 411 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 412 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 413 } 414 415 // ------------------------------------------------------------------ 416 // Click tests 417 // ------------------------------------------------------------------ 418 419 // Test a single click. 420 test(click_without_suppression) { 421 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 422 const unsigned long BASE_TIME = 65500; 423 uint8_t expected; 424 425 // reset the button 426 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 427 testableConfig.setFeature(ButtonConfig::kFeatureClick); 428 429 // initial button state 430 helper.releaseButton(BASE_TIME + 0); 431 assertEqual(0, eventTracker.getNumEvents()); 432 433 // initilization phase 434 helper.releaseButton(BASE_TIME + 50); 435 assertEqual(0, eventTracker.getNumEvents()); 436 437 // button pressed, but must wait to debounce 438 helper.pressButton(BASE_TIME + 140); 439 assertEqual(0, eventTracker.getNumEvents()); 440 441 // after 50 ms or more, we should get an event 442 helper.pressButton(BASE_TIME + 190); 443 assertEqual(1, eventTracker.getNumEvents()); 444 expected = AceButton::kEventPressed; 445 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 446 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 447 448 // release the button within 200 ms for a click 449 helper.releaseButton(BASE_TIME + 300); 450 assertEqual(0, eventTracker.getNumEvents()); 451 452 // Wait another 50 ms to get event 453 helper.releaseButton(BASE_TIME + 350); 454 assertEqual(2, eventTracker.getNumEvents()); 455 expected = AceButton::kEventClicked; 456 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 457 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 458 expected = AceButton::kEventReleased; 459 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 460 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 461 } 462 463 // Test a single click. 464 test(click_with_suppression) { 465 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 466 const unsigned long BASE_TIME = 65500; 467 uint8_t expected; 468 469 // reset the button 470 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 471 testableConfig.setFeature(ButtonConfig::kFeatureClick); 472 testableConfig.setFeature(ButtonConfig::kFeatureSuppressAfterClick); 473 474 // initial button state 475 helper.releaseButton(BASE_TIME + 0); 476 assertEqual(0, eventTracker.getNumEvents()); 477 478 // initilization phase 479 helper.releaseButton(BASE_TIME + 50); 480 assertEqual(0, eventTracker.getNumEvents()); 481 482 // button pressed, but must wait to debounce 483 helper.pressButton(BASE_TIME + 140); 484 assertEqual(0, eventTracker.getNumEvents()); 485 486 // after 50 ms or more, we should get an event 487 helper.pressButton(BASE_TIME + 190); 488 assertEqual(1, eventTracker.getNumEvents()); 489 expected = AceButton::kEventPressed; 490 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 491 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 492 493 // release the button within 200 ms for a click 494 helper.releaseButton(BASE_TIME + 300); 495 assertEqual(0, eventTracker.getNumEvents()); 496 497 // Wait another 50 ms to get event 498 helper.releaseButton(BASE_TIME + 350); 499 assertEqual(1, eventTracker.getNumEvents()); 500 expected = AceButton::kEventClicked; 501 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 502 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 503 } 504 505 // Test that no click generated with isFeature() flag off. 506 test(no_click_without_feature_flag) { 507 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 508 const unsigned long BASE_TIME = 65500; 509 uint8_t expected; 510 511 // reset the button 512 // make sure isFeatureClick flag is cleared 513 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 514 testableConfig.clearFeature(ButtonConfig::kFeatureClick); 515 516 // initial button state 517 helper.releaseButton(BASE_TIME + 0); 518 assertEqual(0, eventTracker.getNumEvents()); 519 520 // initilization phase 521 helper.releaseButton(BASE_TIME + 50); 522 assertEqual(0, eventTracker.getNumEvents()); 523 524 // button pressed, but must wait to debounce 525 helper.pressButton(BASE_TIME + 140); 526 assertEqual(0, eventTracker.getNumEvents()); 527 528 // after 50 ms or more, we should get an event 529 helper.pressButton(BASE_TIME + 190); 530 assertEqual(1, eventTracker.getNumEvents()); 531 expected = AceButton::kEventPressed; 532 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 533 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 534 535 // release the button within 200 ms for a click 536 helper.releaseButton(BASE_TIME + 300); 537 assertEqual(0, eventTracker.getNumEvents()); 538 539 // Wait another 50 ms to get event. Only a Released event should be generated. 540 helper.releaseButton(BASE_TIME + 350); 541 assertEqual(1, eventTracker.getNumEvents()); 542 expected = AceButton::kEventReleased; 543 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 544 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 545 } 546 547 // ------------------------------------------------------------------ 548 // DoubleClick tests 549 // ------------------------------------------------------------------ 550 551 // Test a double click. Verify also that a triple-click does not generate a 552 // spurious second double click. It should generate only the following: 553 // Pressed, Clicked, Pressed, DoubleClicked, Pressed, Clicked 554 // because we have suppressed the Released events. 555 test(double_click_suppressed) { 556 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 557 const unsigned long BASE_TIME = 65500; 558 uint8_t expected; 559 560 // reset the button 561 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 562 testableConfig.setFeature(ButtonConfig::kFeatureDoubleClick); 563 testableConfig.setFeature(ButtonConfig::kFeatureSuppressAfterClick); 564 testableConfig.setFeature(ButtonConfig::kFeatureSuppressAfterDoubleClick); 565 566 // initial button state 567 helper.releaseButton(BASE_TIME + 0); 568 assertEqual(0, eventTracker.getNumEvents()); 569 570 // initilization phase 571 helper.releaseButton(BASE_TIME + 50); 572 assertEqual(0, eventTracker.getNumEvents()); 573 574 // button pressed, but must wait to debounce 575 helper.pressButton(BASE_TIME + 140); 576 assertEqual(0, eventTracker.getNumEvents()); 577 578 // generate first click 579 580 // after 50 ms or more, we should get an event 581 helper.pressButton(BASE_TIME + 190); 582 assertEqual(1, eventTracker.getNumEvents()); 583 expected = AceButton::kEventPressed; 584 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 585 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 586 587 // release the button within 200 ms for a click, but must wait for debounce 588 helper.releaseButton(BASE_TIME + 300); 589 assertEqual(0, eventTracker.getNumEvents()); 590 591 // Wait another 50 ms for debounce. 592 helper.releaseButton(BASE_TIME + 350); 593 assertEqual(1, eventTracker.getNumEvents()); 594 expected = AceButton::kEventClicked; 595 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 596 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 597 598 // generate generate second click within 400 ms of the CLICK event (which 599 // occurred at +350 ms) for a double click 600 601 // button pressed, but must wait to debounce 602 helper.pressButton(BASE_TIME + 500); 603 assertEqual(0, eventTracker.getNumEvents()); 604 605 // after 50 ms or more, we should get an event 606 helper.pressButton(BASE_TIME + 550); 607 assertEqual(1, eventTracker.getNumEvents()); 608 expected = AceButton::kEventPressed; 609 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 610 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 611 612 // release the button within 200 ms for a click, but must wait for debounce 613 helper.releaseButton(BASE_TIME + 650); 614 assertEqual(0, eventTracker.getNumEvents()); 615 616 // Wait another 50 ms for debounce. Should get a double-click. 617 helper.releaseButton(BASE_TIME + 700); 618 assertEqual(1, eventTracker.getNumEvents()); 619 expected = AceButton::kEventDoubleClicked; 620 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 621 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 622 623 // generate third click within 400 ms of the DoubleClicked event (which 624 // occurred at +700 ms) 625 626 // button pressed, but must wait to debounce 627 helper.pressButton(BASE_TIME + 900); 628 assertEqual(0, eventTracker.getNumEvents()); 629 630 // after 50 ms or more, we should get an event, 631 helper.pressButton(BASE_TIME + 950); 632 assertEqual(1, eventTracker.getNumEvents()); 633 expected = AceButton::kEventPressed; 634 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 635 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 636 637 // release the button within 200 ms for a click, but must wait for debounce 638 helper.releaseButton(BASE_TIME + 1050); 639 assertEqual(0, eventTracker.getNumEvents()); 640 641 // Wait another 50 ms for debounce. 642 // Verify that we get only 1 Clicked event not another DoubleClicked. 643 helper.releaseButton(BASE_TIME + 1100); 644 assertEqual(1, eventTracker.getNumEvents()); 645 expected = AceButton::kEventClicked; 646 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 647 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 648 } 649 650 // Test a double click without kFeatureSuppressAfterDoubleClick. 651 // Three rapid clicks should generate the following: 652 // Pressed, Released, Clicked, Pressed, Released, DoubleClicked, Pressed, 653 // Released, Clicked. 654 test(double_click_not_suppressed) { 655 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 656 const unsigned long BASE_TIME = 65500; 657 uint8_t expected; 658 659 // reset the button 660 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 661 testableConfig.setFeature(ButtonConfig::kFeatureDoubleClick); 662 663 // initial button state 664 helper.releaseButton(BASE_TIME + 0); 665 assertEqual(0, eventTracker.getNumEvents()); 666 667 // initilization phase 668 helper.releaseButton(BASE_TIME + 50); 669 assertEqual(0, eventTracker.getNumEvents()); 670 671 // generate first click 672 673 // button pressed, but must wait to debounce 674 helper.pressButton(BASE_TIME + 140); 675 assertEqual(0, eventTracker.getNumEvents()); 676 677 // after 50 ms or more, we should get an event 678 helper.pressButton(BASE_TIME + 190); 679 assertEqual(1, eventTracker.getNumEvents()); 680 expected = AceButton::kEventPressed; 681 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 682 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 683 684 // release the button within 200 ms for a click, but must wait for debounce 685 helper.releaseButton(BASE_TIME + 300); 686 assertEqual(0, eventTracker.getNumEvents()); 687 688 // Wait another 50 ms for debounce. 689 helper.releaseButton(BASE_TIME + 350); 690 assertEqual(2, eventTracker.getNumEvents()); 691 expected = AceButton::kEventClicked; 692 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 693 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 694 expected = AceButton::kEventReleased; 695 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 696 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 697 698 // generate second click within 400 ms of the Clicked event (which 699 // occurred at +350 ms) for a double click 700 701 // button pressed, but must wait to debounce 702 helper.pressButton(BASE_TIME + 500); 703 assertEqual(0, eventTracker.getNumEvents()); 704 705 // after 50 ms or more, we should get an event 706 helper.pressButton(BASE_TIME + 550); 707 assertEqual(1, eventTracker.getNumEvents()); 708 expected = AceButton::kEventPressed; 709 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 710 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 711 712 // release the button within 200 ms for a click, but must wait for debounce 713 helper.releaseButton(BASE_TIME + 650); 714 assertEqual(0, eventTracker.getNumEvents()); 715 716 // Wait another 50 ms for debounce. Should get a DoubleClicked, and a 717 // Released because we don't suppress. 718 helper.releaseButton(BASE_TIME + 700); 719 assertEqual(2, eventTracker.getNumEvents()); 720 expected = AceButton::kEventDoubleClicked; 721 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 722 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 723 expected = AceButton::kEventReleased; 724 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 725 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 726 727 // generate third click within 400 ms of the DoubleClicked event (which 728 // occurred at +700 ms) 729 730 // button pressed, but must wait to debounce 731 helper.pressButton(BASE_TIME + 900); 732 assertEqual(0, eventTracker.getNumEvents()); 733 734 // after 50 ms or more, we should get an event, 735 helper.pressButton(BASE_TIME + 950); 736 assertEqual(1, eventTracker.getNumEvents()); 737 expected = AceButton::kEventPressed; 738 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 739 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 740 741 // release the button within 200 ms for a click, but must wait for debounce 742 helper.releaseButton(BASE_TIME + 1050); 743 assertEqual(0, eventTracker.getNumEvents()); 744 745 // Wait another 50 ms for debounce. 746 // Verify that we get only 1 Clicked event not another DoubleClicked, 747 // and an unsuppressed Released. 748 helper.releaseButton(BASE_TIME + 1100); 749 assertEqual(2, eventTracker.getNumEvents()); 750 expected = AceButton::kEventClicked; 751 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 752 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 753 expected = AceButton::kEventReleased; 754 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 755 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 756 } 757 758 // Test that no double clicks generated with isFeature() flag off. 759 test(no_double_click_without_feature_flag) { 760 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 761 const unsigned long BASE_TIME = 65500; 762 uint8_t expected; 763 764 // reset the button 765 // make sure isFeatureDoubleClick flag is cleared 766 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 767 testableConfig.setFeature(ButtonConfig::kFeatureClick); 768 testableConfig.clearFeature(ButtonConfig::kFeatureDoubleClick); 769 770 // initial button state 771 helper.releaseButton(BASE_TIME + 0); 772 assertEqual(0, eventTracker.getNumEvents()); 773 774 // initilization phase 775 helper.releaseButton(BASE_TIME + 50); 776 assertEqual(0, eventTracker.getNumEvents()); 777 778 // generate first click 779 780 // button pressed, but must wait to debounce 781 helper.pressButton(BASE_TIME + 140); 782 assertEqual(0, eventTracker.getNumEvents()); 783 784 // after 50 ms or more, we should get an event 785 helper.pressButton(BASE_TIME + 190); 786 assertEqual(1, eventTracker.getNumEvents()); 787 expected = AceButton::kEventPressed; 788 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 789 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 790 791 // release the button within 200 ms for a click, but must wait for debounce 792 helper.releaseButton(BASE_TIME + 300); 793 assertEqual(0, eventTracker.getNumEvents()); 794 795 // Wait another 50 ms for debounce to get Released 796 helper.releaseButton(BASE_TIME + 350); 797 assertEqual(2, eventTracker.getNumEvents()); 798 expected = AceButton::kEventClicked; 799 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 800 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 801 expected = AceButton::kEventReleased; 802 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 803 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 804 805 // generate second click within 400 ms of the Clicked event (which 806 // occurred at +350 ms) for a double click 807 808 // button pressed, but must wait to debounce 809 helper.pressButton(BASE_TIME + 500); 810 assertEqual(0, eventTracker.getNumEvents()); 811 812 // after 50 ms or more, we should get an event 813 helper.pressButton(BASE_TIME + 550); 814 assertEqual(1, eventTracker.getNumEvents()); 815 expected = AceButton::kEventPressed; 816 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 817 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 818 819 // release the button within 200 ms for a click, but must wait for debounce 820 helper.releaseButton(BASE_TIME + 650); 821 assertEqual(0, eventTracker.getNumEvents()); 822 823 // Wait another 50 ms for debounce. Should get just another click since 824 // double-click is turned off. 825 helper.releaseButton(BASE_TIME + 700); 826 assertEqual(2, eventTracker.getNumEvents()); 827 expected = AceButton::kEventClicked; 828 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 829 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 830 expected = AceButton::kEventReleased; 831 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 832 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 833 } 834 835 // Test that an orphaned click is properly removed to prevent spurious 836 // double-click if the second click happens slightly over 65.536 seconds later. 837 test(orphaned_click_cleared) { 838 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 839 const unsigned long BASE_TIME = 65500; 840 const unsigned long ROLLOVER_TIME = 65536; 841 uint8_t expected; 842 843 // reset the button, and enable double-click 844 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 845 testableConfig.setFeature(ButtonConfig::kFeatureClick); 846 testableConfig.setFeature(ButtonConfig::kFeatureDoubleClick); 847 848 // initial button state 849 helper.releaseButton(BASE_TIME + 0); 850 assertEqual(0, eventTracker.getNumEvents()); 851 852 // initilization phase 853 helper.releaseButton(BASE_TIME + 50); 854 assertEqual(0, eventTracker.getNumEvents()); 855 856 // button pressed, but must wait to debounce 857 helper.pressButton(BASE_TIME + 140); 858 assertEqual(0, eventTracker.getNumEvents()); 859 860 // after 50 ms or more, we should get an event 861 helper.pressButton(BASE_TIME + 190); 862 assertEqual(1, eventTracker.getNumEvents()); 863 expected = AceButton::kEventPressed; 864 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 865 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 866 867 // release the button within 200 ms for a click, but must wait for debounce 868 helper.releaseButton(BASE_TIME + 300); 869 assertEqual(0, eventTracker.getNumEvents()); 870 871 // Wait another 50 ms to get event 872 helper.releaseButton(BASE_TIME + 350); 873 assertEqual(2, eventTracker.getNumEvents()); 874 expected = AceButton::kEventClicked; 875 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 876 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 877 expected = AceButton::kEventReleased; 878 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 879 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 880 881 // Move time forward, so that the orphaned click is cleared. 882 // If AceButton.checkOrphanedClick() is disabled, or this statement is removed 883 // (thereby preventing a call to checkOrphanedClick()), then the asserts below 884 // will fail. 885 helper.checkTime(BASE_TIME + 5000); 886 assertEqual(0, eventTracker.getNumEvents()); 887 888 // Generate another click between (65.535s, 65.535s + 400 ms) of the first 889 // CLICK event (i.e. +250 ms). If the first orphaned click was not properly 890 // reset, then this will genearte a double click instead of a single click. 891 892 // button pressed, but must wait to debounce 893 helper.pressButton(ROLLOVER_TIME + BASE_TIME + 400); 894 assertEqual(0, eventTracker.getNumEvents()); 895 896 // after 50 ms or more, we should get an event 897 helper.pressButton(ROLLOVER_TIME + BASE_TIME + 450); 898 assertEqual(1, eventTracker.getNumEvents()); 899 expected = AceButton::kEventPressed; 900 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 901 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 902 903 // release the button within 200 ms for a click, but must wait for debounce 904 helper.releaseButton(ROLLOVER_TIME + BASE_TIME + 550); 905 assertEqual(0, eventTracker.getNumEvents()); 906 907 // Wait another 50 ms for debounce. Should get a single click, not 908 // a double click. 909 helper.releaseButton(ROLLOVER_TIME + BASE_TIME + 600); 910 assertEqual(2, eventTracker.getNumEvents()); 911 expected = AceButton::kEventClicked; 912 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 913 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 914 expected = AceButton::kEventReleased; 915 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 916 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 917 } 918 919 // Test that an orphaned click generates a double click if not cleared. 920 test(orphaned_click_causes_double_click_if_not_cleared) { 921 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 922 const unsigned long BASE_TIME = 65500; 923 const unsigned long ROLLOVER_TIME = 65536; 924 uint8_t expected; 925 926 // reset the button, and enable double-click 927 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 928 testableConfig.setFeature(ButtonConfig::kFeatureClick); 929 testableConfig.setFeature(ButtonConfig::kFeatureDoubleClick); 930 931 // initial button state 932 helper.releaseButton(BASE_TIME + 0); 933 assertEqual(0, eventTracker.getNumEvents()); 934 935 // initilization phase 936 helper.releaseButton(BASE_TIME + 50); 937 assertEqual(0, eventTracker.getNumEvents()); 938 939 // button pressed, but must wait to debounce 940 helper.pressButton(BASE_TIME + 140); 941 assertEqual(0, eventTracker.getNumEvents()); 942 943 // after 50 ms or more, we should get an event 944 helper.pressButton(BASE_TIME + 190); 945 assertEqual(1, eventTracker.getNumEvents()); 946 expected = AceButton::kEventPressed; 947 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 948 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 949 950 // release the button within 200 ms for a click, but must wait for debounce 951 helper.releaseButton(BASE_TIME + 300); 952 assertEqual(0, eventTracker.getNumEvents()); 953 954 // Wait another 50 ms to get event 955 helper.releaseButton(BASE_TIME + 350); 956 assertEqual(2, eventTracker.getNumEvents()); 957 expected = AceButton::kEventClicked; 958 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 959 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 960 expected = AceButton::kEventReleased; 961 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 962 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 963 964 // Simulate an orphaned click not getting cleared by not calling 965 // AceButton.check() for 65536 milliseconds. 966 967 // Generate another click between (65.535s, 65.535s + 400 ms) of the first 968 // CLICK event (i.e. +250 ms). If the first orphaned click was not properly 969 // reset, then this will genearte a double click instead of a single click. 970 971 // button pressed, but must wait to debounce 972 helper.pressButton(ROLLOVER_TIME + BASE_TIME + 400); 973 assertEqual(0, eventTracker.getNumEvents()); 974 975 // after 50 ms or more, we should get an event 976 helper.pressButton(ROLLOVER_TIME + BASE_TIME + 450); 977 assertEqual(1, eventTracker.getNumEvents()); 978 expected = AceButton::kEventPressed; 979 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 980 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 981 982 // release the button within 200 ms for a click, but must wait for debounce 983 helper.releaseButton(ROLLOVER_TIME + BASE_TIME + 550); 984 assertEqual(0, eventTracker.getNumEvents()); 985 986 // Wait another 50 ms for debounce. Should get a double click because the 987 // orphaned click was not removed before the 16-bit integer overflowed . 988 helper.releaseButton(ROLLOVER_TIME + BASE_TIME + 600); 989 assertEqual(2, eventTracker.getNumEvents()); 990 expected = AceButton::kEventDoubleClicked; 991 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 992 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 993 expected = AceButton::kEventReleased; 994 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 995 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 996 } 997 998 // Test that an orphaned click is removed if Click is enabled. 999 test(orphaned_click_removed_if_click_enabled) { 1000 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 1001 const unsigned long BASE_TIME = 65500; 1002 const unsigned long ROLLOVER_TIME = 65536; 1003 uint8_t expected; 1004 1005 // reset the button, and enable double-click 1006 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 1007 testableConfig.setFeature(ButtonConfig::kFeatureClick); 1008 1009 // initial button state 1010 helper.releaseButton(BASE_TIME + 0); 1011 assertEqual(0, eventTracker.getNumEvents()); 1012 1013 // initilization phase 1014 helper.releaseButton(BASE_TIME + 50); 1015 assertEqual(0, eventTracker.getNumEvents()); 1016 1017 // button pressed, but must wait to debounce 1018 helper.pressButton(BASE_TIME + 140); 1019 assertEqual(0, eventTracker.getNumEvents()); 1020 1021 // after 50 ms or more, we should get an event 1022 helper.pressButton(BASE_TIME + 190); 1023 assertEqual(1, eventTracker.getNumEvents()); 1024 expected = AceButton::kEventPressed; 1025 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1026 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1027 1028 // release the button within 200 ms for a click, but must wait for debounce 1029 helper.releaseButton(BASE_TIME + 300); 1030 assertEqual(0, eventTracker.getNumEvents()); 1031 1032 // Wait another 50 ms to get event 1033 helper.releaseButton(BASE_TIME + 350); 1034 assertEqual(2, eventTracker.getNumEvents()); 1035 expected = AceButton::kEventClicked; 1036 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1037 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1038 expected = AceButton::kEventReleased; 1039 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 1040 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 1041 1042 // Move time forward, so that the orphaned click is cleared. 1043 // If AceButton.checkOrphanedClick() is disabled, or this statement is removed 1044 // (thereby preventing a call to checkOrphanedClick()), then the asserts below 1045 // will fail. 1046 helper.checkTime(BASE_TIME + 5000); 1047 assertEqual(0, eventTracker.getNumEvents()); 1048 1049 // Turn on DoubleClick in the middle of click processing. If we called 1050 // checkOrphanedClick() only if DoubleClick was enabled (instead of checking 1051 // it when Click is enabled as well), then this change in ButtonConfig will 1052 // cause this test to fail. 1053 testableConfig.setFeature(ButtonConfig::kFeatureDoubleClick); 1054 1055 // Generate another click between (65.535s, 65.535s + 400 ms) of the first 1056 // CLICK event (i.e. +250 ms). If the first orphaned click was not properly 1057 // reset, then this will genearte a double click instead of a single click. 1058 1059 // button pressed, but must wait to debounce 1060 helper.pressButton(ROLLOVER_TIME + BASE_TIME + 400); 1061 assertEqual(0, eventTracker.getNumEvents()); 1062 1063 // after 50 ms or more, we should get an event 1064 helper.pressButton(ROLLOVER_TIME + BASE_TIME + 450); 1065 assertEqual(1, eventTracker.getNumEvents()); 1066 expected = AceButton::kEventPressed; 1067 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1068 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1069 1070 // release the button within 200 ms for a click, but must wait for debounce 1071 helper.releaseButton(ROLLOVER_TIME + BASE_TIME + 550); 1072 assertEqual(0, eventTracker.getNumEvents()); 1073 1074 // Wait another 50 ms for debounce. Should get a single click, not 1075 // a double click. 1076 helper.releaseButton(ROLLOVER_TIME + BASE_TIME + 600); 1077 assertEqual(2, eventTracker.getNumEvents()); 1078 expected = AceButton::kEventClicked; 1079 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1080 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1081 expected = AceButton::kEventReleased; 1082 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 1083 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 1084 } 1085 1086 // Test that kFeatureSuppressClickBeforeDoubleClick causes the first Clicked to 1087 // be postponed until it can determine if a DoubleClick actually occurred. 1088 test(suppress_click_before_double_click) { 1089 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 1090 const unsigned long BASE_TIME = 65500; 1091 uint8_t expected; 1092 1093 // reset the button 1094 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 1095 testableConfig.setFeature(ButtonConfig::kFeatureDoubleClick); 1096 testableConfig.setFeature( 1097 ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); 1098 1099 // initial button state 1100 helper.releaseButton(BASE_TIME + 0); 1101 assertEqual(0, eventTracker.getNumEvents()); 1102 1103 // initilization phase 1104 helper.releaseButton(BASE_TIME + 50); 1105 assertEqual(0, eventTracker.getNumEvents()); 1106 1107 // generate first click 1108 1109 // button pressed, but must wait to debounce 1110 helper.pressButton(BASE_TIME + 140); 1111 assertEqual(0, eventTracker.getNumEvents()); 1112 1113 // after 50 ms or more, we should get an event 1114 helper.pressButton(BASE_TIME + 190); 1115 assertEqual(1, eventTracker.getNumEvents()); 1116 expected = AceButton::kEventPressed; 1117 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1118 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1119 1120 // release the button within 200 ms for a click, but must wait for debounce 1121 helper.releaseButton(BASE_TIME + 300); 1122 assertEqual(0, eventTracker.getNumEvents()); 1123 1124 // Wait another 50 ms for debounce. Check that this first Click is 1125 // postponed, so we get only the Released. 1126 helper.releaseButton(BASE_TIME + 350); 1127 assertEqual(1, eventTracker.getNumEvents()); 1128 expected = AceButton::kEventReleased; 1129 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1130 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1131 1132 // generate second click within 400 ms of the Clicked event (which 1133 // occurred at +350 ms) for a double click 1134 1135 // button pressed, but must wait to debounce 1136 helper.pressButton(BASE_TIME + 500); 1137 assertEqual(0, eventTracker.getNumEvents()); 1138 1139 // after 50 ms or more, we should get a Pressed 1140 helper.pressButton(BASE_TIME + 550); 1141 assertEqual(1, eventTracker.getNumEvents()); 1142 expected = AceButton::kEventPressed; 1143 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1144 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1145 1146 // release the button within 200 ms for a click, but must wait for debounce 1147 helper.releaseButton(BASE_TIME + 650); 1148 assertEqual(0, eventTracker.getNumEvents()); 1149 1150 // Wait another 50 ms for debounce. Should get a (DoubleClicked, Released) but 1151 // not a Clicked because we suppressed the first postponed Clicked. 1152 helper.releaseButton(BASE_TIME + 700); 1153 assertEqual(2, eventTracker.getNumEvents()); 1154 expected = AceButton::kEventDoubleClicked; 1155 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1156 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1157 expected = AceButton::kEventReleased; 1158 assertEqual(expected, eventTracker.getRecord(1).getEventType()); 1159 assertEqual(HIGH, eventTracker.getRecord(1).getButtonState()); 1160 1161 // generate third click within 400 ms of the DoubleClicked event (which 1162 // occurred at +700 ms) 1163 1164 // button pressed, but must wait to debounce 1165 helper.pressButton(BASE_TIME + 900); 1166 assertEqual(0, eventTracker.getNumEvents()); 1167 1168 // after 50 ms or more, we should get a Pressed event 1169 helper.pressButton(BASE_TIME + 950); 1170 assertEqual(1, eventTracker.getNumEvents()); 1171 expected = AceButton::kEventPressed; 1172 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1173 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1174 1175 // release the button within 200 ms for a click, but must wait for debounce 1176 helper.releaseButton(BASE_TIME + 1050); 1177 assertEqual(0, eventTracker.getNumEvents()); 1178 1179 // Wait another 50 ms for debounce. 1180 // Verify that we get only a Released event not another DoubleClicked. 1181 // The Clicked event is postponed again. 1182 helper.releaseButton(BASE_TIME + 1100); 1183 assertEqual(1, eventTracker.getNumEvents()); 1184 expected = AceButton::kEventReleased; 1185 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1186 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1187 1188 // Wait 300 ms, nothing should happen. 1189 helper.checkTime(BASE_TIME + 1400); 1190 assertEqual(0, eventTracker.getNumEvents()); 1191 1192 // Wait 400 ms to get the long postponed Clicked. 1193 helper.checkTime(BASE_TIME + 1500); 1194 assertEqual(1, eventTracker.getNumEvents()); 1195 assertEqual(+AceButton::kEventClicked, 1196 eventTracker.getRecord(0).getEventType()); 1197 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1198 } 1199 1200 // ------------------------------------------------------------------ 1201 // LongPress tests 1202 // ------------------------------------------------------------------ 1203 1204 // Test a long press without suppression should generate a released event at 1205 // the end. 1206 test(long_press_without_suppression) { 1207 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 1208 const unsigned long BASE_TIME = 65500; 1209 uint8_t expected; 1210 1211 // reset the button 1212 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 1213 testableConfig.setFeature(ButtonConfig::kFeatureLongPress); 1214 1215 // initial button state 1216 helper.releaseButton(BASE_TIME + 0); 1217 assertEqual(0, eventTracker.getNumEvents()); 1218 1219 // initilization phase 1220 helper.releaseButton(BASE_TIME + 50); 1221 assertEqual(0, eventTracker.getNumEvents()); 1222 1223 // button pressed, but must wait to debounce 1224 helper.pressButton(BASE_TIME + 140); 1225 assertEqual(0, eventTracker.getNumEvents()); 1226 1227 // after 50 ms or more, we should get an event 1228 helper.pressButton(BASE_TIME + 190); 1229 assertEqual(1, eventTracker.getNumEvents()); 1230 expected = AceButton::kEventPressed; 1231 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1232 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1233 1234 // keeping holding the button 1235 helper.pressButton(BASE_TIME + 1100); 1236 assertEqual(0, eventTracker.getNumEvents()); 1237 1238 // keeping holding the button longer than 1000 ms 1239 helper.pressButton(BASE_TIME + 1200); 1240 assertEqual(1, eventTracker.getNumEvents()); 1241 expected = AceButton::kEventLongPressed; 1242 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1243 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1244 1245 // finally release the button 1246 helper.releaseButton(BASE_TIME + 1600); 1247 assertEqual(0, eventTracker.getNumEvents()); 1248 1249 // Must wait for debouncing for the kEventReleased. 1250 helper.releaseButton(BASE_TIME + 1660); 1251 assertEqual(1, eventTracker.getNumEvents()); 1252 expected = AceButton::kEventReleased; 1253 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1254 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1255 } 1256 1257 // Test a long press with suppression should produce no released event. 1258 test(long_press_with_supression) { 1259 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 1260 const unsigned long BASE_TIME = 65500; 1261 uint8_t expected; 1262 1263 // reset the button 1264 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 1265 testableConfig.setFeature(ButtonConfig::kFeatureLongPress); 1266 testableConfig.setFeature(ButtonConfig::kFeatureSuppressAfterLongPress); 1267 1268 // initial button state 1269 helper.releaseButton(BASE_TIME + 0); 1270 assertEqual(0, eventTracker.getNumEvents()); 1271 1272 // initilization phase 1273 helper.releaseButton(BASE_TIME + 50); 1274 assertEqual(0, eventTracker.getNumEvents()); 1275 1276 // button pressed, but must wait to debounce 1277 helper.pressButton(BASE_TIME + 140); 1278 assertEqual(0, eventTracker.getNumEvents()); 1279 1280 // after 50 ms or more, we should get an event 1281 helper.pressButton(BASE_TIME + 190); 1282 assertEqual(1, eventTracker.getNumEvents()); 1283 expected = AceButton::kEventPressed; 1284 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1285 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1286 1287 // keeping holding the button 1288 helper.pressButton(BASE_TIME + 1100); 1289 assertEqual(0, eventTracker.getNumEvents()); 1290 1291 // keeping holding the button longer than 1000 ms 1292 helper.pressButton(BASE_TIME + 1200); 1293 assertEqual(1, eventTracker.getNumEvents()); 1294 expected = AceButton::kEventLongPressed; 1295 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1296 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1297 1298 // finally release the button 1299 helper.releaseButton(BASE_TIME + 1600); 1300 assertEqual(0, eventTracker.getNumEvents()); 1301 1302 // Must wait for debouncing. We elected kFeatureSuppressAfterLongPress so 1303 // no kEventReleased is generated. 1304 helper.releaseButton(BASE_TIME + 1660); 1305 assertEqual(0, eventTracker.getNumEvents()); 1306 } 1307 1308 // Test that no LongPress generated with isFeature() flag off. 1309 test(no_long_press_without_feature_flag) { 1310 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 1311 const unsigned long BASE_TIME = 65500; 1312 uint8_t expected; 1313 1314 // reset the button 1315 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 1316 testableConfig.clearFeature(ButtonConfig::kFeatureLongPress); 1317 1318 // initial button state 1319 helper.releaseButton(BASE_TIME + 0); 1320 assertEqual(0, eventTracker.getNumEvents()); 1321 1322 // initilization phase 1323 helper.releaseButton(BASE_TIME + 50); 1324 assertEqual(0, eventTracker.getNumEvents()); 1325 1326 // button pressed, but must wait to debounce 1327 helper.pressButton(BASE_TIME + 140); 1328 assertEqual(0, eventTracker.getNumEvents()); 1329 1330 // after 50 ms or more, we should get an event 1331 helper.pressButton(BASE_TIME + 190); 1332 assertEqual(1, eventTracker.getNumEvents()); 1333 expected = AceButton::kEventPressed; 1334 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1335 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1336 1337 // keeping holding the button 1338 helper.pressButton(BASE_TIME + 1100); 1339 assertEqual(0, eventTracker.getNumEvents()); 1340 1341 // keeping holding the button longer than 1000 ms 1342 helper.pressButton(BASE_TIME + 1200); 1343 assertEqual(0, eventTracker.getNumEvents()); 1344 1345 // finally release the button 1346 helper.releaseButton(BASE_TIME + 1600); 1347 assertEqual(0, eventTracker.getNumEvents()); 1348 1349 // Must wait for debouncing. Only a Released event should be generated. 1350 helper.releaseButton(BASE_TIME + 1660); 1351 assertEqual(1, eventTracker.getNumEvents()); 1352 expected = AceButton::kEventReleased; 1353 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1354 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1355 } 1356 1357 // ------------------------------------------------------------------ 1358 // RepeatPress tests 1359 // ------------------------------------------------------------------ 1360 1361 // Test repeated press 1362 test(repeat_press_without_suppression) { 1363 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 1364 const unsigned long BASE_TIME = 65500; 1365 uint8_t expected; 1366 1367 // reset the button 1368 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 1369 testableConfig.setFeature(ButtonConfig::kFeatureRepeatPress); 1370 1371 // initial button state 1372 helper.releaseButton(BASE_TIME + 0); 1373 assertEqual(0, eventTracker.getNumEvents()); 1374 1375 // initilization phase 1376 helper.releaseButton(BASE_TIME + 50); 1377 assertEqual(0, eventTracker.getNumEvents()); 1378 1379 // button pressed, but must wait to debounce 1380 helper.pressButton(BASE_TIME + 140); 1381 assertEqual(0, eventTracker.getNumEvents()); 1382 1383 // after 50 ms or more, we should get an event 1384 helper.pressButton(BASE_TIME + 190); 1385 assertEqual(1, eventTracker.getNumEvents()); 1386 expected = AceButton::kEventPressed; 1387 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1388 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1389 1390 // keeping holding the button 1391 helper.pressButton(BASE_TIME + 1100); 1392 assertEqual(0, eventTracker.getNumEvents()); 1393 1394 // keeping holding the button longer than 1000 ms, the kEventRepeatPressed 1395 // should trigger immediately after this duration 1396 helper.pressButton(BASE_TIME + 1200); 1397 assertEqual(1, eventTracker.getNumEvents()); 1398 expected = AceButton::kEventRepeatPressed; 1399 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1400 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1401 1402 // keeping holding the button for longer than repeat interval (200ms) 1403 helper.pressButton(BASE_TIME + 1400); 1404 assertEqual(1, eventTracker.getNumEvents()); 1405 expected = AceButton::kEventRepeatPressed; 1406 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1407 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1408 1409 // finally release the button 1410 helper.releaseButton(BASE_TIME + 1700); 1411 assertEqual(0, eventTracker.getNumEvents()); 1412 1413 // Must wait for debouncing for the kEventReleased. 1414 helper.releaseButton(BASE_TIME + 1760); 1415 assertEqual(1, eventTracker.getNumEvents()); 1416 expected = AceButton::kEventReleased; 1417 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1418 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1419 } 1420 1421 // Test repeated press 1422 test(repeat_press_with_suppression) { 1423 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 1424 const unsigned long BASE_TIME = 65500; 1425 uint8_t expected; 1426 1427 // reset the button 1428 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 1429 testableConfig.setFeature(ButtonConfig::kFeatureRepeatPress); 1430 testableConfig.setFeature(ButtonConfig::kFeatureSuppressAfterRepeatPress); 1431 1432 // initial button state 1433 helper.releaseButton(BASE_TIME + 0); 1434 assertEqual(0, eventTracker.getNumEvents()); 1435 1436 // initilization phase 1437 helper.releaseButton(BASE_TIME + 50); 1438 assertEqual(0, eventTracker.getNumEvents()); 1439 1440 // button pressed, but must wait to debounce 1441 helper.pressButton(BASE_TIME + 140); 1442 assertEqual(0, eventTracker.getNumEvents()); 1443 1444 // after 50 ms or more, we should get an event 1445 helper.pressButton(BASE_TIME + 190); 1446 assertEqual(1, eventTracker.getNumEvents()); 1447 expected = AceButton::kEventPressed; 1448 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1449 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1450 1451 // keeping holding the button 1452 helper.pressButton(BASE_TIME + 1100); 1453 assertEqual(0, eventTracker.getNumEvents()); 1454 1455 // keeping holding the button longer than 1000 ms, the kEventRepeatPressed 1456 // should trigger immediately after this duration 1457 helper.pressButton(BASE_TIME + 1200); 1458 assertEqual(1, eventTracker.getNumEvents()); 1459 expected = AceButton::kEventRepeatPressed; 1460 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1461 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1462 1463 // keeping holding the button for longer than repeat interval (200ms) 1464 helper.pressButton(BASE_TIME + 1400); 1465 assertEqual(1, eventTracker.getNumEvents()); 1466 expected = AceButton::kEventRepeatPressed; 1467 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1468 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1469 1470 // finally release the button 1471 helper.releaseButton(BASE_TIME + 1700); 1472 assertEqual(0, eventTracker.getNumEvents()); 1473 1474 // Must wait for debouncing for the kEventReleased. 1475 // But there is no Released event because of suppression. 1476 helper.releaseButton(BASE_TIME + 1760); 1477 assertEqual(0, eventTracker.getNumEvents()); 1478 } 1479 1480 // Test that no RepeatPress generated with isFeature() flag off. 1481 test(no_repeat_press_without_feature_flag) { 1482 const uint8_t DEFAULT_RELEASED_STATE = HIGH; 1483 const unsigned long BASE_TIME = 65500; 1484 uint8_t expected; 1485 1486 // reset the button 1487 helper.init(PIN, DEFAULT_RELEASED_STATE, BUTTON_ID); 1488 testableConfig.clearFeature(ButtonConfig::kFeatureRepeatPress); 1489 1490 // initial button state 1491 helper.releaseButton(BASE_TIME + 0); 1492 assertEqual(0, eventTracker.getNumEvents()); 1493 1494 // initilization phase 1495 helper.releaseButton(BASE_TIME + 50); 1496 assertEqual(0, eventTracker.getNumEvents()); 1497 1498 // button pressed, but must wait to debounce 1499 helper.pressButton(BASE_TIME + 140); 1500 assertEqual(0, eventTracker.getNumEvents()); 1501 1502 // after 50 ms or more, we should get an event 1503 helper.pressButton(BASE_TIME + 190); 1504 assertEqual(1, eventTracker.getNumEvents()); 1505 expected = AceButton::kEventPressed; 1506 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1507 assertEqual(LOW, eventTracker.getRecord(0).getButtonState()); 1508 1509 // keeping holding the button 1510 helper.pressButton(BASE_TIME + 1100); 1511 assertEqual(0, eventTracker.getNumEvents()); 1512 1513 // keeping holding the button longer than 1000 ms, nothing should 1514 // should trigger 1515 helper.pressButton(BASE_TIME + 1200); 1516 assertEqual(0, eventTracker.getNumEvents()); 1517 1518 // keeping holding the button for longer than repeat interval (200ms) 1519 helper.pressButton(BASE_TIME + 1400); 1520 assertEqual(0, eventTracker.getNumEvents()); 1521 1522 // finally release the button 1523 helper.releaseButton(BASE_TIME + 1700); 1524 assertEqual(0, eventTracker.getNumEvents()); 1525 1526 // Must wait for debouncing. Only a Released event should be generated. 1527 helper.releaseButton(BASE_TIME + 1760); 1528 assertEqual(1, eventTracker.getNumEvents()); 1529 expected = AceButton::kEventReleased; 1530 assertEqual(expected, eventTracker.getRecord(0).getEventType()); 1531 assertEqual(HIGH, eventTracker.getRecord(0).getButtonState()); 1532 }