#include "dummyLibs.h"
#include "module_setup.h"
Module module; // Объект для работы с параметрами модуля
Device device; // Объект для работы с копией устройства
KTANEBusSlave busSlave(&device, &module, I2C_ADDR); // Объект для работы с KTANEBus как слейв
uint8_t winState = 0; // Состояние переключателей для деактивации модуля
void setup() {
// Конфигурируем входы
for (uint8_t i = 0; i < SWITCHES_NUMBER; i++) {
pinMode(SWITCHES[i], INPUT_PULLUP);
}
// Конфигурируем выходы
pinMode(RGB_LED_R, OUTPUT);
pinMode(RGB_LED_G, OUTPUT);
for (uint8_t i = 0; i < SWITCHES_NUMBER; i++) {
pinMode(SWITCH_LEDS[i], OUTPUT);
}
busSlave.begin();
// Генерируем случайную выигрышную комбинацию,
generateRandomWinState();
module.status = RUNNING;
/*************************************** Debug *******************************************************/
Serial.begin(115200);
}
void loop() {
readInputs();
handleSwitches();
handleMistakes();
handleModuleStatus();
writeOutputs();
/*************************************** Debug *******************************************************/
printDebugInfo();
}
// Генерируем случайную выигрышную комбинацию
inline void generateRandomWinState() {
readInputs();
randomSeed(analogRead(A6) ^ micros());
bool winStateIsBad = true;
// Если сгенерированная комбинация совпала с проигрышной или с текущим положенем переключателей, то начинаем заново
while (winStateIsBad) {
winState = random(1, (1 << SWITCHES_NUMBER) - 1); // Случайное число от 1 до 2^SWITCHES_NUMBER - 2
winStateIsBad = false;
for (uint8_t i = 0; i < LOSE_STATES_NUMBER; i++) {
if (winState == LOSE_STATES[i]) {
winStateIsBad = true;
break;
}
}
if (winState == inputs.switches) {
winStateIsBad = true;
}
}
outputs.switchLeds = winState;
}
// Считываем состояния входов (переключателей)
inline void readInputs() {
inputs.switches = 0;
for (uint8_t i = 0; i < SWITCHES_NUMBER; i++) {
inputs.switches |= digitalRead(SWITCHES[i]) << i;
}
}
// Обрабатываем положение переключателей
inline void handleSwitches() {
static uint8_t prevSwitchesState = inputs.switches;
// Положение переключателей изменилось
if (inputs.switches != prevSwitchesState && module.status == RUNNING) {
prevSwitchesState = inputs.switches;
// Проверяем на выигрыш
if (inputs.switches == winState) {
module.status = SOLVED;
return;
}
// Проверяем на проигрыш
for (uint8_t i = 0; i < LOSE_STATES_NUMBER; i++) {
if (inputs.switches == LOSE_STATES[i]) {
module.mistakesNumber++;
return;
}
}
}
}
// Обрабатываем ошибки решения
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() {
// Пишем состояния светодиодов переключателей
for (uint8_t i = 0; i < SWITCHES_NUMBER; i++) {
digitalWrite(SWITCH_LEDS[i], outputs.switchLeds & (1 << i));
}
digitalWrite(RGB_LED_G, outputs.rgbLedGreen);
digitalWrite(RGB_LED_R, outputs.rgbLedRed);
}
/*************************************** Debug *******************************************************/
void printDebugInfo() {
uint32_t currentTime = millis();
static uint32_t prevTime = 0;
if (currentTime - prevTime > 3000) {
Serial.print(F("mistakes: "));
Serial.println(module.mistakesNumber);
Serial.print(F("module.status: "));
Serial.println(module.status);
Serial.print(F("winning state: "));
Serial.println(winState, BIN);
Serial.print(F("switcthes state: "));
Serial.println(inputs.switches, BIN);
Serial.println(F("------------------"));
prevTime = currentTime;
}
}