Math and morse modules done
This commit is contained in:
commit
106a7dfe2d
|
@ -0,0 +1,2 @@
|
|||
/*/build/
|
||||
/*/.vscode/
|
|
@ -0,0 +1,14 @@
|
|||
#include <M5StickCPlus.h>
|
||||
void setup() {
|
||||
M5.begin();
|
||||
M5.Lcd.fillScreen(WHITE);
|
||||
|
||||
pinMode(26, OUTPUT_OPEN_DRAIN);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
digitalWrite(26, HIGH);
|
||||
delay(25);
|
||||
digitalWrite(26, LOW);
|
||||
delay(25);
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
#include <M5StickCPlus.h>
|
||||
|
||||
#define buttonPin 25
|
||||
#define inputPauseRegisterMills 1500
|
||||
|
||||
typedef void (*OnFinishInputMode)(int);
|
||||
OnFinishInputMode onFinishInputMode = nullptr;
|
||||
|
||||
int pressedTimes = 0;
|
||||
bool isInputMode = false;
|
||||
|
||||
long lastInputTime = 0;
|
||||
void onPressed(){
|
||||
if (!isInputMode)
|
||||
{
|
||||
isInputMode = true;
|
||||
}
|
||||
lastInputTime = millis();
|
||||
|
||||
pressedTimes++;
|
||||
}
|
||||
|
||||
// void m_onFinishInputMode(){
|
||||
// M5.Lcd.fillScreen(WHITE);
|
||||
// M5.Lcd.setTextPadding(10);
|
||||
// M5.Lcd.setCursor(10, 10);
|
||||
// M5.Lcd.setTextSize(6);
|
||||
// M5.Lcd.print(pressedTimes);
|
||||
|
||||
// Serial.println("Registed: " + pressedTimes);
|
||||
|
||||
// // Reset count
|
||||
// pressedTimes = 0;
|
||||
// }
|
||||
|
||||
bool buttonDowned = false;
|
||||
void updateInput()
|
||||
{
|
||||
// Detect button down
|
||||
if (!buttonDowned && digitalRead(buttonPin) == LOW)
|
||||
{
|
||||
buttonDowned = true;
|
||||
|
||||
onPressed();
|
||||
}
|
||||
else if (buttonDowned && digitalRead(buttonPin) == HIGH)
|
||||
{
|
||||
buttonDowned = false;
|
||||
}
|
||||
|
||||
// Detect if no input for 3 seconds
|
||||
if (isInputMode && millis() - lastInputTime > inputPauseRegisterMills)
|
||||
{
|
||||
isInputMode = false;
|
||||
if (onFinishInputMode != nullptr)
|
||||
onFinishInputMode(pressedTimes);
|
||||
|
||||
pressedTimes = false;
|
||||
}
|
||||
}
|
||||
|
||||
void initInputSystem(OnFinishInputMode callback)
|
||||
{
|
||||
onFinishInputMode = callback;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#include <M5StickCPlus.h>
|
||||
|
||||
// -1 if error
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
int targetResult = 0;
|
||||
|
||||
enum class Operator{
|
||||
plus,
|
||||
minus,
|
||||
mult
|
||||
};
|
||||
|
||||
void initRandomSeed(){
|
||||
M5.IMU.Init();
|
||||
float accX, accY, accZ;
|
||||
delay(250); // Wait for imu init
|
||||
M5.IMU.getAccelData(&accX, &accY, &accZ);
|
||||
float accelSum = accX + accY + accZ;
|
||||
|
||||
unsigned long seed = accelSum * 1000000;
|
||||
randomSeed(seed);
|
||||
}
|
||||
|
||||
String generateQuestion(){
|
||||
Operator oper = static_cast<Operator>(random(0, 3));
|
||||
switch (oper)
|
||||
{
|
||||
case Operator::plus:
|
||||
a = random(0, 15);
|
||||
b = random(1, 15);
|
||||
|
||||
targetResult = a + b;
|
||||
return String(a) + "+" + String(b) + " = ?";
|
||||
|
||||
case Operator::minus:
|
||||
do
|
||||
{
|
||||
a = random(15, 30);
|
||||
b = random(0, 15);
|
||||
|
||||
targetResult = a - b;
|
||||
} while (targetResult <= 0);
|
||||
return String(a) + "-" + String(b) + "= ?";
|
||||
|
||||
case Operator::mult:
|
||||
a = random(0, 10);
|
||||
b = random(1, 10);
|
||||
|
||||
targetResult = a * b;
|
||||
return String(a) + "*" + String(b) + "= ?";
|
||||
|
||||
default:
|
||||
Serial.println("Failed to create math question");
|
||||
return "Error";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
#include <M5StickCPlus.h>
|
||||
#include "InputSystem.h"
|
||||
#include "MathSystem.h"
|
||||
|
||||
#define extenderPin 26
|
||||
#define buttonPin 25
|
||||
|
||||
#define UIRefreshDelay 250
|
||||
|
||||
String mathExpression = "";
|
||||
bool hasWon = false;
|
||||
|
||||
void onInputDone(int inputNum){
|
||||
Serial.println("Reveiced: " + String(inputNum));
|
||||
Serial.println("Target: " + String(targetResult));
|
||||
|
||||
if (inputNum == targetResult){
|
||||
hasWon = true;
|
||||
}
|
||||
|
||||
if (!hasWon){
|
||||
M5.Lcd.fillScreen(RED);
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
M5.Lcd.setRotation(1);
|
||||
|
||||
initRandomSeed();
|
||||
|
||||
digitalWrite(extenderPin, HIGH); // Push out
|
||||
|
||||
pinMode(extenderPin, OUTPUT_OPEN_DRAIN);
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
|
||||
Serial.begin(115200);
|
||||
mathExpression = generateQuestion();
|
||||
|
||||
initInputSystem(*onInputDone);
|
||||
}
|
||||
|
||||
void drawUI(){
|
||||
if (!hasWon)
|
||||
{
|
||||
M5.Lcd.fillScreen(BLACK);
|
||||
|
||||
if (!isInputMode)
|
||||
{
|
||||
// Draw expression
|
||||
M5.Lcd.setCursor(10, 50);
|
||||
M5.Lcd.setTextSize(4);
|
||||
M5.Lcd.print(mathExpression);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw pressed times
|
||||
M5.Lcd.setCursor(80, 40);
|
||||
M5.Lcd.setTextSize(7);
|
||||
M5.Lcd.print(pressedTimes);
|
||||
}
|
||||
}
|
||||
else {
|
||||
M5.Lcd.fillScreen(GREEN);
|
||||
digitalWrite(extenderPin, LOW);
|
||||
|
||||
// Wait for reset click
|
||||
while (digitalRead(buttonPin) == HIGH){
|
||||
delay(10);
|
||||
}
|
||||
while (digitalRead(buttonPin) == LOW)
|
||||
{
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// Reset
|
||||
digitalWrite(extenderPin, HIGH);
|
||||
mathExpression = generateQuestion();
|
||||
hasWon = false;
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
updateInput();
|
||||
|
||||
if (isInputMode || millis() % UIRefreshDelay < 100)
|
||||
drawUI();
|
||||
|
||||
delay(25);
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
#include <M5StickCPlus.h>
|
||||
#include "MorsePart.h"
|
||||
|
||||
#define refreshDelay 1000
|
||||
|
||||
#define BTN_A 37
|
||||
#define BTN_B 39
|
||||
|
||||
#define extenderPin 26
|
||||
|
||||
int currentlySelected = 1000;
|
||||
|
||||
const int numCodes = 11;
|
||||
const String codes[] = {
|
||||
"bond", "swap", "call", "repo", "yield", "index", "asset", "bear", "bull", "gain", "loss"};
|
||||
|
||||
#define selectedDisplayLength 0 // Used for debug but not used for production
|
||||
bool isSelectionMode = false;
|
||||
long onSelectedTime = 0;
|
||||
|
||||
int correctIndex;
|
||||
|
||||
bool hasWon = false;
|
||||
|
||||
void initRandomSeed()
|
||||
{
|
||||
M5.IMU.Init();
|
||||
float accX, accY, accZ;
|
||||
delay(250); // Wait for imu init
|
||||
M5.IMU.getAccelData(&accX, &accY, &accZ);
|
||||
float accelSum = accX + accY + accZ;
|
||||
|
||||
unsigned long seed = accelSum * 1000000;
|
||||
randomSeed(seed);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
M5.begin();
|
||||
M5.Lcd.setRotation(1);
|
||||
M5.Lcd.fillScreen(BLACK);
|
||||
|
||||
pinMode(BTN_A, INPUT_PULLDOWN);
|
||||
pinMode(BTN_B, INPUT_PULLDOWN);
|
||||
|
||||
Serial.begin(115200);
|
||||
updateUI();
|
||||
|
||||
initRandomSeed();
|
||||
//correctIndex = 1;
|
||||
correctIndex = random(0, 12);
|
||||
|
||||
morseInit(correctIndex, 0, 0, 300, 100);
|
||||
}
|
||||
|
||||
void updateUI()
|
||||
{
|
||||
Serial.println("Next correct: " + codes[correctIndex]);
|
||||
|
||||
// Clear screen
|
||||
M5.Lcd.fillRect(0, 100, 300, 100, BLACK);
|
||||
|
||||
if (hasWon)
|
||||
{
|
||||
M5.Lcd.fillScreen(GREEN);
|
||||
digitalWrite(extenderPin, LOW);
|
||||
|
||||
delay(3000);
|
||||
|
||||
// Wait for reset click
|
||||
while (digitalRead(BTN_A) == HIGH || digitalRead(BTN_B) == HIGH)
|
||||
{
|
||||
delay(10);
|
||||
}
|
||||
while (digitalRead(BTN_A) == HIGH || digitalRead(BTN_B) == HIGH)
|
||||
{
|
||||
delay(10);
|
||||
}
|
||||
|
||||
digitalWrite(extenderPin, HIGH);
|
||||
hasWon = false;
|
||||
M5.Lcd.fillScreen(BLUE);
|
||||
correctIndex = random(0, 12);
|
||||
delay(1000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSelectionMode)
|
||||
{
|
||||
// Draw divider
|
||||
M5.Lcd.drawLine(0, 100, 300, 100, WHITE);
|
||||
|
||||
// Draw left text
|
||||
M5.Lcd.setTextSize(2);
|
||||
M5.Lcd.setCursor(20, 110);
|
||||
M5.Lcd.setTextColor(WHITE);
|
||||
M5.Lcd.print(codes[(currentlySelected - 1) % numCodes]);
|
||||
// Draw selected text
|
||||
M5.Lcd.fillRect(90, 110 - 5, 14 * 5, 25, WHITE);
|
||||
M5.Lcd.setTextSize(2);
|
||||
M5.Lcd.setCursor(95, 110);
|
||||
M5.Lcd.setTextColor(BLACK);
|
||||
M5.Lcd.print(codes[(currentlySelected) % numCodes]);
|
||||
// Draw right text
|
||||
M5.Lcd.setTextSize(2);
|
||||
M5.Lcd.setCursor(175, 110);
|
||||
M5.Lcd.setTextColor(WHITE);
|
||||
M5.Lcd.print(codes[(currentlySelected + 1) % numCodes]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw selected text
|
||||
M5.Lcd.setTextSize(4);
|
||||
M5.Lcd.setCursor(10, 20);
|
||||
M5.Lcd.setTextColor(WHITE);
|
||||
M5.Lcd.print(codes[(currentlySelected) % numCodes]);
|
||||
}
|
||||
}
|
||||
|
||||
void onBothPressed()
|
||||
{
|
||||
isSelectionMode = true;
|
||||
Serial.println("Selected: " + codes[(currentlySelected) % numCodes]);
|
||||
updateUI();
|
||||
|
||||
if (correctIndex == (currentlySelected) % numCodes)
|
||||
hasWon = true;
|
||||
else
|
||||
{
|
||||
M5.Lcd.fillScreen(RED);
|
||||
|
||||
delay(3000);
|
||||
|
||||
morseDisplayIndex = 0; // Reset morse
|
||||
}
|
||||
|
||||
onSelectedTime = millis();
|
||||
}
|
||||
|
||||
bool isButtonAPressed, isButtonBPressed = false;
|
||||
|
||||
void loop()
|
||||
{
|
||||
morseUpdate();
|
||||
|
||||
if (millis() % refreshDelay < 100)
|
||||
updateUI();
|
||||
|
||||
if (!isButtonAPressed && digitalRead(BTN_A) == LOW)
|
||||
{
|
||||
isButtonAPressed = true;
|
||||
//Serial.println("A pressed");
|
||||
|
||||
if (isButtonBPressed)
|
||||
{
|
||||
onBothPressed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (isButtonAPressed && digitalRead(BTN_A) == HIGH)
|
||||
{
|
||||
isButtonAPressed = false;
|
||||
//Serial.println("A released");
|
||||
if (!isSelectionMode)
|
||||
{
|
||||
currentlySelected++;
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
if (!isButtonBPressed && digitalRead(BTN_B) == LOW)
|
||||
{
|
||||
isButtonBPressed = true;
|
||||
//Serial.println("B pressed");
|
||||
|
||||
if (isButtonAPressed)
|
||||
{
|
||||
onBothPressed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (isButtonBPressed && digitalRead(BTN_B) == HIGH)
|
||||
{
|
||||
isButtonBPressed = false;
|
||||
//Serial.println("B released");
|
||||
if (!isSelectionMode)
|
||||
{
|
||||
currentlySelected--;
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
if (isSelectionMode && onSelectedTime + selectedDisplayLength < millis())
|
||||
{
|
||||
isSelectionMode = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
#include <M5StickCPlus.h>
|
||||
|
||||
#define nextItemDelayTime 500
|
||||
|
||||
#define dotDisplayTime 500 + nextItemDelayTime
|
||||
#define dashDisplayTime 1500 + nextItemDelayTime
|
||||
#define nextLetterDelayTime 1000
|
||||
#define restartDelayTime 5000
|
||||
|
||||
const String morseCodes[11] = {
|
||||
"-.../---/-./-..;", // "bond"
|
||||
".../.--/.-/.--.;", // "swap"
|
||||
"-.-./.-/.-../.-..;", // "call"
|
||||
".-././.--./---;", // "repo"
|
||||
"-.--/./../.-../-..;", // "yield"
|
||||
"../-./-.././-..-;", // "index"
|
||||
".-/.../..././-;", // "asset"
|
||||
"-..././.-/.-.;", // "bear"
|
||||
"-.../..-/.-../.-..;", // "bull"
|
||||
"--./.-/../-.;", // "gain"
|
||||
".-../---/.../...;" // "loss"
|
||||
};
|
||||
|
||||
int x, y, w, h;
|
||||
|
||||
int morseDisplayIndex = -1; // Which char iscurrently going to be displayed
|
||||
int morseCodeLength;
|
||||
int morseCorrectIndex;
|
||||
|
||||
void morseInit(int CorrectIndex, int X, int Y, int W, int H)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
morseCorrectIndex = CorrectIndex;
|
||||
morseCodeLength = strlen(morseCodes[CorrectIndex].c_str());
|
||||
}
|
||||
|
||||
bool isLit = false;
|
||||
long getDisplayTime(char morseChar)
|
||||
{
|
||||
switch (morseChar)
|
||||
{
|
||||
case '.':
|
||||
isLit = true;
|
||||
Serial.println("dot");
|
||||
return dotDisplayTime;
|
||||
|
||||
case '-':
|
||||
isLit = true;
|
||||
Serial.println("dash");
|
||||
return dashDisplayTime;
|
||||
|
||||
case '/':
|
||||
isLit = false;
|
||||
Serial.println("space");
|
||||
return nextLetterDelayTime;
|
||||
|
||||
case ';':
|
||||
isLit = false;
|
||||
Serial.println("stop");
|
||||
return restartDelayTime;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
long actionStartTime = 0;
|
||||
long actionDurationTime = 0;
|
||||
void morseUpdate()
|
||||
{
|
||||
long currentTime = millis();
|
||||
if (actionStartTime + actionDurationTime < currentTime)
|
||||
{
|
||||
morseDisplayIndex++;
|
||||
actionStartTime = currentTime;
|
||||
|
||||
// get next display time
|
||||
char nextChar = morseCodes[morseCorrectIndex][morseDisplayIndex % morseCodeLength];
|
||||
actionDurationTime = getDisplayTime(nextChar);
|
||||
}
|
||||
|
||||
if (isLit && actionStartTime + actionDurationTime - nextItemDelayTime < currentTime)
|
||||
{
|
||||
isLit = false;
|
||||
}
|
||||
|
||||
if (isLit)
|
||||
M5.Lcd.fillRect(x, y, w, h, WHITE);
|
||||
else
|
||||
M5.Lcd.fillRect(x, y, w, h, BLACK);
|
||||
}
|
Loading…
Reference in New Issue