mirror of
https://github.com/osiweb/unified_retro_keyboard.git
synced 2024-11-27 23:49:42 +00:00
449 lines
13 KiB
C
449 lines
13 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdint.h>
|
||
|
#include "unity.h"
|
||
|
#include "asdf_repeat.h"
|
||
|
|
||
|
#define REPEAT_TIMED_OUT 10000
|
||
|
#define NUM_REPETITIONS 10
|
||
|
|
||
|
uint32_t count_repeat_ticks(uint32_t timeout)
|
||
|
{
|
||
|
uint32_t count = 0;
|
||
|
uint32_t test;
|
||
|
|
||
|
do {
|
||
|
test = asdf_repeat();
|
||
|
count++;
|
||
|
} while (!test && count < timeout);
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
|
||
|
void setUp(void)
|
||
|
{
|
||
|
asdf_repeat_init();
|
||
|
}
|
||
|
void tearDown(void) {}
|
||
|
|
||
|
|
||
|
// On initialization, autorepeat should be enabled by default.
|
||
|
void test_asdf_repeat_init_resets_to_autorepeat_default(void)
|
||
|
{
|
||
|
|
||
|
uint32_t delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// If autorepeat is turned off, then holding down a simulated key should not
|
||
|
// cause a repeat event.
|
||
|
void test_asdf_repeat_no_repeat_if_auto_turned_off(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
asdf_repeat_auto_off();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
|
||
|
}
|
||
|
|
||
|
// If autorepeat is turned on, then holding down a simulated key should cause a
|
||
|
// repeat event after the autorepeat interval.
|
||
|
void test_asdf_repeat_autorepeat_if_auto_turned_on(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
asdf_repeat_auto_off();
|
||
|
asdf_repeat_auto_on();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// After the autorepeat interval, subsequent repeat events should occur at the
|
||
|
// regular repeat interval.
|
||
|
void test_asf_repeat_autorepeat_fast_repeat_after_delay(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
// wait out the autorepeat delay
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
|
||
|
|
||
|
// now verify the next repeat interval is short:
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
|
||
|
// If autorepeat is turned on, then holding down a key should cause a repeat
|
||
|
// event at the autorepeat interval. This should be true if autorepeat was
|
||
|
// previously off, or if it was already on, so test both cases here.
|
||
|
void test_asdf_repeat_auto_repeat_if_auto_turned_on(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
asdf_repeat_auto_on();
|
||
|
asdf_repeat_auto_on();
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
|
||
|
asdf_repeat_auto_off();
|
||
|
asdf_repeat_auto_on();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// When in autorepeat mode, calling asdf_repeat_reset_count() should reset the
|
||
|
// repeat timer to the autorepeat interval.
|
||
|
void test_asdf_repeat_reset_count_works_in_autorepeat_mode(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
// wait 1/2 of autorepeat time and release a key
|
||
|
delay = count_repeat_ticks(ASDF_AUTOREPEAT_TIME_MS / 2);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT((ASDF_AUTOREPEAT_TIME_MS / 2), delay);
|
||
|
|
||
|
asdf_repeat_reset_count();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// When in repeat mode (repeat key held down), calling asdf_repeat_reset_count()
|
||
|
// should reset the repeat timer to the repeat interval.
|
||
|
void test_asdf_repeat_reset_count_works_in_repeat_mode(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
// wait 1/2 of autorepeat time and release a key
|
||
|
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
delay = count_repeat_ticks(ASDF_REPEAT_TIME_MS / 2);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT((ASDF_REPEAT_TIME_MS / 2), delay);
|
||
|
|
||
|
asdf_repeat_reset_count();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
|
||
|
// When Autoreat is enabled, activating repeat mode (pressing the repeat key)
|
||
|
// should cause repeat events to occur at the fast repeat rate, skipping the
|
||
|
// autorepeat interval.
|
||
|
void test_asdf_repeat_activate_with_auto_on(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
asdf_repeat_auto_on();
|
||
|
|
||
|
asdf_repeat_activate();
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// When Autoreat is off, activating repeat mode (pressing the repeat key)
|
||
|
// should cause repeat events to occur at the fast repeat rate
|
||
|
void test_asdf_repeat_activate_with_auto_off(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
asdf_repeat_auto_off();
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// If autorepeat is disabled, then activating and deactivating repeat mode
|
||
|
// (pressing and releasing the repeat key) should return to the autorepeat
|
||
|
// disabled mode.
|
||
|
void test_asdf_repeat_deactivate_returns_to_baseline_no_repeat(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
asdf_repeat_auto_off();
|
||
|
|
||
|
// simulate a brief REPEAT key press (3 repeat cycles)
|
||
|
|
||
|
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
delay = 0;
|
||
|
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
|
||
|
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
}
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
|
||
|
|
||
|
asdf_repeat_deactivate();
|
||
|
|
||
|
// now that repeat is deactivated, we should time out before hitting a repeat
|
||
|
// event:
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
|
||
|
}
|
||
|
|
||
|
// If autorepeat is enabled, then activating and deactivating repeat mode
|
||
|
// (pressing and releasing the repeat key) should return to the autorepeat
|
||
|
// enabled mode.
|
||
|
void test_asdf_repeat_deactivate_returns_to_baseline_autorepeat(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
// simulate a brief REPEAT key press (1/2 autorepeat time)
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
delay = 0;
|
||
|
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
|
||
|
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
}
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
|
||
|
|
||
|
asdf_repeat_deactivate();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// When Autoreat is enabled, and the autorepeat timer is activated by holding
|
||
|
// down a key, then activating repeat (pressing the repeat key) should skip the
|
||
|
// rest of the autorepeat interval, and cause repeat events to occur at the fast
|
||
|
// repeat rate.
|
||
|
void test_asdf_repeat_repeat_key_circumvents_initial_autorepeat_delay(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
// simulate a brief keypress (1/2 autorepeat time)
|
||
|
delay = count_repeat_ticks(ASDF_AUTOREPEAT_TIME_MS / 2);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT((ASDF_AUTOREPEAT_TIME_MS / 2), delay);
|
||
|
|
||
|
// simulate pressing the REPEAT key in the middle of an autorepeat interval
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// If autorepeat is on, and a key is being held down to start the autorepeat
|
||
|
// interval, then turning off autorepeat mode should prevent the key from
|
||
|
// repeating.
|
||
|
void test_asdf_repeat_turning_off_auto_cancels_autorepeat_delay_in_progress(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
asdf_repeat_auto_on();
|
||
|
// simulate a brief keypress (1/2 autorepeat time)
|
||
|
delay = count_repeat_ticks(ASDF_AUTOREPEAT_TIME_MS / 2);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT((ASDF_AUTOREPEAT_TIME_MS / 2), delay);
|
||
|
|
||
|
asdf_repeat_auto_off();
|
||
|
|
||
|
// simulate continued holding down key
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
|
||
|
}
|
||
|
|
||
|
// If a key is autorepeating (held down until it repeats, without the repeat key
|
||
|
// being held down), then turning off autorepeat mode should stop the key from
|
||
|
// repeating.
|
||
|
void test_asdf_repeat_turning_off_auto_cancels_autorepeating_keypress(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
asdf_repeat_auto_on();
|
||
|
// simulate an autorepeating key. Wait out entire autorepeat delay.
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
|
||
|
// wait NUM_REPETITIONS repeat cycles:
|
||
|
delay = 0;
|
||
|
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
|
||
|
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
}
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
|
||
|
|
||
|
asdf_repeat_auto_off();
|
||
|
|
||
|
for (delay = 0; !asdf_repeat() && (delay < REPEAT_TIMED_OUT); delay++) {
|
||
|
}
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
|
||
|
}
|
||
|
|
||
|
|
||
|
// If you press the REPEAT key while a key is already autorepeating (i.e., after
|
||
|
// the autorepeat delay interval), then the repeat timing shall not be affected.
|
||
|
void test_asdf_repeat_activate_while_autorepeating_wont_affect_timing(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
asdf_repeat_auto_on();
|
||
|
// simulate an autorepeating key. Wait out entire autorepeat delay.
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
|
||
|
// wait 1/2 fast repeat cycle:
|
||
|
// simulate an autorepeating key. Wait out entire autorepeat delay.
|
||
|
delay = count_repeat_ticks(ASDF_REPEAT_TIME_MS / 2);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT((ASDF_REPEAT_TIME_MS / 2), delay);
|
||
|
|
||
|
// turn on repeat mode (press REPEAT key)
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
// now verify the repeat interval was not affected. Finish the current repeat
|
||
|
// interval
|
||
|
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// If in autorepeat mode and the repeat key is released while a key is
|
||
|
// repeating, the next repeat event should occur after a new autorepeat delay
|
||
|
// interval.
|
||
|
void test_asdf_repeat_deactivate_while_repeating_resets_autorepeat_counter(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
asdf_repeat_auto_on();
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
// wait NUM_REPETITIONS repeat cycles:
|
||
|
delay = 0;
|
||
|
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
|
||
|
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
}
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
|
||
|
|
||
|
// releast REPEAT key:
|
||
|
asdf_repeat_deactivate();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
// should have waited entire autorepeat delay interval
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// If autorepeat is disabled and the repeat key is released while a key is
|
||
|
// repeating, then the key should stop repeating.
|
||
|
void test_asdf_repeat_deactivate_while_repeating_stops_repeating(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
asdf_repeat_auto_off();
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
// wait NUM_REPETITIONS repeat cycles:
|
||
|
delay = 0;
|
||
|
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
|
||
|
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
}
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
|
||
|
|
||
|
// releast REPEAT key:
|
||
|
asdf_repeat_deactivate();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
// should have waited entire autorepeat delay interval
|
||
|
TEST_ASSERT_EQUAL_INT(REPEAT_TIMED_OUT, delay);
|
||
|
}
|
||
|
|
||
|
// pressing a new value key when REPEAT is active should start repeating right
|
||
|
// away.
|
||
|
void test_asdf_repeat_new_key_while_repeat_active_keeps_repeating(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
asdf_repeat_activate();
|
||
|
|
||
|
// wait NUM_REPETITIONS repeat cycles:
|
||
|
delay = 0;
|
||
|
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
|
||
|
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
}
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
|
||
|
|
||
|
// simulate half a repeat interval
|
||
|
delay = count_repeat_ticks(ASDF_REPEAT_TIME_MS / 2);
|
||
|
|
||
|
// simulate a new key press:
|
||
|
asdf_repeat_reset_count();
|
||
|
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
// should have waited the key repeat interval
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
|
||
|
// pressing a new value key when autorepeating should start new autorepeat
|
||
|
// delay.
|
||
|
void test_asdf_repeat_new_key_while_autorepeating_starts_new_autorepeat(void)
|
||
|
{
|
||
|
uint32_t delay;
|
||
|
|
||
|
asdf_repeat_auto_on();
|
||
|
|
||
|
// simulate an autorepeating key. Wait out entire autorepeat delay.
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
|
||
|
// wait NUM_REPETITIONS repeat cycles:
|
||
|
delay = 0;
|
||
|
for (uint32_t i = 0; i < NUM_REPETITIONS; i++) {
|
||
|
delay += count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
}
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_REPEAT_TIME_MS * NUM_REPETITIONS, delay);
|
||
|
|
||
|
// simulate new keypress:
|
||
|
asdf_repeat_reset_count();
|
||
|
|
||
|
// now measure interval until next repeat event.
|
||
|
delay = count_repeat_ticks(REPEAT_TIMED_OUT);
|
||
|
|
||
|
TEST_ASSERT_EQUAL_INT(ASDF_AUTOREPEAT_TIME_MS, delay);
|
||
|
}
|
||
|
int main(void)
|
||
|
{
|
||
|
UNITY_BEGIN();
|
||
|
RUN_TEST(test_asdf_repeat_init_resets_to_autorepeat_default);
|
||
|
RUN_TEST(test_asdf_repeat_no_repeat_if_auto_turned_off);
|
||
|
RUN_TEST(test_asdf_repeat_auto_repeat_if_auto_turned_on);
|
||
|
RUN_TEST(test_asf_repeat_autorepeat_fast_repeat_after_delay);
|
||
|
RUN_TEST(test_asdf_repeat_reset_count_works_in_autorepeat_mode);
|
||
|
RUN_TEST(test_asdf_repeat_reset_count_works_in_repeat_mode);
|
||
|
RUN_TEST(test_asdf_repeat_activate_with_auto_on);
|
||
|
RUN_TEST(test_asdf_repeat_activate_with_auto_off);
|
||
|
RUN_TEST(test_asdf_repeat_deactivate_returns_to_baseline_autorepeat);
|
||
|
RUN_TEST(test_asdf_repeat_deactivate_returns_to_baseline_no_repeat);
|
||
|
RUN_TEST(test_asdf_repeat_repeat_key_circumvents_initial_autorepeat_delay);
|
||
|
RUN_TEST(test_asdf_repeat_activate_while_autorepeating_wont_affect_timing);
|
||
|
RUN_TEST(test_asdf_repeat_turning_off_auto_cancels_autorepeating_keypress);
|
||
|
RUN_TEST(test_asdf_repeat_turning_off_auto_cancels_autorepeat_delay_in_progress);
|
||
|
RUN_TEST(test_asdf_repeat_deactivate_while_repeating_resets_autorepeat_counter);
|
||
|
RUN_TEST(test_asdf_repeat_deactivate_while_repeating_stops_repeating);
|
||
|
RUN_TEST(test_asdf_repeat_new_key_while_repeat_active_keeps_repeating);
|
||
|
RUN_TEST(test_asdf_repeat_new_key_while_autorepeating_starts_new_autorepeat);
|
||
|
return UNITY_END();
|
||
|
}
|