Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: friend device can speak on button press [WIP] #1243

Draft
wants to merge 60 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
5135bd7
Update transport.c
vincentkoc Nov 3, 2024
1637309
Update transport.c
vincentkoc Nov 3, 2024
2b23601
Update speaker.c
vincentkoc Nov 3, 2024
25044a3
Update speaker.c
vincentkoc Nov 3, 2024
26d591e
Update speaker.c
vincentkoc Nov 3, 2024
bcc7956
Update speaker.c
vincentkoc Nov 3, 2024
1ac0552
Update button.c
vincentkoc Nov 3, 2024
9f6fc90
Update button.c
vincentkoc Nov 3, 2024
4a2273f
Update button.c
vincentkoc Nov 3, 2024
be2e2fe
Update button.c
vincentkoc Nov 3, 2024
ce62e98
Update button.c
vincentkoc Nov 3, 2024
5a1d1c9
Update button.c
vincentkoc Nov 3, 2024
e64d495
Update speaker.h
vincentkoc Nov 3, 2024
0559d9e
Update button.h
vincentkoc Nov 3, 2024
8635c49
Update button.c
vincentkoc Nov 3, 2024
a9806be
Update button.c
vincentkoc Nov 3, 2024
3695884
Update button.c
vincentkoc Nov 3, 2024
5c8d9a2
Update button.h
vincentkoc Nov 3, 2024
087f194
Update button.h
vincentkoc Nov 3, 2024
66ad8cd
Update transport.c
vincentkoc Nov 3, 2024
2c726d9
Update transport.h
vincentkoc Nov 3, 2024
5d91948
Update transport.c
vincentkoc Nov 3, 2024
e39c39e
Update transport.c
vincentkoc Nov 3, 2024
b39bd78
Update transport.c
vincentkoc Nov 3, 2024
34b9f56
Update button.c
vincentkoc Nov 3, 2024
073d6b6
Create talk_audio_on_friend.py
vincentkoc Nov 3, 2024
3377663
Update discover_devices.py
vincentkoc Nov 3, 2024
fd0be4a
Update discover_devices.py
vincentkoc Nov 3, 2024
5f0dd65
Update transport.c
vincentkoc Nov 3, 2024
ee0e05b
Update transport.c
vincentkoc Nov 3, 2024
5b9fe67
Update transport.c
vincentkoc Nov 3, 2024
7adea66
Update button.c
vincentkoc Nov 3, 2024
1685775
Update button.c
vincentkoc Nov 3, 2024
acd8243
Update button.c
vincentkoc Nov 3, 2024
7193fd9
Update button.c
vincentkoc Nov 3, 2024
123833b
Update transport.c
vincentkoc Nov 3, 2024
32eeef2
Update transport.c
vincentkoc Nov 3, 2024
459b8e0
Update transport.c
vincentkoc Nov 3, 2024
5858e75
Update transport.h
vincentkoc Nov 3, 2024
f4ddee5
Update talk_audio_on_friend.py
vincentkoc Nov 3, 2024
c70d2f3
Update speaker.c
vincentkoc Nov 3, 2024
bbf044f
Update transport.c
vincentkoc Nov 3, 2024
af21c33
Update talk_audio_on_friend.py
vincentkoc Nov 3, 2024
a90704d
Update transport.c
vincentkoc Nov 3, 2024
882a429
Update transport.c
vincentkoc Nov 3, 2024
827934f
Update transport.c
vincentkoc Nov 3, 2024
c848140
Update speaker.c
vincentkoc Nov 3, 2024
0693b22
Update button.c
vincentkoc Nov 3, 2024
c00d916
Update transport.c
vincentkoc Nov 3, 2024
5e061f4
Revert "Update transport.c"
vincentkoc Nov 4, 2024
1f34114
Update transport.h
vincentkoc Nov 4, 2024
c63f839
Update transport.c
vincentkoc Nov 4, 2024
fe3586c
Update transport.c
vincentkoc Nov 4, 2024
66a2fba
Update mic.h
vincentkoc Nov 4, 2024
7b59a55
Update mic.c
vincentkoc Nov 4, 2024
a9bb12a
Update codec.h
vincentkoc Nov 4, 2024
b32e9a5
Update codec.c
vincentkoc Nov 4, 2024
d06c44a
Update button.c
vincentkoc Nov 4, 2024
29bffa4
Update button.c
vincentkoc Nov 4, 2024
bf2bd2a
Update button.c
vincentkoc Nov 4, 2024
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
118 changes: 83 additions & 35 deletions Friend/firmware/firmware_v1.0/src/button.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "button.h"
#include "transport.h"
#include "speaker.h"
#include "codec.h"
#include "storage.h"
LOG_MODULE_REGISTER(button, CONFIG_LOG_DEFAULT_LEVEL);

