Compare commits

...

5 Commits

Author SHA1 Message Date
5ffc2b609b add support for modifed game 2026-04-10 13:38:14 -05:00
3b2f8957e4 p2s2 2026-04-10 12:19:28 -05:00
852939830c Namespace the steps 2026-04-10 11:14:15 -05:00
f5c938d61f switch to event based input system (untested) 2026-04-10 07:58:31 -05:00
2f1ff23678 update pins and stuff to bump to rev 2.x 2026-04-10 07:15:51 -05:00
66 changed files with 2053 additions and 402 deletions

View File

@ -4,7 +4,9 @@ set(SOURCES
"TM1640/TM1640.cpp"
"SparkFunBQ27441/SparkFunBQ27441.cpp"
"esp_lcd_ili9488/esp_lcd_ili9488.c"
"bottom_half.cpp"
# "bottom_half.cpp"
"event_based_bottom_half.cpp"
"inputs.cpp"
"char_lcd.cpp"
"game_timer.cpp"
"i2c_lcd_pcf8574.c"

View File

@ -32,8 +32,8 @@ static void init_i2c() {
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = GPIO_NUM_5,
.scl_io_num = GPIO_NUM_6,
.sda_io_num = PIN_I2C_SDA,
.scl_io_num = PIN_I2C_SCL,
.sda_pullup_en = GPIO_PULLUP_DISABLE,
.scl_pullup_en = GPIO_PULLUP_DISABLE,
// .sda_pullup_en = GPIO_PULLUP_ENABLE,

View File

@ -1,6 +1,9 @@
#ifndef ALL_H
#define ALL_H
#define PIN_I2C_SDA GPIO_NUM_7
#define PIN_I2C_SCL GPIO_NUM_15
#include "char_lcd.h"
#include "bottom_half.h"
#include "sd.h"

View File

@ -190,10 +190,12 @@ static void poll_bottom_task(void *arg) {
// TODO: if using an interupt, switch this to use a queue
while (1) {
bool new_data = gpio_get_level(BOTTOM_PIN_INTERUPT) == 0;
// bool new_data = 1;
if (new_data) {
uint8_t delta = receive_delta();
// ESP_LOGI(_TAG, "delta: %d", delta);
if (delta == 0) ESP_LOGW(TAG, "delta pin was low, but delta register returned 0");
// if (delta == 0) ESP_LOGW(TAG, "delta pin was low, but delta register returned 0");
if (delta != 0) ESP_LOGI(TAG, "delta!");
if (delta & (1 << DELTA_BIT_KP)) receive_keypad();
if (delta & (1 << DELTA_BIT_BUTTON_SWITCH)) receive_button_switch();

View File

@ -6,7 +6,7 @@
#define BOTTOM_I2C_NUM I2C_NUM_0
#define BOTTOM_I2C_ADDR 126
#define BOTTOM_PIN_INTERUPT GPIO_NUM_0
#define BOTTOM_PIN_INTERUPT GPIO_NUM_13
#define DELTA_BIT_KP 0
#define DELTA_BIT_BUTTON_SWITCH 1

View File

@ -128,7 +128,7 @@ static esp_err_t panel_ili9488_init(esp_lcd_panel_t *panel)
// ORIGINAL
lcd_init_cmd_t ili9488_init[] =
{
#if CONFIG_USE_NEW_DISPLAY
#if CONFIG_USE_NEW_DISPLAY || 1
{ ILI9488_POSITIVE_GAMMA_CTL, { 0x00, 0x08, 0x0c, 0x02, 0x0e, 0x04, 0x30, 0x45, 0x47, 0x04, 0x0C, 0x0a, 0x2e, 0x34, 0x0F }, 15 },
{ ILI9488_NEGATIVE_GAMMA_CTL, { 0x00, 0x11, 0x0d, 0x01, 0x0f, 0x05, 0x39, 0x36, 0x51, 0x06, 0x0f, 0x0d, 0x33, 0x37, 0x0F }, 15 },
#else

View File

@ -0,0 +1,326 @@
#include "bottom_half.h"
#include "inputs.hpp"
#include <array>
static uint8_t reverse_4_bits(uint8_t value) {
return static_cast<uint8_t>(((value & 0x1) << 3) |
((value & 0x2) << 1) |
((value & 0x4) >> 1) |
((value & 0x8) >> 3));
}
static KeypadKey map_input_keypad_key(InputKeypadKey key) {
switch (key) {
case InputKeypadKey::K0: return KeypadKey::k0;
case InputKeypadKey::K1: return KeypadKey::k1;
case InputKeypadKey::K2: return KeypadKey::k2;
case InputKeypadKey::K3: return KeypadKey::k3;
case InputKeypadKey::K4: return KeypadKey::k4;
case InputKeypadKey::K5: return KeypadKey::k5;
case InputKeypadKey::K6: return KeypadKey::k6;
case InputKeypadKey::K7: return KeypadKey::k7;
case InputKeypadKey::K8: return KeypadKey::k8;
case InputKeypadKey::K9: return KeypadKey::k9;
case InputKeypadKey::A: return KeypadKey::ka;
case InputKeypadKey::B: return KeypadKey::kb;
case InputKeypadKey::C: return KeypadKey::kc;
case InputKeypadKey::D: return KeypadKey::kd;
case InputKeypadKey::STAR: return KeypadKey::star;
case InputKeypadKey::POUND: return KeypadKey::pound;
default: return KeypadKey::k0;
}
}
static uint8_t get_fingerprint_touch_state() {
InputsState current = InputsController::get_input_state();
return static_cast<uint8_t>((current.touch_state >> 4) & 0x1);
}
static bool touch_state_initialized = false;
static bool touch_state_last = false;
static bool update_fingerprint_transition(bool want_pressed) {
bool current = get_fingerprint_touch_state();
if (!touch_state_initialized) {
touch_state_last = current;
touch_state_initialized = true;
return false;
}
bool transition = want_pressed ? (current && !touch_state_last)
: (!current && touch_state_last);
touch_state_last = current;
return transition;
}
static std::array<SwitchFlip, 8> pending_switch_flips;
static size_t pending_switch_flip_count = 0;
static void push_pending_switch_flip(const SwitchFlip& event) {
if (pending_switch_flip_count < pending_switch_flips.size()) {
pending_switch_flips[pending_switch_flip_count++] = event;
return;
}
// Drop the oldest event if the buffer is full.
for (size_t i = 1; i < pending_switch_flips.size(); ++i) {
pending_switch_flips[i - 1] = pending_switch_flips[i];
}
pending_switch_flips.back() = event;
}
static bool pop_pending_switch_flip(bool want_up, SwitchFlip& out) {
for (size_t i = 0; i < pending_switch_flip_count; ++i) {
if (pending_switch_flips[i].is_up() == want_up) {
out = pending_switch_flips[i];
for (size_t j = i + 1; j < pending_switch_flip_count; ++j) {
pending_switch_flips[j - 1] = pending_switch_flips[j];
}
--pending_switch_flip_count;
return true;
}
}
return false;
}
static void clear_pending_switch_flips() {
pending_switch_flip_count = 0;
}
static std::array<SwitchTouch, 8> pending_switch_touches;
static size_t pending_switch_touch_count = 0;
static void push_pending_switch_touch(const SwitchTouch& event) {
if (pending_switch_touch_count < pending_switch_touches.size()) {
pending_switch_touches[pending_switch_touch_count++] = event;
return;
}
for (size_t i = 1; i < pending_switch_touches.size(); ++i) {
pending_switch_touches[i - 1] = pending_switch_touches[i];
}
pending_switch_touches.back() = event;
}
static bool pop_pending_switch_touch(bool want_touched, SwitchTouch& out) {
for (size_t i = 0; i < pending_switch_touch_count; ++i) {
if (pending_switch_touches[i].is_touched() == want_touched) {
out = pending_switch_touches[i];
for (size_t j = i + 1; j < pending_switch_touch_count; ++j) {
pending_switch_touches[j - 1] = pending_switch_touches[j];
}
--pending_switch_touch_count;
return true;
}
}
return false;
}
static void clear_pending_switch_touches() {
pending_switch_touch_count = 0;
}
void init_bottom_half() {
init_expander();
clear_all_pressed_released();
}
void clear_all_pressed_released() {
InputsController::clear_all_events();
clear_pending_switch_flips();
clear_pending_switch_touches();
touch_state_initialized = false;
}
bool get_keypad_pressed(KeypadKey* kp) {
auto opt = InputsController::get_keypad_press();
if (!opt.has_value()) {
return false;
}
if (kp != nullptr) {
*kp = map_input_keypad_key(opt.value());
}
return true;
}
bool get_keypad_released(KeypadKey* kp) {
auto opt = InputsController::get_keypad_release();
if (!opt.has_value()) {
return false;
}
if (kp != nullptr) {
*kp = map_input_keypad_key(opt.value());
}
return true;
}
char char_of_keypad_key(KeypadKey kp) {
switch (kp) {
case KeypadKey::k1: return '1';
case KeypadKey::k2: return '2';
case KeypadKey::k3: return '3';
case KeypadKey::k4: return '4';
case KeypadKey::k5: return '5';
case KeypadKey::k6: return '6';
case KeypadKey::k7: return '7';
case KeypadKey::k8: return '8';
case KeypadKey::k9: return '9';
case KeypadKey::k0: return '0';
case KeypadKey::ka: return 'A';
case KeypadKey::kb: return 'B';
case KeypadKey::kc: return 'C';
case KeypadKey::kd: return 'D';
case KeypadKey::star: return '*';
case KeypadKey::pound: return '#';
default: return ' ';
}
}
static bool take_button(ButtonKey* button, std::optional<Button> opt) {
if (!opt.has_value()) {
return false;
}
if (button != nullptr) {
*button = static_cast<ButtonKey>(static_cast<uint8_t>(opt.value()));
}
return true;
}
bool get_button_pressed(ButtonKey* button) {
return take_button(button, InputsController::get_button_press());
}
bool get_button_released(ButtonKey* button) {
return take_button(button, InputsController::get_button_release());
}
uint8_t get_button_state() {
return reverse_4_bits(InputsController::button_state() & 0xF);
}
static bool take_switch_key(SwitchKey* switch_, const SwitchFlip& event) {
if (switch_ != nullptr) {
*switch_ = static_cast<SwitchKey>(static_cast<uint8_t>(event.get_switch()));
}
return true;
}
bool get_switch_flipped_up(SwitchKey* switch_) {
SwitchFlip event;
if (pop_pending_switch_flip(true, event)) {
return take_switch_key(switch_, event);
}
while (true) {
auto opt = InputsController::get_switch_flip();
if (!opt.has_value()) {
return false;
}
if (opt->is_up()) {
return take_switch_key(switch_, *opt);
}
push_pending_switch_flip(*opt);
}
}
bool get_switch_flipped_down(SwitchKey* switch_) {
SwitchFlip event;
if (pop_pending_switch_flip(false, event)) {
return take_switch_key(switch_, event);
}
while (true) {
auto opt = InputsController::get_switch_flip();
if (!opt.has_value()) {
return false;
}
if (!opt->is_up()) {
return take_switch_key(switch_, *opt);
}
push_pending_switch_flip(*opt);
}
}
bool get_switch_flipped(SwitchKey* switch_) {
if (pending_switch_flip_count > 0) {
SwitchFlip event = pending_switch_flips[0];
for (size_t i = 1; i < pending_switch_flip_count; ++i) {
pending_switch_flips[i - 1] = pending_switch_flips[i];
}
--pending_switch_flip_count;
return take_switch_key(switch_, event);
}
auto opt = InputsController::get_switch_flip();
if (!opt.has_value()) {
return false;
}
return take_switch_key(switch_, *opt);
}
uint8_t get_switch_state() {
return reverse_4_bits(InputsController::switch_state() & 0xF);
}
static bool take_switch_touch(SwitchKey* switch_, const SwitchTouch& event) {
if (switch_ != nullptr) {
*switch_ = static_cast<SwitchKey>(static_cast<uint8_t>(event.get_switch()));
}
return true;
}
bool get_switch_touch_pressed(SwitchKey* switch_) {
SwitchTouch event;
if (pop_pending_switch_touch(true, event)) {
return take_switch_touch(switch_, event);
}
while (true) {
auto opt = InputsController::get_switch_touch();
if (!opt.has_value()) {
return false;
}
if (opt->is_touched()) {
return take_switch_touch(switch_, *opt);
}
push_pending_switch_touch(*opt);
}
}
bool get_switch_touch_released(SwitchKey* switch_) {
SwitchTouch event;
if (pop_pending_switch_touch(false, event)) {
return take_switch_touch(switch_, event);
}
while (true) {
auto opt = InputsController::get_switch_touch();
if (!opt.has_value()) {
return false;
}
if (!opt->is_touched()) {
return take_switch_touch(switch_, *opt);
}
push_pending_switch_touch(*opt);
}
}
uint8_t get_switch_touch_state() {
return reverse_4_bits(InputsController::switch_touch_state() & 0xF);
}
bool get_touch_state() {
return get_fingerprint_touch_state() != 0;
}
bool get_touch_pressed() {
return update_fingerprint_transition(true);
}
bool get_touch_released() {
return update_fingerprint_transition(false);
}

475
main/drivers/inputs.cpp Normal file
View File

@ -0,0 +1,475 @@
#include "inputs.hpp"
#include "pins.h"
#include "driver/i2c.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_err.h"
static const char *TAG = "INPUTS";
static TaskHandle_t expander_task_handle = NULL;
const static uint8_t REG_WHOAMI = 0x01;
const static uint8_t REG_SW_VERSION = 0x02;
const static uint8_t REG_EVENT_QUEUE_POP = 0x10;
const static uint8_t REG_EVENT_QUEUE_LEN = 0x11;
const static uint8_t REG_STATE_BUTTONS = 0x20;
const static uint8_t REG_STATE_SWITCHES = 0x21;
const static uint8_t REG_STATE_KEYPAD = 0x22;
const static uint8_t REG_STATE_TOUCH = 0x23;
const static uint8_t REG_STATE_RFID = 0x24;
const static uint8_t REG_STATE_HALL = 0x25;
const static uint8_t REG_STATE_CLOSE = 0x26;
const static uint8_t REG_RESET = 0x30;
const static uint8_t REG_HALL_SENSITIVITY = 0x31;
const static uint8_t REG_CLOSE_SENSITIVITY = 0x32;
const static uint8_t REG_SWITCH_TOUCH_EVENT = 0x33;
/// The global data for the expander peripheral.
class ExpanderPeripheral {
// TODO: change these to private
// or even make this class hidden
public:
SemaphoreHandle_t state_mutex;
InputsState state;
// channels
QueueHandle_t button_press_events;
QueueHandle_t button_release_events;
QueueHandle_t switch_flip_events;
QueueHandle_t switch_touch_events;
QueueHandle_t touch_events;
QueueHandle_t keypad_press_events;
QueueHandle_t keypad_release_events;
};
ExpanderPeripheral expander_peripheral_singleton;
// forward declarations
static void get_events();
static void handle_event(uint8_t event);
static void handle_button_switch_event(uint8_t event);
static void handle_keypad_event(uint8_t event);
static void handle_touch_event(uint8_t event);
static void handle_rfid_event(uint8_t event);
static void handle_close_hal_event(uint8_t event);
static void expander_task(void *arg);
// ISR handler
static void IRAM_ATTR expander_isr_handler(void *arg) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (expander_task_handle != NULL) {
vTaskNotifyGiveFromISR(expander_task_handle, &xHigherPriorityTaskWoken);
}
if (xHigherPriorityTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
void init_expander() {
ESP_LOGI(TAG, "Initializing expander...");
// legacy I2C driver: use the shared I2C_NUM_0 bus already configured elsewhere.
// TODO: replace all these ESP_ERROR_CHECK with proper error handling that doesn't just crash the program
// setup interrupt on PIN_EXPANDER_INT
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << PIN_EXPANDER_INT),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_NEGEDGE
};
ESP_ERROR_CHECK(gpio_config(&io_conf));
// Install ISR service (only call once in your program)
ESP_ERROR_CHECK(gpio_install_isr_service(0));
// Attach the ISR to the expander pin
ESP_ERROR_CHECK(gpio_isr_handler_add(PIN_EXPANDER_INT, expander_isr_handler, NULL));
// verify the expander connection status by reading the WHOAMI register
uint8_t read_buf[2] = {0};
ESP_ERROR_CHECK(i2c_master_write_read_device(I2C_NUM_0, EXPANDER_I2C_ADDR, &REG_WHOAMI, 1, read_buf, 1, pdMS_TO_TICKS(EXPANDER_TIMEOUT_MS)));
if (read_buf[0] != EXPANDER_WHOAMI_VALUE) {
ESP_LOGE(TAG, "WHOAMI mismatch, expected 0x%02X, got 0x%02X", EXPANDER_WHOAMI_VALUE, read_buf[0]);
return;
}
ESP_LOGD(TAG, "Expander WHOAMI check passed");
ESP_ERROR_CHECK(i2c_master_write_read_device(I2C_NUM_0, EXPANDER_I2C_ADDR, &REG_SW_VERSION, 1, read_buf, 2, pdMS_TO_TICKS(EXPANDER_TIMEOUT_MS)));
// init the peripheral struct
expander_peripheral_singleton.state_mutex = xSemaphoreCreateMutex();
expander_peripheral_singleton.button_press_events= xQueueCreate(EXPANDER_EVENT_QUEUE_SIZE, sizeof(Button));
expander_peripheral_singleton.button_release_events= xQueueCreate(EXPANDER_EVENT_QUEUE_SIZE, sizeof(Button));
expander_peripheral_singleton.switch_flip_events= xQueueCreate(EXPANDER_EVENT_QUEUE_SIZE, sizeof(SwitchFlip));
expander_peripheral_singleton.switch_touch_events= xQueueCreate(EXPANDER_EVENT_QUEUE_SIZE, sizeof(SwitchTouch));
expander_peripheral_singleton.touch_events= xQueueCreate(EXPANDER_EVENT_QUEUE_SIZE, sizeof(TouchedReleased));
expander_peripheral_singleton.keypad_press_events= xQueueCreate(EXPANDER_KEYPAD_QUEUE_SIZE, sizeof(InputKeypadKey));
expander_peripheral_singleton.keypad_release_events= xQueueCreate(EXPANDER_KEYPAD_QUEUE_SIZE, sizeof(InputKeypadKey));
ESP_LOGI(TAG, "Expander initialized! SW version: v%d.%d", read_buf[0], read_buf[1]);
// Create the expander background worker task
BaseType_t task_created = xTaskCreate(
expander_task,
"expander_task",
4096,
NULL,
tskIDLE_PRIORITY + 1,
&expander_task_handle
);
if (task_created != pdPASS) {
ESP_LOGE(TAG, "Failed to create expander task");
}
}
static void expander_task(void *arg) {
(void)arg;
while (true) {
get_events();
// Wait for interrupt notification (signal is sent when INT falls)
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
}
}
static void get_events() {
uint8_t recv;
while (gpio_get_level(PIN_EXPANDER_INT) == 0) {
ESP_ERROR_CHECK(i2c_master_write_read_device(I2C_NUM_0, EXPANDER_I2C_ADDR, &REG_EVENT_QUEUE_POP, 1, &recv, 1, pdMS_TO_TICKS(EXPANDER_TIMEOUT_MS)));
handle_event(recv);
}
}
static void handle_event(uint8_t event) {
const uint8_t BUTTON_SWITCH = 0b000;
const uint8_t KEYPAD = 0b001;
const uint8_t TOUCH = 0b010;
const uint8_t RFID = 0b011;
ESP_LOGD(TAG, "Expander event: 0b%08b (0x%02X)", event, event);
if (event == 0) {
ESP_LOGE(TAG, "We read from event queue while it was empty!");
return;
}
uint8_t type_bits = event >> 5;
switch (type_bits) {
case BUTTON_SWITCH:
handle_button_switch_event(event);
break;
case KEYPAD:
handle_keypad_event(event);
break;
case TOUCH:
handle_touch_event(event);
break;
case RFID:
handle_rfid_event(event);
break;
default:
handle_close_hal_event(event);
break;
}
}
static void handle_button_switch_event(uint8_t event) {
const uint8_t PRESSED_NOT_RELEASED_BIT = 0b10000;
const uint8_t SWITCH_NOT_BUTTON_BIT = 0b01000;
const uint8_t SWITCH_UP_NOT_DOWN_BIT = 0b00100;
const uint8_t NUMBER_MASK = 0b00011;
bool pressed = (event & PRESSED_NOT_RELEASED_BIT) != 0;
uint8_t number = event & NUMBER_MASK;
if ((event & SWITCH_NOT_BUTTON_BIT) != 0) {
// For now, we support two position switches by only looking at the switch up events
bool switch_up = (event & SWITCH_UP_NOT_DOWN_BIT) != 0;
if (!switch_up) {
return;
}
Switch sw = static_cast<Switch>(number);
SwitchFlip sw_flip = SwitchFlip(sw, pressed);
xQueueSendToBack(expander_peripheral_singleton.switch_flip_events, &sw_flip, 0);
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
if (pressed) {
// set
expander_peripheral_singleton.state.switch_state |= 1 << number;
} else {
// clear
expander_peripheral_singleton.state.switch_state &= ~(1 << number);
}
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
} else {
// button
Button button = static_cast<Button>(number);
if (pressed) {
xQueueSendToBack(expander_peripheral_singleton.button_press_events, &button, 0);
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
expander_peripheral_singleton.state.button_state |= 1 << number;
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
} else {
xQueueSendToBack(expander_peripheral_singleton.button_release_events, &button, 0);
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
expander_peripheral_singleton.state.button_state &= ~(1 << number);
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
}
}
}
static void handle_keypad_event(uint8_t event) {
const uint8_t PRESSED_NOT_RELEASED_BIT = 0b10000;
const uint8_t KEY_MASK = 0b1111;
bool pressed = (event & PRESSED_NOT_RELEASED_BIT) != 0;
uint8_t number = event & KEY_MASK;
InputKeypadKey key = static_cast<InputKeypadKey>(number);
// starcode system gets first dibs
// TODO: do starcode inbetweener
// if starcode_handle_keypad(key, pressed).await {
// return;
// }
if (pressed) {
xQueueSendToBack(expander_peripheral_singleton.keypad_press_events, &key, 0);
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
expander_peripheral_singleton.state.keypad_state |= 1 << number;
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
} else {
xQueueSendToBack(expander_peripheral_singleton.keypad_release_events, &key, 0);
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
expander_peripheral_singleton.state.keypad_state &= ~(1 << number);
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
}
}
static void handle_touch_event(uint8_t event) {
const uint8_t TOUCHED_NOT_UNTOUCHED_BIT = 0b10000;
const uint8_t SENSOR_MASK = 0b0111;
const uint8_t FINGERPRINT_BIT = 0b0100;
bool touched = (event & TOUCHED_NOT_UNTOUCHED_BIT) != 0;
uint8_t sensor = event & SENSOR_MASK;
if ((sensor & FINGERPRINT_BIT) != 0) {
TouchedReleased touch_state = static_cast<TouchedReleased>(touched);
xQueueSendToBack(expander_peripheral_singleton.touch_events, &touch_state, 0);
} else {
Switch sw = static_cast<Switch>(sensor);
SwitchTouch sw_touch = SwitchTouch(sw, touched);
xQueueSendToBack(expander_peripheral_singleton.switch_touch_events, &sw_touch, 0);
}
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
if (touched) {
expander_peripheral_singleton.state.touch_state |= 1 << sensor;
} else {
expander_peripheral_singleton.state.touch_state &= ~(1 << sensor);
}
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
}
static void handle_rfid_event(uint8_t event) {
// TODO: impl
(void)event;
}
static void handle_close_hal_event(uint8_t event) {
// TODO: impl
(void)event;
}
// InputsController implementations
/// Clears all events waiting in the queues.
void InputsController::clear_all_events() {
xQueueReset(expander_peripheral_singleton.button_press_events);
xQueueReset(expander_peripheral_singleton.button_release_events);
xQueueReset(expander_peripheral_singleton.switch_flip_events);
xQueueReset(expander_peripheral_singleton.switch_touch_events);
xQueueReset(expander_peripheral_singleton.touch_events);
xQueueReset(expander_peripheral_singleton.keypad_press_events);
xQueueReset(expander_peripheral_singleton.keypad_release_events);
}
InputsState InputsController::get_input_state() {
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
InputsState state_copy = expander_peripheral_singleton.state;
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
return state_copy;
}
/// Returns `true` iff there is a button press event waiting.
bool InputsController::has_button_press() {
return uxQueueMessagesWaiting(expander_peripheral_singleton.button_press_events) > 0;
}
/// Gets the next button press event (if any).
std::optional<Button> InputsController::get_button_press() {
Button b;
if (xQueueReceive(expander_peripheral_singleton.button_press_events, &b, 0) == pdTRUE) {
return b;
}
return std::nullopt;
}
/// Gets the next button press event, waiting if neccesary.
Button InputsController::wait_button_press() {
Button b;
xQueueReceive(expander_peripheral_singleton.button_press_events, &b, portMAX_DELAY);
return b;
}
/// Gets the current state of the buttons.
uint8_t InputsController::button_state() {
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
uint8_t value = expander_peripheral_singleton.state.button_state;
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
return value;
}
/// Returns `true` iff there is a button release event waiting.
bool InputsController::has_button_release() {
return uxQueueMessagesWaiting(expander_peripheral_singleton.button_release_events) > 0;
}
/// Gets the next button release event (if any).
std::optional<Button> InputsController::get_button_release() {
Button b;
if (xQueueReceive(expander_peripheral_singleton.button_release_events, &b, 0) == pdTRUE) {
return b;
}
return std::nullopt;
}
/// Gets the next button release event, waiting if neccesary.
Button InputsController::wait_button_release() {
Button b;
xQueueReceive(expander_peripheral_singleton.button_release_events, &b, portMAX_DELAY);
return b;
}
/// Returns `true` iff there is a switch flip event waiting.
bool InputsController::has_switch_flip() {
return uxQueueMessagesWaiting(expander_peripheral_singleton.switch_flip_events) > 0;
}
/// Gets the next switch flip event (if any).
std::optional<SwitchFlip> InputsController::get_switch_flip() {
SwitchFlip s;
if (xQueueReceive(expander_peripheral_singleton.switch_flip_events, &s, 0) == pdTRUE) {
return s;
}
return std::nullopt;
}
/// Gets the next switch flip event, waiting if neccesary.
SwitchFlip InputsController::wait_switch_flip() {
SwitchFlip s;
xQueueReceive(expander_peripheral_singleton.switch_flip_events, &s, portMAX_DELAY);
return s;
}
/// Gets the current state of the switches.
uint8_t InputsController::switch_state() {
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
uint8_t value = expander_peripheral_singleton.state.switch_state;
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
return value;
}
/// Returns `true` iff there is a switch touch event waiting.
bool InputsController::has_switch_touch() {
return uxQueueMessagesWaiting(expander_peripheral_singleton.switch_touch_events) > 0;
}
/// Gets the next switch touch event (if any).
std::optional<SwitchTouch> InputsController::get_switch_touch() {
SwitchTouch s;
if (xQueueReceive(expander_peripheral_singleton.switch_touch_events, &s, 0) == pdTRUE) {
return s;
}
return std::nullopt;
}
/// Gets the next switch touch event, waiting if neccesary.
SwitchTouch InputsController::wait_switch_touch() {
SwitchTouch s;
xQueueReceive(expander_peripheral_singleton.switch_touch_events, &s, portMAX_DELAY);
return s;
}
/// Gets the current state of the touch sensors.
uint8_t InputsController::switch_touch_state() {
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
uint8_t value = expander_peripheral_singleton.state.touch_state;
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
return value;
}
/// Returns `true` iff there is a keypad press event waiting.
bool InputsController::has_keypad_press() {
return uxQueueMessagesWaiting(expander_peripheral_singleton.keypad_press_events) > 0;
}
/// Gets the next keypad press event (if any).
std::optional<InputKeypadKey> InputsController::get_keypad_press() {
InputKeypadKey k;
if (xQueueReceive(expander_peripheral_singleton.keypad_press_events, &k, 0) == pdTRUE) {
return k;
}
return std::nullopt;
}
/// Gets the next keypad press event, waiting if neccesary.
InputKeypadKey InputsController::wait_keypad_press() {
InputKeypadKey k;
xQueueReceive(expander_peripheral_singleton.keypad_press_events, &k, portMAX_DELAY);
return k;
}
/// Returns `true` iff there is a keypad release event waiting.
bool InputsController::has_keypad_release() {
return uxQueueMessagesWaiting(expander_peripheral_singleton.keypad_release_events) > 0;
}
/// Gets the next keypad release event (if any).
std::optional<InputKeypadKey> InputsController::get_keypad_release() {
InputKeypadKey k;
if (xQueueReceive(expander_peripheral_singleton.keypad_release_events, &k, 0) == pdTRUE) {
return k;
}
return std::nullopt;
}
/// Gets the next keypad release event, waiting if neccesary.
InputKeypadKey InputsController::wait_keypad_release() {
InputKeypadKey k;
xQueueReceive(expander_peripheral_singleton.keypad_release_events, &k, portMAX_DELAY);
return k;
}
/// Gets the current state of the keypad.
uint16_t InputsController::keypad_state() {
xSemaphoreTake(expander_peripheral_singleton.state_mutex, portMAX_DELAY);
uint16_t value = expander_peripheral_singleton.state.keypad_state;
xSemaphoreGive(expander_peripheral_singleton.state_mutex);
return value;
}

275
main/drivers/inputs.hpp Normal file
View File

@ -0,0 +1,275 @@
#ifndef INPUTS_H
#define INPUTS_H
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include <freertos/semphr.h>
#include <optional>
#define EXPANDER_I2C_ADDR (0x7E)
#define EXPANDER_I2C_SPEED (400000)
// the actual transaction takes ~0.3ms, but for some reason a timout of ~10 or lower causes issues.
#define EXPANDER_TIMEOUT_MS (100)
#define EXPANDER_WHOAMI_VALUE (0x85)
// queue sizes
#define EXPANDER_EVENT_QUEUE_SIZE 4
#define EXPANDER_KEYPAD_QUEUE_SIZE 16
void init_expander();
/// The four buttons on the bottom half.
enum class Button: uint8_t {
B1 = 0,
B2 = 1,
B3 = 2,
B4 = 3,
GREEN = 0,
RED = 1,
YELLOW = 2,
BLUE = 3,
};
constexpr uint8_t raw_value(Button v) { return static_cast<uint8_t>(v); }
constexpr Button button_from_raw(uint8_t raw) { return static_cast<Button>(raw & 0b11); }
/// The four switches on the bottom half.
enum class Switch: uint8_t {
S1 = 0,
S2 = 1,
S3 = 2,
S4 = 3,
};
constexpr uint8_t raw_value(Switch v) { return static_cast<uint8_t>(v); }
constexpr Switch switch_from_raw(uint8_t raw) { return static_cast<Switch>(raw & 0b11); }
enum class TouchedReleased: uint8_t {
Released = 0,
Touched = 1,
};
constexpr uint8_t raw_value(TouchedReleased v) { return static_cast<uint8_t>(v); }
constexpr TouchedReleased touched_released_from_raw(uint8_t raw) { return static_cast<TouchedReleased>(raw & 0b1); }
/// One of the keys on the keypad.
enum class InputKeypadKey: uint8_t {
K0 = 0,
K1 = 1,
K2 = 2,
K3 = 3,
K4 = 4,
K5 = 5,
K6 = 6,
K7 = 7,
K8 = 8,
K9 = 9,
A = 10,
B = 11,
C = 12,
D = 13,
STAR = 14,
POUND = 15,
};
constexpr uint8_t raw_value(InputKeypadKey v) { return static_cast<uint8_t>(v); }
constexpr InputKeypadKey keypad_key_from_raw(uint8_t raw) { return static_cast<InputKeypadKey>(raw & 0b1111); }
constexpr char keypad_key_to_char(InputKeypadKey key) {
static constexpr char lookup[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', '*', '#'
};
return lookup[static_cast<uint8_t>(key) & 0b1111];
}
struct SwitchFlip {
private:
// [bit2: up] [bit1-0: switch]
uint8_t data;
public:
// Constructor
SwitchFlip(Switch sw, bool up)
: data((static_cast<uint8_t>(sw) & 0b11) |
((up ? 1 : 0) << 2)) {}
// Default constructor
SwitchFlip() : data(0) {}
// Raw value constructor
explicit SwitchFlip(uint8_t raw_data) : data(raw_data) {}
// Raw value getter
uint8_t raw() const { return data; }
// Getters
Switch get_switch() const {
return static_cast<Switch>(data & 0b11);
}
bool is_up() const {
return (data >> 2) & 1;
}
// Setters
void set_switch(Switch sw) {
data = (data & ~0b11) | (static_cast<uint8_t>(sw) & 0b11);
}
void set_up(bool up) {
data = (data & ~(1 << 2)) | ((up ? 1 : 0) << 2);
}
};
static_assert(sizeof(SwitchFlip) == 1);
struct SwitchTouch {
private:
// [bit2: touched] [bit1-0: switch]
uint8_t data;
public:
// Constructor
SwitchTouch(Switch sw, bool touched)
: data((static_cast<uint8_t>(sw) & 0b11) |
((touched ? 1 : 0) << 2)) {}
// Default constructor
SwitchTouch() : data(0) {}
// Raw value constructor
explicit SwitchTouch(uint8_t raw_data) : data(raw_data) {}
// Raw value getter
uint8_t raw() const { return data; }
// Getters
Switch get_switch() const {
return static_cast<Switch>(data & 0b11);
}
bool is_touched() const {
return (data >> 2) & 1;
}
// Setters
void set_switch(Switch sw) {
data = (data & ~0b11) | (static_cast<uint8_t>(sw) & 0b11);
}
void set_touched(bool touched) {
data = (data & ~(1 << 2)) | ((touched ? 1 : 0) << 2);
}
};
static_assert(sizeof(SwitchTouch) == 1);
struct ButtonOrSwitch {
private:
// [bit2: is_switch] [bit1-0: number]
uint8_t data;
public:
// Constructor
ButtonOrSwitch(uint8_t number, bool is_switch)
: data((number & 0b11) |
((is_switch ? 1 : 0) << 2)) {}
ButtonOrSwitch() : data(0) {}
// Raw value constructor
explicit ButtonOrSwitch(uint8_t raw_data) : data(raw_data) {}
// Raw value getter
uint8_t raw() const { return data; }
// Getters
uint8_t number() const {
return data & 0b11;
}
bool is_switch() const {
return (data >> 2) & 1;
}
// Setters
void set_number(uint8_t number) {
data = (data & ~0b11) | (number & 0b11);
}
void set_is_switch(bool is_switch) {
data = (data & ~(1 << 2)) | ((is_switch ? 1 : 0) << 2);
}
};
static_assert(sizeof(ButtonOrSwitch) == 1);
/// @brief The state of the bottom half of the box.
struct InputsState {
/// The touch state of the switches in the lower 4 bits.
/// The touch pad state in bit 4.
uint8_t touch_state;
/// The current state of the buttons in the lower 4 bits.
uint8_t button_state;
/// The current state of the switches. Up switches are stored
/// in the lower 4 bits, switches that are down are stored in
/// the upper 4 bits. If switches are in the middle, the
/// corresponding bit will be `0` in the upper and lower 4.
uint8_t switch_state;
/// The state of the keypad.
uint16_t keypad_state;
/// The sensitivity of the `hal` value to auto update.
uint16_t hal_sense;
/// The sensitivity of the `close_hal` value to auto update.
uint16_t close_hal_sense;
/// A non-exact hal value reading.
/// This only gets updated when it changes by `hal_sense`
uint16_t hal;
/// A non-exact hal value reading.
/// This only gets updated when it changes by `close_hal_sense`
uint16_t close_hal;
/// The RFID card that was presented last.
uint32_t rfid_state;
InputsState() : touch_state(0), button_state(0), switch_state(0), keypad_state(0), hal_sense(0), close_hal_sense(0), hal(0), close_hal(0), rfid_state(0) {}
};
class InputsController {
public:
static void clear_all_events();
static InputsState get_input_state();
static bool has_button_press();
static std::optional<Button> get_button_press();
static Button wait_button_press();
static uint8_t button_state();
static bool has_button_release();
static std::optional<Button> get_button_release();
static Button wait_button_release();
static bool has_switch_flip();
static std::optional<SwitchFlip> get_switch_flip();
static SwitchFlip wait_switch_flip();
static uint8_t switch_state();
static bool has_switch_touch();
static std::optional<SwitchTouch> get_switch_touch();
static SwitchTouch wait_switch_touch();
static uint8_t switch_touch_state();
static bool has_keypad_press();
static std::optional<InputKeypadKey> get_keypad_press();
static InputKeypadKey wait_keypad_press();
static bool has_keypad_release();
static std::optional<InputKeypadKey> get_keypad_release();
static InputKeypadKey wait_keypad_release();
static uint16_t keypad_state();
// TODO: impl and add the hal and RFID stuff
};
#endif // INPUTS_H

View File

@ -1,10 +1,23 @@
#ifndef LEDS_H
#define LEDS_H
#include "main.h"
#include <stdint.h>
#define LED_COUNT 21
#define NEOPIXEL_PIN GPIO_NUM_7
#ifdef CONTROL_REV_2_0
#define NEOPIXEL_PIN GPIO_NUM_0
#endif
#ifdef CONTROL_REV_2_1
#define NEOPIXEL_PIN GPIO_NUM_21
#endif
#ifndef CONTROL_REV_2_0
#ifndef CONTROL_REV_2_1
#error "define rev2.0 or rev2.1"
#endif
#endif
// 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)

48
main/drivers/pins.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef PINS_H
#define PINS_H
#include "driver/gpio.h"
// ONLY INPUTS.HPP uses this file
#define PIN_SDA (GPIO_NUM_7)
#define PIN_SCL (GPIO_NUM_15)
#define PIN_LCD_MISO (GPIO_NUM_16)
#define PIN_LCD_MOSI (GPIO_NUM_17)
#define PIN_LCD_CLK (GPIO_NUM_18)
#define PIN_LCD_RS (GPIO_NUM_8)
#define PIN_LCD_RST (GPIO_NUM_9)
#define PIN_USB_DM (GPIO_NUM_19)
#define PIN_USB_DP (GPIO_NUM_20)
#define PIN_I2S_DAT (GPIO_NUM_3)
#define PIN_I2S_BCLK (GPIO_NUM_11)
#define PIN_I2S_LRCLK (GPIO_NUM_12)
#define PIN_SSEG_DAT (GPIO_NUM_46)
#define PIN_SSEG_CLK (GPIO_NUM_48)
#define PIN_MPU_INT (GPIO_NUM_10)
#define PIN_EXPANDER_INT (GPIO_NUM_13)
#define PIN_IR_RCV (GPIO_NUM_14)
// #define PIN_NEOPIXEL (GPIO_NUM_21) // Rev 2.1
#define PIN_NEOPIXEL (GPIO_NUM_0) // Rev 2.0
#define PIN_SD_DAT0 (GPIO_NUM_38)
#define PIN_SD_DAT1 (GPIO_NUM_47)
#define PIN_SD_DAT2 (GPIO_NUM_42)
#define PIN_SD_DAT3 (GPIO_NUM_41)
#define PIN_SD_CMD (GPIO_NUM_40)
#define PIN_SD_CLK (GPIO_NUM_39)
#define PIN_PERH0 (GPIO_NUM_6)
#define PIN_PERH1 (GPIO_NUM_5)
#define PIN_PERH2 (GPIO_NUM_4)
#define PIN_PERH3 (GPIO_NUM_2)
#define PIN_PERH4 (GPIO_NUM_1)
#endif // PINS_H

View File

@ -1,6 +1,7 @@
#ifndef SD_H
#define SD_H
#include "main.h"
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
@ -12,12 +13,18 @@
extern sdmmc_card_t *card;
#define SD_PIN_CLK GPIO_NUM_48
#define SD_PIN_CMD GPIO_NUM_45
#define SD_PIN_D0 GPIO_NUM_47
#define SD_PIN_D1 GPIO_NUM_21
#define SD_PIN_D2 GPIO_NUM_39
#define SD_PIN_D3 GPIO_NUM_38
#define SD_PIN_CLK GPIO_NUM_39
#define SD_PIN_CMD GPIO_NUM_40
#define SD_PIN_D0 GPIO_NUM_38
#define SD_PIN_D2 GPIO_NUM_42
#define SD_PIN_D3 GPIO_NUM_41
#ifdef CONTROL_REV_2_0
#define SD_PIN_D1 GPIO_NUM_45
#endif
#ifdef CONTROL_REV_2_1
#define SD_PIN_D1 GPIO_NUM_47
#endif
/// @brief Initializes the SD card
///

View File

@ -15,8 +15,8 @@
#include "sdkconfig.h"
#include "sd.h"
#define SPEAKER_PIN_BCLK GPIO_NUM_46
#define SPEAKER_PIN_WS GPIO_NUM_9
#define SPEAKER_PIN_BCLK GPIO_NUM_11
#define SPEAKER_PIN_WS GPIO_NUM_12
#define SPEAKER_PIN_DOUT GPIO_NUM_3
#define SAMPLE_RATE 44100
// The maximum number of clips that can be queued at one time.

View File

@ -4,8 +4,8 @@
#include "TM1640/TM1640.h"
#include <esp_log.h>
#define SSEG_PIN_DATA GPIO_NUM_10
#define SSEG_PIN_CLK GPIO_NUM_11
#define SSEG_PIN_DATA GPIO_NUM_46
#define SSEG_PIN_CLK GPIO_NUM_48
extern TM1640* sseg;

View File

@ -44,11 +44,11 @@
#define SPI_MAX_TRANSFER_SIZE 32768
#define TFT_PIN_MOSI GPIO_NUM_17
#define TFT_PIN_MISO GPIO_NUM_18
#define TFT_PIN_CLK GPIO_NUM_16
#define TFT_PIN_MISO GPIO_NUM_16
#define TFT_PIN_CLK GPIO_NUM_18
#define TFT_PIN_CS GPIO_NUM_NC
#define TFT_PIN_DC GPIO_NUM_15
#define TFT_PIN_RESET GPIO_NUM_8
#define TFT_PIN_DC GPIO_NUM_8
#define TFT_PIN_RESET GPIO_NUM_9
#define TFT_INVERT_COLOR false

View File

@ -26,8 +26,8 @@ static void receive_button(void);
void init_wires(void) {
i2c_config_t wires_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = GPIO_NUM_41,
.scl_io_num = GPIO_NUM_42,
.sda_io_num = PIN_WIRES_SDA,
.scl_io_num = PIN_WIRES_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master = {
@ -35,8 +35,8 @@ void init_wires(void) {
}
};
gpio_reset_pin(GPIO_NUM_41);
gpio_reset_pin(GPIO_NUM_42);
gpio_reset_pin(PIN_WIRES_SDA);
gpio_reset_pin(PIN_WIRES_SCL);
ESP_ERROR_CHECK(i2c_param_config(WIRES_I2C_NUM, &wires_conf));
ESP_ERROR_CHECK(i2c_driver_install(WIRES_I2C_NUM, wires_conf.mode, 0, 0, 0));

View File

@ -9,7 +9,16 @@
#include "drivers/game_timer.h"
#include "main.h"
#define WIRES_PIN_DELTA GPIO_NUM_2
#define PIN_PERH0 GPIO_NUM_6
#define PIN_PERH1 GPIO_NUM_5
#define PIN_PERH2 GPIO_NUM_4
#define PIN_PERH3 GPIO_NUM_2
#define PIN_PERH4 GPIO_NUM_1
#define WIRES_PIN_DELTA PIN_PERH3
#define PIN_WIRES_SDA PIN_PERH1
#define PIN_WIRES_SCL PIN_PERH2
#define WIRES_I2C_NUM I2C_NUM_1
#define WIRES_I2C_ADDR 125

View File

@ -13,19 +13,104 @@
#include "helper.h"
#include "steps/step0.h"
#include "steps/step1.h"
#include "steps/step2.h"
#include "steps/step3.h"
#include "steps/step4.h"
#include "steps/step5.h"
#include "steps/step6.h"
#include "steps/p001_step1.h"
#include "steps/p001_step2.h"
#include "steps/p001_step3.h"
#include "steps/p001_step4.h"
#include "steps/p001_step5.h"
#include "steps/p001_step6.h"
#include "steps/p002_step1.h"
#include "steps/p002_step2.h"
#include "steps/p002_step3.h"
#include "steps/p002_step4.h"
#include "steps/p002_step5.h"
#include "steps/p002_step6.h"
bool play_modified;
static const char *TAG = "main";
uint32_t initial_game_time = 90*60*1000 + 1000;
uint32_t skip_to_step = 0;
uint32_t current_step = 0;
uint32_t puzzle = 0;
extern uint32_t total_strikes;
static void do_p001() {
set_game_time(initial_game_time);
start_game_timer();
total_strikes = 0;
clean_bomb();
current_step = 1;
if (skip_to_step <= 1) p001_step1();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 2;
if (skip_to_step <= 2) p001_step2();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 3;
if (skip_to_step <= 3) p001_step3();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 4;
if (skip_to_step <= 4) p001_step4();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 5;
if (skip_to_step <= 5) p001_step5();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 6;
if (skip_to_step <= 6) p001_step6();
start_game_timer();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
stop_game_timer();
ESP_LOGI(TAG, "Bomb has been diffused. Counter-Terrorists win.");
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
display_game_results();
}
static void do_p002() {
set_game_time(initial_game_time);
start_game_timer();
total_strikes = 0;
clean_bomb();
current_step = 1;
if (skip_to_step <= 1) p002_step1();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 2;
if (skip_to_step <= 2) p002_step2();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 3;
if (skip_to_step <= 3) p002_step3();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 4;
if (skip_to_step <= 4) p002_step4();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 5;
if (skip_to_step <= 5) p002_step5();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 6;
if (skip_to_step <= 6) p002_step6();
start_game_timer();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
stop_game_timer();
ESP_LOGI(TAG, "Bomb has been diffused. Counter-Terrorists win.");
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
display_game_results();
}
extern "C" void app_main(void) {
printf("app_main\n");
@ -39,49 +124,9 @@ extern "C" void app_main(void) {
clean_bomb();
step0();
// set_recording_source(stdout, false);
FILE* record_file = fopen(MOUNT_POINT "/record.txt", "w");
if (record_file == nullptr) {
ESP_LOGE("main", "failed to open record.txt");
if (puzzle == 1) {
do_p001();
} else {
do_p002();
}
set_recording_source(record_file, true);
start_recording();
set_game_time(initial_game_time);
start_game_timer();
total_strikes = 0;
clean_bomb();
current_step = 1;
if (skip_to_step <= 1) step1();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 2;
if (skip_to_step <= 2) step2();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 3;
if (skip_to_step <= 3) step3();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 4;
if (skip_to_step <= 4) step4();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 5;
if (skip_to_step <= 5) step5();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
current_step = 6;
if (skip_to_step <= 6) step6();
start_game_timer();
step_finish_times[current_step-1] = get_game_time();
clean_bomb();
stop_game_timer();
ESP_LOGI(TAG, "Bomb has been diffused. Counter-Terrorists win.");
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
display_game_results();
stop_recording();
}

View File

@ -1,8 +1,13 @@
#ifndef MAIN_H
#define MAIN_H
#define CONTROL_REV_2_0
// #define CONTROL_REV_2_1
#include <cstddef>
extern bool play_modified;
constexpr size_t N_STEPS = 6;
#endif /* MAIN_H */

View File

@ -1,12 +1,18 @@
set(SOURCES
"setup_wires.cpp"
"step0.cpp"
"step1.cpp"
"step2.cpp"
"step3.cpp"
"step4.cpp"
"step5.cpp"
"step6.cpp"
"p001_step1.cpp"
"p001_step2.cpp"
"p001_step3.cpp"
"p001_step4.cpp"
"p001_step5.cpp"
"p001_step6.cpp"
"p002_step1.cpp"
"p002_step2.cpp"
"p002_step3.cpp"
"p002_step4.cpp"
"p002_step5.cpp"
"p002_step6.cpp"
"wires_puzzle.cpp"
)

View File

@ -1,4 +1,4 @@
#include "step1.h"
#include "p001_step1.h"
__attribute__((unused))
static const char *TAG = "step1";
@ -276,7 +276,7 @@ static bool play_part(uint32_t time) {
return true;
}
void step1(void) {
void p001_step1(void) {
while (get_switch_flipped(nullptr));
init_step();

10
main/steps/p001_step1.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef P001_STEP_1_H
#define P001_STEP_1_H
#include <random>
#include "../drivers/all.h"
#include "../helper.h"
void p001_step1(void);
#endif /* P001_STEP_1_H */

View File

@ -1,4 +1,4 @@
#include "step2.h"
#include "p001_step2.h"
__attribute__((unused))
static const char *TAG = "step2";
@ -91,7 +91,7 @@ static void new_puzzle(void) {
set_module_sseg_raw(display_map);
}
void step2(void) {
void p001_step2(void) {
KeypadKey key;
int solved_times = 0;

View File

@ -1,5 +1,5 @@
#ifndef STEP_2_H
#define STEP_2_H
#ifndef P001_STEP_2_H
#define P001_STEP_2_H
#include "../drivers/bottom_half.h"
#include "../drivers/wires.h"
@ -11,6 +11,6 @@
#include <random>
#include <map>
void step2(void);
void p001_step2(void);
#endif /* STEP_2_H */
#endif /* P001_STEP_2_H */

View File

@ -1,4 +1,4 @@
#include "step3.h"
#include "p001_step3.h"
#define ONE_SECOND_TIME 90'000
#define THREE_SECOND_TIME 90'000
@ -63,7 +63,7 @@ static bool one_second();
static bool three_second();
static bool six_second();
void step3(void) {
void p001_step3(void) {
StarCodeHandler star_codes[] = {
{
.code = "*1642",

10
main/steps/p001_step3.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef P001_STEP_3_H
#define P001_STEP_3_H
#include <random>
#include "../drivers/all.h"
#include "../helper.h"
void p001_step3(void);
#endif /* P001_STEP_3_H */

View File

@ -1,4 +1,5 @@
#include "step4.h"
#include "p001_step4.h"
#include "main.h"
__attribute__((unused))
static const char *TAG = "step4";
@ -233,8 +234,11 @@ bool play_game(int time, int required_score) {
target_score = required_score;
score = 0;
update_score();
if (!play_modified) {
set_module_time(time);
start_module_timer();
}
clear_board();
@ -272,6 +276,7 @@ bool play_game(int time, int required_score) {
show_board();
if (score >= required_score) {
if (!play_modified)
stop_module_timer();
return true;
}
@ -307,6 +312,7 @@ bool play_game(int time, int required_score) {
show_board();
if (score >= required_score) {
if (!play_modified)
stop_module_timer();
return true;
}
@ -314,11 +320,12 @@ bool play_game(int time, int required_score) {
}
}
if (get_module_time() <= 0) {
if ((!play_modified) && get_module_time() <= 0) {
stop_module_timer();
strike("Out of time");
return false;
}
// if (get_switch_flipped(&switch_)) {
// printf("%d\n", piece);
// for (int i = 0; i < sizeof(piece_nodes)/sizeof(piece_nodes[0]); i++) {
@ -333,6 +340,7 @@ bool play_game(int time, int required_score) {
// game over
ESP_LOGI(TAG, "Game Over. Score: %d", score);
if (!play_modified)
stop_module_timer();
strike("Out of room");
return false;
@ -379,7 +387,7 @@ static void fail() {
}
}
void step4() {
void p001_step4() {
StarCodeHandler star_code = {
.code = "*3850",
.display_text = "Starting...",
@ -389,13 +397,16 @@ void step4() {
do_star_codes(&star_code, 1);
init_screen();
while (!play_game(4*60*1000, 2)) fail();
int lines_1 = play_modified ? 2 : 2;
int lines_2 = play_modified ? 5 : 4;
int lines_3 = play_modified ? 12 : 8;
while (!play_game(4*60*1000, lines_1)) fail();
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
complete();
while (!play_game(4*60*1000, 4)) fail();
while (!play_game(4*60*1000, lines_2)) fail();
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
complete();
while (!play_game(7*60*1000, 8)) fail();
while (!play_game(6*60*1000, lines_3)) fail();
play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0);
complete();

View File

@ -1,5 +1,5 @@
#ifndef STEP_4_H
#define STEP_4_H
#ifndef P001_STEP_4_H
#define P001_STEP_4_H
#include <random>
#include "../drivers/tft.h"
@ -13,6 +13,6 @@
#define TETRIS_USE_FLASH_IMG
#define TETRIS_USE_FLASH_BG_IMG
void step4(void);
void p001_step4(void);
#endif /* STEP_4_H */
#endif /* P001_STEP_4_H */

View File

@ -1,4 +1,4 @@
#include "step5.h"
#include "p001_step5.h"
#define TIME_CLEAR 30'000
#define TIME_PLANK 40'000
@ -178,7 +178,7 @@ bool submit_6(bool* buttons_cycling, bool button_turned_on, int led_off) {
return true;
}
void step5(void) {
void p001_step5(void) {
StarCodeHandler star_codes[] = {
{
.code = "*2648",
@ -651,154 +651,8 @@ void step5(void) {
break;
}
case 7: {
lcd_print("What");
set_module_time(TIME_WHAT);
start_module_timer();
std::uniform_int_distribution<> math_number_dist(1, 9);
std::vector<float> math_numbers;
std::vector<int> math_operations;
std::map<int, char> operation_map = {
{0, '+'},
{1, '-'},
{2, '*'},
{3, '/'},
};
int expression_answer = -1;
std::string display_expression;
while (expression_answer < 0) {
math_numbers = {static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen))};
std::vector<int> possible_math_operations = {0, 1, 2, 3};
math_operations = unique_values(possible_math_operations, 3);
display_expression = std::to_string(static_cast<int>(math_numbers[0]));
for (int i = 0; i < 3; i++) {
display_expression += operation_map[math_operations[i]];
display_expression += std::to_string(static_cast<int>(math_numbers[i + 1]));
}
// Solve
for (int j = 0; j < 3; j++) {
bool found = false;
for (int i = 0; i < math_operations.size(); i++) {
if (math_operations[i] == 2) {
// ESP_LOGI(TAG, "i = %i, condensing %f * %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] * math_numbers[i+1]));
math_numbers[i] = math_numbers[i] * math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
} else if (math_operations[i] == 3) {
// ESP_LOGI(TAG, "i = %i, condensing %f / %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] / math_numbers[i+1]));
math_numbers[i] = math_numbers[i] / math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
}
}
if (found) continue;
for (int i = 0; i < math_operations.size(); i++) {
if (math_operations[i] == 0) {
// ESP_LOGI(TAG, "i = %i, condensing %f + %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] + math_numbers[i+1]));
math_numbers[i] = math_numbers[i] + math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
} else if (math_operations[i] == 1) {
// ESP_LOGI(TAG, "i = %i, condensing %f - %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] - math_numbers[i+1]));
math_numbers[i] = math_numbers[i] - math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
}
}
}
expression_answer = static_cast<int>(std::floor(math_numbers[0]));
}
// display expression
lcd_print(1, 2, display_expression.c_str());
// set LEDs
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_YELLOW,
};
std::uniform_int_distribution<> add_sub_indicator_dist(1, 6);
std::uniform_int_distribution<> mult_div_indicator_dist(1, 3);
int modifier_indicators[4] = {add_sub_indicator_dist(gen), add_sub_indicator_dist(gen), mult_div_indicator_dist(gen), mult_div_indicator_dist(gen)};
while ((((expression_answer + (modifier_indicators[0] * 3) - modifier_indicators[1]) * std::pow(3, modifier_indicators[2])) / std::pow(2, modifier_indicators[3])) < 0) {
modifier_indicators[0] = add_sub_indicator_dist(gen);
modifier_indicators[1] = add_sub_indicator_dist(gen);
modifier_indicators[2] = mult_div_indicator_dist(gen);
modifier_indicators[3] = mult_div_indicator_dist(gen);
}
expression_answer += modifier_indicators[0] * 3;
expression_answer -= modifier_indicators[1];
expression_answer *= std::pow(3, modifier_indicators[2]);
expression_answer /= std::pow(2, modifier_indicators[3]);
std::vector<int> led_options = all_leds;
for (int i = 0; i < 4; i++) {
set_unique_leds(led_options, modifier_indicators[i], COLORS[i]);
}
leds_flush();
std::string answer_string = std::to_string(expression_answer);
std::string entered_string = "";
ESP_LOGI(TAG, "Solved full answer: %s", answer_string.c_str());
KeypadKey key;
while (1) {
if (get_keypad_pressed(&key)) {
if (key == KeypadKey::star) {
// clear
entered_string = "";
} else if (key == KeypadKey::pound) {
// submit
if (entered_string != answer_string) {
strike("Incorrect answer!");
} else {
solved_correctly = true;
}
break;
} else {
entered_string += char_of_keypad_key(key);
}
lcd_clear();
lcd_print(1, 1, "What");
lcd_print(1, 2, display_expression.c_str());
lcd_print(1, 3, entered_string.c_str());
}
if (get_module_time() <= 0) {
strike("Ran out of time!");
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
break;
}
case 8: {
if (play_modified) {
// do PLINK
lcd_print("Plink");
set_module_time(TIME_PLINK);
start_module_timer();
@ -893,9 +747,159 @@ void step5(void) {
if (!failed) {
solved_correctly = true;
}
} else {
// do WHAT
lcd_print(1, 1, "What");
set_module_time(TIME_WHAT);
start_module_timer();
std::uniform_int_distribution<> math_number_dist(1, 9);
std::vector<float> math_numbers;
std::vector<int> math_operations;
std::map<int, char> operation_map = {
{0, '+'},
{1, '-'},
{2, '*'},
{3, '/'},
};
int expression_answer = -1;
std::string display_expression;
while (expression_answer < 0) {
math_numbers = {static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen)), static_cast<float>(math_number_dist(gen))};
std::vector<int> possible_math_operations = {0, 1, 2, 3};
math_operations = unique_values(possible_math_operations, 3);
display_expression = std::to_string(static_cast<int>(math_numbers[0]));
for (int i = 0; i < 3; i++) {
display_expression += operation_map[math_operations[i]];
display_expression += std::to_string(static_cast<int>(math_numbers[i + 1]));
}
// Solve
for (int j = 0; j < 3; j++) {
bool found = false;
for (int i = 0; i < math_operations.size(); i++) {
if (math_operations[i] == 2) {
// ESP_LOGI(TAG, "i = %i, condensing %f * %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] * math_numbers[i+1]));
math_numbers[i] = math_numbers[i] * math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
} else if (math_operations[i] == 3) {
// ESP_LOGI(TAG, "i = %i, condensing %f / %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] / math_numbers[i+1]));
math_numbers[i] = math_numbers[i] / math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
}
}
if (found) continue;
for (int i = 0; i < math_operations.size(); i++) {
if (math_operations[i] == 0) {
// ESP_LOGI(TAG, "i = %i, condensing %f + %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] + math_numbers[i+1]));
math_numbers[i] = math_numbers[i] + math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
} else if (math_operations[i] == 1) {
// ESP_LOGI(TAG, "i = %i, condensing %f - %f to %f", i, math_numbers[i], math_numbers[i + 1], (math_numbers[i] - math_numbers[i+1]));
math_numbers[i] = math_numbers[i] - math_numbers[i + 1];
math_numbers.erase(math_numbers.begin() + i + 1);
math_operations.erase(math_operations.begin() + i);
found = true;
break;
}
}
}
expression_answer = static_cast<int>(std::floor(math_numbers[0]));
}
// display expression
lcd_print(2, 1, display_expression.c_str());
// set LEDs
const uint32_t COLORS[] = {
LEDColor::LED_COLOR_BLUE,
LEDColor::LED_COLOR_RED,
LEDColor::LED_COLOR_GREEN,
LEDColor::LED_COLOR_YELLOW,
};
std::uniform_int_distribution<> add_sub_indicator_dist(1, 6);
std::uniform_int_distribution<> mult_div_indicator_dist(1, 3);
int modifier_indicators[4] = {add_sub_indicator_dist(gen), add_sub_indicator_dist(gen), mult_div_indicator_dist(gen), mult_div_indicator_dist(gen)};
while ((((expression_answer + (modifier_indicators[0] * 3) - modifier_indicators[1]) * std::pow(3, modifier_indicators[2])) / std::pow(2, modifier_indicators[3])) < 0) {
modifier_indicators[0] = add_sub_indicator_dist(gen);
modifier_indicators[1] = add_sub_indicator_dist(gen);
modifier_indicators[2] = mult_div_indicator_dist(gen);
modifier_indicators[3] = mult_div_indicator_dist(gen);
}
expression_answer += modifier_indicators[0] * 3;
expression_answer -= modifier_indicators[1];
expression_answer *= std::pow(3, modifier_indicators[2]);
expression_answer /= std::pow(2, modifier_indicators[3]);
std::vector<int> led_options = all_leds;
for (int i = 0; i < 4; i++) {
set_unique_leds(led_options, modifier_indicators[i], COLORS[i]);
}
leds_flush();
std::string answer_string = std::to_string(expression_answer);
std::string entered_string = "";
ESP_LOGI(TAG, "Solved full answer: %s", answer_string.c_str());
KeypadKey key;
while (1) {
if (get_keypad_pressed(&key)) {
if (key == KeypadKey::star) {
// clear
entered_string = "";
} else if (key == KeypadKey::pound) {
// submit
if (entered_string != answer_string) {
strike("Incorrect answer!");
} else {
solved_correctly = true;
}
break;
} else {
entered_string += char_of_keypad_key(key);
}
lcd_clear();
lcd_print(1, 1, "What");
lcd_print(2, 1, display_expression.c_str());
lcd_print(3, 1, entered_string.c_str());
}
if (get_module_time() <= 0) {
strike("Ran out of time!");
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
break;
}
default: {
ESP_LOGE(TAG, "Invalid puzzle number %d", puzzle);
}
}
stop_module_timer();
if (solved_correctly) {

View File

@ -1,5 +1,5 @@
#ifndef STEP_5_H
#define STEP_5_H
#ifndef P001_STEP_5_H
#define P001_STEP_5_H
#include "../drivers/bottom_half.h"
#include "../drivers/game_timer.h"
@ -15,6 +15,6 @@
#include <cmath>
#include <array>
void step5(void);
void p001_step5(void);
#endif /* STEP_5_H */
#endif /* P001_STEP_5_H */

View File

@ -1,11 +1,11 @@
#include "step6.h"
#include "p001_step6.h"
__attribute__((unused))
static const char *TAG = "step6";
static uint8_t cut_wires = 0;
void step6(void) {
void p001_step6(void) {
get_cut_wires();
clear_all_pressed_released();

10
main/steps/p001_step6.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef P001_STEP_6_H
#define P001_STEP_6_H
#include "wires_puzzle.h"
#include "../drivers/all.h"
#include "../helper.h"
void p001_step6(void);
#endif /* P001_STEP_6_H */

View File

@ -0,0 +1,8 @@
#include "p002_step1.h"
__attribute__((unused))
static const char *TAG = "step1";
void p002_step1(void) {
// TODO: implement step 1
}

8
main/steps/p002_step1.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_1_H
#define P002_STEP_1_H
#include "../drivers/all.h"
void p002_step1(void);
#endif /* P002_STEP_1_H */

272
main/steps/p002_step2.cpp Normal file
View File

@ -0,0 +1,272 @@
#include "p002_step2.h"
#include "helper.h"
#include <cstdio>
#include <cstring>
#include <random>
__attribute__((unused))
static const char *TAG = "step2";
static const uint8_t BOARD_COUNT = 9;
static const uint8_t BOARD_SIZE = 6;
static const uint8_t PART_SHOTS[3] = {20, 15, 12};
static const char *PART_LABELS[3] = {"Alpha", "Bravo", "Charlie"};
static const char ROW_LABELS[BOARD_SIZE] = {'A', 'B', 'C', 'D', 'E', 'F'};
static std::random_device random_device;
static std::mt19937 random_engine(random_device());
static std::uniform_int_distribution<int> random_board(0, BOARD_COUNT - 1);
static const uint8_t ALL_BOARDS[BOARD_COUNT][BOARD_SIZE][BOARD_SIZE] = {
{
{0,0,0,0,0,0},
{0,0,1,1,1,1},
{0,1,0,0,0,0},
{0,1,0,1,1,0},
{0,1,0,0,0,0},
{0,0,0,1,0,0},
},
{
{0,1,0,0,0,0},
{0,1,0,1,1,0},
{0,1,0,0,0,0},
{0,0,0,1,0,0},
{0,0,0,0,0,0},
{1,1,1,1,0,0},
},
{
{0,0,1,1,1,1},
{0,1,0,0,0,0},
{0,1,0,0,0,0},
{0,1,0,0,0,0},
{0,0,1,0,0,0},
{1,0,1,0,0,0},
},
{
{1,0,0,0,0,0},
{1,0,0,0,0,0},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{0,0,0,0,1,0},
{0,1,1,1,0,0},
},
{
{1,1,0,1,0,0},
{0,0,0,1,0,0},
{0,1,0,1,0,0},
{0,0,0,0,0,0},
{0,1,1,1,1,0},
{0,0,0,0,0,0},
},
{
{0,0,1,0,1,0},
{1,0,1,0,1,0},
{0,0,1,0,1,0},
{0,0,1,0,0,0},
{0,0,0,0,0,0},
{1,1,0,0,0,0},
},
{
{0,0,0,0,0,1},
{1,1,0,0,0,0},
{0,0,0,0,1,0},
{1,1,1,0,1,0},
{0,0,0,0,1,0},
{0,0,0,0,1,0},
},
{
{0,1,1,0,0,0},
{0,0,0,0,1,0},
{0,0,0,0,1,0},
{0,0,1,0,1,0},
{0,0,0,0,0,0},
{1,1,1,1,0,0},
},
{
{0,0,0,0,0,0},
{1,0,0,0,0,0},
{0,1,0,0,1,1},
{0,1,0,1,0,0},
{0,1,0,1,0,0},
{0,1,0,1,0,0},
},
};
static bool row_from_button_state(uint8_t state, uint8_t *row) {
switch (state) {
case 0b1100: *row = 0; return true; // B1 + B2 -> A
case 0b1010: *row = 1; return true; // B1 + B3 -> B
case 0b1001: *row = 2; return true; // B1 + B4 -> C
case 0b0110: *row = 3; return true; // B2 + B3 -> D
case 0b0101: *row = 4; return true; // B2 + B4 -> E
case 0b0011: *row = 5; return true; // B3 + B4 -> F
default: return false;
}
}
static bool column_from_switch_state(uint8_t state, uint8_t *col) {
uint8_t value = state & 0xF;
if (value >= 1 && value <= 6) {
*col = value - 1;
return true;
}
return false;
}
static int count_ship_segments(const uint8_t board[BOARD_SIZE][BOARD_SIZE]) {
int count = 0;
for (uint8_t row = 0; row < BOARD_SIZE; ++row) {
for (uint8_t col = 0; col < BOARD_SIZE; ++col) {
if (board[row][col] == 1) {
++count;
}
}
}
return count;
}
static void copy_board(uint8_t dest[BOARD_SIZE][BOARD_SIZE], const uint8_t src[BOARD_SIZE][BOARD_SIZE]) {
memcpy(dest, src, BOARD_SIZE * BOARD_SIZE);
}
static void render_status(const char *part_name,
int shots_left,
int hits,
int misses,
int row,
int col,
const char *info) {
char line0[21] = {0};
char line1[21] = {0};
char line2[21] = {0};
char line3[21] = {0};
snprintf(line0, sizeof(line0), "%s Shots:%2d", part_name, shots_left);
if (row >= 0 && col >= 0) {
snprintf(line1, sizeof(line1), "Row %c Col %d", ROW_LABELS[row], col + 1);
} else {
snprintf(line1, sizeof(line1), "Row - Col -");
}
snprintf(line2, sizeof(line2), "Hits:%2d Misses:%2d", hits, misses);
snprintf(line3, sizeof(line3), "%s", info);
lcd_clear();
lcd_print(0, 0, line0);
lcd_print(0, 1, line1);
lcd_print(0, 2, line2);
lcd_print(0, 3, line3);
}
void p002_step2(void) {
clean_bomb();
for (int part = 0; part < 3; ++part) {
const char *part_name = PART_LABELS[part];
const int max_shots = PART_SHOTS[part];
bool completed = false;
while (!completed) {
uint8_t board[BOARD_SIZE][BOARD_SIZE];
copy_board(board, ALL_BOARDS[random_board(random_engine)]);
int shots_taken = 0;
int hits = 0;
int misses = 0;
int current_row = -1;
int current_col = -1;
const char *status = "Hold 2 buttons + set switches";
render_status(part_name, max_shots - shots_taken, hits, misses, -1, -1, status);
clean_bomb();
while (true) {
uint8_t button_state = get_button_state();
uint8_t switch_state = get_switch_state();
uint8_t row = 0;
uint8_t col = 0;
bool row_valid = row_from_button_state(button_state, &row);
bool col_valid = column_from_switch_state(switch_state, &col);
if (row_valid) {
current_row = row;
} else {
current_row = -1;
}
if (col_valid) {
current_col = col;
} else {
current_col = -1;
}
KeypadKey key;
if (get_keypad_pressed(&key)) {
if (key == KeypadKey::k5) {
if (!row_valid) {
status = "Invalid row selection";
} else if (!col_valid) {
status = "Invalid column value";
} else {
uint8_t cell = board[row][col];
if (cell == 2 || cell == 3) {
status = "Already fired there";
} else {
shots_taken += 1;
if (cell == 1) {
board[row][col] = 3;
hits += 1;
status = "Hit!";
led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_RED);
} else {
board[row][col] = 2;
misses += 1;
status = "Miss!";
led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_WHITE);
}
leds_flush();
vTaskDelay(pdMS_TO_TICKS(250));
led_set(IndicatorLED::LED_LCD, LEDColor::LED_COLOR_OFF);
leds_flush();
}
}
}
}
render_status(part_name,
max_shots - shots_taken,
hits,
misses,
current_row,
current_col,
status);
if (count_ship_segments(board) == 0) {
completed = true;
break;
}
if (shots_taken >= max_shots) {
strike("Out of shots!");
status = "Out of shots! Retry";
render_status(part_name,
0,
hits,
misses,
current_row,
current_col,
status);
vTaskDelay(pdMS_TO_TICKS(2000));
break;
}
vTaskDelay(pdMS_TO_TICKS(50));
}
}
if (part < 2)
play_clip_wav(MOUNT_POINT "/partdone.wav", true, false, 0, 0);
clean_bomb();
}
play_clip_wav(MOUNT_POINT "/stepdone.wav", true, false, 1, 0);
lcd_clear();
}

8
main/steps/p002_step2.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_2_H
#define P002_STEP_2_H
#include "../drivers/all.h"
void p002_step2(void);
#endif /* P002_STEP_2_H */

View File

@ -0,0 +1,8 @@
#include "p002_step3.h"
__attribute__((unused))
static const char *TAG = "step3";
void p002_step3(void) {
// TODO: implement step 3
}

8
main/steps/p002_step3.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_3_H
#define P002_STEP_3_H
#include "../drivers/all.h"
void p002_step3(void);
#endif /* P002_STEP_3_H */

View File

@ -0,0 +1,8 @@
#include "p002_step4.h"
__attribute__((unused))
static const char *TAG = "step4";
void p002_step4(void) {
// TODO: implement step 4
}

8
main/steps/p002_step4.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_4_H
#define P002_STEP_4_H
#include "../drivers/all.h"
void p002_step4(void);
#endif /* P002_STEP_4_H */

View File

@ -0,0 +1,8 @@
#include "p002_step5.h"
__attribute__((unused))
static const char *TAG = "step5";
void p002_step5(void) {
// TODO: implement step 5
}

8
main/steps/p002_step5.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_5_H
#define P002_STEP_5_H
#include "../drivers/all.h"
void p002_step5(void);
#endif /* P002_STEP_5_H */

View File

@ -0,0 +1,8 @@
#include "p002_step6.h"
__attribute__((unused))
static const char *TAG = "step6";
void p002_step6(void) {
// TODO: implement step 6
}

8
main/steps/p002_step6.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef P002_STEP_6_H
#define P002_STEP_6_H
#include "../drivers/all.h"
void p002_step6(void);
#endif /* P002_STEP_6_H */

View File

@ -5,6 +5,7 @@ static const char* TAG = "step0";
extern uint32_t initial_game_time;
extern uint32_t skip_to_step;
extern uint32_t puzzle;
static void set_game_time();
static void skip_to_step1() { skip_to_step = 1; }
@ -13,12 +14,12 @@ static void skip_to_step3() { skip_to_step = 3; }
static void skip_to_step4() { skip_to_step = 4; }
static void skip_to_step5() { skip_to_step = 5; }
static void skip_to_step6() { skip_to_step = 6; }
static void try_step1() { clean_bomb(); step1(); }
static void try_step2() { clean_bomb(); step2(); }
static void try_step3() { clean_bomb(); step3(); }
static void try_step4() { clean_bomb(); step4(); }
static void try_step5() { clean_bomb(); step5(); }
static void try_step6() { clean_bomb(); step6(); }
static void try_step1() { clean_bomb(); p001_step1(); }
static void try_step2() { clean_bomb(); p001_step2(); }
static void try_step3() { clean_bomb(); p001_step3(); }
static void try_step4() { clean_bomb(); p001_step4(); }
static void try_step5() { clean_bomb(); p001_step5(); }
static void try_step6() { clean_bomb(); p001_step6(); }
static void issue_strike() { strike("Strike Issued"); }
static void flashbang();
static void debug_switches();
@ -45,6 +46,20 @@ static void replay_last() {
start_playback();
}
static void do_p001() {
play_modified = false;
puzzle = 1;
}
static void do_p001_modified() {
play_modified = true;
puzzle = 1;
}
static void do_p002() {
puzzle = 2;
}
/// Wait for "*9819"
void step0() {
led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE);
@ -53,13 +68,25 @@ void step0() {
StarCodeHandler star_codes[] = {
{
.code = "*9819",
.display_text = "Defusal Initiated",
.display_text = "Start P001DH",
.should_exit = true,
.callback = nullptr,
.callback = do_p001,
},
{
.code = "*9818",
.display_text = "Start P001DM",
.should_exit = true,
.callback = do_p001_modified,
},
{
.code = "*3141",
.display_text = "Start P002",
.should_exit = true,
.callback = do_p002,
},
{
.code = "*59861",
.display_text = "Set Up Wires",
.display_text = "Setup Wires",
.should_exit = false,
.callback = setup_wires,
},

View File

@ -8,12 +8,12 @@
#include "setup_wires.h"
#include "../helper.h"
#include "step1.h"
#include "step2.h"
#include "step3.h"
#include "step4.h"
#include "step5.h"
#include "step6.h"
#include "p001_step1.h"
#include "p001_step2.h"
#include "p001_step3.h"
#include "p001_step4.h"
#include "p001_step5.h"
#include "p001_step6.h"
/// Wait for "*9819"
void step0(void);

View File

@ -1,15 +0,0 @@
#ifndef STEP_1_H
#define STEP_1_H
#include <random>
#include "../drivers/bottom_half.h"
#include "../drivers/tft.h"
#include "../drivers/leds.h"
#include "../drivers/wires.h"
#include "../drivers/speaker.h"
#include "../drivers/game_timer.h"
#include "../drivers/char_lcd.h"
void step1(void);
#endif /* STEP_1_H */

View File

@ -1,15 +0,0 @@
#ifndef STEP_3_H
#define STEP_3_H
#include <random>
#include "../drivers/bottom_half.h"
#include "../drivers/wires.h"
#include "../drivers/speaker.h"
#include "../drivers/leds.h"
#include "../drivers/char_lcd.h"
#include "../drivers/game_timer.h"
#include "../helper.h"
void step3(void);
#endif /* STEP_3_H */

View File

@ -1,12 +0,0 @@
#ifndef STEP_6_H
#define STEP_6_H
#include "wires_puzzle.h"
#include "drivers/wires.h"
#include "drivers/bottom_half.h"
#include "drivers/sd.h"
#include "drivers/speaker.h"
void step6(void);
#endif /* STEP_6_H */

BIN
resources/correct.raw Normal file

Binary file not shown.

BIN
resources/diffused.raw Normal file

Binary file not shown.

BIN
resources/flash.raw Normal file

Binary file not shown.

BIN
resources/high-1.raw Normal file

Binary file not shown.

BIN
resources/high-3.raw Normal file

Binary file not shown.

BIN
resources/high-6.raw Normal file

Binary file not shown.

BIN
resources/incorrect.raw Normal file

Binary file not shown.

BIN
resources/low-1.raw Normal file

Binary file not shown.

BIN
resources/low-3.raw Normal file

Binary file not shown.

BIN
resources/low-6.raw Normal file

Binary file not shown.

BIN
resources/partdone.raw Normal file

Binary file not shown.

BIN
resources/piano.raw Normal file

Binary file not shown.

BIN
resources/ready.raw Normal file

Binary file not shown.

BIN
resources/startup.raw Normal file

Binary file not shown.

BIN
resources/stepdone.raw Normal file

Binary file not shown.

BIN
resources/tetris.raw Normal file

Binary file not shown.

115
sdkconfig
View File

@ -1,6 +1,6 @@
#
# Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) 5.3.2 Project Configuration
# Espressif IoT Development Framework (ESP-IDF) 5.3.5 Project Configuration
#
CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000
CONFIG_SOC_MPU_REGIONS_MAX_NUM=8
@ -11,6 +11,7 @@ CONFIG_SOC_PHY_SUPPORTED=y
CONFIG_SOC_WIFI_SUPPORTED=y
CONFIG_SOC_TWAI_SUPPORTED=y
CONFIG_SOC_GDMA_SUPPORTED=y
CONFIG_SOC_UHCI_SUPPORTED=y
CONFIG_SOC_AHB_GDMA_SUPPORTED=y
CONFIG_SOC_GPTIMER_SUPPORTED=y
CONFIG_SOC_LCDCAM_SUPPORTED=y
@ -64,6 +65,7 @@ CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y
CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y
CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y
CONFIG_SOC_PM_SUPPORTED=y
CONFIG_SOC_SIMD_INSTRUCTION_SUPPORTED=y
CONFIG_SOC_XTAL_SUPPORT_40M=y
CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y
CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y
@ -100,7 +102,8 @@ CONFIG_SOC_CPU_HAS_FPU=y
CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y
CONFIG_SOC_CPU_BREAKPOINTS_NUM=2
CONFIG_SOC_CPU_WATCHPOINTS_NUM=2
CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64
CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40
CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16
CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096
CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16
CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100
@ -176,7 +179,7 @@ CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8
CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48
CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y
CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y
CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP=y
CONFIG_SOC_RMT_SUPPORT_ASYNC_STOP=y
CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y
CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y
CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y
@ -203,7 +206,8 @@ CONFIG_SOC_RTCIO_PIN_COUNT=22
CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y
CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y
CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y
CONFIG_SOC_SDM_GROUPS=y
CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y
CONFIG_SOC_SDM_GROUPS=1
CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8
CONFIG_SOC_SDM_CLK_SUPPORT_APB=y
CONFIG_SOC_SPI_PERIPH_NUM=3
@ -243,6 +247,8 @@ CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54
CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y
CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y
CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4
CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32
CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16
CONFIG_SOC_TOUCH_SENSOR_VERSION=2
CONFIG_SOC_TOUCH_SENSOR_NUM=15
CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y
@ -265,6 +271,7 @@ CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y
CONFIG_SOC_UART_SUPPORT_APB_CLK=y
CONFIG_SOC_UART_SUPPORT_RTC_CLK=y
CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y
CONFIG_SOC_UHCI_NUM=1
CONFIG_SOC_USB_OTG_PERIPH_NUM=1
CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968
CONFIG_SOC_SHA_SUPPORT_DMA=y
@ -350,6 +357,7 @@ CONFIG_SOC_WIFI_HW_TSF=y
CONFIG_SOC_WIFI_FTM_SUPPORT=y
CONFIG_SOC_WIFI_GCMP_SUPPORT=y
CONFIG_SOC_WIFI_WAPI_SUPPORT=y
CONFIG_SOC_WIFI_TXOP_SUPPORT=y
CONFIG_SOC_WIFI_CSI_SUPPORT=y
CONFIG_SOC_WIFI_MESH_SUPPORT=y
CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y
@ -366,7 +374,7 @@ CONFIG_IDF_TOOLCHAIN="gcc"
CONFIG_IDF_TARGET_ARCH_XTENSA=y
CONFIG_IDF_TARGET_ARCH="xtensa"
CONFIG_IDF_TARGET="esp32s3"
CONFIG_IDF_INIT_VERSION="5.3.2"
CONFIG_IDF_INIT_VERSION="5.3.5"
CONFIG_IDF_TARGET_ESP32S3=y
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009
@ -593,7 +601,21 @@ CONFIG_APPTRACE_LOCK_ENABLE=y
# Bluetooth
#
# CONFIG_BT_ENABLED is not set
CONFIG_BT_ALARM_MAX_NUM=50
#
# Common Options
#
#
# BLE Log
#
# CONFIG_BLE_LOG_ENABLED is not set
# end of BLE Log
# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set
# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set
# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set
# end of Common Options
# end of Bluetooth
#
@ -617,6 +639,7 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y
# Legacy ADC Driver Configuration
#
# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set
#
# Legacy ADC Calibration Configuration
@ -629,42 +652,55 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y
# Legacy MCPWM Driver Configurations
#
# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy MCPWM Driver Configurations
#
# Legacy Timer Group Driver Configurations
#
# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy Timer Group Driver Configurations
#
# Legacy RMT Driver Configurations
#
# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy RMT Driver Configurations
#
# Legacy I2S Driver Configurations
#
# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy I2S Driver Configurations
#
# Legacy I2C Driver Configurations
#
# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy I2C Driver Configurations
#
# Legacy PCNT Driver Configurations
#
# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy PCNT Driver Configurations
#
# Legacy SDM Driver Configurations
#
# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy SDM Driver Configurations
#
# Legacy Temperature Sensor Driver Configurations
#
# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set
# CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK is not set
# end of Legacy Temperature Sensor Driver Configurations
# end of Driver Configurations
@ -687,6 +723,7 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y
# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set
# CONFIG_ESP_TLS_PSK_VERIFICATION is not set
# CONFIG_ESP_TLS_INSECURE is not set
CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y
# end of ESP-TLS
#
@ -724,6 +761,7 @@ CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y
# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set
# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set
CONFIG_GPTIMER_OBJ_CACHE_SAFE=y
# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:GPTimer Configurations
@ -807,6 +845,14 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
# CONFIG_UART_ISR_IN_IRAM is not set
# end of ESP-Driver:UART Configurations
#
# ESP-Driver:UHCI Configurations
#
# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set
# CONFIG_UHCI_ISR_CACHE_SAFE is not set
# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set
# end of ESP-Driver:UHCI Configurations
#
# ESP-Driver:USB Serial/JTAG Configuration
#
@ -842,6 +888,13 @@ CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y
CONFIG_ESP_GDBSTUB_MAX_TASKS=32
# end of GDB Stub
#
# ESP HID
#
CONFIG_ESPHID_TASK_SIZE_BT=2048
CONFIG_ESPHID_TASK_SIZE_BLE=4096
# end of ESP HID
#
# ESP HTTP client
#
@ -1015,7 +1068,11 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y
# CONFIG_ESP_PHY_RF_CAL_NONE is not set
# CONFIG_ESP_PHY_RF_CAL_FULL is not set
CONFIG_ESP_PHY_CALIBRATION_MODE=0
CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000
# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set
# CONFIG_ESP_PHY_RECORD_USED_TIME is not set
CONFIG_ESP_PHY_IRAM_OPT=y
# CONFIG_ESP_PHY_DEBUG is not set
# end of PHY
#
@ -1035,9 +1092,11 @@ CONFIG_SPIRAM=y
#
# SPI RAM config
#
# CONFIG_SPIRAM_MODE_QUAD is not set
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_MODE_QUAD=y
# CONFIG_SPIRAM_MODE_OCT is not set
CONFIG_SPIRAM_TYPE_AUTO=y
# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_CLK_IO=30
@ -1045,11 +1104,12 @@ CONFIG_SPIRAM_CS_IO=26
# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set
# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set
# CONFIG_SPIRAM_RODATA is not set
# CONFIG_SPIRAM_SPEED_120M is not set
# CONFIG_SPIRAM_SPEED_80M is not set
CONFIG_SPIRAM_SPEED_40M=y
CONFIG_SPIRAM_SPEED=40
# CONFIG_SPIRAM_ECC_ENABLE is not set
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y
# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
# CONFIG_SPIRAM_USE_MEMMAP is not set
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
@ -1214,9 +1274,9 @@ CONFIG_ESP_WIFI_ENABLED=y
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y
# CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER is not set
CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=32
CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y
# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set
CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0
@ -1226,7 +1286,6 @@ CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP_WIFI_TX_BA_WIN=6
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP_WIFI_RX_BA_WIN=6
# CONFIG_ESP_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP_WIFI_NVS_ENABLED=y
CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y
# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set
@ -1268,7 +1327,6 @@ CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y
# end of WPS Configuration Options
# CONFIG_ESP_WIFI_DEBUG_PRINT is not set
# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set
CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y
# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set
# end of Wi-Fi
@ -1398,7 +1456,6 @@ CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2
CONFIG_HAL_WDT_USE_ROM_IMPL=y
CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y
CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y
# CONFIG_HAL_ECDSA_GEN_SIG_CM is not set
# end of Hardware Abstraction Layer (HAL) and Low Level (LL)
#
@ -1487,6 +1544,7 @@ CONFIG_LWIP_DHCPS=y
CONFIG_LWIP_DHCPS_LEASE_UNIT=60
CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8
CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y
CONFIG_LWIP_DHCPS_ADD_DNS=y
# end of DHCP server
# CONFIG_LWIP_AUTOIP is not set
@ -1638,6 +1696,7 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set
# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set
CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y
# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set
CONFIG_MBEDTLS_PKCS7_C=y
# end of mbedTLS v3.x related
@ -1671,6 +1730,7 @@ CONFIG_MBEDTLS_HAVE_TIME=y
# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set
# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y
CONFIG_MBEDTLS_SHA1_C=y
CONFIG_MBEDTLS_SHA512_C=y
# CONFIG_MBEDTLS_SHA3_C is not set
CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
@ -1750,6 +1810,7 @@ CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y
# CONFIG_MBEDTLS_THREADING_C is not set
CONFIG_MBEDTLS_ERROR_STRINGS=y
CONFIG_MBEDTLS_FS_IO=y
# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set
# end of mbedTLS
#
@ -1800,25 +1861,12 @@ CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y
# CONFIG_OPENTHREAD_ENABLED is not set
#
# Thread Operational Dataset
# OpenThread Spinel
#
CONFIG_OPENTHREAD_NETWORK_NAME="OpenThread-ESP"
CONFIG_OPENTHREAD_MESH_LOCAL_PREFIX="fd00:db8:a0:0::/64"
CONFIG_OPENTHREAD_NETWORK_CHANNEL=15
CONFIG_OPENTHREAD_NETWORK_PANID=0x1234
CONFIG_OPENTHREAD_NETWORK_EXTPANID="dead00beef00cafe"
CONFIG_OPENTHREAD_NETWORK_MASTERKEY="00112233445566778899aabbccddeeff"
CONFIG_OPENTHREAD_NETWORK_PSKC="104810e2315100afd6bc9215a6bfac53"
# end of Thread Operational Dataset
CONFIG_OPENTHREAD_XTAL_ACCURACY=130
# CONFIG_OPENTHREAD_SPINEL_ONLY is not set
CONFIG_OPENTHREAD_RX_ON_WHEN_IDLE=y
# end of OpenThread Spinel
#
# Thread Address Query Config
#
# end of Thread Address Query Config
# CONFIG_OPENTHREAD_DEBUG is not set
# end of OpenThread
#
@ -1827,6 +1875,7 @@ CONFIG_OPENTHREAD_RX_ON_WHEN_IDLE=y
CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y
CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y
CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y
CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y
# end of Protocomm
#
@ -1878,6 +1927,7 @@ CONFIG_SPI_FLASH_SUSPEND_QVL_SUPPORTED=y
# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set
CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50
# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set
# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set
# end of Optional and Experimental Features (READ DOCS FIRST)
# end of Main Flash configuration
@ -2457,7 +2507,6 @@ CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
CONFIG_ESP32S3_DEBUG_OCDAWARE=y
CONFIG_BROWNOUT_DET=y
CONFIG_ESP32S3_BROWNOUT_DET=y
CONFIG_ESP32S3_BROWNOUT_DET=y
CONFIG_BROWNOUT_DET_LVL_SEL_7=y
CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y
# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set
@ -2480,17 +2529,14 @@ CONFIG_ESP32_WIFI_ENABLED=y
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
# CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER is not set
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_CSI_ENABLED is not set
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=6
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_RX_BA_WIN=6
CONFIG_ESP32_WIFI_RX_BA_WIN=6
# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set
@ -2511,7 +2557,6 @@ CONFIG_WPA_MBEDTLS_TLS_CLIENT=y
# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set
# CONFIG_WPA_WPS_STRICT is not set
# CONFIG_WPA_DEBUG_PRINT is not set
# CONFIG_WPA_TESTING_OPTIONS is not set
# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set
# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set
CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y