Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,33 @@ The default configuration for ESP32-S3-BOX-3.
For M5Stack-CoreS3 - uncomment BSP in `idf_component.yml`


## Quick start

```shell
idf.py build flash
pushd apps/tic_tac_toe
idf.py build
esptool.py --chip esp32s3 --baud 921600 --before default_reset --after hard_reset write_flash 0x220000 build/tic_tac_toe.bin
popd
pushd apps/wifi_list
esptool.py --chip esp32s3 --baud 921600 --before default_reset --after hard_reset write_flash 0x4E0000 build/wifi_list.bin
popd
pushd apps/calculator
esptool.py --chip esp32s3 --baud 921600 --before default_reset --after hard_reset write_flash 0x7A0000 build/calculator.bin
popd
```

## Build

Initial build and flash of the application and partition table.

```
```shell
idf.py build flash monitor
```

After the initial flash, it's possible to use following command, just to update the factory application:

```
```shell
idf.py app-flash monitor
```

Expand All @@ -26,7 +42,7 @@ idf.py app-flash monitor
Applications are stored in ota_0 - ota_4.

Build application (e.g. hello_world):
```
```shell
idf.py build
```

Expand All @@ -53,7 +69,7 @@ The bootloader is using OTA mechanism. It's necessary to add following code to t
in order to reboot to bootloader.

Put the following code to main, before starting the rest of the application:
```
```c
#include "esp_ota_ops.h"

const esp_partition_t* factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
Expand All @@ -64,7 +80,9 @@ if (factory_partition != NULL) {

Here's more elaborate version which can be put somwhere into application, like reaction on back button:

```
```c
#include "esp_ota_ops.h"

// Get the partition structure for the factory partition
const esp_partition_t *factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
if (factory_partition != NULL) {
Expand All @@ -87,6 +105,6 @@ If the project is using explicit list of components, you need to add `app_update
idf_component_register(
SRCS "main.cpp"
INCLUDE_DIRS "."
REQUIRES esp-box-3 app_update
REQUIRES app_update
)
```
6 changes: 6 additions & 0 deletions apps/calculator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(calculator)
3 changes: 3 additions & 0 deletions apps/calculator/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
idf_component_register(SRCS "calculator.c"
INCLUDE_DIRS "."
REQUIRES app_update)
132 changes: 132 additions & 0 deletions apps/calculator/main/calculator.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "lvgl.h"
#include "bsp/esp-bsp.h"
#include "esp_timer.h"
#include "esp_ota_ops.h"

#define TAG "Calculator"

static lv_obj_t *display_label;
static char current_input[64] = "";
static double stored_value = 0;
static char current_operator = 0;
static bool clear_next = false;
static int64_t last_press_time = 0;

static void update_display() {
bsp_display_lock(0);
lv_label_set_text(display_label, current_input);
bsp_display_unlock();
}

static void clear_input() {
current_input[0] = '\0';
update_display();
}

static void append_input(const char *text) {
if (clear_next) {
clear_input();
clear_next = false;
}
if (strlen(current_input) < sizeof(current_input) - 1) {
strcat(current_input, text);
}
update_display();
}

static void handle_operator(char operator) {
if (current_operator != 0 && !clear_next) {
double current_value = atof(current_input);
switch (current_operator) {
case '+': stored_value += current_value; break;
case '-': stored_value -= current_value; break;
case '*': stored_value *= current_value; break;
case '/': if (current_value != 0) stored_value /= current_value; break;
}
snprintf(current_input, sizeof(current_input), "%g", stored_value);
update_display();
} else {
stored_value = atof(current_input);
}
current_operator = operator;
clear_next = true;
}

static void btn_event_cb(lv_event_t *e) {
int64_t now = esp_timer_get_time();
if (now - last_press_time < 500000) { // 500 ms debounce time
return;
}
last_press_time = now;

lv_obj_t *btn = lv_event_get_target(e);
const char *txt = lv_btnmatrix_get_btn_text(btn, lv_btnmatrix_get_selected_btn(btn));

if (strcmp(txt, "C") == 0) {
clear_input();
stored_value = 0;
current_operator = 0;
} else if (strcmp(txt, "=") == 0) {
handle_operator(0);
current_operator = 0;
clear_next = true;
} else if (strchr("+-*/", txt[0]) != NULL) {
handle_operator(txt[0]);
} else {
append_input(txt);
}
}

void reset_to_factory_app() {
// Get the partition structure for the factory partition
const esp_partition_t *factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
if (factory_partition != NULL) {
if (esp_ota_set_boot_partition(factory_partition) == ESP_OK) {
printf("Set boot partition to factory, restarting now.\n");
} else {
printf("Failed to set boot partition to factory.\n");
}
} else {
printf("Factory partition not found.\n");
}

fflush(stdout);
}

void app_main(void) {
// Reset to factory app for the next boot.
// It should return to graphical bootloader.
reset_to_factory_app();

// Initialize the BSP
bsp_i2c_init();
bsp_display_start();
lv_init();

// Create a label for the display
display_label = lv_label_create(lv_scr_act());
lv_obj_set_size(display_label, 300, 30);
lv_obj_align(display_label, LV_ALIGN_TOP_MID, 0, 10);
lv_label_set_text(display_label, "0");

// Create a button matrix for the calculator
static const char *btn_map[] = {
"7", "8", "9", "C", "\n",
"4", "5", "6", "*", "\n",
"1", "2", "3", "-", "\n",
"0", ".", "/", "+", "\n",
"=", ""
};

lv_obj_t *btnm = lv_btnmatrix_create(lv_scr_act());
lv_btnmatrix_set_map(btnm, btn_map);
lv_obj_set_size(btnm, 320, 180);
lv_obj_align(btnm, LV_ALIGN_CENTER, 0, 30);
lv_obj_add_event_cb(btnm, btn_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

bsp_display_backlight_on();
}
11 changes: 11 additions & 0 deletions apps/calculator/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## IDF Component Manager Manifest File
dependencies:
espressif/esp-box: "^3.1.0"
#espressif/esp-box-3: "^1.2.0"
# Workaround for i2c: CONFLICT! driver_ng is not allowed to be used with this old driver
esp_codec_dev:
public: true
version: "==1.1.0"
## Required IDF version
idf:
version: ">=5.0.0"
6 changes: 6 additions & 0 deletions apps/tic_tac_toe/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(tic_tac_toe)
3 changes: 3 additions & 0 deletions apps/tic_tac_toe/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
idf_component_register(SRCS "tic_tac_toe.c"
INCLUDE_DIRS "."
REQUIRES app_update)
11 changes: 11 additions & 0 deletions apps/tic_tac_toe/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## IDF Component Manager Manifest File
dependencies:
espressif/esp-box: "^3.1.0"
#espressif/esp-box-3: "^1.2.0"
# Workaround for i2c: CONFLICT! driver_ng is not allowed to be used with this old driver
esp_codec_dev:
public: true
version: "==1.1.0"
## Required IDF version
idf:
version: ">=5.0.0"
Loading