bool is_off = false;
Expand All @@ -27,7 +29,13 @@ static struct bt_gatt_attr button_service_attr[] = {

static struct bt_gatt_service button_service = BT_GATT_SERVICE(button_service_attr);

static void button_ccc_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value)
static inline void notify_tap(void);
static inline void notify_press(void);
static inline void notify_unpress(void);
static inline void notify_double_tap(void);
static inline void notify_long_tap(void);

static void button_ccc_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value)
{
if (value == BT_GATT_CCC_NOTIFY)
{
Expand All @@ -43,15 +51,18 @@ static void button_ccc_config_changed_handler(const struct bt_gatt_attr *attr, u
}

}
struct gpio_dt_spec d4_pin = {.port = DEVICE_DT_GET(DT_NODELABEL(gpio0)), .pin=4, .dt_flags = GPIO_OUTPUT_ACTIVE}; //3.3
struct gpio_dt_spec d5_pin_input = {.port = DEVICE_DT_GET(DT_NODELABEL(gpio0)), .pin=5, .dt_flags = GPIO_INT_EDGE_RISING};
struct gpio_dt_spec d4_pin = {.port = DEVICE_DT_GET(DT_NODELABEL(gpio0)), .pin=4, .dt_flags = GPIO_OUTPUT};
struct gpio_dt_spec d5_pin_input = { .port = DEVICE_DT_GET(DT_NODELABEL(gpio0)), .pin = 5, .dt_flags = GPIO_INPUT | GPIO_INT_EDGE_BOTH };

static uint32_t current_button_time = 0;
static uint32_t previous_button_time = 0;

const int max_debounce_interval = 700;
static bool was_pressed = false;

// Add voice interaction state to button FSM
static bool voice_capture_active = false;

//
// button
//
Expand Down Expand Up @@ -83,15 +94,6 @@ void check_button_level(struct k_work *work_item);
K_WORK_DELAYABLE_DEFINE(button_work, check_button_level);


#define DEFAULT_STATE 0
#define SINGLE_TAP 1
#define DOUBLE_TAP 2
#define LONG_TAP 3
#define BUTTON_PRESS 4
#define BUTTON_RELEASE 5


// 4 is button down, 5 is button up
static FSM_STATE_T current_button_state = IDLE;
static uint32_t inc_count_1 = 0;
static uint32_t inc_count_0 = 0;
Expand All @@ -115,48 +117,91 @@ static inline void notify_press()
}
}

