diff --git a/include/furble_control.h b/include/furble_control.h new file mode 100644 index 0000000..d60275b --- /dev/null +++ b/include/furble_control.h @@ -0,0 +1,19 @@ +#ifndef FURBLE_CONTROL_H +#define FURBLE_CONTROL_H + +#include + +#define CONTROL_CMD_QUEUE_LEN (32) + +typedef enum { + CONTROL_CMD_SHUTTER_PRESS, + CONTROL_CMD_SHUTTER_RELEASE, + CONTROL_CMD_FOCUS_PRESS, + CONTROL_CMD_FOCUS_RELEASE, + CONTROL_CMD_GPS_UPDATE +} control_cmd_t; + +void control_update_gps(Furble::Camera::gps_t &gps, Furble::Camera::timesync_t ×ync); +void control_task(void *param); + +#endif diff --git a/include/furble_gps.h b/include/furble_gps.h index b40710e..bf0fa1c 100644 --- a/include/furble_gps.h +++ b/include/furble_gps.h @@ -9,6 +9,6 @@ extern TinyGPSPlus furble_gps; extern bool furble_gps_enable; void furble_gps_init(void); -void furble_gps_update_geodata(Furble::Camera *camera); +void furble_gps_update(Furble::Camera *camera); #endif diff --git a/include/furble_ui.h b/include/furble_ui.h index 76e09d7..7dc9b73 100644 --- a/include/furble_ui.h +++ b/include/furble_ui.h @@ -8,4 +8,6 @@ struct FurbleCtx { bool reconnected; }; +void vUITask(void *param); + #endif diff --git a/lib/M5ez/src/M5ez.cpp b/lib/M5ez/src/M5ez.cpp index cae73b0..858af36 100644 --- a/lib/M5ez/src/M5ez.cpp +++ b/lib/M5ez/src/M5ez.cpp @@ -743,9 +743,6 @@ void ezSettings::begin() { #ifdef M5EZ_BATTERY ez.battery.begin(); #endif -#ifdef M5EZ_CLOCK - ez.clock.begin(); -#endif #ifdef M5EZ_BACKLIGHT ez.backlight.begin(); #endif @@ -1075,9 +1072,6 @@ void M5ez::yield() { } } } -#ifdef M5EZ_CLOCK - events(); // TMP -#endif } void M5ez::addEvent(uint16_t (*function)(void *private_data), diff --git a/lib/furble/Camera.cpp b/lib/furble/Camera.cpp index 7368fec..9777e11 100644 --- a/lib/furble/Camera.cpp +++ b/lib/furble/Camera.cpp @@ -24,6 +24,14 @@ bool Camera::connect(esp_power_level_t power, progressFunc pFunc, void *pCtx) { return connected; } +bool Camera::isActive(void) { + return m_Active; +} + +void Camera::setActive(bool active) { + m_Active = active; +} + const char *Camera::getName(void) { return m_Name.c_str(); } diff --git a/lib/furble/Camera.h b/lib/furble/Camera.h index 3a3c55e..651fcc3 100644 --- a/lib/furble/Camera.h +++ b/lib/furble/Camera.h @@ -87,6 +87,16 @@ class Camera { */ virtual bool isConnected(void); + /** + * Camera is active (ie. connect() has succeeded previously). + */ + bool isActive(void); + + /** + * Set camera activity state. + */ + void setActive(bool active); + const char *getName(void); void fillSaveName(char *name); @@ -115,6 +125,8 @@ class Camera { const uint16_t m_Latency = 1; // double the disconnect timeout const uint16_t m_Timeout = (2 * BLE_GAP_INITIAL_SUPERVISION_TIMEOUT); + + bool m_Active = false; }; } // namespace Furble diff --git a/src/furble.cpp b/src/furble.cpp index 2eaced9..df5468d 100644 --- a/src/furble.cpp +++ b/src/furble.cpp @@ -4,12 +4,14 @@ #include +#include "furble_control.h" #include "furble_gps.h" #include "furble_ui.h" #include "interval.h" #include "settings.h" const uint32_t SCAN_DURATION = (60 * 5); +static QueueHandle_t queue; /** * Progress bar update function. @@ -75,11 +77,14 @@ static void remote_control(FurbleCtx *fctx) { auto camera = fctx->camera; static unsigned long shutter_lock_start_ms = 0; static bool shutter_lock = false; + control_cmd_t cmd; ESP_LOGI(LOG_TAG, "Remote Control"); show_shutter_control(false, 0); + ESP_LOGW(LOG_TAG, "queue = %p", queue); + do { ez.yield(); @@ -91,7 +96,8 @@ static void remote_control(FurbleCtx *fctx) { if (M5.BtnPWR.wasClicked() || M5.BtnC.wasPressed()) { if (shutter_lock) { // ensure shutter is released on exit - camera->shutterRelease(); + cmd = CONTROL_CMD_SHUTTER_RELEASE; + xQueueSend(queue, &cmd, 0); } ESP_LOGI(LOG_TAG, "Exit shutter"); break; @@ -101,16 +107,16 @@ static void remote_control(FurbleCtx *fctx) { // release shutter if either shutter or focus is pressed if (M5.BtnA.wasClicked() || M5.BtnB.wasClicked()) { shutter_lock = false; - camera->shutterRelease(); + cmd = CONTROL_CMD_SHUTTER_RELEASE; + xQueueSend(queue, &cmd, 0); show_shutter_control(false, 0); - ESP_LOGI(LOG_TAG, "shutterRelease(unlock)"); } else { show_shutter_control(true, shutter_lock_start_ms); } } else { if (M5.BtnA.wasPressed()) { - camera->shutterPress(); - ESP_LOGI(LOG_TAG, "shutterPress()"); + cmd = CONTROL_CMD_SHUTTER_PRESS; + xQueueSend(queue, &cmd, 0); continue; } @@ -122,21 +128,21 @@ static void remote_control(FurbleCtx *fctx) { show_shutter_control(true, shutter_lock_start_ms); ESP_LOGI(LOG_TAG, "shutter lock"); } else { - camera->shutterRelease(); - ESP_LOGI(LOG_TAG, "shutterRelease()"); + cmd = CONTROL_CMD_SHUTTER_RELEASE; + xQueueSend(queue, &cmd, 0); } continue; } if (M5.BtnB.wasPressed()) { - camera->focusPress(); - ESP_LOGI(LOG_TAG, "focusPress()"); + cmd = CONTROL_CMD_FOCUS_PRESS; + xQueueSend(queue, &cmd, 0); continue; } if (M5.BtnB.wasReleased()) { - camera->focusRelease(); - ESP_LOGI(LOG_TAG, "focusRelease()"); + cmd = CONTROL_CMD_FOCUS_RELEASE; + xQueueSend(queue, &cmd, 0); continue; } } @@ -153,7 +159,7 @@ static uint16_t statusRefresh(void *private_data) { auto camera = fctx->camera; if (camera->isConnected()) { - furble_gps_update_geodata(camera); + furble_gps_update(camera); return 500; } @@ -204,6 +210,7 @@ static void menu_remote(FurbleCtx *fctx) { ez.removeEvent(statusRefresh); fctx->camera->disconnect(); + fctx->camera->setActive(false); ez.backlight.inactivity(USER_SET); } @@ -255,11 +262,13 @@ static void menu_connect(bool scan) { FurbleCtx fctx = {Furble::CameraList::get(i - 1), false}; - ezProgressBar progress_bar(FURBLE_STR, {"Connecting ..."}, {""}); + ezProgressBar progress_bar(FURBLE_STR, {std::string("Connecting to ") + fctx.camera->getName()}, + {""}); if (fctx.camera->connect(settings_load_esp_tx_power(), &update_progress_bar, &progress_bar)) { if (scan) { Furble::CameraList::save(fctx.camera); } + fctx.camera->setActive(true); menu_remote(&fctx); } } @@ -317,37 +326,34 @@ static void mainmenu_poweroff(void) { M5.Power.powerOff(); } -void setup() { - Serial.begin(115200); +void vUITask(void *param) { + queue = static_cast(param); #include #include #include ez.begin(); - Furble::Device::init(); furble_gps_init(); - Furble::Scan::init(settings_load_esp_tx_power()); -} + while (true) { + size_t save_count = Furble::CameraList::getSaveCount(); -void loop() { - size_t save_count = Furble::CameraList::getSaveCount(); + ezMenu mainmenu(FURBLE_STR); + mainmenu.buttons({"OK", "down"}); + if (save_count > 0) { + mainmenu.addItem("Connect", "", do_saved); + } + mainmenu.addItem("Scan", "", do_scan); + if (save_count > 0) { + mainmenu.addItem("Delete Saved", "", menu_delete); + } + mainmenu.addItem("Settings", "", menu_settings); + mainmenu.addItem("Power Off", "", mainmenu_poweroff); + mainmenu.downOnLast("first"); - ezMenu mainmenu(FURBLE_STR); - mainmenu.buttons({"OK", "down"}); - if (save_count > 0) { - mainmenu.addItem("Connect", "", do_saved); + do { + mainmenu.runOnce(); + } while (Furble::CameraList::getSaveCount() == save_count); } - mainmenu.addItem("Scan", "", do_scan); - if (save_count > 0) { - mainmenu.addItem("Delete Saved", "", menu_delete); - } - mainmenu.addItem("Settings", "", menu_settings); - mainmenu.addItem("Power Off", "", mainmenu_poweroff); - mainmenu.downOnLast("first"); - - do { - mainmenu.runOnce(); - } while (Furble::CameraList::getSaveCount() == save_count); } diff --git a/src/furble_control.cpp b/src/furble_control.cpp new file mode 100644 index 0000000..84f9a15 --- /dev/null +++ b/src/furble_control.cpp @@ -0,0 +1,58 @@ +#include + +#include "furble_control.h" + +static QueueHandle_t queue; + +static Furble::Camera::gps_t last_gps; +static Furble::Camera::timesync_t last_timesync; + +void control_update_gps(Furble::Camera::gps_t &gps, Furble::Camera::timesync_t ×ync) { + last_gps = gps; + last_timesync = timesync; + + control_cmd_t cmd = CONTROL_CMD_GPS_UPDATE; + xQueueSend(queue, &cmd, sizeof(control_cmd_t)); +} + +void control_task(void *param) { + queue = static_cast(param); + + while (true) { + control_cmd_t cmd; + BaseType_t ret = xQueueReceive(queue, &cmd, pdMS_TO_TICKS(50)); + if (ret == pdTRUE) { + for (size_t n = 0; n < Furble::CameraList::size(); n++) { + Furble::Camera *camera = Furble::CameraList::get(n); + if (!camera->isActive()) { + continue; + } + + switch (cmd) { + case CONTROL_CMD_SHUTTER_PRESS: + camera->shutterPress(); + ESP_LOGI(LOG_TAG, "shutterPress()"); + break; + case CONTROL_CMD_SHUTTER_RELEASE: + ESP_LOGI(LOG_TAG, "shutterRelease()"); + camera->shutterRelease(); + break; + case CONTROL_CMD_FOCUS_PRESS: + ESP_LOGI(LOG_TAG, "focusPress()"); + camera->focusPress(); + break; + case CONTROL_CMD_FOCUS_RELEASE: + ESP_LOGI(LOG_TAG, "focusRelease()"); + camera->focusRelease(); + break; + case CONTROL_CMD_GPS_UPDATE: + ESP_LOGI(LOG_TAG, "updateGeoData()"); + camera->updateGeoData(last_gps, last_timesync); + break; + default: + ESP_LOGE(LOG_TAG, "Invalid control command %d.", cmd); + } + } + } + } +} diff --git a/src/furble_gps.cpp b/src/furble_gps.cpp index 2bf8fba..2a979b7 100644 --- a/src/furble_gps.cpp +++ b/src/furble_gps.cpp @@ -3,6 +3,7 @@ #include #include +#include "furble_control.h" #include "furble_gps.h" #include "settings.h" @@ -51,7 +52,7 @@ static uint16_t service_grove_gps(void *private_data) { /** * Update geotag data. */ -void furble_gps_update_geodata(Furble::Camera *camera) { +void furble_gps_update(Furble::Camera *camera) { if (!furble_gps_enable) { return; } @@ -65,7 +66,7 @@ void furble_gps_update_geodata(Furble::Camera *camera) { furble_gps.date.day(), furble_gps.time.hour(), furble_gps.time.minute(), furble_gps.time.second()}; - camera->updateGeoData(dgps, timesync); + control_update_gps(dgps, timesync); ez.header.draw("gps"); } } diff --git a/src/interval.cpp b/src/interval.cpp index f805720..c6385a5 100644 --- a/src/interval.cpp +++ b/src/interval.cpp @@ -86,7 +86,6 @@ static void do_interval(FurbleCtx *fctx, interval_t *interval) { do { ez.yield(); - furble_gps_update_geodata(camera); now = millis(); if (fctx->reconnected) { diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6e8ce4d --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,42 @@ +#include +#include + +#include "nimconfig.h" + +#include "Device.h" +#include "Furble.h" + +#include "furble_control.h" +#include "furble_ui.h" +#include "settings.h" + +void setup() { + BaseType_t xRet; + TaskHandle_t xControlHandle = NULL; + TaskHandle_t xUIHandle = NULL; + + Serial.begin(115200); + + QueueHandle_t queue = xQueueCreate(CONTROL_CMD_QUEUE_LEN, sizeof(control_cmd_t)); + if (queue == NULL) { + ESP_LOGE(LOG_TAG, "Failed to create control queue."); + abort(); + } + + Furble::Device::init(); + Furble::Scan::init(settings_load_esp_tx_power()); + + xRet = xTaskCreatePinnedToCore(control_task, "control", 8192, queue, 3, &xControlHandle, 1); + if (xRet != pdPASS) { + ESP_LOGE(LOG_TAG, "Failed to create control task."); + abort(); + } + + xRet = xTaskCreatePinnedToCore(vUITask, "UI-M5ez", 32768, queue, 2, &xUIHandle, 1); + if (xRet != pdPASS) { + ESP_LOGE(LOG_TAG, "Failed to create UI task."); + abort(); + } +} + +void loop() {} diff --git a/src/spinner.cpp b/src/spinner.cpp index ec72048..7975089 100644 --- a/src/spinner.cpp +++ b/src/spinner.cpp @@ -149,7 +149,6 @@ static void spinner_preset(const char *title, SpinValue *sv) { } ez.yield(); - delay(50); } while (!ok); // reconstruct the value