add generic number_input

main
radex 2024-02-28 15:07:13 +01:00
parent 3a5af46135
commit 9014650fed
Signed by: radex
SSH Key Fingerprint: SHA256:hvqRXAGG1h89yqnS+cyFTLKQbzjWD4uXIqw7Y+0ws30
3 changed files with 167 additions and 80 deletions

View File

@ -1,95 +1,21 @@
#include "input.h"
#include "buzzer.h"
#include "screen.h"
#include "characters.h"
String wireDiameterInput = "";
int8_t dotPosition = -1;
#define ENCODER_STEP 0.1
#include "number_input.h"
#include "buzzer.h"
void customize_setup();
void customize_update();
void customize() {
customize_setup();
while (true) {
auto input = handleInput();
if (input.key) {
auto len = wireDiameterInput.length();
auto digit = getPressedDigit(input.key);
if (input.key == KEY_HASH) {
if (len) {
if (dotPosition == len - 1) {
dotPosition = -1;
}
wireDiameterInput = wireDiameterInput.substring(0, len - 1);
tick();
} else {
beep();
}
} else if (wireDiameterInput.length() >= 8) {
beep();
} else if (digit != -1) {
wireDiameterInput += digit;
tick();
} else if (input.key == KEY_ASTERISK) {
if (dotPosition == -1 && len >= 1) {
dotPosition = wireDiameterInput.length();
wireDiameterInput += ".";
tick();
} else {
beep();
}
} else {
beep();
}
customize_update();
} else if (input.encoderEvent) {
if (wireDiameterInput.length() == 0) {
wireDiameterInput = "0";
}
auto len = wireDiameterInput.length();
auto previousDecimalPlaces = dotPosition == -1 ? 0 : len - dotPosition - 1;
auto wireDia = wireDiameterInput.toFloat();
wireDia += input.encoderEvent * ENCODER_STEP;
if (wireDia < 0) {
wireDia = 0;
beep();
} else {
tick();
}
wireDiameterInput = String(wireDia, max(previousDecimalPlaces, 1));
dotPosition = wireDiameterInput.indexOf('.');
customize_update();
} else if (input.hasInput && input.switchEvent != SWITCH_PRESSED) {
beep();
}
customize_setup();
float wireDiameter = number_input(-1, 0.1);
tick();
Serial.println(wireDiameter);
}
}
void customize_setup() {
wireDiameterInput = "";
dotPosition = -1;
lcd.clear();
lcd.print("Wire diameter:");
lcd.setCursor(14, 1);
lcd.print("mm");
lcd.cursor();
customize_update();
}
void customize_update() {
lcd.setCursor(0, 1);
lcd.print(wireDiameterInput);
// Delete following character (if backspace was pressed), then move cursor back to position
lcd.write(' ');
lcd.setCursor(wireDiameterInput.length(), 1);
}

View File

@ -0,0 +1,142 @@
#include "input.h"
#include "buzzer.h"
#include "screen.h"
#include "characters.h"
String numberInput = "";
int8_t dotPosition = -1;
#define MAX_LENGTH 8
void number_input_update();
float number_input(float defaultValue, float encoderStep) {
// setup
if (defaultValue < 0) {
numberInput = "";
dotPosition = -1;
} else {
// see how many decimal places the default value has (max 3)
unsigned char decimalPlaces = 3;
numberInput = String(defaultValue, decimalPlaces);
if (numberInput.endsWith(".000")) {
decimalPlaces = 0;
} else if (numberInput.endsWith("00")) {
decimalPlaces = 1;
} else if (numberInput.endsWith("0")) {
decimalPlaces = 2;
}
// stringify again
numberInput = String(defaultValue, decimalPlaces);
dotPosition = numberInput.indexOf('.');
if (numberInput.length() > MAX_LENGTH) {
beep();
numberInput = numberInput.substring(0, MAX_LENGTH);
}
}
// set up screen
lcd.cursor();
number_input_update();
// loop
while (true) {
auto input = handleInput();
auto len = numberInput.length();
bool isAtLength = len >= MAX_LENGTH;
if (input.key) {
auto digit = getPressedDigit(input.key);
if (digit != -1) {
// append digit (if it fits)
if (isAtLength) {
beep();
} else {
numberInput += digit;
tick();
}
} else if (input.key == KEY_ASTERISK) {
// append decimal point (if possible)
if (isAtLength) {
beep();
} else if (dotPosition == -1 && len >= 1) {
dotPosition = numberInput.length();
numberInput += ".";
tick();
} else {
beep();
}
} else if (input.key == KEY_HASH) {
// backspace
if (len) {
if (dotPosition == len - 1) {
dotPosition = -1;
}
numberInput = numberInput.substring(0, len - 1);
tick();
} else {
beep();
}
} else if (input.key == KEY_B) {
goto on_back;
} else if (input.key == KEY_C) {
goto on_continue;
} else {
beep();
}
number_input_update();
} else if (input.encoderEvent) {
// normalize input
if (numberInput.length() == 0) {
numberInput = "0";
}
// remember decimal places
len = numberInput.length();
auto previousDecimalPlaces = dotPosition == -1 ? 0 : len - dotPosition - 1;
// calculate new value
auto wireDia = numberInput.toFloat();
wireDia += input.encoderEvent * encoderStep;
// clamp to 0
if (wireDia < 0) {
wireDia = 0;
beep();
} else {
tick();
}
// stringify
numberInput = String(wireDia, max(previousDecimalPlaces, 1));
dotPosition = numberInput.indexOf('.');
number_input_update();
} else if (input.switchEvent == SWITCH_RELEASED) {
goto on_continue;
} else if (input.hasInput && input.switchEvent != SWITCH_PRESSED) {
beep();
}
}
on_continue:
lcd.noCursor();
return numberInput.length() ? numberInput.toFloat() : -1;
on_back:
lcd.noCursor();
return -1;
}
void number_input_update() {
lcd.setCursor(0, 1);
lcd.print(numberInput);
// Delete following character (if backspace was pressed), then move cursor back to position
lcd.write(' ');
lcd.setCursor(numberInput.length(), 1);
}

View File

@ -0,0 +1,19 @@
#pragma once
/**
* Uses second row of the screen, keyboard, and encoder to get a number from the user.
*
* Number cannot be longer than 8 characters, or less than 0.
*
* If defaultValue is -1, it will default to empty string.
* defaultValue will be truncated to at most 3 decimal places.
*
* It will return the number when it's confirmed by encoder press or [C]ontinue.
* It will return -1 if [B]ack is pressed.
*
* LCD is set to .noCursor() before returning.
*/
float number_input(
float defaultValue,
float encoderStep
);