Skip to content

Commit 17a20c2

Browse files
committed
Update radio firmware to v3.3.2 and modify the system protocol client accordingly
1 parent 44e4de1 commit 17a20c2

8 files changed

Lines changed: 401 additions & 137 deletions

Makefile

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ BADGELINK_CONN := $(if $(BADGELINKPORT),$(if $(findstring :,$(BADGELINKPORT)),--
88

99
IDF_PATH ?= $(shell cat .IDF_PATH 2>/dev/null || echo `pwd`/esp-idf)
1010
IDF_TOOLS_PATH ?= $(shell cat .IDF_TOOLS_PATH 2>/dev/null || echo `pwd`/esp-idf-tools)
11-
IDF_BRANCH ?= v5.5.1
12-
#IDF_COMMIT ?= aaebc374676621980878789c49d239232ea714c5
11+
IDF_BRANCH ?= v5.5.2
1312
IDF_EXPORT_QUIET ?= 1
1413
IDF_GITHUB_ASSETS ?= dl.espressif.com/github_assets
1514
MAKEFLAGS += --silent
@@ -74,8 +73,6 @@ sdk:
7473
if test -d "$(IDF_PATH)"; then echo -e "ESP-IDF target folder exists!\r\nPlease remove the folder or un-set the environment variable."; exit 1; fi
7574
if test -d "$(IDF_TOOLS_PATH)"; then echo -e "ESP-IDF tools target folder exists!\r\nPlease remove the folder or un-set the environment variable."; exit 1; fi
7675
git clone --recursive --branch "$(IDF_BRANCH)" https://github.com/espressif/esp-idf.git "$(IDF_PATH)" --depth=1 --shallow-submodules
77-
# cd "$(IDF_PATH)"; git fetch origin "$(IDF_COMMIT)" --recurse-submodules || true
78-
# cd "$(IDF_PATH)"; git checkout "$(IDF_COMMIT)"
7976
cd "$(IDF_PATH)"; git submodule update --init --recursive
8077
cd "$(IDF_PATH)"; bash install.sh all
8178

@@ -114,16 +111,6 @@ fullclean: clean
114111
checkbuildenv:
115112
if [ -z "$(IDF_PATH)" ]; then echo "IDF_PATH is not set!"; exit 1; fi
116113
if [ -z "$(IDF_TOOLS_PATH)" ]; then echo "IDF_TOOLS_PATH is not set!"; exit 1; fi
117-
# Check if the IDF commit id the one we need
118-
#if [ -d "$(IDF_PATH)" ]; then \
119-
# if [ "$(IDF_COMMIT)" != "$(shell cd $(IDF_PATH); git rev-parse HEAD)" ]; then \
120-
# echo "ESP-IDF commit id does not match! Expected '$(IDF_COMMIT)' got '$(shell git rev-parse HEAD)'"; \
121-
# echo "Run $ make refreshsdk"; \
122-
# echo "To update the ESP-IDF to the correct commit id"; \
123-
# echo "Or set the IDF_COMMIT variable in the Makefile to the correct commit id"; \
124-
# exit 1; \
125-
# fi; \
126-
#fi
127114

128115
# Building
129116

main/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ dependencies:
33
badgeteam/badge-bsp: "^1.0.0"
44
robotman2412/pax-gfx: "^2.1.0"
55
robotman2412/pax-codecs: "^1.0.1"
6-
badgeteam/appfs: "^1.0.2"
6+
badgeteam/appfs: "^1.2.0"
77
badgeteam/custom-certificates: "^1.1.0"
88
nicolaielectronics/wifi-manager: "^0.3.0"
99
nicolaielectronics/tanmatsu-wifi: "^1.2.0"

main/main.c

Lines changed: 18 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -148,22 +148,26 @@ static void wifi_task(void* pvParameters) {
148148
#if defined(CONFIG_BSP_TARGET_TANMATSU) || defined(CONFIG_BSP_TARGET_KONSOOL)
149149
radio_system_protocol_information_t radio_information = {0};
150150
if (radio_system_protocol_get_information(&radio_information) == ESP_OK) {
151-
wifi_firmware_version_mismatch = (strcmp(radio_information.firmware_version, "v3.3.0") != 0);
151+
wifi_firmware_version_mismatch = (strcmp(radio_information.firmware_version, "v3.3.2") != 0);
152152
} else {
153153
wifi_firmware_version_mismatch = true;
154-
ESP_LOGW(TAG, "Radio version mismatch (expected 'v3.3.0', found '%s')", radio_information.firmware_version);
154+
ESP_LOGW(TAG, "Radio version mismatch (expected 'v3.3.2', found '%s')", radio_information.firmware_version);
155155
}
156156

157157
device_identity_t identity = {0};
158158
if (read_device_identity(&identity) == ESP_OK) {
159-
if (radio_information.board_revision != identity.revision) {
160-
if (radio_system_protocol_set_board_revision(identity.revision) == ESP_OK) {
161-
ESP_LOGI(TAG, "Set board revision on radio");
159+
if (radio_information.board_revision != identity.revision ||
160+
radio_information.country_code[0] != identity.region[0] ||
161+
radio_information.country_code[1] != identity.region[1]) {
162+
radio_system_protocol_configuration_t configuration;
163+
configuration.board_revision = identity.revision, memcpy(configuration.country_code, identity.region, 2);
164+
if (radio_system_protocol_set_configuration(&configuration) == ESP_OK) {
165+
ESP_LOGI(TAG, "Configured radio");
162166
} else {
163-
ESP_LOGW(TAG, "Failed to set board revision on radio");
167+
ESP_LOGW(TAG, "Failed to configure radio");
164168
}
165169
} else {
166-
ESP_LOGI(TAG, "Board revision on radio already configured");
170+
ESP_LOGI(TAG, "Radio already configured");
167171
}
168172
} else {
169173
ESP_LOGW(TAG, "Failed to read device identity");
@@ -570,9 +574,9 @@ void app_main(void) {
570574
esp_restart();
571575
}
572576
}
573-
if (patch < 5 && wifi_stack_get_version_mismatch()) {
574-
// Patch level 2-5: new radio update, attempt updating radio
575-
nvs_settings_set_firmware_patch_level(5);
577+
if (patch < 6 && wifi_stack_get_version_mismatch()) {
578+
// Patch level 2-6: new radio update, attempt updating radio
579+
nvs_settings_set_firmware_patch_level(6);
576580
bsp_audio_set_amplifier(false); // Disable amplifier to prevent noise on reboot
577581
radio_ota_update();
578582
bsp_power_set_radio_state(BSP_POWER_RADIO_STATE_OFF);
@@ -610,53 +614,16 @@ void app_main(void) {
610614
uint8_t welcome = 0;
611615
nvs_settings_get_welcome_message_state(&welcome);
612616

613-
const uint8_t welcome_target = 3;
617+
const uint8_t welcome_target = 4;
614618
if (welcome < welcome_target) {
615619
const esp_app_desc_t* app_description = esp_app_get_description();
616620
char title_buffer[128] = {0};
617621
snprintf(title_buffer, sizeof(title_buffer), "Welcome to Tanmatsu launcher %s", app_description->version);
618622
device_identity_t identity = {0};
619623
read_device_identity(&identity);
620-
if (identity.revision == 1) {
621-
message_screen(get_icon(ICON_HELP), title_buffer,
622-
"This update fixes issues with LoRa connectivity on\n"
623-
"revision 1 boards. Your board is a revision 1 board\n"
624-
"LoRa should now function correctly, we recommend you\n"
625-
"try one of the Meshcore apps. Another small change is\n"
626-
"that we moved the 'LoRa info' menu from the\n"
627-
"homescreen to the information menu, accessible using\n"
628-
"the yellow square button or from the settings page.\n");
629-
} else if (identity.revision == 7) {
630-
message_screen(get_icon(ICON_HELP), title_buffer,
631-
"This update fixes issues with LoRa connectivity on\n"
632-
"revision 1 boards. Your board is newer so nothing\n"
633-
"has changed there. Another small change is that\n"
634-
"we moved the 'LoRa info' menu from the homescreen\n"
635-
"to the information menu, accessible using the yellow\n"
636-
"square button or from the settings page.\n"
637-
"\n"
638-
"A new infrared API is now available on the radio to\n"
639-
"utilize the infrared LED. Your board has the infrared\n"
640-
"LED installed, however not all 3D printed back cases\n"
641-
"have the cutout for the LED. If your device doesn't\n"
642-
"have the LED visible you can download a new revision\n"
643-
"of the 3d printable back cover from Github at:\n"
644-
"github.com/Nicolai-Electronics/tanmatsu-mechanical\n");
645-
} else {
646-
message_screen(get_icon(ICON_HELP), title_buffer,
647-
"This update fixes issues with LoRa connectivity on\n"
648-
"revision 1 boards. Your board is newer so nothing\n"
649-
"has changed there. Another small change is that\n"
650-
"we moved the 'LoRa info' menu from the homescreen\n"
651-
"to the information menu, accessible using the yellow\n"
652-
"square button or from the settings page.\n"
653-
"\n"
654-
"A new infrared API is now available on the radio to\n"
655-
"utilize the infrared LED. Your device doesn't have\n"
656-
"the LED installed, however the footprint is available.\n"
657-
"Any small IR LED will work, for the updated back cover\n"
658-
"you can use EVERLIGHT IR968-8P(X1-X4)XBY (C17179483).\n");
659-
}
624+
message_screen(get_icon(ICON_HELP), title_buffer,
625+
"This release fixes multiple issues in the LoRa driver\n"
626+
"that is part of the radio firmware.\n");
660627
nvs_settings_set_welcome_message_state(welcome_target);
661628
}
662629
#endif

main/radio_ir_protocol_client.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#include "radio_ir_protocol_client.h"
2+
#include <stdbool.h>
3+
#include <stdint.h>
4+
#include <string.h>
5+
#include "esp_err.h"
6+
#include "esp_log.h"
7+
#include "freertos/FreeRTOS.h"
8+
9+
#if defined(CONFIG_IDF_TARGET_ESP32P4)
10+
#include "esp_hosted.h"
11+
12+
static const char TAG[] = "ir client";
13+
14+
static SemaphoreHandle_t ir_protocol_client_mutex = NULL;
15+
static SemaphoreHandle_t ir_protocol_client_transaction_semaphore = NULL;
16+
static uint8_t ir_protocol_client_packet_buffer[512] = {0};
17+
static uint32_t ir_protocol_client_packet_size = 0;
18+
static uint32_t ir_protocol_client_sequence_number = 0;
19+
20+
static esp_err_t ir_protocol_client_transaction(const uint8_t* request, size_t request_length, uint8_t* out_response,
21+
size_t* response_length, size_t max_response_length) {
22+
if (!ir_protocol_client_mutex || !ir_protocol_client_transaction_semaphore) {
23+
ESP_LOGE(TAG, "Invalid state");
24+
return ESP_ERR_INVALID_STATE;
25+
}
26+
27+
esp_err_t result = ESP_FAIL;
28+
xSemaphoreTake(ir_protocol_client_mutex, portMAX_DELAY);
29+
xSemaphoreTake(ir_protocol_client_transaction_semaphore, 0); // Clear semaphore
30+
result = esp_hosted_send_custom_data(0x04, (uint8_t*)request, request_length);
31+
if (result == ESP_OK) {
32+
if (xSemaphoreTake(ir_protocol_client_transaction_semaphore, pdMS_TO_TICKS(2000)) ==
33+
pdTRUE) { // Wait for response
34+
if (ir_protocol_client_packet_size <= max_response_length) {
35+
memcpy(out_response, ir_protocol_client_packet_buffer, ir_protocol_client_packet_size);
36+
*response_length = ir_protocol_client_packet_size;
37+
result = ESP_OK;
38+
} else {
39+
ESP_LOGE(TAG, "Invalid size");
40+
result = ESP_ERR_INVALID_SIZE;
41+
}
42+
} else {
43+
ESP_LOGE(TAG, "Timeout");
44+
result = ESP_ERR_TIMEOUT;
45+
}
46+
}
47+
ir_protocol_client_sequence_number++;
48+
xSemaphoreGive(ir_protocol_client_mutex);
49+
return result;
50+
}
51+
52+
static void ir_protocol_client_transaction_receive(uint32_t msg_id, const uint8_t* packet, size_t length) {
53+
if (msg_id != 0x04) {
54+
ESP_LOGW(TAG, "Received IR message with unknown ID: %u", msg_id);
55+
return;
56+
}
57+
58+
if (!ir_protocol_client_mutex || !ir_protocol_client_transaction_semaphore) {
59+
ESP_LOGW(TAG, "Received IR message but client not initialized");
60+
return;
61+
}
62+
if (length > sizeof(ir_protocol_client_packet_buffer) || length < sizeof(ir_protocol_client_header_t)) {
63+
ESP_LOGW(TAG, "Received IR message but size incorrect");
64+
return;
65+
}
66+
memcpy(ir_protocol_client_packet_buffer, packet, length);
67+
ir_protocol_client_packet_size = length;
68+
xSemaphoreGive(ir_protocol_client_transaction_semaphore);
69+
}
70+
71+
static esp_err_t validate_response(const uint8_t* response, size_t response_length, uint32_t expected_seq,
72+
uint32_t expected_type, size_t min_body_size) {
73+
if (response_length < sizeof(ir_protocol_client_header_t) + min_body_size) {
74+
ESP_LOGE(TAG, "Response too short: %zu bytes", response_length);
75+
return ESP_FAIL;
76+
}
77+
const ir_protocol_client_header_t* h = (const ir_protocol_client_header_t*)response;
78+
if (h->sequence_number != expected_seq) {
79+
ESP_LOGE(TAG, "Response sequence number mismatch: %u != %u", h->sequence_number, expected_seq);
80+
return ESP_FAIL;
81+
}
82+
if (h->type == IR_PROTOCOL_CLIENT_TYPE_NACK) {
83+
return ESP_FAIL;
84+
}
85+
if (h->type != expected_type) {
86+
ESP_LOGE(TAG, "Response type mismatch: %u != %u", h->type, expected_type);
87+
return ESP_FAIL;
88+
}
89+
return ESP_OK;
90+
}
91+
92+
esp_err_t ir_protocol_client_init(void) {
93+
ir_protocol_client_mutex = xSemaphoreCreateMutex();
94+
ir_protocol_client_transaction_semaphore = xSemaphoreCreateBinary();
95+
if (ir_protocol_client_mutex == NULL || ir_protocol_client_transaction_semaphore == NULL) {
96+
if (ir_protocol_client_mutex != NULL) {
97+
vSemaphoreDelete(ir_protocol_client_mutex);
98+
}
99+
if (ir_protocol_client_transaction_semaphore != NULL) {
100+
vSemaphoreDelete(ir_protocol_client_transaction_semaphore);
101+
}
102+
return ESP_ERR_NO_MEM;
103+
}
104+
105+
esp_hosted_register_custom_callback(0x04, ir_protocol_client_transaction_receive);
106+
return ESP_OK;
107+
}
108+
109+
esp_err_t ir_protocol_client_get_supported(void) {
110+
uint8_t request[sizeof(ir_protocol_client_header_t)] = {0};
111+
ir_protocol_client_header_t* header = (ir_protocol_client_header_t*)request;
112+
header->sequence_number = ir_protocol_client_sequence_number;
113+
header->type = IR_PROTOCOL_CLIENT_TYPE_GET_SUPPORTED;
114+
115+
uint8_t response[sizeof(ir_protocol_client_header_t)] = {0};
116+
size_t response_length = 0;
117+
esp_err_t result =
118+
ir_protocol_client_transaction(request, sizeof(request), response, &response_length, sizeof(response));
119+
if (result != ESP_OK) return result;
120+
return validate_response(response, response_length, header->sequence_number, IR_PROTOCOL_CLIENT_TYPE_ACK, 0);
121+
}
122+
123+
esp_err_t ir_protocol_client_set_config(const ir_protocol_client_config_t* config) {
124+
if (config == NULL) return ESP_ERR_INVALID_ARG;
125+
126+
uint8_t request[sizeof(ir_protocol_client_header_t) + sizeof(ir_protocol_client_config_t)] = {0};
127+
ir_protocol_client_header_t* header = (ir_protocol_client_header_t*)request;
128+
header->sequence_number = ir_protocol_client_sequence_number;
129+
header->type = IR_PROTOCOL_CLIENT_TYPE_SET_CONFIG;
130+
memcpy(request + sizeof(ir_protocol_client_header_t), config, sizeof(ir_protocol_client_config_t));
131+
132+
uint8_t response[sizeof(ir_protocol_client_header_t)] = {0};
133+
size_t response_length = 0;
134+
esp_err_t result =
135+
ir_protocol_client_transaction(request, sizeof(request), response, &response_length, sizeof(response));
136+
if (result != ESP_OK) return result;
137+
return validate_response(response, response_length, header->sequence_number, IR_PROTOCOL_CLIENT_TYPE_ACK, 0);
138+
}
139+
140+
esp_err_t ir_protocol_client_send_nec(const ir_protocol_client_nec_scan_code_t* scan_code) {
141+
if (scan_code == NULL) return ESP_ERR_INVALID_ARG;
142+
143+
uint8_t request[sizeof(ir_protocol_client_header_t) + sizeof(ir_protocol_client_nec_scan_code_t)] = {0};
144+
ir_protocol_client_header_t* header = (ir_protocol_client_header_t*)request;
145+
header->sequence_number = ir_protocol_client_sequence_number;
146+
header->type = IR_PROTOCOL_CLIENT_TYPE_SEND_NEC;
147+
memcpy(request + sizeof(ir_protocol_client_header_t), scan_code, sizeof(ir_protocol_client_nec_scan_code_t));
148+
149+
uint8_t response[sizeof(ir_protocol_client_header_t)] = {0};
150+
size_t response_length = 0;
151+
esp_err_t result =
152+
ir_protocol_client_transaction(request, sizeof(request), response, &response_length, sizeof(response));
153+
if (result != ESP_OK) return result;
154+
return validate_response(response, response_length, header->sequence_number, IR_PROTOCOL_CLIENT_TYPE_ACK, 0);
155+
}
156+
157+
#endif

main/radio_ir_protocol_client.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#include <stddef.h>
4+
#include <stdint.h>
5+
#include "esp_err.h"
6+
7+
typedef enum {
8+
IR_PROTOCOL_CLIENT_TYPE_ACK = 0x00,
9+
IR_PROTOCOL_CLIENT_TYPE_NACK = 0x01,
10+
IR_PROTOCOL_CLIENT_TYPE_GET_SUPPORTED = 0x02,
11+
IR_PROTOCOL_CLIENT_TYPE_SET_CONFIG = 0x03,
12+
IR_PROTOCOL_CLIENT_TYPE_SEND_NEC = 0x10,
13+
} ir_protocol_client_packet_type_t;
14+
15+
typedef struct {
16+
uint32_t sequence_number;
17+
uint32_t type; // ir_protocol_client_packet_type_t
18+
} __attribute__((packed)) ir_protocol_client_header_t;
19+
20+
typedef struct {
21+
uint32_t frequency_hz;
22+
uint8_t duty_cycle;
23+
} __attribute__((packed)) ir_protocol_client_config_t;
24+
25+
typedef struct {
26+
uint16_t address;
27+
uint16_t command;
28+
} __attribute__((packed)) ir_protocol_client_nec_scan_code_t;
29+
30+
// Functions
31+
32+
esp_err_t ir_protocol_client_init(void);
33+
esp_err_t ir_protocol_client_get_supported(void);
34+
esp_err_t ir_protocol_client_set_config(const ir_protocol_client_config_t* config);
35+
esp_err_t ir_protocol_client_send_nec(const ir_protocol_client_nec_scan_code_t* scan_code);

main/radio_ota.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#ifdef CONFIG_BSP_TARGET_TANMATSU
1818

19-
#define BASE_URL "https://ota.tanmatsu.cloud/radio-v3.3.0"
19+
#define BASE_URL "https://ota.tanmatsu.cloud/radio-v3.3.2"
2020

2121
#include "esptoolsquared.h"
2222

0 commit comments

Comments
 (0)