diff --git a/data/config.txt b/data/config.txt
index f29256d..0c08b4a 100644
--- a/data/config.txt
+++ b/data/config.txt
@@ -1,10 +1,8 @@
#nick=your nick, picked randomly on first run
brightness=200
-msg_freq=1800
-msg_ms=20
-sys_freq=440
-sys_ms=10
+tones_msg=T300 O4 l8 D l4 A+
+tones_sys=T300 O4 l8 A l4 D+
touch_threshold=300
diff --git a/platformio.ini b/platformio.ini
index 440f7cc..4a5bfe5 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -18,16 +18,21 @@ board_build.filesystem = littlefs
monitor_speed = 115200
upload_speed = 921600
;monitor_filters = send_on_enter
-build_src_filter = + -
+build_src_filter =
+ +
+ -
lib_deps =
lovyan03/LovyanGFX @ ^1.2
lvgl/lvgl @ ^9.0
; t-vk/ESP32 BLE Keyboard@^0.3.2
https://github.com/sakul-the-one/sakuls-ESP32-BLE-Keyboard
h2zero/NimBLE-Arduino
+ https://github.com/maxint-rd/MmlMusic
build_flags =
-DLV_CONF_INCLUDE_SIMPLE
-I include
+ ; use strchr instead of strchr_P
+ -Dstrchr_P=strchr
; We only need HID peripheral from NimBLE
; saving some memory here.
-DCONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
@@ -39,7 +44,9 @@ board = esp32dev
framework = arduino
monitor_speed = 115200
upload_speed = 921600
-build_src_filter = - + ; ignores root
+build_src_filter =
+ -
+ + ; ignores meshberry
lib_deps =
build_flags =
-I include
\ No newline at end of file
diff --git a/src/meshberry/chat.cpp b/src/meshberry/chat.cpp
index d8d4a7c..e8edb9b 100644
--- a/src/meshberry/chat.cpp
+++ b/src/meshberry/chat.cpp
@@ -403,8 +403,14 @@ void handleCommand(const char* in) {
ui_push_message("", "Usage: /set color_bg ff0000", false, true);
} else {
*sp = '\0';
- if (settings_set_color(args, sp + 1))
+ size_t klen = strlen(args);
+ bool is_tones = klen > 6 && !strcmp(args + klen - 6, "_tones");
+ bool ok = is_tones ? settings_set_tones(args, sp + 1)
+ : settings_set_color(args, sp + 1);
+ if (ok)
ui_push_message("", "Saved. Restart to apply.", false, true);
+ else if (is_tones)
+ ui_push_message("", "Unknown tones key.", false, true);
else
ui_push_message("", "Unknown color or bad hex value.", false, true);
}
@@ -435,7 +441,7 @@ void handleCommand(const char* in) {
ui_push_message("", "/bt : toggle BT send mode", false, true);
ui_push_message("", "/set color_bg ff0000 : set a color (restart to apply)", false, true);
ui_push_message("", "/people : list connected", false, true);
- ui_push_message("", "/sleep : sleep device", false, true);
+ ui_push_message("", "/sleep or /s : sleep device", false, true);
ui_push_message("", "TAB : notes mode", false, true);
//drawChatWindow();
diff --git a/src/meshberry/main.cpp b/src/meshberry/main.cpp
index 97efc30..de6d223 100644
--- a/src/meshberry/main.cpp
+++ b/src/meshberry/main.cpp
@@ -45,5 +45,6 @@ void loop() {
char key = Serial.available() ? (char)Serial.read() : cardkb_read();
chat_tick(key); // TODO: debug why a serial key does not show in the UI?
ui_tick();
+ sound_tick();
delay(5);
}
diff --git a/src/meshberry/settings.cpp b/src/meshberry/settings.cpp
index e2d41f3..c84c028 100644
--- a/src/meshberry/settings.cpp
+++ b/src/meshberry/settings.cpp
@@ -1,16 +1,15 @@
#include "settings.h"
#include
#include
+#include
settings_t g_settings;
static const settings_t DEFAULTS = {
.nick = NICK_DEFAULT_PREFIX,
.brightness = 200,
- .msg_freq = 1800,
- .msg_ms = 20,
- .sys_freq = 440,
- .sys_ms = 10,
+ .tones_msg = "T140 G",
+ .tones_sys = "T140 A",
.touch_threshold = TOUCH_THRESHOLD,
.color_bg = {.blue = 0x11, .green = 0x11, .red = 0x11},
.color_header_bg = {.blue = 0x1e, .green = 0x1e, .red = 0x1e},
@@ -43,10 +42,8 @@ static bool is_hex6(const char* s) {
static bool apply_kv(const char* key, const char* val) {
if (!strcmp(key, "nick")) { strncpy(g_settings.nick, val, CHAT_MAX_NICK_LEN - 1); }
else if (!strcmp(key, "brightness")) { g_settings.brightness = (uint8_t)constrain(atoi(val), 0, 255); }
- else if (!strcmp(key, "msg_freq")) { g_settings.msg_freq = (uint16_t)atoi(val); }
- else if (!strcmp(key, "msg_ms")) { g_settings.msg_ms = (uint16_t)atoi(val); }
- else if (!strcmp(key, "sys_freq")) { g_settings.sys_freq = (uint16_t)atoi(val); }
- else if (!strcmp(key, "sys_ms")) { g_settings.sys_ms = (uint16_t)atoi(val); }
+ else if (!strcmp(key, "tones_msg")) { g_settings.tones_msg = String(val); }
+ else if (!strcmp(key, "tones_sys")) { g_settings.tones_sys = String(val); }
else if (!strcmp(key, "touch_threshold")) { g_settings.touch_threshold = (uint16_t)atoi(val); }
else if (!strcmp(key, "color_bg")) { if (!is_hex6(val)) return false; g_settings.color_bg = parse_color(val); }
else if (!strcmp(key, "color_header_bg")) { if (!is_hex6(val)) return false; g_settings.color_header_bg = parse_color(val); }
@@ -60,12 +57,12 @@ static bool apply_kv(const char* key, const char* val) {
}
static void dump_settings() {
- Serial.println("[settings] ---- effective config ----");
+ Serial.println("[settings]");
Serial.printf ("[settings] nick=%s brightness=%d\n",
g_settings.nick, g_settings.brightness);
- Serial.printf ("[settings] msg_freq=%u msg_ms=%u sys_freq=%u sys_ms=%u touch_threshold=%u\n",
- g_settings.msg_freq, g_settings.msg_ms, g_settings.sys_freq,
- g_settings.sys_ms, g_settings.touch_threshold);
+ Serial.printf ("[settings] tones_msg=%s tones_sys=%s\n",
+ g_settings.tones_msg.c_str(), g_settings.tones_sys.c_str());
+ Serial.printf ("[settings] touch_threshold=%u\n", g_settings.touch_threshold);
Serial.printf ("[settings] color_bg=%02x%02x%02x color_header_bg=%02x%02x%02x\n",
g_settings.color_bg.red, g_settings.color_bg.green, g_settings.color_bg.blue,
g_settings.color_header_bg.red, g_settings.color_header_bg.green, g_settings.color_header_bg.blue);
@@ -76,7 +73,7 @@ static void dump_settings() {
Serial.printf ("[settings] color_system=%02x%02x%02x color_input_prompt=%02x%02x%02x\n",
g_settings.color_system.red, g_settings.color_system.green, g_settings.color_system.blue,
g_settings.color_input_prompt.red, g_settings.color_input_prompt.green, g_settings.color_input_prompt.blue);
- Serial.println("[settings] ----------------------------");
+ Serial.println("[settings]");
}
// Public
@@ -170,3 +167,13 @@ bool settings_set_color(const char* key, const char* hex) {
rewrite_config_line(key, hex);
return true;
}
+
+
+bool settings_set_tones(const char* key, const char* tones) {
+ if (strlen(key) <= 6 || strcmp(key + strlen(key) - 6, "_tones") != 0) {
+ return false;
+ }
+ if (!apply_kv(key, tones)) return false; // unknown key or bad tones
+ rewrite_config_line(key, tones);
+ return true;
+}
\ No newline at end of file
diff --git a/src/meshberry/settings.h b/src/meshberry/settings.h
index 6651cb9..40c3094 100644
--- a/src/meshberry/settings.h
+++ b/src/meshberry/settings.h
@@ -1,16 +1,15 @@
#pragma once
#include
#include "config.h"
+#include
// All values read from /config.txt on LittleFS.
struct settings_t {
char nick[CHAT_MAX_NICK_LEN];
uint8_t brightness;
- uint16_t msg_freq; // Hz, notification beep for incoming messages
- uint16_t msg_ms; // duration in ms
- uint16_t sys_freq; // Hz, beep for join / leave events
- uint16_t sys_ms; // duration in ms
- uint16_t touch_threshold; // touch7 (GPIO27) wake-from-sleep sensitivity
+ String tones_msg; // MML string for incoming message
+ String tones_sys; // MML string for system message
+ uint16_t touch_threshold; // touch7 (GPIO27) wake-from-sleep sensitivity
lv_color_t color_bg;
lv_color_t color_header_bg;
lv_color_t color_msg;
@@ -26,3 +25,4 @@ extern settings_t g_settings;
void settings_load();
void settings_set_nick(const char* nick);
bool settings_set_color(const char* key, const char* hex);
+bool settings_set_tones(const char* key, const char* tones);
diff --git a/src/meshberry/sound.cpp b/src/meshberry/sound.cpp
index 16f4fd0..38f48cd 100644
--- a/src/meshberry/sound.cpp
+++ b/src/meshberry/sound.cpp
@@ -2,11 +2,35 @@
#include "config.h"
#include "settings.h"
#include
+#include
+
+MmlMusic music;
+
+static bool sound_tone_callback(unsigned int frequency, unsigned long length, uint8_t nTrack, uint8_t nVolume) {
+ if (frequency > 0) {
+ tone(PIN_SPEAKER, frequency);
+ } else if (length == 0) {
+ noTone(PIN_SPEAKER);
+ }
+ return true;
+}
void sound_init() {
pinMode(PIN_SPEAKER_EN, OUTPUT);
digitalWrite(PIN_SPEAKER_EN, LOW); // LOW = amp enabled
+ music.setToneCallback(sound_tone_callback);
}
-void sound_msg_in() { tone(PIN_SPEAKER, g_settings.msg_freq, g_settings.msg_ms); }
-void sound_system() { tone(PIN_SPEAKER, g_settings.sys_freq, g_settings.sys_ms); }
+void sound_tick() {
+ music.continuePlaying();
+}
+
+void sound_msg_in() {
+ //tone(PIN_SPEAKER, g_settings.snd_msg_freq, g_settings.snd_msg_ms);
+ //music.play("T140 O5 O5 D L4 G L8 D G L4 B. G8 G. F#8 G. G#8 A2");
+ music.play(g_settings.tones_msg.c_str());
+}
+void sound_system() {
+ // tone(PIN_SPEAKER, g_settings.snd_sys_freq, g_settings.snd_sys_ms);
+ music.play(g_settings.tones_sys.c_str());
+}
\ No newline at end of file
diff --git a/src/meshberry/sound.h b/src/meshberry/sound.h
index 79348eb..e3df084 100644
--- a/src/meshberry/sound.h
+++ b/src/meshberry/sound.h
@@ -1,5 +1,6 @@
#pragma once
void sound_init();
+void sound_tick(); // call regularly from loop() to advance MML playback
void sound_msg_in(); // short high beep, new chat message
void sound_system(); // short low beep , join / leave