static inline void notify_unpress()
{
final_button_state[0] = BUTTON_RELEASE;
LOG_INF("unpressed");
static inline void notify_unpress() {
if (voice_interaction_active) {
LOG_INF("Button released, stopping voice interaction");
stop_voice_interaction();
k_msleep(10); // Give time for cleanup
}

final_button_state[0] = BUTTON_RELEASE;
struct bt_conn *conn = get_current_connection();
if (conn != NULL)
{
if (conn != NULL) {
bt_gatt_notify(conn, &button_service.attrs[1], &final_button_state, sizeof(final_button_state));
}
}

static inline void notify_tap()
{
final_button_state[0] = SINGLE_TAP;
LOG_INF("tap");
LOG_INF("single tap");
struct bt_conn *conn = get_current_connection();
if (conn != NULL)
{
bt_gatt_notify(conn, &button_service.attrs[1], &final_button_state, sizeof(final_button_state));
}
}

static inline void notify_double_tap()
{
final_button_state[0] = DOUBLE_TAP; //button press
LOG_INF("double tap");
struct bt_conn *conn = get_current_connection();
if (conn != NULL)
{
bt_gatt_notify(conn, &button_service.attrs[1], &final_button_state, sizeof(final_button_state));
static inline void notify_double_tap() {
// Only start voice interaction if device is not in sleep mode
if (!is_off) {
final_button_state[0] = DOUBLE_TAP;
LOG_INF("Double tap detected");

struct bt_conn *conn = get_current_connection();
if (conn != NULL) {
bt_gatt_notify(conn, &button_service.attrs[1], &final_button_state, sizeof(final_button_state));

if (!voice_interaction_active) {
// Start voice interaction
start_voice_interaction();
k_msleep(10); // Give time for state change
} else {
// Stop if already active
stop_voice_interaction();
k_msleep(10);
}
}
}

// Reset state
current_button_state = GRACE;
reset_count();
}

static inline void notify_long_tap()
{
final_button_state[0] = LONG_TAP; //button press
LOG_INF("long tap");
static inline void notify_long_tap() {
// If voice interaction is active, stop it before sleep
if (voice_interaction_active) {
LOG_INF("Stopping voice interaction before sleep");
stop_voice_interaction();
}

final_button_state[0] = LONG_TAP;
LOG_INF("long tap - toggling sleep mode");

struct bt_conn *conn = get_current_connection();
if (conn != NULL)
{
if (conn != NULL) {
bt_gatt_notify(conn, &button_service.attrs[1], &final_button_state, sizeof(final_button_state));
}

// Handle sleep mode
is_off = !is_off;
play_haptic_milli(100);

if (is_off) {
LOG_INF("Entering sleep mode");
bt_disable();
int err = bt_le_adv_stop();
if (err) {
LOG_ERR("Failed to stop Bluetooth %d", err);
}
} else {
int err = bt_enable(NULL);
if (err) {
LOG_ERR("Failed to enable Bluetooth %d", err);
}
bt_on();
}
}

#define LONG_PRESS_INTERVAL 25
Expand Down Expand Up @@ -307,6 +352,9 @@ void check_button_level(struct k_work *work_item)
if (inc_count_0 == 0 && (inc_count_1 > 0))
{
notify_unpress();

// End voice interaction if it was active
stop_voice_interaction();
}
inc_count_0++;
if (inc_count_0 > 1)
Expand Down Expand Up @@ -362,7 +410,7 @@ int button_init()
return -1;
}

int err2 = gpio_pin_configure_dt(&d5_pin_input,GPIO_INPUT);
int err2 = gpio_pin_configure_dt(&d5_pin_input, GPIO_INPUT | GPIO_INT_EDGE_BOTH);

if (err2 != 0)
{
Expand Down Expand Up @@ -405,4 +453,4 @@ void register_button_service()
FSM_STATE_T get_current_button_state()
{
return current_button_state;
}
}
13 changes: 10 additions & 3 deletions Friend/firmware/firmware_v1.0/src/button.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
#ifndef BUTTON_H
#define BUTTON_H

// Button states
#define DEFAULT_STATE 0
#define SINGLE_TAP 1 // Quick press and release
#define DOUBLE_TAP 2 // Two quick presses - Currently used for voice interaction
#define LONG_TAP 3 // Long press - Currently used for sleep/wake
#define BUTTON_PRESS 4 // Button down event
#define BUTTON_RELEASE 5 // Button up event

typedef enum {
IDLE,
IDLE,
ONE_PRESS,
TWO_PRESS,
GRACE
Expand All @@ -11,7 +19,6 @@ typedef enum {
int button_init();
void activate_button_work();
void register_button_service();

FSM_STATE_T get_current_button_state();

#endif
#endif
15 changes: 15 additions & 0 deletions Friend/firmware/firmware_v1.0/src/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ static uint8_t m_opus_encoder[OPUS_ENCODER_SIZE];
static OpusEncoder *const m_opus_state = (OpusEncoder *)m_opus_encoder;
#endif

// Add voice mode configuration
static bool voice_mode = false;

void set_voice_mode(bool enabled) {
voice_mode = enabled;
if (enabled) {
// Configure OPUS for voice settings
opus_encoder_ctl(m_opus_state, OPUS_SET_BITRATE(24000));
opus_encoder_ctl(m_opus_state, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
} else {
// Restore normal settings
opus_encoder_ctl(m_opus_state, OPUS_SET_BITRATE(CODEC_OPUS_BITRATE));
}
}

void codec_entry()
{

Expand Down
14 changes: 12 additions & 2 deletions Friend/firmware/firmware_v1.0/src/codec.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
#ifndef CODEC_H
#define CODEC_H
#include <zephyr/kernel.h>

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <zephyr/sys/ring_buffer.h>

// Expose codec ring buffer for voice interaction
extern struct ring_buf codec_ring_buf;

// Voice mode functions
void set_voice_mode(bool enabled);

// Callback
typedef void (*codec_callback)(uint8_t *data, size_t len);
typedef void (*codec_callback)(uint8_t *data, size_t size);
void set_codec_callback(codec_callback callback);

// Integration
Expand Down
36 changes: 35 additions & 1 deletion Friend/firmware/firmware_v1.0/src/mic.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,41 @@ int mic_start()
return 0;
}

void set_mic_callback(mix_handler callback)
void set_mic_callback(mix_handler callback)
{
_callback = callback;
}

// Add a public function to be called from transport.c
int mic_configure_for_voice(void) {
// Stop PDM first
nrfx_pdm_stop();
k_msleep(10); // Give hardware time to stop

// Uninit current config
nrfx_pdm_uninit();
k_msleep(10);

// Configure for voice
nrfx_pdm_config_t voice_config = NRFX_PDM_DEFAULT_CONFIG(PDM_CLK_PIN, PDM_DIN_PIN);
voice_config.gain_l = VOICE_GAIN;
voice_config.gain_r = VOICE_GAIN;
voice_config.clock_freq = NRF_PDM_FREQ_1032K;
voice_config.mode = NRF_PDM_MODE_MONO;
voice_config.edge = NRF_PDM_EDGE_LEFTFALLING;

// Initialize with new config
if (nrfx_pdm_init(&voice_config, pdm_irq_handler) != NRFX_SUCCESS) {
LOG_ERR("Failed to initialize PDM for voice");
return -1;
}

// Start PDM
if (nrfx_pdm_start() != NRFX_SUCCESS) {
LOG_ERR("Failed to start PDM for voice");
nrfx_pdm_uninit();
return -1;
}

return 0;
}
23 changes: 12 additions & 11 deletions Friend/firmware/firmware_v1.0/src/mic.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#ifndef MIC_H
#define MIC_H

typedef void (*mix_handler)(int16_t *);
#include <stdint.h>

/**
* @brief Initialize the Microphone
*
* Initializes the Microphone
*
* @return 0 if successful, negative errno code if error
*/
int mic_start();
void set_mic_callback(mix_handler _callback);
// Add voice configuration
#define VOICE_GAIN 0x50 // Adjusted gain for voice capture

#endif
// Existing declarations...
typedef void (*mix_handler)(int16_t *data);
void set_mic_callback(mix_handler callback);
int mic_start(void);

// Change return type to int
int mic_configure_for_voice(void);

#endif
Loading