Skip to content

Instantly share code, notes, and snippets.

@YaLTeR
Last active April 4, 2024 13:41
Show Gist options
  • Save YaLTeR/8e8bd0cddb324a9e372b32e742ff992a to your computer and use it in GitHub Desktop.
Save YaLTeR/8e8bd0cddb324a9e372b32e742ff992a to your computer and use it in GitHub Desktop.
Latency measuring device firmware
#include <Bounce2.h>
// Where I have stuff plugged in on my board.
#define BUTTON_PIN 2
#define LIGHT_PIN 23
// This one is standard for Teensy.
#define LED_PIN 13
// The program repeatedly:
// 1. presses the first key
// 2. waits for light sensor change
// 3. releases the first key
// 4. waits for a bit
// 5. does the same with the second key
//
// This allows to loop the measurements, like entering and
// erasing a space in a terminal.
//
// These are the two keys it uses.
#define KEY_FIRST KEY_SPACE
#define KEY_SECOND KEY_BACKSPACE
// If defined, this modifier will be held for the entire duration
// of the test.
#define MODIFIER MODIFIERKEY_CTRL
// Number of times to repeat the sequence above before
// automatically stopping.
#define TIMES 120
// Light threshold for step 2. Seems big enough to not trigger on noise.
#define RELEASE_LIGHT_THRESHOLD 50
// Constant wait duration for step 4.
//
// Light level more or less stabilizes after this time.
#define WAIT_MS 400
// Random wait duration for step 4.
//
// This gets rid of aliasing with display refresh rate.
// 15 is the GCD of 144 (my current refresh rate) and
// 60 (another common / interesting refresh rate), so
// it produces a uniform random start time for those
// refresh cycles.
#define RANDOM_WAIT_MS (1000 / 12)
Button button = Button();
int working = 0;
int state = 0;
int timesLeft = 0;
int startLight = 0;
elapsedMicros sinceStart;
elapsedMillis sinceRelease;
void setup() {
button.attach(BUTTON_PIN, INPUT);
button.interval(5);
button.setPressedState(LOW);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, working);
// Not required on Teensy, but waits until the serial port is ready.
Serial.begin(9600);
}
void print(int light) {
Serial.print("T");
Serial.print(sinceStart);
Serial.print("L");
Serial.print(light);
Serial.println("D");
}
void print_ts(char c) {
Serial.print(c);
Serial.print(sinceStart);
Serial.println(c);
}
void setWorking(bool value) {
working = value;
digitalWrite(LED_PIN, working);
if (working) {
state = 0;
timesLeft = TIMES;
sinceStart = 0;
sinceRelease = 0;
#ifdef MODIFIER
Keyboard.press(MODIFIER);
#endif
} else {
Keyboard.release(KEY_FIRST);
Keyboard.release(KEY_SECOND);
#ifdef MODIFIER
Keyboard.release(MODIFIER);
#endif
}
}
void loop() {
button.update();
if (button.pressed())
setWorking(!working);
if (!working)
return;
int light = 0;
switch (state) {
case 0:
light = analogRead(LIGHT_PIN);
print(light);
if (sinceRelease < WAIT_MS)
break;
print_ts('+');
startLight = light;
Keyboard.press(KEY_FIRST);
state = 1;
break;
case 1:
light = analogRead(LIGHT_PIN);
print(light);
if (max(light, startLight) - min(light, startLight) > RELEASE_LIGHT_THRESHOLD) {
Keyboard.release(KEY_FIRST);
sinceRelease = random(RANDOM_WAIT_MS);
state = 2;
}
break;
case 2:
light = analogRead(LIGHT_PIN);
print(light);
if (sinceRelease < WAIT_MS)
break;
print_ts('=');
startLight = light;
Keyboard.press(KEY_SECOND);
state = 3;
break;
case 3:
light = analogRead(LIGHT_PIN);
print(light);
if (max(light, startLight) - min(light, startLight) > RELEASE_LIGHT_THRESHOLD) {
Keyboard.release(KEY_SECOND);
sinceRelease = random(RANDOM_WAIT_MS);
state = 0;
if (--timesLeft == 0)
setWorking(false);
}
break;
default:
return;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment