#include <LiquidCrystal.h>
#include "dummyLibs.h"
#include "morse.h"
#include "module_setup.h"
uint8_t curFrequencyIndex = 0; // Индекс выбранной частоты
uint8_t curWordIndex = 0; // Индекс отображаемого кодом Морзе слова
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7); // Инициализация ЖК дисплея LCD1602
Module module; // Объект для работы с параметрами модуля
Device device; // Объект для работы с копией устройства
KTANEBusSlave busSlave(&device, &module, I2C_ADDR); // Объект для работы с KTANEBus как слейв
Morse morse; // Объект для работы с кодом Морзе
void setup() {
lcd.begin(16, 2);
// Конфигурируем входы
pinMode(LEFT_BTN, INPUT_PULLUP);
pinMode(RIGHT_BTN, INPUT_PULLUP);
pinMode(TX_BTN, INPUT_PULLUP);
// Конфигурируем выходы
pinMode(MORSE_LED, OUTPUT);
pinMode(RGB_LED_G, OUTPUT);
pinMode(RGB_LED_R, OUTPUT);
busSlave.begin();
// Инициализация генератора случайных чисел и выбор случайного слова
randomSeed(analogRead(A6) ^ micros());
curWordIndex = random(morse.getPairCount());
morse.setWordIndex(curWordIndex);
module.status = RUNNING;
}
void loop() {
readInputs();
handleButtons();
handleMistakes();
handleModuleStatus();
outputs.morseLed = morse.update();
updateDisplay();
writeOutputs();
}
// Считываем состояния входов в переменные
inline void readInputs() {
inputs.leftButton = !digitalRead(LEFT_BTN);
inputs.rightButton = !digitalRead(RIGHT_BTN);
inputs.txButton = !digitalRead(TX_BTN);
}
// Обновляем данные на дисплее
inline void updateDisplay() {
// Печатаем первую строку
lcd.setCursor(0, 0);
// Печатаем "===" до индикатора настройки частоты
for (uint8_t i = 0; i < curFrequencyIndex; i++) {
lcd.print('=');
}
// Печатаем символ '█' индикатора настройки частоты
lcd.print((char)0xFF);
// Печатаем "===" после индикатора частоты
for (uint8_t i = curFrequencyIndex + 1; i < 16; i++) {
lcd.print('=');
}
// Печатаем вторую строку
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.print(morse.getFrequencyValue(curFrequencyIndex), 3);
lcd.print(" MHz ");
}
// Обработчик нажатия кнопок
inline void handleButtons() {
handleLeftButton();
handleRightButton();
handleTXButton();
}
// Обработчик нажатия кнопки слева от дисплея
inline void handleLeftButton() {
static bool prevButtonState = false;
// не минимальная величина && восходящий фронт
if (curFrequencyIndex > 0 && inputs.leftButton && !prevButtonState) {
curFrequencyIndex--;
}
prevButtonState = inputs.leftButton;
}
// Обработчик нажатия кнопки справа от дисплея
inline void handleRightButton() {
static bool prevButtonState = false;
// не максимальная величина && восходящий фронт
if (curFrequencyIndex < morse.getPairCount() - 1 && inputs.rightButton && !prevButtonState) {
curFrequencyIndex++;
}
prevButtonState = inputs.rightButton;
}
// Обработчик нажатия кнопки TX
inline void handleTXButton() {
static bool prevButtonState = false; // Предыдущее состояние кнопки
if (inputs.txButton && !prevButtonState && module.status == RUNNING) { // восходящий фронт и модуль в RUNNING
if (curFrequencyIndex == curWordIndex) {
module.status = SOLVED;
} else {
module.mistakesNumber++;
}
}
prevButtonState = inputs.txButton;
}
// Обрабатываем ошибки решения
void handleMistakes() {
uint32_t currentTime = millis();
static uint32_t prevTime = 0;
static uint8_t prevMistakesNumber = 0;
if (module.mistakesNumber > prevMistakesNumber) {
outputs.rgbLedRed = true;
prevTime = currentTime;
}
if (currentTime - prevTime >= MISTAKE_FLASH_DURATION) {
outputs.rgbLedRed = false;
}
prevMistakesNumber = module.mistakesNumber;
}
// Обрабатывем статусы модуля
void handleModuleStatus() {
if (module.status == SOLVED) {
outputs.rgbLedGreen = true;
}
}
// Записываем состояния выходов из переменных
inline void writeOutputs() {
digitalWrite(MORSE_LED, outputs.morseLed);
digitalWrite(RGB_LED_G, outputs.rgbLedGreen);
digitalWrite(RGB_LED_R, outputs.rgbLedRed);
}Left
Right
TX