Compare commits
3 Commits
5329e3594e
...
6542b16a96
| Author | SHA1 | Date | |
|---|---|---|---|
| 6542b16a96 | |||
| 27e9b11400 | |||
| 0bde53743e |
@ -30,6 +30,11 @@ static void receive_keypad();
|
|||||||
static void receive_button_switch();
|
static void receive_button_switch();
|
||||||
static void receive_touch();
|
static void receive_touch();
|
||||||
|
|
||||||
|
static bool replay_handler(const char* event, char* arg) {
|
||||||
|
// no reply neccesary
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: add intrupt on bottom half delta pin
|
// TODO: add intrupt on bottom half delta pin
|
||||||
// static void IRAM_ATTR gpio_isr_handler(void* arg)
|
// static void IRAM_ATTR gpio_isr_handler(void* arg)
|
||||||
// {
|
// {
|
||||||
@ -57,6 +62,8 @@ void init_bottom_half() {
|
|||||||
|
|
||||||
xTaskCreate(poll_bottom_task, "poll_bottom", 4096, NULL, 10, NULL);
|
xTaskCreate(poll_bottom_task, "poll_bottom", 4096, NULL, 10, NULL);
|
||||||
|
|
||||||
|
register_replay_fn(replay_handler);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Bottom half initialized!");
|
ESP_LOGI(TAG, "Bottom half initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include "./i2c_lcd_pcf8574.h"
|
#include "./i2c_lcd_pcf8574.h"
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include "state_tracking.h"
|
#include "state_tracking.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
i2c_lcd_pcf8574_handle_t lcd;
|
i2c_lcd_pcf8574_handle_t lcd;
|
||||||
|
|
||||||
@ -10,6 +11,83 @@ static const char *TAG = "char_lcd";
|
|||||||
|
|
||||||
static char buf[65];
|
static char buf[65];
|
||||||
|
|
||||||
|
static bool replay_handler(const char* event, char* arg) {
|
||||||
|
if (strcmp(event, "LCD_CLEAR") == 0) {
|
||||||
|
lcd_clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_CURSOR") == 0) {
|
||||||
|
char* col_str = strtok(arg, ",");
|
||||||
|
char* row_str = strtok(NULL, ",");
|
||||||
|
uint32_t col = atoi(col_str);
|
||||||
|
uint32_t row = atoi(row_str);
|
||||||
|
lcd_set_cursor_pos(col, row);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_SET_DISPLAY") == 0) {
|
||||||
|
lcd_set_display(strcmp(arg, "true") == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_CURSOR_VIS") == 0) {
|
||||||
|
lcd_set_cursor_vis(strcmp(arg, "true") == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_CURSOR_BLINK") == 0) {
|
||||||
|
lcd_set_cursor_blink(strcmp(arg, "true") == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_SCROLL_DISPLAY_LEFT") == 0) {
|
||||||
|
lcd_scroll_display_left();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_SCROLL_DISPLAY_RIGHT") == 0) {
|
||||||
|
lcd_scroll_display_right();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_LEFT_TO_RIGHT") == 0) {
|
||||||
|
lcd_left_to_right();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_RIGHT_TO_LEFT") == 0) {
|
||||||
|
lcd_right_to_left();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_AUTOSCROLL") == 0) {
|
||||||
|
lcd_set_autoscroll(strcmp(arg, "true") == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_BACKLIGHT") == 0) {
|
||||||
|
uint32_t brightness = atoi(arg);
|
||||||
|
lcd_set_backlight(brightness);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_CREATE_CHAR") == 0) {
|
||||||
|
char* location_str = strtok(arg, ",");
|
||||||
|
uint8_t location = atoi(location_str);
|
||||||
|
|
||||||
|
uint8_t charmap[8];
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
char* str = strtok(NULL, ",");
|
||||||
|
charmap[i] = atoi(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
lcd_create_char(location, charmap);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_WRITE") == 0) {
|
||||||
|
uint8_t value = atoi(arg);
|
||||||
|
lcd_write(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LCD_PRINT") == 0) {
|
||||||
|
// TODO: handle \r and \n
|
||||||
|
lcd_print(arg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void init_lcd() {
|
void init_lcd() {
|
||||||
ESP_LOGI(TAG, "Initializing LCD...");
|
ESP_LOGI(TAG, "Initializing LCD...");
|
||||||
|
|
||||||
@ -18,6 +96,8 @@ void init_lcd() {
|
|||||||
|
|
||||||
lcd_set_backlight(&lcd, 255);
|
lcd_set_backlight(&lcd, 255);
|
||||||
|
|
||||||
|
register_replay_fn(replay_handler);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "LCD initialized!");
|
ESP_LOGI(TAG, "LCD initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,14 +181,14 @@ void lcd_left_to_right() {
|
|||||||
lcd_left_to_right(&lcd);
|
lcd_left_to_right(&lcd);
|
||||||
|
|
||||||
if (is_state_tracking()) {
|
if (is_state_tracking()) {
|
||||||
event_occured("LCD_SCROLL_LEFT_TO_RIGHT", NULL);
|
event_occured("LCD_LEFT_TO_RIGHT", NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void lcd_right_to_left() {
|
void lcd_right_to_left() {
|
||||||
lcd_right_to_left(&lcd);
|
lcd_right_to_left(&lcd);
|
||||||
|
|
||||||
if (is_state_tracking()) {
|
if (is_state_tracking()) {
|
||||||
event_occured("LCD_SCROLL_RIGHT_TO_LEFT", NULL);
|
event_occured("LCD_RIGHT_TO_LEFT", NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +238,7 @@ void lcd_print(const char* str) {
|
|||||||
lcd_print(&lcd, str);
|
lcd_print(&lcd, str);
|
||||||
|
|
||||||
if (is_state_tracking()) {
|
if (is_state_tracking()) {
|
||||||
|
// TODO: handle \r and \n
|
||||||
event_occured("LCD_PRINT", str);
|
event_occured("LCD_PRINT", str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,32 @@
|
|||||||
#include "led_strip.h"
|
#include "led_strip.h"
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include "state_tracking.h"
|
#include "state_tracking.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
static const char* TAG = "leds";
|
static const char* TAG = "leds";
|
||||||
|
|
||||||
static led_strip_handle_t leds;
|
static led_strip_handle_t leds;
|
||||||
|
|
||||||
|
static bool replay_handler(const char* event, char* arg) {
|
||||||
|
if (strcmp(event, "LED_SET") == 0) {
|
||||||
|
uint32_t led = atoi(strtok(arg, ","));
|
||||||
|
uint32_t color = atoi(strtok(NULL, ","));
|
||||||
|
ESP_LOGI("leds", "color: %ld", color);
|
||||||
|
led_set(led, color);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LED_FLUSH") == 0) {
|
||||||
|
leds_flush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "LED_CLR") == 0) {
|
||||||
|
leds_clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void init_leds() {
|
void init_leds() {
|
||||||
ESP_LOGI(TAG, "Initializing LEDs...");
|
ESP_LOGI(TAG, "Initializing LEDs...");
|
||||||
|
|
||||||
@ -25,6 +46,8 @@ void init_leds() {
|
|||||||
|
|
||||||
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &leds));
|
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &leds));
|
||||||
|
|
||||||
|
register_replay_fn(replay_handler);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "LEDs initialized!");
|
ESP_LOGI(TAG, "LEDs initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,27 @@ QueueHandle_t play_clip_queue;
|
|||||||
/// The clips that are currently playing
|
/// The clips that are currently playing
|
||||||
std::vector<playing_audio_clip_t> playing_clips;
|
std::vector<playing_audio_clip_t> playing_clips;
|
||||||
|
|
||||||
|
static bool replay_handler(const char* event, char* arg) {
|
||||||
|
if (strcmp(event, "PLAY_WAV") == 0) {
|
||||||
|
char* file_name = strtok(arg, ":");
|
||||||
|
char* play_immediately_str = strtok(NULL, ":");
|
||||||
|
char* repeat_str = strtok(NULL, ":");
|
||||||
|
char* prescaler_str = strtok(NULL, ":");
|
||||||
|
|
||||||
|
bool play_immediately = strcmp(play_immediately_str, "true") == 0;
|
||||||
|
bool repeat = strcmp(repeat_str, "true") == 0;
|
||||||
|
uint8_t prescaler = atoi(prescaler_str);
|
||||||
|
play_clip_wav(file_name, play_immediately, repeat, prescaler, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "STOP_WAV") == 0) {
|
||||||
|
stop_clip(arg, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool push_clip(audio_clip_t clip) {
|
static bool push_clip(audio_clip_t clip) {
|
||||||
ESP_LOGD(TAG, "playing %s", clip.file_name);
|
ESP_LOGD(TAG, "playing %s", clip.file_name);
|
||||||
FILE* fh = fopen(clip.file_name, "rb");
|
FILE* fh = fopen(clip.file_name, "rb");
|
||||||
@ -234,5 +255,7 @@ void init_speaker(void) {
|
|||||||
|
|
||||||
play_clip_wav(MOUNT_POINT "/startup.wav", true, false, 4, 0);
|
play_clip_wav(MOUNT_POINT "/startup.wav", true, false, 4, 0);
|
||||||
|
|
||||||
|
register_replay_fn(replay_handler);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Speaker initialized!");
|
ESP_LOGI(TAG, "Speaker initialized!");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,62 @@
|
|||||||
#include "sseg.h"
|
#include "sseg.h"
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include "state_tracking.h"
|
#include "state_tracking.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
TM1640* sseg = nullptr;
|
TM1640* sseg = nullptr;
|
||||||
|
|
||||||
static const char *TAG = "sseg";
|
static const char *TAG = "sseg";
|
||||||
|
|
||||||
|
static bool replay_handler(const char* event, char* arg) {
|
||||||
|
if (strcmp(event, "SSEG_G_RAW") == 0) {
|
||||||
|
uint8_t segments[4];
|
||||||
|
segments[0] = atoi(strtok(arg, ","));
|
||||||
|
for (int i = 1; i < 4; i++) {
|
||||||
|
segments[i] = atoi(strtok(NULL, ","));
|
||||||
|
}
|
||||||
|
set_game_sseg_raw(segments);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "SSEG_G_CLR") == 0) {
|
||||||
|
clear_game_sseg();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "SSEG_M_RAW") == 0) {
|
||||||
|
uint8_t segments[4];
|
||||||
|
segments[0] = atoi(strtok(arg, ","));
|
||||||
|
for (int i = 1; i < 4; i++) {
|
||||||
|
segments[i] = atoi(strtok(NULL, ","));
|
||||||
|
}
|
||||||
|
set_module_sseg_raw(segments);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "SSEG_M_CLR") == 0) {
|
||||||
|
clear_module_sseg();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "SSEG_G") == 0) {
|
||||||
|
uint32_t value = atoi(strtok(arg, ","));
|
||||||
|
uint8_t dot_pos = atoi(strtok(NULL, ","));
|
||||||
|
set_game_sseg_num(value, dot_pos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strcmp(event, "SSEG_M") == 0) {
|
||||||
|
uint32_t value = atoi(strtok(arg, ","));
|
||||||
|
uint8_t dot_pos = atoi(strtok(NULL, ","));
|
||||||
|
set_module_sseg_num(value, dot_pos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void init_sseg() {
|
void init_sseg() {
|
||||||
ESP_LOGI(TAG, "Initializing sseg...");
|
ESP_LOGI(TAG, "Initializing sseg...");
|
||||||
|
|
||||||
sseg = new TM1640(SSEG_PIN_DATA, SSEG_PIN_CLK, 8);
|
sseg = new TM1640(SSEG_PIN_DATA, SSEG_PIN_CLK, 8);
|
||||||
|
|
||||||
|
register_replay_fn(replay_handler);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Sseg initialized!");
|
ESP_LOGI(TAG, "Sseg initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +108,7 @@ void clear_module_sseg() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set_game_sseg_num(uint32_t value, uint8_t dot_pos) {
|
void set_game_sseg_num(uint32_t value, uint8_t dot_pos) {
|
||||||
|
uint32_t initial_value = value;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
auto idx = value % 10;
|
auto idx = value % 10;
|
||||||
sseg->sendChar(3-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
sseg->sendChar(3-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
||||||
@ -70,12 +117,13 @@ void set_game_sseg_num(uint32_t value, uint8_t dot_pos) {
|
|||||||
|
|
||||||
if (is_state_tracking()) {
|
if (is_state_tracking()) {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
sprintf(buf, "%ld,%d", value, dot_pos);
|
sprintf(buf, "%ld,%d", initial_value, dot_pos);
|
||||||
event_occured("SSEG_G", buf);
|
event_occured("SSEG_G", buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_module_sseg_num(uint32_t value, uint8_t dot_pos) {
|
void set_module_sseg_num(uint32_t value, uint8_t dot_pos) {
|
||||||
|
uint32_t initial_value = value;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
auto idx = value % 10;
|
auto idx = value % 10;
|
||||||
sseg->sendChar(7-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
sseg->sendChar(7-i, TM16XX_NUMBER_FONT[idx], i == dot_pos);
|
||||||
@ -84,7 +132,7 @@ void set_module_sseg_num(uint32_t value, uint8_t dot_pos) {
|
|||||||
|
|
||||||
if (is_state_tracking()) {
|
if (is_state_tracking()) {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
sprintf(buf, "%ld,%d", value, dot_pos);
|
sprintf(buf, "%ld,%d", initial_value, dot_pos);
|
||||||
event_occured("SSEG_M", buf);
|
event_occured("SSEG_M", buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,13 +2,15 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
static const char* PLAYBACK_TAG = "playback";
|
||||||
|
|
||||||
enum state_t {
|
enum state_t {
|
||||||
STATE_IDLE = 0,
|
STATE_IDLE = 0,
|
||||||
STATE_RECORDING = 1,
|
STATE_RECORDING = 1,
|
||||||
STATE_PLAYBACK = 2,
|
STATE_PLAYBACK = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<EventCB> event_cbs;
|
static std::vector<bool(*)(const char*, char*)> replay_fns;
|
||||||
|
|
||||||
static bool should_close_recording_stream;
|
static bool should_close_recording_stream;
|
||||||
static FILE* recording_stream;
|
static FILE* recording_stream;
|
||||||
@ -17,6 +19,9 @@ TaskHandle_t flush_file_task_handle;
|
|||||||
|
|
||||||
static bool should_close_playback_stream;
|
static bool should_close_playback_stream;
|
||||||
static FILE* playback_stream;
|
static FILE* playback_stream;
|
||||||
|
static uint32_t playback_start_time;
|
||||||
|
TaskHandle_t playback_task_handle;
|
||||||
|
|
||||||
static volatile state_t state = STATE_IDLE;
|
static volatile state_t state = STATE_IDLE;
|
||||||
|
|
||||||
|
|
||||||
@ -37,12 +42,97 @@ static void flush_file_task(void* arg) {
|
|||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_event_cb(const char* name, void (*replay_callback)(uint32_t, const char*)) {
|
static void playback_task(void* arg) {
|
||||||
EventCB event = {
|
const size_t size = 16*1024;
|
||||||
.name = name,
|
char* buf = (char*) malloc(size*sizeof(char));
|
||||||
.replay_callback = replay_callback,
|
if (buf == nullptr) {
|
||||||
};
|
ESP_LOGE(PLAYBACK_TAG, "buf alloc failure");
|
||||||
event_cbs.push_back(event);
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (state == STATE_PLAYBACK && playback_stream != nullptr) {
|
||||||
|
char* ret = fgets(buf, size, playback_stream);
|
||||||
|
if (ret == nullptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (buf[0] == '\0') {
|
||||||
|
ESP_LOGI(PLAYBACK_TAG, "playback done");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// get rid of the '\n' and possibly '\r' in the string
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (buf[i] == '\0') break;
|
||||||
|
if (buf[i] == '\r' || buf[i] == '\n') {
|
||||||
|
buf[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_LOGI(PLAYBACK_TAG, "handling: %s", buf);
|
||||||
|
|
||||||
|
// look for a comma, indicating the end of the "ticks" part
|
||||||
|
// TODO: replace with strtok
|
||||||
|
size_t comma_pos = 0;
|
||||||
|
for (int i = 0; i < 11; i++) {
|
||||||
|
if (buf[i] == ',') {
|
||||||
|
comma_pos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (comma_pos == 0) {
|
||||||
|
ESP_LOGE(PLAYBACK_TAG, "Failed to find comma in playback line");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[comma_pos] = '\0';
|
||||||
|
uint32_t tick = atoi(buf);
|
||||||
|
|
||||||
|
// now look for the colon to indicate the end of the event name
|
||||||
|
size_t colon_pos = 0;
|
||||||
|
int i = comma_pos + 1; // start looking right after the comma
|
||||||
|
while (i < size) {
|
||||||
|
if (buf[i] == ':') {
|
||||||
|
colon_pos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (colon_pos == 0) {
|
||||||
|
ESP_LOGE(PLAYBACK_TAG, "Failed to find colon in playback line");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[colon_pos] = '\0';
|
||||||
|
char* event_name = buf + (comma_pos + 1);
|
||||||
|
char* arg = buf + (colon_pos + 1);
|
||||||
|
|
||||||
|
int32_t ticks_to_wait = ((int32_t) tick) - (int32_t)(xTaskGetTickCount() - playback_start_time);
|
||||||
|
|
||||||
|
if (ticks_to_wait < 0) {
|
||||||
|
ESP_LOGW(PLAYBACK_TAG, "Playback is behind by %ld ticks!", ticks_to_wait);
|
||||||
|
}
|
||||||
|
if (ticks_to_wait > 0) {
|
||||||
|
vTaskDelay(ticks_to_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matched = false;
|
||||||
|
for (const auto& fn : replay_fns) {
|
||||||
|
matched = (fn)(event_name, arg);
|
||||||
|
if (matched) break;
|
||||||
|
}
|
||||||
|
if (!matched) {
|
||||||
|
ESP_LOGW(PLAYBACK_TAG, "Failed to match event: %s!", event_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
playback_task_handle = NULL;
|
||||||
|
|
||||||
|
stop_playback();
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_replay_fn(bool (*replay_fn)(const char*, char*)) {
|
||||||
|
replay_fns.push_back(replay_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_occured(const char* name, const char* arg) {
|
void event_occured(const char* name, const char* arg) {
|
||||||
@ -102,13 +192,30 @@ bool stop_recording() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool start_playback() {
|
bool start_playback() {
|
||||||
// TODO: impl
|
if (state != STATE_IDLE) return false;
|
||||||
return false;
|
if (playback_stream == nullptr) return false;
|
||||||
|
|
||||||
|
state = STATE_PLAYBACK;
|
||||||
|
playback_start_time = xTaskGetTickCount();
|
||||||
|
xTaskCreate(playback_task, "playback", 4096, NULL, 2, &playback_task_handle);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stop_playback() {
|
bool stop_playback() {
|
||||||
// TODO: impl
|
if (state != STATE_PLAYBACK) return false;
|
||||||
return false;
|
|
||||||
|
state = STATE_IDLE;
|
||||||
|
if (should_close_playback_stream) {
|
||||||
|
fclose(playback_stream);
|
||||||
|
playback_stream = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playback_task_handle != nullptr) {
|
||||||
|
// TODO: NO!! This leaks the malloc. Instead, use a queue to request a graceful stop
|
||||||
|
vTaskDelete(playback_task_handle);
|
||||||
|
playback_task_handle = NULL;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_state_tracking() {
|
bool is_state_tracking() {
|
||||||
|
|||||||
@ -4,20 +4,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "esp_vfs_fat.h"
|
#include "esp_vfs_fat.h"
|
||||||
|
|
||||||
/// @brief An event that represents the physical bomb state moving.
|
/// @brief Registers function to be called on replay.
|
||||||
struct EventCB {
|
/// @param replay_callback A function to call to playback the event.
|
||||||
// The name of the event.
|
void register_replay_fn(bool (*replay_fn)(const char*, char*));
|
||||||
// This should not contain whitespace or the characters ':', ','
|
|
||||||
const char* name;
|
|
||||||
// An optional callback function for recreating the state.
|
|
||||||
// Arguments are "ticks" and the serialized argument
|
|
||||||
void (*replay_callback)(uint32_t, const char*);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief Registers a callback for a certain event to be called on replay.
|
|
||||||
/// @param name The name of the event to respond to.
|
|
||||||
/// @param replay_callback A function to call to playback this state transition.
|
|
||||||
void register_event_cb(const char* name, void (*replay_callback)(uint32_t, const char*));
|
|
||||||
|
|
||||||
// TODO: add one for generically responding to all events.
|
// TODO: add one for generically responding to all events.
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,10 @@ static lv_style_t style_screen;
|
|||||||
|
|
||||||
SemaphoreHandle_t xGuiSemaphore;
|
SemaphoreHandle_t xGuiSemaphore;
|
||||||
|
|
||||||
|
static bool replay_handler(const char* event, char* arg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool notify_lvgl_flush_ready(
|
static bool notify_lvgl_flush_ready(
|
||||||
esp_lcd_panel_io_handle_t panel_io,
|
esp_lcd_panel_io_handle_t panel_io,
|
||||||
esp_lcd_panel_io_event_data_t *edata,
|
esp_lcd_panel_io_event_data_t *edata,
|
||||||
@ -46,7 +50,7 @@ static void lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t
|
|||||||
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
|
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
|
||||||
|
|
||||||
// TODO: change this to be a kconfig value
|
// TODO: change this to be a kconfig value
|
||||||
#if true
|
#if false
|
||||||
|
|
||||||
if (is_state_tracking()) {
|
if (is_state_tracking()) {
|
||||||
size_t size = (offsetx2 + 1 - offsetx1) * (offsety2 + 1 - offsety1) + 1;
|
size_t size = (offsetx2 + 1 - offsetx1) * (offsety2 + 1 - offsety1) + 1;
|
||||||
@ -224,5 +228,7 @@ void init_tft() {
|
|||||||
initialize_display();
|
initialize_display();
|
||||||
xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 5, NULL, 1);
|
xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 5, NULL, 1);
|
||||||
|
|
||||||
|
register_replay_fn(replay_handler);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "TFT initialized!");
|
ESP_LOGI(TAG, "TFT initialized!");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,9 @@ extern "C" void app_main(void) {
|
|||||||
init_wires();
|
init_wires();
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
|
||||||
|
clean_bomb();
|
||||||
|
step0();
|
||||||
|
|
||||||
// set_recording_source(stdout, false);
|
// set_recording_source(stdout, false);
|
||||||
FILE* record_file = fopen(MOUNT_POINT "/record.txt", "w");
|
FILE* record_file = fopen(MOUNT_POINT "/record.txt", "w");
|
||||||
if (record_file == nullptr) {
|
if (record_file == nullptr) {
|
||||||
@ -44,10 +47,6 @@ extern "C" void app_main(void) {
|
|||||||
set_recording_source(record_file, true);
|
set_recording_source(record_file, true);
|
||||||
start_recording();
|
start_recording();
|
||||||
|
|
||||||
clean_bomb();
|
|
||||||
step0();
|
|
||||||
|
|
||||||
|
|
||||||
set_game_time(initial_game_time);
|
set_game_time(initial_game_time);
|
||||||
start_game_timer();
|
start_game_timer();
|
||||||
total_strikes = 0;
|
total_strikes = 0;
|
||||||
@ -55,7 +54,6 @@ extern "C" void app_main(void) {
|
|||||||
current_step = 1;
|
current_step = 1;
|
||||||
if (skip_to_step <= 1) step1();
|
if (skip_to_step <= 1) step1();
|
||||||
step_finish_times[current_step-1] = get_game_time();
|
step_finish_times[current_step-1] = get_game_time();
|
||||||
stop_recording();
|
|
||||||
clean_bomb();
|
clean_bomb();
|
||||||
current_step = 2;
|
current_step = 2;
|
||||||
if (skip_to_step <= 2) step2();
|
if (skip_to_step <= 2) step2();
|
||||||
@ -84,5 +82,6 @@ extern "C" void app_main(void) {
|
|||||||
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
|
play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0);
|
||||||
|
|
||||||
display_game_results();
|
display_game_results();
|
||||||
|
stop_recording();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ void setup_wires(void) {
|
|||||||
clear_all_pressed_released();
|
clear_all_pressed_released();
|
||||||
get_cut_wires();
|
get_cut_wires();
|
||||||
lcd_clear();
|
lcd_clear();
|
||||||
lcd_set_cursor_vis(false);
|
lcd_set_cursor_vis(true);
|
||||||
|
|
||||||
WireColor wires[NUM_WIRES];
|
WireColor wires[NUM_WIRES];
|
||||||
load_wires_from_sd_card(wires);
|
load_wires_from_sd_card(wires);
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#include "step0.h"
|
#include "step0.h"
|
||||||
|
#include "drivers/state_tracking.h"
|
||||||
|
|
||||||
static const char* TAG = "step0";
|
static const char* TAG = "step0";
|
||||||
|
|
||||||
@ -34,6 +35,16 @@ static void battery_stats() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove. This is temperary
|
||||||
|
static void replay_last() {
|
||||||
|
FILE* record_file = fopen(MOUNT_POINT "/record.txt", "r");
|
||||||
|
if (record_file == nullptr) {
|
||||||
|
ESP_LOGE("main", "failed to open record.txt");
|
||||||
|
}
|
||||||
|
set_playback_source(record_file, true);
|
||||||
|
start_playback();
|
||||||
|
}
|
||||||
|
|
||||||
/// Wait for "*9819"
|
/// Wait for "*9819"
|
||||||
void step0() {
|
void step0() {
|
||||||
led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE);
|
led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE);
|
||||||
@ -154,6 +165,12 @@ void step0() {
|
|||||||
.should_exit = false,
|
.should_exit = false,
|
||||||
.callback = flashbang,
|
.callback = flashbang,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.code = "*1113",
|
||||||
|
.display_text = "replay_last",
|
||||||
|
.should_exit = false,
|
||||||
|
.callback = replay_last,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
int len = sizeof(star_codes)/sizeof(StarCodeHandler);
|
int len = sizeof(star_codes)/sizeof(StarCodeHandler);
|
||||||
do_star_codes(star_codes, len);
|
do_star_codes(star_codes, len);
|
||||||
|
|||||||
@ -88,6 +88,7 @@ static void new_puzzle(void) {
|
|||||||
// ESP_LOGI(TAG, "Flipping bit %i on display %i", i, display);
|
// ESP_LOGI(TAG, "Flipping bit %i on display %i", i, display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
set_module_sseg_raw(display_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void step2(void) {
|
void step2(void) {
|
||||||
@ -98,7 +99,6 @@ void step2(void) {
|
|||||||
int strike_time = 0;
|
int strike_time = 0;
|
||||||
while(solved_times < NUM_SOLVES) {
|
while(solved_times < NUM_SOLVES) {
|
||||||
// for every bit in the answer-
|
// for every bit in the answer-
|
||||||
set_module_sseg_raw(display_map);
|
|
||||||
if (get_keypad_pressed(&key)) {
|
if (get_keypad_pressed(&key)) {
|
||||||
lcd_clear();
|
lcd_clear();
|
||||||
char c = char_of_keypad_key(key);
|
char c = char_of_keypad_key(key);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user