mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-02 10:33:47 +00:00
buzzer and led queued offline message indicator
- buzzer was bugged when message received - green led: hearthbeat, blue led: message received indicator (when not connected to app) - if only one led blinks: hearthbeat 20msec, message received 200msec
This commit is contained in:
@@ -16,6 +16,10 @@
|
||||
#include <ZephyrSensorManager.h>
|
||||
#include <adapters/sensors/SimpleLPP.h>
|
||||
#include <adapters/ble/ZephyrBLE.h>
|
||||
#if IS_ENABLED(CONFIG_ZEPHCORE_UI_BUTTONS) || IS_ENABLED(CONFIG_ZEPHCORE_UI_BUZZER) || IS_ENABLED(CONFIG_ZEPHCORE_UI_DISPLAY)
|
||||
#include <ui_task.h>
|
||||
#define ZEPHCORE_HAS_UI_TASK 1
|
||||
#endif
|
||||
LOG_MODULE_REGISTER(zephcore_companion, CONFIG_ZEPHCORE_MAIN_LOG_LEVEL);
|
||||
|
||||
/* Protocol commands (matches Arduino companion_radio) - sorted by opcode */
|
||||
@@ -589,7 +593,6 @@ ContactInfo *CompanionMesh::processAck(const uint8_t *data)
|
||||
uint32_t trip_time = now - sent_time;
|
||||
put_le32(&ack_push[4], trip_time);
|
||||
sendPush(PUSH_CODE_SEND_CONFIRMED, ack_push, 8);
|
||||
|
||||
return lookupContactByPubKey(ci.id.pub_key, PUB_KEY_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -611,6 +614,10 @@ void CompanionMesh::onMessageRecv(const ContactInfo &contact, mesh::Packet *pkt,
|
||||
markConnectionActive(contact);
|
||||
queueContactMessage(contact, pkt, TXT_TYPE_PLAIN, sender_timestamp, nullptr, 0, text);
|
||||
sendPush(PUSH_CODE_MSG_WAITING);
|
||||
#if ZEPHCORE_HAS_UI_TASK
|
||||
ui_set_msg_count((uint16_t)_offline_queue_count);
|
||||
ui_notify(UI_EVENT_CONTACT_MSG);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CompanionMesh::queueContactMessage(const ContactInfo &contact, mesh::Packet *pkt,
|
||||
@@ -685,6 +692,10 @@ void CompanionMesh::onSignedMessageRecv(const ContactInfo &contact, mesh::Packet
|
||||
// sender_prefix is 4 bytes
|
||||
queueContactMessage(contact, pkt, TXT_TYPE_SIGNED_PLAIN, sender_timestamp, sender_prefix, 4, text);
|
||||
sendPush(PUSH_CODE_MSG_WAITING);
|
||||
#if ZEPHCORE_HAS_UI_TASK
|
||||
ui_set_msg_count((uint16_t)_offline_queue_count);
|
||||
ui_notify(UI_EVENT_CONTACT_MSG);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t CompanionMesh::calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const
|
||||
@@ -747,6 +758,10 @@ void CompanionMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh
|
||||
LOG_DBG("onChannelMessageRecv: frame_len=%d channel_idx=%d", i, channel_idx);
|
||||
queueOfflineMessage(frame, i);
|
||||
sendPush(PUSH_CODE_MSG_WAITING);
|
||||
#if ZEPHCORE_HAS_UI_TASK
|
||||
ui_set_msg_count((uint16_t)_offline_queue_count);
|
||||
ui_notify(UI_EVENT_CHANNEL_MSG);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CompanionMesh::onChannelDataRecv(const mesh::GroupChannel &channel, mesh::Packet *pkt,
|
||||
@@ -1766,6 +1781,9 @@ bool CompanionMesh::handleProtocolFrame(const uint8_t *data, size_t len)
|
||||
if (_sync_pending) {
|
||||
confirmOfflineMessage();
|
||||
_sync_pending = false;
|
||||
#if ZEPHCORE_HAS_UI_TASK
|
||||
ui_set_msg_count((uint16_t)_offline_queue_count);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t buf[MAX_FRAME_SIZE];
|
||||
|
||||
@@ -91,19 +91,28 @@ LOG_MODULE_REGISTER(ui_task, CONFIG_ZEPHCORE_BOARD_LOG_LEVEL);
|
||||
* Works alongside displays; boards that want to disable it can
|
||||
* remove the led0 alias or override this with a Kconfig guard. */
|
||||
#if DT_NODE_HAS_PROP(DT_ALIAS(led0), gpios)
|
||||
#define LED_NODE DT_ALIAS(led0)
|
||||
static const struct gpio_dt_spec heartbeat_led =
|
||||
GPIO_DT_SPEC_GET(LED_NODE, gpios);
|
||||
GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
|
||||
#define HAS_HEARTBEAT_LED 1
|
||||
#elif DT_NODE_HAS_PROP(DT_ALIAS(led1), gpios)
|
||||
#define LED_NODE DT_ALIAS(led1)
|
||||
static const struct gpio_dt_spec heartbeat_led =
|
||||
GPIO_DT_SPEC_GET(LED_NODE, gpios);
|
||||
GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios);
|
||||
#define HAS_HEARTBEAT_LED 1
|
||||
#else
|
||||
#define HAS_HEARTBEAT_LED 0
|
||||
#endif
|
||||
|
||||
/* Message indicator LED — solid ON while offline queue is non-empty.
|
||||
* Uses led1 only when led0 is already taken by the heartbeat. */
|
||||
#if HAS_HEARTBEAT_LED && DT_NODE_HAS_PROP(DT_ALIAS(led0), gpios) && \
|
||||
DT_NODE_HAS_PROP(DT_ALIAS(led1), gpios)
|
||||
static const struct gpio_dt_spec msg_led =
|
||||
GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios);
|
||||
#define HAS_MSG_LED 1
|
||||
#else
|
||||
#define HAS_MSG_LED 0
|
||||
#endif
|
||||
|
||||
#define LED_CYCLE_MS 4000 /* Total heartbeat period */
|
||||
#define LED_ON_MS 20 /* Normal pulse width */
|
||||
#define LED_ON_MSG_MS 200 /* Pulse width when unread messages */
|
||||
@@ -183,6 +192,9 @@ static void led_off_work_handler(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
gpio_pin_set_dt(&heartbeat_led, 0);
|
||||
#if HAS_MSG_LED
|
||||
gpio_pin_set_dt(&msg_led, 0);
|
||||
#endif
|
||||
|
||||
/* Schedule next ON after remainder of cycle */
|
||||
struct ui_state *s = get_state();
|
||||
@@ -195,10 +207,16 @@ static void led_on_work_handler(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
gpio_pin_set_dt(&heartbeat_led, 1);
|
||||
|
||||
/* Schedule OFF after pulse width */
|
||||
#if HAS_MSG_LED
|
||||
struct ui_state *s = get_state();
|
||||
if (s->msg_count > 0) {
|
||||
gpio_pin_set_dt(&msg_led, 1);
|
||||
}
|
||||
uint16_t on_ms = (s->msg_count > 0) ? LED_ON_MSG_MS : LED_ON_MS;
|
||||
#else
|
||||
struct ui_state *s = get_state();
|
||||
uint16_t on_ms = (s->msg_count > 0) ? LED_ON_MSG_MS : LED_ON_MS;
|
||||
#endif
|
||||
|
||||
k_work_reschedule(&led_off_work, K_MSEC(on_ms));
|
||||
}
|
||||
@@ -550,12 +568,15 @@ static void action_deep_sleep(void)
|
||||
#ifdef CONFIG_POWEROFF
|
||||
LOG_INF("deep sleep: shutting down...");
|
||||
|
||||
/* 1. Stop LED heartbeat */
|
||||
/* 1. Stop LED heartbeat and msg indicator */
|
||||
#if HAS_HEARTBEAT_LED
|
||||
k_work_cancel_delayable(&led_on_work);
|
||||
k_work_cancel_delayable(&led_off_work);
|
||||
gpio_pin_set_dt(&heartbeat_led, 0);
|
||||
#endif
|
||||
#if HAS_MSG_LED
|
||||
gpio_pin_set_dt(&msg_led, 0);
|
||||
#endif
|
||||
|
||||
/* 2. Play shutdown melody (blocking wait) */
|
||||
#ifdef CONFIG_ZEPHCORE_UI_BUZZER
|
||||
@@ -860,6 +881,12 @@ int ui_init(void)
|
||||
LOG_INF("LED heartbeat started");
|
||||
}
|
||||
#endif
|
||||
#if HAS_MSG_LED
|
||||
if (gpio_is_ready_dt(&msg_led)) {
|
||||
gpio_pin_configure_dt(&msg_led, GPIO_OUTPUT_INACTIVE);
|
||||
LOG_INF("msg LED ready");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* NOTE: startup chime is NOT played here. It's played from main()
|
||||
* after loadPrefs() so we can respect the persisted buzzer_quiet setting.
|
||||
@@ -938,12 +965,24 @@ void ui_notify(enum ui_event event)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wake display on notifications.
|
||||
* Repeater: never wake display on events — only user button wakes it.
|
||||
* Companion: wake unless phone is connected (phone handles its own). */
|
||||
/* On message events: flash heartbeat LED immediately (if not BLE connected
|
||||
* and LEDs are enabled). Cancel the current cycle, turn on now, let
|
||||
* led_off_work resume the normal heartbeat after LED_ON_MSG_MS. */
|
||||
#if HAS_HEARTBEAT_LED
|
||||
if (is_msg_event && !get_state()->ble_connected && !get_state()->leds_disabled
|
||||
&& gpio_is_ready_dt(&heartbeat_led)) {
|
||||
k_work_cancel_delayable(&led_on_work);
|
||||
k_work_cancel_delayable(&led_off_work);
|
||||
gpio_pin_set_dt(&heartbeat_led, 1);
|
||||
k_work_reschedule(&led_off_work, K_MSEC(LED_ON_MSG_MS));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Wake display on non-message notifications (BLE connect/disconnect etc).
|
||||
* Message notifications use buzzer + LED flash instead of waking the display. */
|
||||
#ifdef CONFIG_ZEPHCORE_UI_DISPLAY
|
||||
#ifndef ZEPHCORE_REPEATER
|
||||
if (!(is_msg_event && get_state()->ble_connected)) {
|
||||
if (!is_msg_event) {
|
||||
mc_display_on();
|
||||
schedule_render();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user