From 800bfa4b8573a4508623b64e28bbf62379ec4d65 Mon Sep 17 00:00:00 2001 From: kevvz Date: Thu, 29 Aug 2024 16:42:44 -0700 Subject: [PATCH 01/12] sd card support --- Friend/firmware/firmware_v1.0/CMakeLists.txt | 2 + ...ble_sense_devkitv2-adafruit_module.overlay | 40 ++-- .../prj_xiao_ble_sense_devkitv2-adafruit.conf | 30 +-- Friend/firmware/firmware_v1.0/src/codec.c | 4 +- Friend/firmware/firmware_v1.0/src/main.c | 42 ++-- Friend/firmware/firmware_v1.0/src/sdcard.c | 210 ++++++++++++++++++ Friend/firmware/firmware_v1.0/src/sdcard.h | 37 +++ Friend/firmware/firmware_v1.0/src/storage.c | 56 +++++ Friend/firmware/firmware_v1.0/src/storage.h | 4 + Friend/firmware/firmware_v1.0/src/transport.c | 3 + Friend/firmware/testing/get_info_list.py | 30 +++ 11 files changed, 397 insertions(+), 61 deletions(-) create mode 100644 Friend/firmware/firmware_v1.0/src/sdcard.c create mode 100644 Friend/firmware/firmware_v1.0/src/sdcard.h create mode 100644 Friend/firmware/firmware_v1.0/src/storage.c create mode 100644 Friend/firmware/firmware_v1.0/src/storage.h create mode 100644 Friend/firmware/testing/get_info_list.py diff --git a/Friend/firmware/firmware_v1.0/CMakeLists.txt b/Friend/firmware/firmware_v1.0/CMakeLists.txt index c50790ea5..4236bd8c4 100644 --- a/Friend/firmware/firmware_v1.0/CMakeLists.txt +++ b/Friend/firmware/firmware_v1.0/CMakeLists.txt @@ -15,6 +15,8 @@ target_sources(app PRIVATE src/lib/battery/battery.c src/button.c src/speaker.c + src/sdcard.c + src/storage.c ) target_sources_ifdef(CONFIG_CODEC_OPUS app PRIVATE diff --git a/Friend/firmware/firmware_v1.0/overlay/xiao_ble_sense_devkitv2-adafruit_module.overlay b/Friend/firmware/firmware_v1.0/overlay/xiao_ble_sense_devkitv2-adafruit_module.overlay index 685f07103..1de1f878e 100644 --- a/Friend/firmware/firmware_v1.0/overlay/xiao_ble_sense_devkitv2-adafruit_module.overlay +++ b/Friend/firmware/firmware_v1.0/overlay/xiao_ble_sense_devkitv2-adafruit_module.overlay @@ -8,48 +8,40 @@ &pinctrl { i2s0_default: i2s0_default { group1 { - psels = , // SCK pin (bit clock) A3 - , // LRCK pin (word select clock) A2 - ; // SDOUT pin (data out) A1 + psels = , // SCK pin (bit clock) A3 + , // LRCK pin (word select clock) A2 + ; // SDOUT pin (data out) A1 }; }; }; &spi2 { status = "okay"; - pinctrl-0 = <&spi2_default>; - pinctrl-1 = <&spi2_sleep>; + pinctrl-0 = <&custom_spi>; + pinctrl-1 = <&custom_spi>; pinctrl-names = "default", "sleep"; - cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; // SD chip select pin (P0.13) + cs-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; // CS pin on P0.28 sdhc0: sdhc@0 { - compatible = "zephyr,mmc-spi-slot"; + compatible = "zephyr,sdhc-spi-slot"; reg = <0>; status = "okay"; label = "SDHC_0"; - spi-max-frequency = <24000000>; + mmc { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; + spi-max-frequency = <24000000>; // 24 MHz SPI speed for SD card }; }; &pinctrl { - spi2_default: spi2_default { - group1 { - psels = , // SCK connected to P1.15 - , // MOSI connected to P1.13 - ; // MISO connected to P1.14 - }; - }; - - spi2_sleep: spi2_sleep { + custom_spi: custom_spi { group1 { - psels = , - , - ; - low-power-enable; + psels = , // SCK on P1.13 + , // MOSI on P1.15 + ; // MISO on P1.14 }; }; }; -/ { - /delete-node/ lsm6dsl@0; -}; diff --git a/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf b/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf index 9b594ff79..9d4d63b88 100644 --- a/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf +++ b/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf @@ -99,16 +99,16 @@ CONFIG_CODEC_OPUS=y # SD Card Support (all devices required) CONFIG_OFFLINE_STORAGE=y -# CONFIG_DISK_ACCESS=y -# CONFIG_FILE_SYSTEM=y -# CONFIG_FAT_FILESYSTEM_ELM=y -# CONFIG_FS_FATFS_MOUNT_MKFS=y -# CONFIG_FS_FATFS_EXFAT=y +CONFIG_DISK_ACCESS=y +CONFIG_FILE_SYSTEM=y +CONFIG_FAT_FILESYSTEM_ELM=y +CONFIG_FS_FATFS_MOUNT_MKFS=y +CONFIG_FS_FATFS_EXFAT=y # CONFIG_PRINTK=y -# CONFIG_MAIN_STACK_SIZE=5096 +CONFIG_MAIN_STACK_SIZE=5096 # CONFIG_DISK_DRIVER_SDMMC=y # CONFIG_SPI=y -# CONFIG_HEAP_MEM_POOL_SIZE=3048 +CONFIG_HEAP_MEM_POOL_SIZE=3048 # # SD Card for Arduino Audio BFF (v2 device) # CONFIG_MMC_STACK=y @@ -127,12 +127,12 @@ CONFIG_OFFLINE_STORAGE=y # CONFIG_SPI_SDHC=y # File System -CONFIG_FILE_SYSTEM=y -CONFIG_FAT_FILESYSTEM_ELM=y -CONFIG_FS_FATFS_LFN=y -CONFIG_FS_FATFS_READ_ONLY=n -CONFIG_FS_FATFS_MOUNT_MKFS=y -CONFIG_FS_FATFS_EXFAT=y +# CONFIG_FILE_SYSTEM=y +# CONFIG_FAT_FILESYSTEM_ELM=y +# CONFIG_FS_FATFS_LFN=y +# CONFIG_FS_FATFS_READ_ONLY=n +# CONFIG_FS_FATFS_MOUNT_MKFS=y +# CONFIG_FS_FATFS_EXFAT=y # Increase stack and heap sizes CONFIG_MAIN_STACK_SIZE=8192 @@ -154,8 +154,8 @@ CONFIG_I2S_NRFX=y CONFIG_SPI_NRFX=y #THE ACCELEROMETER -CONFIG_ACCELEROMETER=y +CONFIG_ACCELEROMETER=n #ENABLE THE BUTTON! CONFIG_ENABLE_BUTTON=y #ENABLE THE SPEAKER -CONFIG_ENABLE_SPEAKER=y \ No newline at end of file +CONFIG_ENABLE_SPEAKER=n \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/codec.c b/Friend/firmware/firmware_v1.0/src/codec.c index b55a6b54c..c75708d9a 100644 --- a/Friend/firmware/firmware_v1.0/src/codec.c +++ b/Friend/firmware/firmware_v1.0/src/codec.c @@ -7,7 +7,7 @@ #ifdef CODEC_OPUS #include "lib/opus-1.2.1/opus.h" #endif - +// #include "sdcard.c" LOG_MODULE_REGISTER(codec, CONFIG_LOG_DEFAULT_LEVEL); // @@ -28,7 +28,7 @@ void set_codec_callback(codec_callback callback) uint8_t codec_ring_buffer_data[AUDIO_BUFFER_SAMPLES * 2]; // 2 bytes per sample struct ring_buf codec_ring_buf; -int codec_receive_pcm(int16_t *data, size_t len) +int codec_receive_pcm(int16_t *data, size_t len) //this gets called after mic data is finished { int written = ring_buf_put(&codec_ring_buf, (uint8_t *)data, len * 2); if (written != len * 2) diff --git a/Friend/firmware/firmware_v1.0/src/main.c b/Friend/firmware/firmware_v1.0/src/main.c index 5c16e87a7..52462ffed 100644 --- a/Friend/firmware/firmware_v1.0/src/main.c +++ b/Friend/firmware/firmware_v1.0/src/main.c @@ -7,7 +7,7 @@ #include "config.h" #include "audio.h" #include "codec.h" - +#include "sdcard.h" #define BOOT_BLINK_DURATION_MS 600 #define BOOT_PAUSE_DURATION_MS 200 LOG_MODULE_REGISTER(main, CONFIG_LOG_DEFAULT_LEVEL); @@ -124,25 +124,6 @@ int main(void) } // Run the boot LED sequence boot_led_sequence(); - - // // Indicate storage initialization - // set_led_red(true); - // LOG_INF("Initializing storage..."); - // err = storage_init(); - // if (err) { - // LOG_ERR("Failed to initialize storage: %d", err); - // // Blink red LED to indicate error - // for (int i = 0; i < 5; i++) { - // set_led_red(!gpio_pin_get_dt(&led_red)); - // k_msleep(200); - // } - // set_led_red(false); - // return err; - // } - // LOG_INF("Storage initialized successfully"); - // set_led_red(false); - // test_sd_card(); - // Indicate transport initialization set_led_green(true); err = transport_start(); @@ -158,7 +139,28 @@ int main(void) } set_led_green(false); + err = mount_sd_card(); + + + + // printk("result of mount:%d\n",err); + // const char dar[] = "audio/A1.txt"; + // err = create_file(dar); + // printk("result of create file:%d\n",err); + + // const char d[] = "A1 "; + // err=write_info(d); + // printk("result of info write is %d\n",err); + // char *f = get_info_file_data_(); + + // printk("%d\n",f[0]); + // printk("%d\n",f[1]); + // printk("%d\n",f[2]); + // printk("%d\n",f[3]); + + // k_free(f); // Indicate codec initialization + update_info_buffer(); set_led_blue(true); set_codec_callback(codec_handler); err = codec_start(); diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.c b/Friend/firmware/firmware_v1.0/src/sdcard.c new file mode 100644 index 000000000..683aaa77f --- /dev/null +++ b/Friend/firmware/firmware_v1.0/src/sdcard.c @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include "sdcard.h" +static FATFS fat_fs; + +static struct fs_mount_t mount_point = { + .type = FS_FATFS, + .fs_data = &fat_fs, +}; +static bool mounted = false; +bool sd_card_mounted = false; + +#define INFO_FILE "SD:/info.txt" + +static char current_full_path[256]; +static const char *disk_mount_pt = "/SD:/"; + +int mount_sd_card(void) +{ + uint64_t memory_size_mb; + uint32_t block_count; + uint32_t block_size; + static const char *disk_pdrv = "SD"; + int err = disk_access_init(disk_pdrv); + printk("disk_access_init: %d\n", err); + if (disk_access_ioctl(disk_pdrv, DISK_IOCTL_GET_SECTOR_COUNT, &block_count)) + { + printk("Unable to get sector count\n"); + return -1; + } + if (disk_access_ioctl(disk_pdrv, DISK_IOCTL_GET_SECTOR_SIZE, &block_size)) + { + printk("Unable to get sector count\n"); + return -1; + } + printk("Sector size is %u\n",block_size); + + memory_size_mb = (uint64_t)block_count * block_size; + + printk("Memory size: %u\n",memory_size_mb); + + mount_point.mnt_point = "/SD:"; + int res = fs_mount(&mount_point); + + if (res == FR_OK) { + mounted = true; + sd_card_mounted = true; + printk("SD card mounted successfully\n"); + } else { + printk("f_mount failed: %d\n", res); + return -1; + } + + res = fs_mkdir("/SD:/audio"); + if (res == FR_OK) { + printk("audio directory created successfully\n"); + } + else if (res == FR_EXIST) { + printk("audio directory already exists\n"); + } + else { + printk("audio directory creation failed: %d\n", res); + return -1; + } + + return 0; +} + +int create_file(const char *file_path){ + + snprintf(current_full_path, sizeof(current_full_path), "%s%s", disk_mount_pt, file_path); + + int ret = 0; + struct fs_file_t data_filp; + fs_file_t_init(&data_filp); + + ret = fs_open(&data_filp, current_full_path, FS_O_WRITE | FS_O_CREATE); + + if (ret) + { + printk("File creation failed %d\n", ret); + return -2; + } + fs_close(&data_filp); + + return 0; +} + +int write_info(const char *data) +{ + int ret = 0; + struct fs_file_t data_filp; + fs_file_t_init(&data_filp); + + // ret = fs_unlink("/SD:/info.txt"); + + ret = fs_open(&data_filp, "/SD:/info.txt", FS_O_WRITE | FS_O_APPEND); + if(ret) + { + printk("Error creating and writing file\n"); + return -1; + } + + printk("File wrote successfully\n"); + + ret = fs_write(&data_filp, data, strlen(data)); + + if(ret < 0) + { + return -1; + } + + fs_close(&data_filp); + + return 0; +} +static struct fs_file_t data_filp_; +int write_to_file(const char *data,uint16_t length) +{ + int ret = 0; + struct fs_file_t data_filp; + fs_file_t_init(&data_filp); + + + ret = fs_open(&data_filp, "/SD:/audio/A1.txt", FS_O_WRITE | FS_O_APPEND); + if(ret) + { + printk("Error opening file\n"); + return -1; + } + + + + ret = fs_write(&data_filp, data, strlen(data)); + printk("File wrote successfully\n"); + if(ret < 0) + { + return -1; + } + fs_close(&data_filp); + return 0; +} +#define MAX_INFO_FILE_LENGTH 256 +char* get_info_file_data_() { + struct fs_file_t file; + fs_file_t_init(&file); + printk("hello 3\n"); + k_msleep(10); + char *boot_count = (char*)k_malloc(MAX_INFO_FILE_LENGTH); + for (int i = 0; i < MAX_INFO_FILE_LENGTH; i++) { + boot_count[i] = 0; + } + printk("hello 5\n"); + k_msleep(10); + int rc = fs_open(&file, "/SD:/info.txt", FS_O_READ | FS_O_RDWR); + printk("hello 4\n"); + k_msleep(10); + printk("result of file open%d\n",rc); + rc = fs_read(&file, boot_count, 256); + printk("result of file read%d\n",rc); + fs_close(&file); + return boot_count; +} + +// read_params_t read_file(const char *file_path) +// { +// read_params_t readParams; +// readParams.ret = 0; +// char boot_count[1000]; +// struct fs_file_t file; +// int rc; + +// int ret = set_path(file_path); + +// if(ret) +// { +// readParams.ret = -1; +// return readParams; +// } + +// fs_file_t_init(&file); + +// rc = fs_open(&file, current_full_path, FS_O_READ | FS_O_RDWR); + +// if (rc < 0) +// { +// printk("FAIL: open %s: %d\n", current_full_path, rc); +// readParams.ret = rc; +// return readParams; +// } +// rc = fs_read(&file, &boot_count, sizeof(boot_count)); + +// if (rc < 0) +// { +// printk("FAIL: read %s: [rd:%d]\n", current_full_path, rc); +// } + +// boot_count[rc] = 0; + +// readParams.data = boot_count; + +// fs_close(&file); + +// return readParams; +// } + diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.h b/Friend/firmware/firmware_v1.0/src/sdcard.h new file mode 100644 index 000000000..81ac9b1d9 --- /dev/null +++ b/Friend/firmware/firmware_v1.0/src/sdcard.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +#define SD_MOUNT_POINT "SD:" +#define MAX_PATH 256 +static FATFS fat_fs; +typedef struct { + uint8_t *data; + size_t length_; + const char path[MAX_PATH]; + bool end_buffer; + bool concat; +} write_params_t; + +typedef struct { + char *data; + int ret; +} read_params_t; + +typedef struct { + char *data; + uint16_t length; +} info_file_t; + +typedef struct { + char *name; + size_t size; + int res; +} file_info_t; + + +char* get_info_file_data_(); diff --git a/Friend/firmware/firmware_v1.0/src/storage.c b/Friend/firmware/firmware_v1.0/src/storage.c new file mode 100644 index 000000000..b4602826f --- /dev/null +++ b/Friend/firmware/firmware_v1.0/src/storage.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "transport.h" +#include "config.h" +#include "utils.h" +#include "btutils.h" +#include "speaker.h" +#include "sdcard.h" +static void storage_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value); +static ssize_t storage_write_handler(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags); + +static struct bt_uuid_128 storage_service_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x00001540, 0x1212, 0xEFDE, 0x1523, 0x785FEABCD123)); +static struct bt_uuid_128 storage_write_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x00001541, 0x1212, 0xEFDE, 0x1523, 0x785FEABCD123)); +static struct bt_uuid_128 storage_read_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x00001542, 0x1212, 0xEFDE, 0x1523, 0x785FEABCD123)); +static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset); + +static struct bt_gatt_attr storage_service_attr[] = { + BT_GATT_PRIMARY_SERVICE(&storage_service_uuid), + BT_GATT_CHARACTERISTIC(&storage_read_uuid.uuid, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, storage_read_characteristic, NULL, NULL), + // BT_GATT_CHARACTERISTIC(&storage_write_uuid.uuid, BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_WRITE, NULL, storage_write_handler, NULL), + // BT_GATT_CCC(storage_config_changed_handler, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), +}; + +static struct bt_gatt_service storage_service = BT_GATT_SERVICE(storage_service_attr); + + +static info_file_t info_file; +static char hello[256]; + + +void update_info_buffer() { + char* b = get_info_file_data_(); + printk("hg\n"); + memcpy(hello,b,256); + k_free(b); +} + +static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { + printk("hello\n"); + k_msleep(10); + ssize_t result = bt_gatt_attr_read(conn, attr, buf, len, offset, hello, 256); + printk("hello\n"); + k_msleep(10); + return result; +} + +int register_storage_service() { + bt_gatt_service_register(&storage_service); + return 0; +} diff --git a/Friend/firmware/firmware_v1.0/src/storage.h b/Friend/firmware/firmware_v1.0/src/storage.h new file mode 100644 index 000000000..978890ed0 --- /dev/null +++ b/Friend/firmware/firmware_v1.0/src/storage.h @@ -0,0 +1,4 @@ +#pragma once + +int register_storage_service(); +void update_info_buffer(); \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/transport.c b/Friend/firmware/firmware_v1.0/src/transport.c index 6421eaf40..f1f038359 100644 --- a/Friend/firmware/firmware_v1.0/src/transport.c +++ b/Friend/firmware/firmware_v1.0/src/transport.c @@ -285,6 +285,8 @@ static ssize_t dfu_control_point_write_handler(struct bt_conn *conn, const struc return len; } + + // // Battery Service Handlers // @@ -617,6 +619,7 @@ if(!err) { bt_gatt_service_register(&audio_service); bt_gatt_service_register(&dfu_service); + register_storage_service(); err = bt_le_adv_start(BT_LE_ADV_CONN, bt_ad, ARRAY_SIZE(bt_ad), bt_sd, ARRAY_SIZE(bt_sd)); if (err) { diff --git a/Friend/firmware/testing/get_info_list.py b/Friend/firmware/testing/get_info_list.py new file mode 100644 index 000000000..ce6f4c75d --- /dev/null +++ b/Friend/firmware/testing/get_info_list.py @@ -0,0 +1,30 @@ +import argparse +import os +from dotenv import load_dotenv + +import asyncio +import bleak +import numpy as np +from bleak import BleakClient + +load_dotenv() + +device_id = "3CE1CE0A-A629-2E92-D708-E49E71045D07" #Please enter the id of your device (that is, the device id used to connect to your BT device here) +storage_uuid = "00001542-1212-EFDE-1523-785FEABCD123" #dont change this + + +async def main(): + async with BleakClient(device_id) as client: + + r = await client.read_gatt_char(storage_uuid) + await asyncio.sleep(2.0) + + while(True): + await asyncio.sleep(2.0) + print(r) + + +if __name__ == "__main__": + asyncio.run(main()) + + From f70357e0b0dab9fe30d7653a63b0fea4384cbc35 Mon Sep 17 00:00:00 2001 From: kevvz Date: Thu, 29 Aug 2024 18:17:22 -0700 Subject: [PATCH 02/12] updates --- Friend/firmware/firmware_v1.0/src/codec.c | 25 ++++++- Friend/firmware/firmware_v1.0/src/main.c | 7 +- Friend/firmware/firmware_v1.0/src/sdcard.c | 77 +++++++++++---------- Friend/firmware/firmware_v1.0/src/sdcard.h | 9 +++ Friend/firmware/firmware_v1.0/src/speaker.c | 2 +- Friend/firmware/firmware_v1.0/src/storage.c | 1 + 6 files changed, 79 insertions(+), 42 deletions(-) diff --git a/Friend/firmware/firmware_v1.0/src/codec.c b/Friend/firmware/firmware_v1.0/src/codec.c index c75708d9a..6ed417482 100644 --- a/Friend/firmware/firmware_v1.0/src/codec.c +++ b/Friend/firmware/firmware_v1.0/src/codec.c @@ -4,6 +4,7 @@ #include "audio.h" #include "config.h" #include "utils.h" +#include "sdcard.h" #ifdef CODEC_OPUS #include "lib/opus-1.2.1/opus.h" #endif @@ -27,15 +28,37 @@ void set_codec_callback(codec_callback callback) uint8_t codec_ring_buffer_data[AUDIO_BUFFER_SAMPLES * 2]; // 2 bytes per sample struct ring_buf codec_ring_buf; - +static bool wifi_connected = 0; +//here we will check whether there is a connection to offload the device. if not, then we will try to +//dump the pdm data to the sd card file. the pointer is always on. int codec_receive_pcm(int16_t *data, size_t len) //this gets called after mic data is finished { + if(wifi_connected) { int written = ring_buf_put(&codec_ring_buf, (uint8_t *)data, len * 2); if (written != len * 2) { printk("Failed to write %d bytes to codec ring buffer\n", len * 2); return -1; } + else { + printk("mic write succeeded\n"); + } + + } + else { //offline mode + printk("will it blend?\n"); + k_msleep(1); + + int f = write_audio_file_unsafe((uint8_t *)data, len * 2); + printk("womp womp\n"); + + wifi_connected =1; + + close_audio_file(); + + + } + return 0; } diff --git a/Friend/firmware/firmware_v1.0/src/main.c b/Friend/firmware/firmware_v1.0/src/main.c index 52462ffed..2279ae11a 100644 --- a/Friend/firmware/firmware_v1.0/src/main.c +++ b/Friend/firmware/firmware_v1.0/src/main.c @@ -140,10 +140,11 @@ int main(void) set_led_green(false); err = mount_sd_card(); + printk("result of mount:%d\n",err); - + err = initialize_audio_file(); + printk("result of audio file:%d\n",err); - // printk("result of mount:%d\n",err); // const char dar[] = "audio/A1.txt"; // err = create_file(dar); // printk("result of create file:%d\n",err); @@ -198,7 +199,7 @@ int main(void) set_led_green(false); // Indicate successful initialization - LOG_INF("Omi firmware initialized successfully"); + printk("Omi firmware initialized successfully\n"); set_led_blue(true); k_msleep(1000); set_led_blue(false); diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.c b/Friend/firmware/firmware_v1.0/src/sdcard.c index 683aaa77f..bd7ed5f9e 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.c +++ b/Friend/firmware/firmware_v1.0/src/sdcard.c @@ -165,46 +165,49 @@ char* get_info_file_data_() { fs_close(&file); return boot_count; } +//this method will write to an already open file. we will enforce that the file is opened + +static audio_info_t current_audio_file; +// fs_stat() check if dircetory exists +int initialize_audio_file() { + current_audio_file.name = "A1.txt"; + char temp[16] = "a00 00000000000\n"; + current_audio_file.size = 0; + struct fs_file_t *temp_file = malloc(sizeof(struct fs_file_t)); + fs_file_t_init(temp_file); + int ret = fs_open(temp_file, "/SD:/audio/A1.txt", FS_O_WRITE | FS_O_APPEND); + printk("result of audio open: %d\n",ret); + current_audio_file.file = temp_file; + -// read_params_t read_file(const char *file_path) -// { -// read_params_t readParams; -// readParams.ret = 0; -// char boot_count[1000]; -// struct fs_file_t file; -// int rc; + return 0; +} -// int ret = set_path(file_path); - -// if(ret) -// { -// readParams.ret = -1; -// return readParams; -// } - -// fs_file_t_init(&file); - -// rc = fs_open(&file, current_full_path, FS_O_READ | FS_O_RDWR); - -// if (rc < 0) -// { -// printk("FAIL: open %s: %d\n", current_full_path, rc); -// readParams.ret = rc; -// return readParams; -// } -// rc = fs_read(&file, &boot_count, sizeof(boot_count)); - -// if (rc < 0) -// { -// printk("FAIL: read %s: [rd:%d]\n", current_full_path, rc); -// } +int close_audio_file() { + fs_close(current_audio_file.file); + k_free(current_audio_file.file); + return 0; +} -// boot_count[rc] = 0; +int get_audio_file(const char *buf) { + return 1; +} -// readParams.data = boot_count; +int write_audio_file_unsafe(uint8_t *buf, int amount) { + int amount_left = 0; + int amount_ =0; + while(amount >= amount_left) { + amount_ = fs_write(current_audio_file.file, buf+amount_left, amount); + amount_left+=amount_; + printk("amount_left: %d\n",amount_left); + } + + printk("File wrote successfully\n"); -// fs_close(&file); + return 0; -// return readParams; -// } - +} + +int update_length_on_audio_file() { + +} diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.h b/Friend/firmware/firmware_v1.0/src/sdcard.h index 81ac9b1d9..6e96387d6 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.h +++ b/Friend/firmware/firmware_v1.0/src/sdcard.h @@ -33,5 +33,14 @@ typedef struct { int res; } file_info_t; +typedef struct { + char name; + uint32_t size; + struct fs_file_t *file; +} audio_info_t; + char* get_info_file_data_(); +int close_audio_file(); +int initialize_audio_file(); +int write_audio_file_unsafe(uint8_t *buf, int amount); \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/speaker.c b/Friend/firmware/firmware_v1.0/src/speaker.c index 3af270ffa..a01b25ec1 100644 --- a/Friend/firmware/firmware_v1.0/src/speaker.c +++ b/Friend/firmware/firmware_v1.0/src/speaker.c @@ -12,7 +12,7 @@ LOG_MODULE_REGISTER(speaker, CONFIG_LOG_DEFAULT_LEVEL); -#define MAX_BLOCK_SIZE 25000 //24000 * 2 +#define MAX_BLOCK_SIZE 12500 //24000 * 2 #define BLOCK_COUNT 2 #define SAMPLE_FREQUENCY 8000 #define NUMBER_OF_CHANNELS 2 diff --git a/Friend/firmware/firmware_v1.0/src/storage.c b/Friend/firmware/firmware_v1.0/src/storage.c index b4602826f..7f09f6559 100644 --- a/Friend/firmware/firmware_v1.0/src/storage.c +++ b/Friend/firmware/firmware_v1.0/src/storage.c @@ -54,3 +54,4 @@ int register_storage_service() { bt_gatt_service_register(&storage_service); return 0; } + From 664aca1a77453e4cf3cc942d72d63984993e0c2b Mon Sep 17 00:00:00 2001 From: kevvz Date: Fri, 30 Aug 2024 18:28:36 -0700 Subject: [PATCH 03/12] all the files --- .../prj_xiao_ble_sense_devkitv2-adafruit.conf | 4 +- Friend/firmware/firmware_v1.0/src/button.c | 13 +- Friend/firmware/firmware_v1.0/src/button.h | 11 +- Friend/firmware/firmware_v1.0/src/codec.c | 26 +-- Friend/firmware/firmware_v1.0/src/main.c | 31 +-- Friend/firmware/firmware_v1.0/src/sdcard.c | 212 ++++++++++++++---- Friend/firmware/firmware_v1.0/src/sdcard.h | 6 +- Friend/firmware/firmware_v1.0/src/speaker.c | 2 +- Friend/firmware/firmware_v1.0/src/storage.c | 62 ++++- Friend/firmware/firmware_v1.0/src/transport.c | 83 +++++-- Friend/firmware/testing/a01.txt | Bin 0 -> 5529 bytes Friend/firmware/testing/get_audio_file.py | 39 ++++ 12 files changed, 366 insertions(+), 123 deletions(-) create mode 100755 Friend/firmware/testing/a01.txt create mode 100644 Friend/firmware/testing/get_audio_file.py diff --git a/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf b/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf index 9d4d63b88..b517a060b 100644 --- a/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf +++ b/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf @@ -144,7 +144,7 @@ CONFIG_HEAP_MEM_POOL_SIZE=4096 # CONFIG_NRFX_TWIM1=n # Disable LSM6DSL sensor (accelerometer and gyroscope) -CONFIG_LSM6DSL=y +CONFIG_LSM6DSL=n CONFIG_LSM6DSL_ENABLE_TEMP=n CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD=y CONFIG_SENSOR=y @@ -156,6 +156,6 @@ CONFIG_SPI_NRFX=y #THE ACCELEROMETER CONFIG_ACCELEROMETER=n #ENABLE THE BUTTON! -CONFIG_ENABLE_BUTTON=y +CONFIG_ENABLE_BUTTON=n #ENABLE THE SPEAKER CONFIG_ENABLE_SPEAKER=n \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/button.c b/Friend/firmware/firmware_v1.0/src/button.c index 84be096b6..e60a5226e 100644 --- a/Friend/firmware/firmware_v1.0/src/button.c +++ b/Friend/firmware/firmware_v1.0/src/button.c @@ -7,7 +7,7 @@ #include #include #include "transport.h" - +#include "button.h" LOG_MODULE_REGISTER(button, CONFIG_LOG_DEFAULT_LEVEL); static void button_ccc_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value); @@ -75,13 +75,6 @@ void check_button_level(struct k_work *work_item); K_WORK_DELAYABLE_DEFINE(button_work, check_button_level); -typedef enum { - IDLE, - ONE_PRESS, - TWO_PRESS, - GRACE -} FSM_STATE_T; - #define DEFAULT_STATE 0 #define SINGLE_TAP 1 @@ -308,4 +301,8 @@ void activate_button_work() { void register_button_service() { bt_gatt_service_register(&button_service); +} + +FSM_STATE_T get_current_button_state() { + return current_button_state; } \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/button.h b/Friend/firmware/firmware_v1.0/src/button.h index e4c86bad2..6902bb14a 100644 --- a/Friend/firmware/firmware_v1.0/src/button.h +++ b/Friend/firmware/firmware_v1.0/src/button.h @@ -1,5 +1,14 @@ #pragma once +typedef enum { + IDLE, + ONE_PRESS, + TWO_PRESS, + GRACE +} FSM_STATE_T; + int button_init(); void activate_button_work(); -void register_button_service(); \ No newline at end of file +void register_button_service(); + +FSM_STATE_T get_current_button_state(); \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/codec.c b/Friend/firmware/firmware_v1.0/src/codec.c index 6ed417482..4b41fc33b 100644 --- a/Friend/firmware/firmware_v1.0/src/codec.c +++ b/Friend/firmware/firmware_v1.0/src/codec.c @@ -28,36 +28,18 @@ void set_codec_callback(codec_callback callback) uint8_t codec_ring_buffer_data[AUDIO_BUFFER_SAMPLES * 2]; // 2 bytes per sample struct ring_buf codec_ring_buf; -static bool wifi_connected = 0; //here we will check whether there is a connection to offload the device. if not, then we will try to //dump the pdm data to the sd card file. the pointer is always on. int codec_receive_pcm(int16_t *data, size_t len) //this gets called after mic data is finished -{ - if(wifi_connected) { +{ + int written = ring_buf_put(&codec_ring_buf, (uint8_t *)data, len * 2); if (written != len * 2) { printk("Failed to write %d bytes to codec ring buffer\n", len * 2); return -1; } - else { - printk("mic write succeeded\n"); - } - - } - else { //offline mode - printk("will it blend?\n"); - k_msleep(1); - - int f = write_audio_file_unsafe((uint8_t *)data, len * 2); - printk("womp womp\n"); - - wifi_connected =1; - - close_audio_file(); - - - } + return 0; } @@ -86,6 +68,7 @@ static OpusEncoder *const m_opus_state = (OpusEncoder *)m_opus_encoder; void codec_entry() { + uint16_t output_size; while (1) { @@ -96,7 +79,6 @@ void codec_entry() k_sleep(K_MSEC(10)); continue; } - // Read package ring_buf_get(&codec_ring_buf, (uint8_t *)codec_input_samples, CODEC_PACKAGE_SAMPLES * 2); diff --git a/Friend/firmware/firmware_v1.0/src/main.c b/Friend/firmware/firmware_v1.0/src/main.c index 2279ae11a..9ca04a1db 100644 --- a/Friend/firmware/firmware_v1.0/src/main.c +++ b/Friend/firmware/firmware_v1.0/src/main.c @@ -142,26 +142,17 @@ int main(void) err = mount_sd_card(); printk("result of mount:%d\n",err); - err = initialize_audio_file(); - printk("result of audio file:%d\n",err); - - // const char dar[] = "audio/A1.txt"; - // err = create_file(dar); - // printk("result of create file:%d\n",err); - - // const char d[] = "A1 "; - // err=write_info(d); - // printk("result of info write is %d\n",err); - // char *f = get_info_file_data_(); - - // printk("%d\n",f[0]); - // printk("%d\n",f[1]); - // printk("%d\n",f[2]); - // printk("%d\n",f[3]); - - // k_free(f); - // Indicate codec initialization - update_info_buffer(); + + write_entry_info(1,10); + write_entry_info(1,20); + write_entry_info(1,30); + + int size = get_file_size(); + + printk("file size is %d\n", size); + + + k_msleep(100); set_led_blue(true); set_codec_callback(codec_handler); err = codec_start(); diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.c b/Friend/firmware/firmware_v1.0/src/sdcard.c index bd7ed5f9e..6e230ea87 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.c +++ b/Friend/firmware/firmware_v1.0/src/sdcard.c @@ -15,10 +15,66 @@ static bool mounted = false; bool sd_card_mounted = false; #define INFO_FILE "SD:/info.txt" - -static char current_full_path[256]; +#define AUDIO_DIRECTORY "/SD:/audio/" +#define MAX_PATH_LENGTH 32 +#define MAX_INFO_ENTRY_LENGTH 2 +static char current_full_path[MAX_PATH_LENGTH]; static const char *disk_mount_pt = "/SD:/"; +//hehe... +char* generate_new_audio_header(uint8_t num) { + if (num > 9 ) return NULL; + char *ptr_ = k_malloc(14); + ptr_[0] = 'a'; + ptr_[1] = 'u'; + ptr_[2] = 'd'; + ptr_[3] = 'i'; + ptr_[4] = 'o'; + ptr_[5] = '/'; + ptr_[6] = 'a'; + ptr_[7] = '0'; + ptr_[8] = 48 + num; + ptr_[9] = '.'; + ptr_[10] = 't'; + ptr_[11] = 'x'; + ptr_[12] = 't'; + ptr_[13] = '\0'; + + return ptr_; +} + +uint8_t get_info_file_length() { + struct fs_file_t file; + fs_file_t_init(&file); + uint8_t length[2]; + int rc = fs_open(&file, "/SD:/info.txt", FS_O_READ | FS_O_RDWR); + rc = fs_seek(&file,0,FS_SEEK_SET); + rc = fs_read(&file, length, 1); + fs_close(&file); + printk("length is %d\n",length[0]); + return length[0]; +} + +uint8_t update_info_file_length(uint8_t num) { + struct fs_file_t file; + fs_file_t_init(&file); + + uint8_t length[16] = {num+'0'}; + for (int i =1; i < 15; i++) { + length[i] = ' '; + } + length[15] = '\n'; + int rc = fs_open(&file, "/SD:/info.txt", FS_O_WRITE); + rc = fs_seek(&file,0,FS_SEEK_SET); + + printk("result of file open%d\n",rc); + rc = fs_write(&file, length, 16); + printk("result of file read%d\n",rc); + fs_close(&file); + printk("length is %d\n",length[0]); + return length[0]; +} + int mount_sd_card(void) { uint64_t memory_size_mb; @@ -54,6 +110,7 @@ int mount_sd_card(void) printk("f_mount failed: %d\n", res); return -1; } + // res = fs_unlink("/SD:/info.txt"); res = fs_mkdir("/SD:/audio"); if (res == FR_OK) { @@ -64,14 +121,51 @@ int mount_sd_card(void) } else { printk("audio directory creation failed: %d\n", res); - return -1; } + struct fs_dirent entry; //check if the info file exists. if not, generate new info file + const char *info_path = "/SD:/info.txt"; + res = fs_stat(info_path,&entry); + if (res) { + res = create_file("info.txt"); + printk("result of info.txt creation: %d\n ",res); + update_info_file_length(0); + } + + printk("info file size is %d\n",entry.size); + printk("result of check: %d\n",res); + + // snprintf(current_full_path, sizeof(current_full_path), "%s%s%s", disk_mount_pt, disk_mount_pt,disk_mount_pt); + // printk("%s\n",current_full_path); + + //attempt to create new audio file per reset + uint8_t current_file_num = get_info_file_length(); + + uint8_t next_file_num = current_file_num + 1; + printk("current number of audio files is%d\n ", current_file_num); + char *ptr_ = generate_new_audio_header(next_file_num); // will return (audio/axx.txt) + update_info_file_length(next_file_num); + + if(ptr_ != NULL) { + res = create_file(ptr_); + k_free(ptr_); + } + else { + printk("bad header\n"); + } + + //generate new entry in info file + + + + // res = create_file("audio/a01.txt"); + // printk("result of audio text creation: %d\n ",res); + return 0; } int create_file(const char *file_path){ - + //MAGIC STRING CAT!!!!!!! snprintf(current_full_path, sizeof(current_full_path), "%s%s", disk_mount_pt, file_path); int ret = 0; @@ -90,24 +184,47 @@ int create_file(const char *file_path){ return 0; } -int write_info(const char *data) +#define INFO_ENTRY_SIZE 16 +//need length,name +//a01 00000000000\n +int write_entry_info(uint8_t entry_num,uint32_t size) { + if (entry_num == 0) return -1; int ret = 0; + uint8_t *result = malloc(16 * sizeof(uint8_t)); + result[0] = 'a'; + result[1] = '0'; + result[2] = '0'+entry_num; + result[3] = ' '; + result[4] = '0'; + result[5] = '0'; + result[6] = '0'; + result[7] = '0'; + result[8] = '0'; + result[9] = '0'; + result[10] = (size % 100000) / 10000 +'0'; + result[11] = (size % 10000) / 1000 +'0'; + result[12] = (size % 1000) / 100 + '0'; + result[13] = (size % 100) / 10 + '0'; + result[14] = (size % 10) + '0'; + result[15] = '\n'; + struct fs_file_t data_filp; fs_file_t_init(&data_filp); - // ret = fs_unlink("/SD:/info.txt"); + printk("\n"); + ret = fs_open(&data_filp, "/SD:/info.txt", FS_O_WRITE); - ret = fs_open(&data_filp, "/SD:/info.txt", FS_O_WRITE | FS_O_APPEND); if(ret) { printk("Error creating and writing file\n"); return -1; } + fs_seek(&data_filp,0+ 16 * entry_num,FS_SEEK_SET); + ret = fs_write(&data_filp, result, INFO_ENTRY_SIZE); - printk("File wrote successfully\n"); - - ret = fs_write(&data_filp, data, strlen(data)); + printk("total written %d\n",ret); + free(result); if(ret < 0) { @@ -115,28 +232,26 @@ int write_info(const char *data) } fs_close(&data_filp); - return 0; } -static struct fs_file_t data_filp_; -int write_to_file(const char *data,uint16_t length) + + +int write_to_file(uint8_t *data,uint32_t length) { int ret = 0; struct fs_file_t data_filp; fs_file_t_init(&data_filp); + uint8_t *temp_ptr = data; - - ret = fs_open(&data_filp, "/SD:/audio/A1.txt", FS_O_WRITE | FS_O_APPEND); + ret = fs_open(&data_filp, "/SD:/audio/a01.txt", FS_O_WRITE | FS_O_APPEND); if(ret) { printk("Error opening file\n"); return -1; } - - - ret = fs_write(&data_filp, data, strlen(data)); - printk("File wrote successfully\n"); + ret = fs_write(&data_filp, temp_ptr, length); + printk("File wrote successfully, wrote %d\n",ret); if(ret < 0) { return -1; @@ -144,21 +259,22 @@ int write_to_file(const char *data,uint16_t length) fs_close(&data_filp); return 0; } + +int update_length_on_audio_file() { + + +} + + #define MAX_INFO_FILE_LENGTH 256 char* get_info_file_data_() { struct fs_file_t file; fs_file_t_init(&file); - printk("hello 3\n"); - k_msleep(10); char *boot_count = (char*)k_malloc(MAX_INFO_FILE_LENGTH); for (int i = 0; i < MAX_INFO_FILE_LENGTH; i++) { boot_count[i] = 0; } - printk("hello 5\n"); - k_msleep(10); int rc = fs_open(&file, "/SD:/info.txt", FS_O_READ | FS_O_RDWR); - printk("hello 4\n"); - k_msleep(10); printk("result of file open%d\n",rc); rc = fs_read(&file, boot_count, 256); printk("result of file read%d\n",rc); @@ -178,36 +294,38 @@ int initialize_audio_file() { int ret = fs_open(temp_file, "/SD:/audio/A1.txt", FS_O_WRITE | FS_O_APPEND); printk("result of audio open: %d\n",ret); current_audio_file.file = temp_file; - - return 0; } int close_audio_file() { + printk("about to close\n"); + k_msleep(10); fs_close(current_audio_file.file); k_free(current_audio_file.file); return 0; } +static int pos_ = 0; +int read_audio_data(uint8_t *buf, int amount,int offset) { + struct fs_file_t file; + uint8_t *temp_ptr = buf; + printk("about to f\n"); + k_msleep(10); + fs_file_t_init(&file); + int rc = fs_open(&file, "/SD:/audio/a01.txt", FS_O_READ | FS_O_RDWR); -int get_audio_file(const char *buf) { - return 1; -} - -int write_audio_file_unsafe(uint8_t *buf, int amount) { - int amount_left = 0; - int amount_ =0; - while(amount >= amount_left) { - amount_ = fs_write(current_audio_file.file, buf+amount_left, amount); - amount_left+=amount_; - printk("amount_left: %d\n",amount_left); - } - - printk("File wrote successfully\n"); - - return 0; - + printk("result of file open%d\n",rc); + k_msleep(10); + rc = fs_seek(&file,offset,FS_SEEK_SET); + printk("result of file seek: %d\n",rc); + rc = fs_read(&file, temp_ptr, amount); + printk("result of file read%d\n",rc); + fs_close(&file); + return rc; } -int update_length_on_audio_file() { - -} +int get_file_size(){ + struct fs_dirent entry; + const char *audio_path = "/SD:/audio/a01.txt"; + fs_stat(audio_path,&entry); + return entry.size; + } diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.h b/Friend/firmware/firmware_v1.0/src/sdcard.h index 6e96387d6..97b3c8b94 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.h +++ b/Friend/firmware/firmware_v1.0/src/sdcard.h @@ -43,4 +43,8 @@ typedef struct { char* get_info_file_data_(); int close_audio_file(); int initialize_audio_file(); -int write_audio_file_unsafe(uint8_t *buf, int amount); \ No newline at end of file +int write_audio_file_unsafe(uint8_t *buf, int amount); +int create_file(); +int read_audio_data(uint8_t *buf, int amount,int offset); +int write_entry_info(uint8_t entry_num,uint32_t size); +int get_file_size(); \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/speaker.c b/Friend/firmware/firmware_v1.0/src/speaker.c index a01b25ec1..fe6c7117e 100644 --- a/Friend/firmware/firmware_v1.0/src/speaker.c +++ b/Friend/firmware/firmware_v1.0/src/speaker.c @@ -12,7 +12,7 @@ LOG_MODULE_REGISTER(speaker, CONFIG_LOG_DEFAULT_LEVEL); -#define MAX_BLOCK_SIZE 12500 //24000 * 2 +#define MAX_BLOCK_SIZE 10000 //24000 * 2 #define BLOCK_COUNT 2 #define SAMPLE_FREQUENCY 8000 #define NUMBER_OF_CHANNELS 2 diff --git a/Friend/firmware/firmware_v1.0/src/storage.c b/Friend/firmware/firmware_v1.0/src/storage.c index 7f09f6559..404fded14 100644 --- a/Friend/firmware/firmware_v1.0/src/storage.c +++ b/Friend/firmware/firmware_v1.0/src/storage.c @@ -20,11 +20,16 @@ static struct bt_uuid_128 storage_write_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCO static struct bt_uuid_128 storage_read_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x00001542, 0x1212, 0xEFDE, 0x1523, 0x785FEABCD123)); static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset); +void broadcast_storage_packet(struct k_work *work_item); +K_WORK_DELAYABLE_DEFINE(storage_work, broadcast_storage_packet); + static struct bt_gatt_attr storage_service_attr[] = { BT_GATT_PRIMARY_SERVICE(&storage_service_uuid), + BT_GATT_CHARACTERISTIC(&storage_write_uuid.uuid, BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_WRITE, NULL, storage_write_handler, NULL), + BT_GATT_CCC(storage_config_changed_handler, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), BT_GATT_CHARACTERISTIC(&storage_read_uuid.uuid, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, storage_read_characteristic, NULL, NULL), - // BT_GATT_CHARACTERISTIC(&storage_write_uuid.uuid, BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_WRITE, NULL, storage_write_handler, NULL), - // BT_GATT_CCC(storage_config_changed_handler, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), + BT_GATT_CCC(storage_config_changed_handler, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), + }; static struct bt_gatt_service storage_service = BT_GATT_SERVICE(storage_service_attr); @@ -33,7 +38,9 @@ static struct bt_gatt_service storage_service = BT_GATT_SERVICE(storage_service_ static info_file_t info_file; static char hello[256]; - +static void storage_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value) { + printk("hoi \n"); +} void update_info_buffer() { char* b = get_info_file_data_(); printk("hg\n"); @@ -45,8 +52,6 @@ static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt printk("hello\n"); k_msleep(10); ssize_t result = bt_gatt_attr_read(conn, attr, buf, len, offset, hello, 256); - printk("hello\n"); - k_msleep(10); return result; } @@ -55,3 +60,50 @@ int register_storage_service() { return 0; } +static uint8_t storage_write_buffer[256]; +static uint32_t remaining_length = 0; +static bool transport_started = false; +static ssize_t storage_write_handler(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { + //get the requested file and download it. need to use work orders + printk("%s\n",((char*)buf)[0]); + + printk("about to schedule the storage\n"); + k_msleep(10); + get_info_file_data_(); + transport_started = true; + + k_work_schedule(&storage_work, K_MSEC(1000)); + + return len; +} + +static uint32_t offset = 0; +#define MAX_PACKET_LENGTH 256 +void broadcast_storage_packet(struct k_work *work_item) { //staggerable + if (transport_started == true) { + remaining_length = get_file_size(); + transport_started=false; + } + printk("about to broadcast the storage packet\n"); + + uint32_t packet_size = MIN(remaining_length,MAX_PACKET_LENGTH); + int r = read_audio_data(storage_write_buffer,MAX_PACKET_LENGTH,offset); + offset = offset + packet_size; + remaining_length = MAX(remaining_length - packet_size,0); + printk("current offset: %d\n",offset); + printk("current reamining length: %d\n",remaining_length); + struct bt_conn *conn = get_current_connection(); + if (conn == NULL) { + printk("invalid connection\n"); + } + printk("almost there/...\n"); + int err = bt_gatt_notify(conn, &storage_service.attrs[1], &storage_write_buffer,packet_size); + printk("finished broadcast\n"); + if (remaining_length > 0) { + k_work_reschedule(&storage_work,K_MSEC(1000)); + } + else { + printk("finished broadcasting audio file\n"); + } +} + diff --git a/Friend/firmware/firmware_v1.0/src/transport.c b/Friend/firmware/firmware_v1.0/src/transport.c index f1f038359..f3c8a6631 100644 --- a/Friend/firmware/firmware_v1.0/src/transport.c +++ b/Friend/firmware/firmware_v1.0/src/transport.c @@ -14,7 +14,7 @@ #include "btutils.h" #include "lib/battery/battery.h" #include "speaker.h" - +#include "button.h" #include LOG_MODULE_REGISTER(transport, CONFIG_LOG_DEFAULT_LEVEL); @@ -449,12 +449,13 @@ static bool read_from_tx_queue() tx_buffer_size = ring_buf_get(&ring_buf, tx_buffer, (CODEC_OUTPUT_MAX_BYTES + RING_BUFFER_HEADER_SIZE)); // It always fits completely or not at all if (tx_buffer_size != (CODEC_OUTPUT_MAX_BYTES + RING_BUFFER_HEADER_SIZE)) { - LOG_WRN("Failed to read from ring buffer %d", tx_buffer_size); + printk("Failed to read from ring buffer %d\n", tx_buffer_size); return false; } // Adjust size tx_buffer_size = tx_buffer[0] + (tx_buffer[1] << 8); + // printk("tx_buffer_size %d\n",tx_buffer_size); return true; } @@ -468,12 +469,13 @@ K_THREAD_STACK_DEFINE(pusher_stack, 1024); static struct k_thread pusher_thread; static uint16_t packet_next_index = 0; static uint8_t pusher_temp_data[CODEC_OUTPUT_MAX_BYTES + NET_BUFFER_HEADER_SIZE]; - +static char storage_temp_data[CODEC_OUTPUT_MAX_BYTES]; static bool push_to_gatt(struct bt_conn *conn) { // Read data from ring buffer if (!read_from_tx_queue()) { + printk("invalid\n"); return false; } @@ -490,6 +492,11 @@ static bool push_to_gatt(struct bt_conn *conn) pusher_temp_data[1] = (id >> 8) & 0xFF; pusher_temp_data[2] = index; memcpy(pusher_temp_data + NET_BUFFER_HEADER_SIZE, buffer + offset, packet_size); + uint8_t *tr = pusher_temp_data + 2; + // for (int i = 0; i < packet_size; i ++) { + // printk("%d ",tr[i]); + // } + // printk("\n"); offset += packet_size; index++; @@ -520,17 +527,36 @@ static bool push_to_gatt(struct bt_conn *conn) return true; } + + +bool write_to_storage(void) { + if (!read_from_tx_queue()) + { + return false; + } + printk("about to write to storage\n"); + uint8_t *buffer = tx_buffer+2; + uint32_t packet_size = tx_buffer_size; + memcpy(storage_temp_data, buffer, packet_size); + uint8_t *b = (uint8_t*)storage_temp_data; + write_to_file(b,(uint32_t*)packet_size); + return true; +} + +static bool use_storage = true; void pusher(void) { while (1) { + // // Load current connection // struct bt_conn *conn = current_connection; bool use_gatt = true; + // FSM_STATE_T state_ = get_current_button_state(); if (conn) { conn = bt_conn_ref(conn); @@ -549,22 +575,45 @@ void pusher(void) valid = bt_gatt_is_subscribed(conn, &audio_service.attrs[1], BT_GATT_CCC_NOTIFY); // Check if subscribed } + // if (!valid) { + bool result = write_to_storage(); + // if (!result) + // { + // k_sleep(K_MSEC(50)); + // } + // ring_buf_reset(&ring_buf); + // k_sleep(K_MSEC(10)); + // } + + + // if(state_ == IDLE ) { //button is pressed + // write_to_storage(); + // } + // If no valid mode exists - discard whole buffer - if (!valid) - { - ring_buf_reset(&ring_buf); - k_sleep(K_MSEC(10)); - } + // if (!valid) + // { + // ring_buf_reset(&ring_buf); + // k_sleep(K_MSEC(10)); + // } + + + // Handle GATT - if (use_gatt && valid) - { - bool sent = push_to_gatt(conn); - if (!sent) - { - k_sleep(K_MSEC(50)); - } - } + // write_to_storage(); + // if (use_gatt && valid) + // { + // // bool sent =write_to_storage(); + // bool sent = push_to_gatt(conn); + // if (!sent) + // { + // k_sleep(K_MSEC(50)); + // } + // } + + + if (conn) { @@ -573,6 +622,8 @@ void pusher(void) } } + + // // Public functions // diff --git a/Friend/firmware/testing/a01.txt b/Friend/firmware/testing/a01.txt new file mode 100755 index 0000000000000000000000000000000000000000..ce9c4cacdaf6942c5c49b30971223cc11fa52cce GIT binary patch literal 5529 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 b$MN;^l$LcH{|bu)Jec@Iz7$QgAWrwy64j@l literal 0 HcmV?d00001 diff --git a/Friend/firmware/testing/get_audio_file.py b/Friend/firmware/testing/get_audio_file.py new file mode 100644 index 000000000..0747926f1 --- /dev/null +++ b/Friend/firmware/testing/get_audio_file.py @@ -0,0 +1,39 @@ +import argparse +import os +from dotenv import load_dotenv + +import asyncio +import bleak +import numpy as np +from bleak import BleakClient + +load_dotenv() + +device_id = "3CE1CE0A-A629-2E92-D708-E49E71045D07" #Please enter the id of your device (that is, the device id used to connect to your BT device here) +storage_uuid = "00001541-1212-EFDE-1523-785FEABCD123" #dont change this + + +async def main(): + + global device_uuid + global storage_uuid + async with BleakClient(device_id) as client: + result = bytearray() + print('a') + async def on_notify(sender: bleak.BleakGATTCharacteristic, data: bytearray): + print('done') + print(np.frombuffer(data,dtype=np.uint8)) + await client.start_notify(storage_uuid, on_notify) + print('b') + await asyncio.sleep(1) + await client.write_gatt_char(storage_uuid, b'd', response=True) + print('c') + await asyncio.sleep(1) + while True: + await asyncio.sleep(1) + + +if __name__ == "__main__": + asyncio.run(main()) + + From 2c6c6db0734dea762f5d263f57cb8a03ea438210 Mon Sep 17 00:00:00 2001 From: kevvz Date: Sun, 1 Sep 2024 22:21:19 -0700 Subject: [PATCH 04/12] improved read and write stability --- Friend/firmware/firmware_v1.0/src/codec.c | 6 +- Friend/firmware/firmware_v1.0/src/main.c | 13 +- Friend/firmware/firmware_v1.0/src/sdcard.c | 347 ++++++++---------- Friend/firmware/firmware_v1.0/src/sdcard.h | 45 +-- Friend/firmware/firmware_v1.0/src/speaker.c | 1 - Friend/firmware/firmware_v1.0/src/storage.c | 126 ++++--- Friend/firmware/firmware_v1.0/src/storage.h | 6 +- Friend/firmware/firmware_v1.0/src/transport.c | 98 ++--- Friend/firmware/testing/get_audio_file.py | 60 ++- 9 files changed, 373 insertions(+), 329 deletions(-) diff --git a/Friend/firmware/firmware_v1.0/src/codec.c b/Friend/firmware/firmware_v1.0/src/codec.c index 4b41fc33b..24f8c43ef 100644 --- a/Friend/firmware/firmware_v1.0/src/codec.c +++ b/Friend/firmware/firmware_v1.0/src/codec.c @@ -28,15 +28,14 @@ void set_codec_callback(codec_callback callback) uint8_t codec_ring_buffer_data[AUDIO_BUFFER_SAMPLES * 2]; // 2 bytes per sample struct ring_buf codec_ring_buf; -//here we will check whether there is a connection to offload the device. if not, then we will try to -//dump the pdm data to the sd card file. the pointer is always on. int codec_receive_pcm(int16_t *data, size_t len) //this gets called after mic data is finished { int written = ring_buf_put(&codec_ring_buf, (uint8_t *)data, len * 2); if (written != len * 2) { - printk("Failed to write %d bytes to codec ring buffer\n", len * 2); + + // printk("Failed to write %d bytes to codec ring buffer\n", len * 2); return -1; } @@ -76,6 +75,7 @@ void codec_entry() // Check if we have enough data if (ring_buf_size_get(&codec_ring_buf) < CODEC_PACKAGE_SAMPLES * 2) { + // printk("waiting on data....\n"); k_sleep(K_MSEC(10)); continue; } diff --git a/Friend/firmware/firmware_v1.0/src/main.c b/Friend/firmware/firmware_v1.0/src/main.c index 9ca04a1db..b379ad4c8 100644 --- a/Friend/firmware/firmware_v1.0/src/main.c +++ b/Friend/firmware/firmware_v1.0/src/main.c @@ -8,6 +8,8 @@ #include "audio.h" #include "codec.h" #include "sdcard.h" +#include "tests.c" +#include "storage.h" #define BOOT_BLINK_DURATION_MS 600 #define BOOT_PAUSE_DURATION_MS 200 LOG_MODULE_REGISTER(main, CONFIG_LOG_DEFAULT_LEVEL); @@ -142,14 +144,11 @@ int main(void) err = mount_sd_card(); printk("result of mount:%d\n",err); + + // perform_unit_test(); + // write_entry_info(1,10); + storage_init(); - write_entry_info(1,10); - write_entry_info(1,20); - write_entry_info(1,30); - - int size = get_file_size(); - - printk("file size is %d\n", size); k_msleep(100); diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.c b/Friend/firmware/firmware_v1.0/src/sdcard.c index 6e230ea87..9e21ea6f6 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.c +++ b/Friend/firmware/firmware_v1.0/src/sdcard.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "sdcard.h" static FATFS fat_fs; @@ -11,19 +13,26 @@ static struct fs_mount_t mount_point = { .type = FS_FATFS, .fs_data = &fat_fs, }; + static bool mounted = false; bool sd_card_mounted = false; - -#define INFO_FILE "SD:/info.txt" -#define AUDIO_DIRECTORY "/SD:/audio/" +static char *current_header; +static int current_audio_file_number = 0; #define MAX_PATH_LENGTH 32 -#define MAX_INFO_ENTRY_LENGTH 2 + +uint8_t file_count = 0; + +K_MUTEX_DEFINE(audio_mutex); + static char current_full_path[MAX_PATH_LENGTH]; +static char read_buffer[MAX_PATH_LENGTH]; +static char write_buffer[MAX_PATH_LENGTH]; static const char *disk_mount_pt = "/SD:/"; + //hehe... char* generate_new_audio_header(uint8_t num) { - if (num > 9 ) return NULL; + if (num > 99 ) return NULL; char *ptr_ = k_malloc(14); ptr_[0] = 'a'; ptr_[1] = 'u'; @@ -32,8 +41,8 @@ char* generate_new_audio_header(uint8_t num) { ptr_[4] = 'o'; ptr_[5] = '/'; ptr_[6] = 'a'; - ptr_[7] = '0'; - ptr_[8] = 48 + num; + ptr_[7] = 48 + (num / 10); + ptr_[8] = 48 + (num % 10); ptr_[9] = '.'; ptr_[10] = 't'; ptr_[11] = 'x'; @@ -42,37 +51,57 @@ char* generate_new_audio_header(uint8_t num) { return ptr_; } +uint32_t get_file_size(uint8_t num){ + snprintf(current_full_path, sizeof(current_full_path), "%s%s", disk_mount_pt, generate_new_audio_header(num)); + struct fs_dirent entry; + fs_stat(¤t_full_path,&entry); + return (uint32_t)entry.size; + } -uint8_t get_info_file_length() { - struct fs_file_t file; - fs_file_t_init(&file); - uint8_t length[2]; - int rc = fs_open(&file, "/SD:/info.txt", FS_O_READ | FS_O_RDWR); - rc = fs_seek(&file,0,FS_SEEK_SET); - rc = fs_read(&file, length, 1); - fs_close(&file); - printk("length is %d\n",length[0]); - return length[0]; + + +uint8_t get_directory_item_count(struct fs_dir_t *zdp, struct fs_dirent *entry) { + // struct fs_dir_t *zip; + uint8_t count = 0; + int rc = zdp->mp->fs->readdir(zdp, entry); + printk("%s %d ",entry->name,entry->size); + count++; + while (true) { + rc = zdp->mp->fs->readdir(zdp, entry); + count++; + if (rc < 0) { + break; + } + if (entry->name[0] == 0) { + break; + } + printk("%s %d ",entry->name,entry->size); + + } + if (rc < 0) { + // LOG_ERR("directory read error (%d)", rc); + } + printk("\n"); + return count; } -uint8_t update_info_file_length(uint8_t num) { - struct fs_file_t file; - fs_file_t_init(&file); +int rebase_audio_file(uint8_t num) { - uint8_t length[16] = {num+'0'}; - for (int i =1; i < 15; i++) { - length[i] = ' '; - } - length[15] = '\n'; - int rc = fs_open(&file, "/SD:/info.txt", FS_O_WRITE); - rc = fs_seek(&file,0,FS_SEEK_SET); + current_header = generate_new_audio_header(num); + printk("current header: %s\n",current_header); + return 0; +} - printk("result of file open%d\n",rc); - rc = fs_write(&file, length, 16); - printk("result of file read%d\n",rc); - fs_close(&file); - printk("length is %d\n",length[0]); - return length[0]; +int move_read_pointer(uint8_t num) { + char *read_ptr = generate_new_audio_header(num); + snprintf(read_buffer, sizeof(read_buffer), "%s%s", disk_mount_pt, read_ptr); + return 0; +} + +int move_write_pointer(uint8_t num) { + char *write_ptr = generate_new_audio_header(num); + snprintf(write_buffer, sizeof(write_buffer), "%s%s", disk_mount_pt, write_ptr); + return 0; } int mount_sd_card(void) @@ -83,21 +112,6 @@ int mount_sd_card(void) static const char *disk_pdrv = "SD"; int err = disk_access_init(disk_pdrv); printk("disk_access_init: %d\n", err); - if (disk_access_ioctl(disk_pdrv, DISK_IOCTL_GET_SECTOR_COUNT, &block_count)) - { - printk("Unable to get sector count\n"); - return -1; - } - if (disk_access_ioctl(disk_pdrv, DISK_IOCTL_GET_SECTOR_SIZE, &block_size)) - { - printk("Unable to get sector count\n"); - return -1; - } - printk("Sector size is %u\n",block_size); - - memory_size_mb = (uint64_t)block_count * block_size; - - printk("Memory size: %u\n",memory_size_mb); mount_point.mnt_point = "/SD:"; int res = fs_mount(&mount_point); @@ -110,7 +124,26 @@ int mount_sd_card(void) printk("f_mount failed: %d\n", res); return -1; } - // res = fs_unlink("/SD:/info.txt"); + struct fs_dir_t zdp; + fs_dir_t_init(&zdp); + res = fs_opendir(&zdp,"/SD:/audio"); + printk("result of opendir: %d\n",res); + + if (zdp.mp == NULL) { + printk("mp is null \n"); + } + printk("%d\n",get_file_size(5)); + struct fs_dirent entry_; + file_count = get_directory_item_count(&zdp,&entry_); + fs_closedir(&zdp); + file_count= file_count+1; + printk("current num files: %d\n",file_count); + initialize_audio_file(file_count); + + // move_write_pointer(7); + // move_read_pointer(7); + + res = fs_mkdir("/SD:/audio"); if (res == FR_OK) { @@ -129,38 +162,22 @@ int mount_sd_card(void) if (res) { res = create_file("info.txt"); printk("result of info.txt creation: %d\n ",res); - update_info_file_length(0); + } - - printk("info file size is %d\n",entry.size); printk("result of check: %d\n",res); - // snprintf(current_full_path, sizeof(current_full_path), "%s%s%s", disk_mount_pt, disk_mount_pt,disk_mount_pt); - // printk("%s\n",current_full_path); - //attempt to create new audio file per reset - uint8_t current_file_num = get_info_file_length(); - - uint8_t next_file_num = current_file_num + 1; - printk("current number of audio files is%d\n ", current_file_num); - char *ptr_ = generate_new_audio_header(next_file_num); // will return (audio/axx.txt) - update_info_file_length(next_file_num); - - if(ptr_ != NULL) { - res = create_file(ptr_); - k_free(ptr_); - } - else { - printk("bad header\n"); - } - //generate new entry in info file - - // res = create_file("audio/a01.txt"); - // printk("result of audio text creation: %d\n ",res); + current_audio_file_number = 1; + // initialize_audio_file(8); + // initialize_audio_file(3); + // make_and_rebase_audio_file(get_info_file_length()+1); + // // write_entry_info(get_info_file_length()+1,1); + // update_info_file_length(current_audio_file_number+1); + return 0; } @@ -183,149 +200,111 @@ int create_file(const char *file_path){ return 0; } - -#define INFO_ENTRY_SIZE 16 //need length,name //a01 00000000000\n -int write_entry_info(uint8_t entry_num,uint32_t size) -{ - if (entry_num == 0) return -1; - int ret = 0; - uint8_t *result = malloc(16 * sizeof(uint8_t)); - result[0] = 'a'; - result[1] = '0'; - result[2] = '0'+entry_num; - result[3] = ' '; - result[4] = '0'; - result[5] = '0'; - result[6] = '0'; - result[7] = '0'; - result[8] = '0'; - result[9] = '0'; - result[10] = (size % 100000) / 10000 +'0'; - result[11] = (size % 10000) / 1000 +'0'; - result[12] = (size % 1000) / 100 + '0'; - result[13] = (size % 100) / 10 + '0'; - result[14] = (size % 10) + '0'; - result[15] = '\n'; - struct fs_file_t data_filp; - fs_file_t_init(&data_filp); - printk("\n"); - ret = fs_open(&data_filp, "/SD:/info.txt", FS_O_WRITE); +int read_audio_data(uint8_t *buf, int amount,int offset) { + // k_mutex_lock(&audio_mutex,K_FOREVER); + struct fs_file_t file; + fs_file_t_init(&file); + uint8_t *temp_ptr = buf; + struct fs_dirent entry; + // snprintf(current_full_path, sizeof(current_full_path), "%s%s", disk_mount_pt, current_header); + // printk("current full path in read file is %s\n",current_full_path); - if(ret) - { - printk("Error creating and writing file\n"); - return -1; + int rc = fs_open(&file, read_buffer, FS_O_READ | FS_O_RDWR); + rc = fs_seek(&file,offset,FS_SEEK_SET); + rc = fs_read(&file, temp_ptr, amount); + printk("read data :"); + for (int i = 0; i < 10;i++) { + printk("%d ",temp_ptr[i]); } - fs_seek(&data_filp,0+ 16 * entry_num,FS_SEEK_SET); - ret = fs_write(&data_filp, result, INFO_ENTRY_SIZE); - - printk("total written %d\n",ret); - free(result); - - if(ret < 0) - { - return -1; - } - - fs_close(&data_filp); - return 0; + printk("\n"); + fs_close(&file); + // k_mutex_unlock(&audio_mutex); + return rc; } - - +//f + //this is the length of the opus encoding int write_to_file(uint8_t *data,uint32_t length) { + k_mutex_lock(&audio_mutex,K_FOREVER); int ret = 0; struct fs_file_t data_filp; fs_file_t_init(&data_filp); uint8_t *temp_ptr = data; - - ret = fs_open(&data_filp, "/SD:/audio/a01.txt", FS_O_WRITE | FS_O_APPEND); + ret = fs_open(&data_filp, write_buffer , FS_O_WRITE | FS_O_APPEND); if(ret) { printk("Error opening file\n"); + k_mutex_unlock(&audio_mutex); return -1; } - ret = fs_write(&data_filp, temp_ptr, length); - printk("File wrote successfully, wrote %d\n",ret); + printk("write data: "); + for (int i = 0; i < 10; i++) { + printk("%d ",temp_ptr[i]); + } + printk("\n"); + if(ret < 0) { + printk("er %d\n",ret); + k_mutex_unlock(&audio_mutex); return -1; } fs_close(&data_filp); + k_mutex_unlock(&audio_mutex); return 0; } -int update_length_on_audio_file() { - -} - - -#define MAX_INFO_FILE_LENGTH 256 -char* get_info_file_data_() { - struct fs_file_t file; - fs_file_t_init(&file); - char *boot_count = (char*)k_malloc(MAX_INFO_FILE_LENGTH); - for (int i = 0; i < MAX_INFO_FILE_LENGTH; i++) { - boot_count[i] = 0; +// fs_stat() check if dircetory exists +int initialize_audio_file(uint8_t num) { + char *header = generate_new_audio_header(num); + if (header == NULL) { + return -1; } - int rc = fs_open(&file, "/SD:/info.txt", FS_O_READ | FS_O_RDWR); - printk("result of file open%d\n",rc); - rc = fs_read(&file, boot_count, 256); - printk("result of file read%d\n",rc); - fs_close(&file); - return boot_count; -} -//this method will write to an already open file. we will enforce that the file is opened - -static audio_info_t current_audio_file; -// fs_stat() check if dircetory exists -int initialize_audio_file() { - current_audio_file.name = "A1.txt"; - char temp[16] = "a00 00000000000\n"; - current_audio_file.size = 0; - struct fs_file_t *temp_file = malloc(sizeof(struct fs_file_t)); - fs_file_t_init(temp_file); - int ret = fs_open(temp_file, "/SD:/audio/A1.txt", FS_O_WRITE | FS_O_APPEND); - printk("result of audio open: %d\n",ret); - current_audio_file.file = temp_file; + create_file(header); return 0; } -int close_audio_file() { - printk("about to close\n"); - k_msleep(10); - fs_close(current_audio_file.file); - k_free(current_audio_file.file); - return 0; -} -static int pos_ = 0; -int read_audio_data(uint8_t *buf, int amount,int offset) { - struct fs_file_t file; - uint8_t *temp_ptr = buf; - printk("about to f\n"); - k_msleep(10); - fs_file_t_init(&file); - int rc = fs_open(&file, "/SD:/audio/a01.txt", FS_O_READ | FS_O_RDWR); +// int close_audio_file() { +// printk("about to close\n"); +// k_msleep(10); +// fs_close(current_audio_file.file); +// k_free(current_audio_file.file); +// return 0; +// } - printk("result of file open%d\n",rc); - k_msleep(10); - rc = fs_seek(&file,offset,FS_SEEK_SET); - printk("result of file seek: %d\n",rc); - rc = fs_read(&file, temp_ptr, amount); - printk("result of file read%d\n",rc); - fs_close(&file); - return rc; +int make_and_rebase_audio_file(uint8_t num) { + + + initialize_audio_file(num); + rebase_audio_file(num); + current_audio_file_number = num; + + return 0; } -int get_file_size(){ - struct fs_dirent entry; - const char *audio_path = "/SD:/audio/a01.txt"; - fs_stat(audio_path,&entry); - return entry.size; - } +void print_directory_contents(struct fs_dir_t *zdp, struct fs_dirent *entry) { + // struct fs_dir_t *zip; + int rc = zdp->mp->fs->readdir(zdp, entry); + printk("%s %d ",entry->name,entry->size); + while (true) { + rc = zdp->mp->fs->readdir(zdp, entry); + + if (rc < 0) { + break; + } + if (entry->name[0] == 0) { + break; + } + printk("%s %d ",entry->name,entry->size); + } + if (rc < 0) { + } + printk("\n"); + return rc; +} diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.h b/Friend/firmware/firmware_v1.0/src/sdcard.h index 97b3c8b94..6bc42af64 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.h +++ b/Friend/firmware/firmware_v1.0/src/sdcard.h @@ -6,45 +6,26 @@ #include #include -#define SD_MOUNT_POINT "SD:" -#define MAX_PATH 256 static FATFS fat_fs; -typedef struct { - uint8_t *data; - size_t length_; - const char path[MAX_PATH]; - bool end_buffer; - bool concat; -} write_params_t; - -typedef struct { - char *data; - int ret; -} read_params_t; typedef struct { char *data; uint16_t length; } info_file_t; -typedef struct { - char *name; - size_t size; - int res; -} file_info_t; - -typedef struct { - char name; - uint32_t size; - struct fs_file_t *file; -} audio_info_t; +int mount_sd_card(void); +int create_file(const char* file_path); -char* get_info_file_data_(); -int close_audio_file(); -int initialize_audio_file(); -int write_audio_file_unsafe(uint8_t *buf, int amount); -int create_file(); +char* generate_new_audio_header(uint8_t num); +int initialize_audio_file(uint8_t num); +int write_to_file(uint8_t *data,uint32_t length); int read_audio_data(uint8_t *buf, int amount,int offset); -int write_entry_info(uint8_t entry_num,uint32_t size); -int get_file_size(); \ No newline at end of file +int rebase_audio_file(uint8_t num); +uint32_t get_file_size(uint8_t num); + +int make_and_rebase_audio_file(uint8_t num); + +int move_read_pointer(uint8_t num); +int move_write_pointer(uint8_t num); + diff --git a/Friend/firmware/firmware_v1.0/src/speaker.c b/Friend/firmware/firmware_v1.0/src/speaker.c index fe6c7117e..84a8d31f8 100644 --- a/Friend/firmware/firmware_v1.0/src/speaker.c +++ b/Friend/firmware/firmware_v1.0/src/speaker.c @@ -105,7 +105,6 @@ uint16_t speak(uint16_t len, const void *buf) { offset = offset + len; LOG_INF("offset: %u", offset); - i2s_write(speaker, rx_buffer, MAX_BLOCK_SIZE); i2s_trigger(speaker, I2S_DIR_TX, I2S_TRIGGER_START);// calls are probably non blocking i2s_trigger(speaker, I2S_DIR_TX, I2S_TRIGGER_DRAIN); diff --git a/Friend/firmware/firmware_v1.0/src/storage.c b/Friend/firmware/firmware_v1.0/src/storage.c index 404fded14..ec72d08de 100644 --- a/Friend/firmware/firmware_v1.0/src/storage.c +++ b/Friend/firmware/firmware_v1.0/src/storage.c @@ -6,12 +6,13 @@ #include #include #include -#include "transport.h" #include "config.h" #include "utils.h" #include "btutils.h" #include "speaker.h" #include "sdcard.h" +#include +#include static void storage_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value); static ssize_t storage_write_handler(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags); @@ -20,6 +21,11 @@ static struct bt_uuid_128 storage_write_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCO static struct bt_uuid_128 storage_read_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x00001542, 0x1212, 0xEFDE, 0x1523, 0x785FEABCD123)); static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset); +K_THREAD_STACK_DEFINE(storage_stack, 2048); +static struct k_thread storage_thread; + + + void broadcast_storage_packet(struct k_work *work_item); K_WORK_DELAYABLE_DEFINE(storage_work, broadcast_storage_packet); @@ -37,73 +43,111 @@ static struct bt_gatt_service storage_service = BT_GATT_SERVICE(storage_service_ static info_file_t info_file; static char hello[256]; +static char num_buffer[32]; +bool storage_is_on = false; + static void storage_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value) { printk("hoi \n"); -} -void update_info_buffer() { - char* b = get_info_file_data_(); - printk("hg\n"); - memcpy(hello,b,256); - k_free(b); + // snprintf(hello, sizeof(hello), "%d", get_file_size(5) ); + + storage_is_on = true; + } static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { printk("hello\n"); k_msleep(10); + // printk("%d\n",get_file_size(5)); + // get_info_file_data_(); ssize_t result = bt_gatt_attr_read(conn, attr, buf, len, offset, hello, 256); return result; } -int register_storage_service() { - bt_gatt_service_register(&storage_service); - return 0; -} -static uint8_t storage_write_buffer[256]; + + static uint32_t remaining_length = 0; static bool transport_started = false; static ssize_t storage_write_handler(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { - //get the requested file and download it. need to use work orders + printk("%s\n",((char*)buf)[0]); printk("about to schedule the storage\n"); - k_msleep(10); - get_info_file_data_(); + k_msleep(1000); transport_started = true; - k_work_schedule(&storage_work, K_MSEC(1000)); - return len; } +static uint16_t packet_next_index = 0; + + +//start num is assumed to be 2 +static uint8_t lowest_num = 2; +static uint8_t storage_write_buffer[256]; static uint32_t offset = 0; +static uint8_t index = 0; +static uint8_t current_packet_size = 0; +static uint8_t tx_buffer_size = 0; +bool storage_is_subscribed() { + + + return bt_gatt_is_subscribed(get_current_connection(), &storage_service.attrs[1], BT_GATT_CCC_NOTIFY); + +} #define MAX_PACKET_LENGTH 256 -void broadcast_storage_packet(struct k_work *work_item) { //staggerable - if (transport_started == true) { - remaining_length = get_file_size(); +static uint8_t starting_num[2]; +void storage_write(void) { + while (1) { + if ( transport_started) { + offset = 1; + index = 0; + move_read_pointer(7); + // remaining_length = (uint32_t)get_file_size(7); + remaining_length = 1000; + printk("remaining length: %d \n",remaining_length); transport_started=false; - } - printk("about to broadcast the storage packet\n"); - - uint32_t packet_size = MIN(remaining_length,MAX_PACKET_LENGTH); - int r = read_audio_data(storage_write_buffer,MAX_PACKET_LENGTH,offset); - offset = offset + packet_size; - remaining_length = MAX(remaining_length - packet_size,0); - printk("current offset: %d\n",offset); - printk("current reamining length: %d\n",remaining_length); - struct bt_conn *conn = get_current_connection(); - if (conn == NULL) { - printk("invalid connection\n"); - } - printk("almost there/...\n"); - int err = bt_gatt_notify(conn, &storage_service.attrs[1], &storage_write_buffer,packet_size); - printk("finished broadcast\n"); - if (remaining_length > 0) { - k_work_reschedule(&storage_work,K_MSEC(1000)); - } - else { - printk("finished broadcasting audio file\n"); + + read_audio_data(&starting_num,2,0); + tx_buffer_size = starting_num[0]; + printk("first number is %d\n",tx_buffer_size); } + // printk("hello\n"); + + if(remaining_length > 0) { + uint32_t id = packet_next_index++; + + storage_write_buffer[0] = id & 0xFF; + storage_write_buffer[1] = (id >> 8) & 0xFF; + storage_write_buffer[2] = index; + printk("current buffer size is %d\n",tx_buffer_size); + uint32_t packet_size = MIN(remaining_length,tx_buffer_size+1); + + int r = read_audio_data(storage_write_buffer+3,packet_size,offset); + tx_buffer_size=storage_write_buffer[3+packet_size-1]; + // printk("next tx buffer os %d\n",tx_buffer_size); + offset = offset + packet_size; + remaining_length = MAX(remaining_length - packet_size,0); + index++; + + // printk("current offset: %d\n",offset); + printk("current reamining length: %d\n",remaining_length); + struct bt_conn *conn = get_current_connection(); + if (conn == NULL) { + printk("invalid connection\n"); + k_sleep(K_MSEC(10)); + } + int err = bt_gatt_notify(conn, &storage_service.attrs[1], &storage_write_buffer,packet_size+3-1); + + k_sleep(K_MSEC(10)); + } + // printk("hullo\n"); + k_yield(); + } } +int storage_init() { + k_thread_create(&storage_thread, storage_stack, K_THREAD_STACK_SIZEOF(storage_stack), (k_thread_entry_t)storage_write, NULL, NULL, NULL, K_PRIO_PREEMPT(7), 0, K_NO_WAIT); + return 0; +} \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/storage.h b/Friend/firmware/firmware_v1.0/src/storage.h index 978890ed0..83399b034 100644 --- a/Friend/firmware/firmware_v1.0/src/storage.h +++ b/Friend/firmware/firmware_v1.0/src/storage.h @@ -1,4 +1,4 @@ #pragma once - -int register_storage_service(); -void update_info_buffer(); \ No newline at end of file +#include +bool storage_is_subscribed(); +int storage_init(); \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/transport.c b/Friend/firmware/firmware_v1.0/src/transport.c index f3c8a6631..0f508e2e5 100644 --- a/Friend/firmware/firmware_v1.0/src/transport.c +++ b/Friend/firmware/firmware_v1.0/src/transport.c @@ -15,12 +15,13 @@ #include "lib/battery/battery.h" #include "speaker.h" #include "button.h" +#include "sdcard.h" #include LOG_MODULE_REGISTER(transport, CONFIG_LOG_DEFAULT_LEVEL); extern bool is_connected; - +extern bool storage_is_on; struct bt_conn *current_connection = NULL; uint16_t current_mtu = 0; uint16_t current_package_index = 0; @@ -449,7 +450,7 @@ static bool read_from_tx_queue() tx_buffer_size = ring_buf_get(&ring_buf, tx_buffer, (CODEC_OUTPUT_MAX_BYTES + RING_BUFFER_HEADER_SIZE)); // It always fits completely or not at all if (tx_buffer_size != (CODEC_OUTPUT_MAX_BYTES + RING_BUFFER_HEADER_SIZE)) { - printk("Failed to read from ring buffer %d\n", tx_buffer_size); + printk("Failed to read from ring buffer. not enough data %d\n", tx_buffer_size); return false; } @@ -465,17 +466,18 @@ static bool read_from_tx_queue() // // Thread -K_THREAD_STACK_DEFINE(pusher_stack, 1024); +K_THREAD_STACK_DEFINE(pusher_stack, 2048); static struct k_thread pusher_thread; static uint16_t packet_next_index = 0; static uint8_t pusher_temp_data[CODEC_OUTPUT_MAX_BYTES + NET_BUFFER_HEADER_SIZE]; static char storage_temp_data[CODEC_OUTPUT_MAX_BYTES]; + static bool push_to_gatt(struct bt_conn *conn) { // Read data from ring buffer if (!read_from_tx_queue()) { - printk("invalid\n"); + return false; } @@ -492,11 +494,8 @@ static bool push_to_gatt(struct bt_conn *conn) pusher_temp_data[1] = (id >> 8) & 0xFF; pusher_temp_data[2] = index; memcpy(pusher_temp_data + NET_BUFFER_HEADER_SIZE, buffer + offset, packet_size); - uint8_t *tr = pusher_temp_data + 2; - // for (int i = 0; i < packet_size; i ++) { - // printk("%d ",tr[i]); - // } - // printk("\n"); + // printk("sent %d bytes \n",tx_buffer_size); + offset += packet_size; index++; @@ -526,26 +525,36 @@ static bool push_to_gatt(struct bt_conn *conn) return true; } +#define OPUS_PREFIX_LENGTH 1 - - +static uint32_t offset = 0; bool write_to_storage(void) { if (!read_from_tx_queue()) { return false; } - printk("about to write to storage\n"); - uint8_t *buffer = tx_buffer+2; + // printk("about to write to storage\n"); + uint8_t *buffer = tx_buffer+3; uint32_t packet_size = tx_buffer_size; - memcpy(storage_temp_data, buffer, packet_size); + storage_temp_data[0] = (uint8_t)tx_buffer_size; + memcpy(storage_temp_data+OPUS_PREFIX_LENGTH, buffer, packet_size); uint8_t *b = (uint8_t*)storage_temp_data; - write_to_file(b,(uint32_t*)packet_size); + write_to_file(b,(uint32_t*)packet_size+OPUS_PREFIX_LENGTH); + // read_audio_data(pog,10,0); + // read_audio_data(storage_temp_data,packet_size,offset); + offset=offset+packet_size; return true; } static bool use_storage = true; +#define MAX_FILES 10 +#define MAX_AUDIO_FILE_SIZE 300000 + + + void pusher(void) { + k_msleep(500); while (1) { @@ -556,7 +565,10 @@ void pusher(void) struct bt_conn *conn = current_connection; bool use_gatt = true; - // FSM_STATE_T state_ = get_current_button_state(); + uint32_t offset = 0; + int length = 1; + + //FSM_STATE_T state_ = get_current_button_state(); if (conn) { conn = bt_conn_ref(conn); @@ -574,22 +586,25 @@ void pusher(void) { valid = bt_gatt_is_subscribed(conn, &audio_service.attrs[1], BT_GATT_CCC_NOTIFY); // Check if subscribed } - - // if (!valid) { - bool result = write_to_storage(); - // if (!result) - // { - // k_sleep(K_MSEC(50)); - // } - // ring_buf_reset(&ring_buf); - // k_sleep(K_MSEC(10)); - // } + // if (!valid && ( length < 100) && !storage_is_on) { - // if(state_ == IDLE ) { //button is pressed - // write_to_storage(); + // bool result = write_to_storage(); + + // if (result) + // { + // // if (get_file_size(9) > MAX_AUDIO_FILE_SIZE) { + // // printk("Audio file size limit reached, making new file\n"); + // // // make_and_rebase_audio_file(get_info_file_length()+1); + // // } // } - + // else { + // k_sleep(K_MSEC(50)); + // } + // } + // k_yield(); + // ring_buf_reset(&ring_buf); + // k_sleep(K_MSEC(10)); // If no valid mode exists - discard whole buffer // if (!valid) // { @@ -599,21 +614,22 @@ void pusher(void) - + // Handle GATT // write_to_storage(); - // if (use_gatt && valid) - // { - // // bool sent =write_to_storage(); - // bool sent = push_to_gatt(conn); - // if (!sent) - // { - // k_sleep(K_MSEC(50)); - // } - // } - + if (use_gatt && valid) + { + // printk("bt\n"); + // bool sent =write_to_storage(); + bool sent = push_to_gatt(conn); + if (!sent) + { + k_sleep(K_MSEC(50)); + } + } + k_yield(); if (conn) { @@ -670,7 +686,7 @@ if(!err) { bt_gatt_service_register(&audio_service); bt_gatt_service_register(&dfu_service); - register_storage_service(); + err = bt_le_adv_start(BT_LE_ADV_CONN, bt_ad, ARRAY_SIZE(bt_ad), bt_sd, ARRAY_SIZE(bt_sd)); if (err) { diff --git a/Friend/firmware/testing/get_audio_file.py b/Friend/firmware/testing/get_audio_file.py index 0747926f1..818239604 100644 --- a/Friend/firmware/testing/get_audio_file.py +++ b/Friend/firmware/testing/get_audio_file.py @@ -1,36 +1,62 @@ import argparse import os from dotenv import load_dotenv - +import wave import asyncio import bleak import numpy as np from bleak import BleakClient - +import opuslib load_dotenv() - +audio_frames = [] +decoder=opuslib.Decoder(16000, 1) device_id = "3CE1CE0A-A629-2E92-D708-E49E71045D07" #Please enter the id of your device (that is, the device id used to connect to your BT device here) storage_uuid = "00001541-1212-EFDE-1523-785FEABCD123" #dont change this - - +storage_read_uuid = "00001542-1212-EFDE-1523-785FEABCD123" +count = 0 +pcm_data=bytearray() +done =False async def main(): global device_uuid global storage_uuid + global count + global pcm_data + global done + global decoder async with BleakClient(device_id) as client: - result = bytearray() - print('a') - async def on_notify(sender: bleak.BleakGATTCharacteristic, data: bytearray): - print('done') - print(np.frombuffer(data,dtype=np.uint8)) - await client.start_notify(storage_uuid, on_notify) - print('b') - await asyncio.sleep(1) - await client.write_gatt_char(storage_uuid, b'd', response=True) - print('c') - await asyncio.sleep(1) - while True: + with open("my_file.txt", "wb") as binary_file: + result = bytearray() + print('a') + async def on_notify(sender: bleak.BleakGATTCharacteristic, data: bytearray): + # Write bytes to file + # binary_file.write(data) + audio_frames.append(data[3:]) + count +=1 + # print(np.frombuffer(data,dtype=np.uint8)) + if (count > 1000) and not done: + done=True + for frame in audio_frames: + try: + decoded_frame = decoder.decode(bytes(frame), 320) + pcm_data.extend(decoded_frame) + except Exception as e: + print(f"Error decoding frame:{e} ") + with wave.open('out.wav', "wb") as wf: + wf.setnchannels(1) + wf.setsampwidth(2) + wf.setframerate(16000) + wf.writeframes(pcm_data) + stuff = await client.start_notify(storage_uuid, on_notify) + print('b') + # await client.read_gatt_char(storage_read_uuid) await asyncio.sleep(1) + await client.write_gatt_char(storage_uuid, b'd', response=True) + print('c') + print(stuff) + await asyncio.sleep(1) + while True: + await asyncio.sleep(1) if __name__ == "__main__": From d66dd8aa24f11c91c4bebe9d4fbe296ad896e102 Mon Sep 17 00:00:00 2001 From: kevvz Date: Mon, 2 Sep 2024 14:55:52 -0700 Subject: [PATCH 05/12] made it easier to send storage data --- .../prj_xiao_ble_sense_devkitv2-adafruit.conf | 13 +- Friend/firmware/firmware_v1.0/src/main.c | 9 +- Friend/firmware/firmware_v1.0/src/sdcard.c | 205 ++++++++---------- Friend/firmware/firmware_v1.0/src/sdcard.h | 7 - Friend/firmware/firmware_v1.0/src/storage.c | 175 +++++++++------ Friend/firmware/firmware_v1.0/src/storage.h | 2 +- Friend/firmware/firmware_v1.0/src/transport.c | 60 +++-- Friend/firmware/testing/get_audio_file.py | 19 +- Friend/firmware/testing/get_info_list.py | 4 +- 9 files changed, 257 insertions(+), 237 deletions(-) diff --git a/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf b/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf index b517a060b..3d4a1800a 100644 --- a/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf +++ b/Friend/firmware/firmware_v1.0/prj_xiao_ble_sense_devkitv2-adafruit.conf @@ -158,4 +158,15 @@ CONFIG_ACCELEROMETER=n #ENABLE THE BUTTON! CONFIG_ENABLE_BUTTON=n #ENABLE THE SPEAKER -CONFIG_ENABLE_SPEAKER=n \ No newline at end of file +CONFIG_ENABLE_SPEAKER=n + +# CONFIG_SD_STACK=y +CONFIG_SD_INIT_TIMEOUT=1500 +CONFIG_SD_RETRY_COUNT=10 +CONFIG_SD_OCR_RETRY_COUNT=1000 +CONFIG_SD_CMD_TIMEOUT=300 +CONFIG_SD_DATA_TIMEOUT=10000 +# CONFIG_SD_BUFFER_SIZE=64 +CONFIG_SD_DATA_RETRIES=3 +# CONFIG_SD_UHS_PROTOCOL is not set +# CONFIG_MMC_RCA=2 \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/main.c b/Friend/firmware/firmware_v1.0/src/main.c index b379ad4c8..06bfae52a 100644 --- a/Friend/firmware/firmware_v1.0/src/main.c +++ b/Friend/firmware/firmware_v1.0/src/main.c @@ -8,7 +8,6 @@ #include "audio.h" #include "codec.h" #include "sdcard.h" -#include "tests.c" #include "storage.h" #define BOOT_BLINK_DURATION_MS 600 #define BOOT_PAUSE_DURATION_MS 200 @@ -144,14 +143,12 @@ int main(void) err = mount_sd_card(); printk("result of mount:%d\n",err); - - // perform_unit_test(); - // write_entry_info(1,10); + k_msleep(500); storage_init(); - k_msleep(100); + set_led_blue(true); set_codec_callback(codec_handler); err = codec_start(); @@ -189,7 +186,7 @@ int main(void) set_led_green(false); // Indicate successful initialization - printk("Omi firmware initialized successfully\n"); + LOG_INF("Omi firmware initialized successfully\n"); set_led_blue(true); k_msleep(1000); set_led_blue(false); diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.c b/Friend/firmware/firmware_v1.0/src/sdcard.c index 9e21ea6f6..112bf8fdd 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.c +++ b/Friend/firmware/firmware_v1.0/src/sdcard.c @@ -7,6 +7,9 @@ #include #include #include "sdcard.h" + +LOG_MODULE_REGISTER(sdcard, CONFIG_LOG_DEFAULT_LEVEL); + static FATFS fat_fs; static struct fs_mount_t mount_point = { @@ -14,16 +17,11 @@ static struct fs_mount_t mount_point = { .fs_data = &fat_fs, }; -static bool mounted = false; -bool sd_card_mounted = false; static char *current_header; -static int current_audio_file_number = 0; #define MAX_PATH_LENGTH 32 uint8_t file_count = 0; -K_MUTEX_DEFINE(audio_mutex); - static char current_full_path[MAX_PATH_LENGTH]; static char read_buffer[MAX_PATH_LENGTH]; static char write_buffer[MAX_PATH_LENGTH]; @@ -31,28 +29,10 @@ static const char *disk_mount_pt = "/SD:/"; //hehe... -char* generate_new_audio_header(uint8_t num) { - if (num > 99 ) return NULL; - char *ptr_ = k_malloc(14); - ptr_[0] = 'a'; - ptr_[1] = 'u'; - ptr_[2] = 'd'; - ptr_[3] = 'i'; - ptr_[4] = 'o'; - ptr_[5] = '/'; - ptr_[6] = 'a'; - ptr_[7] = 48 + (num / 10); - ptr_[8] = 48 + (num % 10); - ptr_[9] = '.'; - ptr_[10] = 't'; - ptr_[11] = 'x'; - ptr_[12] = 't'; - ptr_[13] = '\0'; - - return ptr_; -} uint32_t get_file_size(uint8_t num){ - snprintf(current_full_path, sizeof(current_full_path), "%s%s", disk_mount_pt, generate_new_audio_header(num)); + char *ptr = generate_new_audio_header(num); + snprintf(current_full_path, sizeof(current_full_path), "%s%s", disk_mount_pt, ptr); + k_free(ptr); struct fs_dirent entry; fs_stat(¤t_full_path,&entry); return (uint32_t)entry.size; @@ -85,17 +65,17 @@ uint8_t get_directory_item_count(struct fs_dir_t *zdp, struct fs_dirent *entry) return count; } -int rebase_audio_file(uint8_t num) { - - current_header = generate_new_audio_header(num); - printk("current header: %s\n",current_header); - return 0; -} - int move_read_pointer(uint8_t num) { - char *read_ptr = generate_new_audio_header(num); + char *read_ptr = generate_new_audio_header(num); snprintf(read_buffer, sizeof(read_buffer), "%s%s", disk_mount_pt, read_ptr); - return 0; + struct fs_dirent entry; //check if the info file exists. if not, generate new info file + int res = fs_stat(&read_buffer,&entry); + if (res) { + printk("invalid file\n"); + + return -1; + } + return 0; } int move_write_pointer(uint8_t num) { @@ -112,18 +92,32 @@ int mount_sd_card(void) static const char *disk_pdrv = "SD"; int err = disk_access_init(disk_pdrv); printk("disk_access_init: %d\n", err); + if (err == -116) { + k_msleep(2000); + disk_access_init(disk_pdrv); + } mount_point.mnt_point = "/SD:"; int res = fs_mount(&mount_point); if (res == FR_OK) { - mounted = true; - sd_card_mounted = true; printk("SD card mounted successfully\n"); } else { printk("f_mount failed: %d\n", res); return -1; } + res = fs_mkdir("/SD:/audio"); + if (res == FR_OK) { + printk("audio directory created successfully\n"); + initialize_audio_file(0); + } + else if (res == FR_EXIST) { + printk("audio directory already exists\n"); + } + else { + printk("audio directory creation failed: %d\n", res); + } + struct fs_dir_t zdp; fs_dir_t_init(&zdp); res = fs_opendir(&zdp,"/SD:/audio"); @@ -132,29 +126,21 @@ int mount_sd_card(void) if (zdp.mp == NULL) { printk("mp is null \n"); } - printk("%d\n",get_file_size(5)); + struct fs_dirent entry_; - file_count = get_directory_item_count(&zdp,&entry_); + file_count = get_directory_item_count(&zdp,&entry_)-1; + fs_closedir(&zdp); - file_count= file_count+1; + + + printk("current num files: %d\n",file_count); + file_count++; initialize_audio_file(file_count); - // move_write_pointer(7); - // move_read_pointer(7); + move_write_pointer(file_count); + move_read_pointer(file_count-1); - - - res = fs_mkdir("/SD:/audio"); - if (res == FR_OK) { - printk("audio directory created successfully\n"); - } - else if (res == FR_EXIST) { - printk("audio directory already exists\n"); - } - else { - printk("audio directory creation failed: %d\n", res); - } struct fs_dirent entry; //check if the info file exists. if not, generate new info file const char *info_path = "/SD:/info.txt"; @@ -167,17 +153,6 @@ int mount_sd_card(void) printk("result of check: %d\n",res); - - - - - current_audio_file_number = 1; - // initialize_audio_file(8); - // initialize_audio_file(3); - // make_and_rebase_audio_file(get_info_file_length()+1); - // // write_entry_info(get_info_file_length()+1,1); - // update_info_file_length(current_audio_file_number+1); - return 0; } @@ -200,67 +175,60 @@ int create_file(const char *file_path){ return 0; } -//need length,name -//a01 00000000000\n - int read_audio_data(uint8_t *buf, int amount,int offset) { - // k_mutex_lock(&audio_mutex,K_FOREVER); struct fs_file_t file; fs_file_t_init(&file); uint8_t *temp_ptr = buf; struct fs_dirent entry; - // snprintf(current_full_path, sizeof(current_full_path), "%s%s", disk_mount_pt, current_header); - // printk("current full path in read file is %s\n",current_full_path); + int rc = fs_open(&file, read_buffer, FS_O_READ | FS_O_RDWR); rc = fs_seek(&file,offset,FS_SEEK_SET); rc = fs_read(&file, temp_ptr, amount); - printk("read data :"); - for (int i = 0; i < 10;i++) { - printk("%d ",temp_ptr[i]); - } - printk("\n"); + // printk("read data :"); + // for (int i = 0; i < amount;i++) { + // printk("%d ",temp_ptr[i]); + // } + // printk("\n"); fs_close(&file); - // k_mutex_unlock(&audio_mutex); + return rc; } -//f - //this is the length of the opus encoding + int write_to_file(uint8_t *data,uint32_t length) { - k_mutex_lock(&audio_mutex,K_FOREVER); + int ret = 0; - struct fs_file_t data_filp; - fs_file_t_init(&data_filp); + struct fs_file_t data_loc; + fs_file_t_init(&data_loc); uint8_t *temp_ptr = data; - ret = fs_open(&data_filp, write_buffer , FS_O_WRITE | FS_O_APPEND); + ret = fs_open(&data_loc, write_buffer , FS_O_WRITE | FS_O_APPEND); if(ret) { printk("Error opening file\n"); - k_mutex_unlock(&audio_mutex); + return -1; } - ret = fs_write(&data_filp, temp_ptr, length); - printk("write data: "); - for (int i = 0; i < 10; i++) { - printk("%d ",temp_ptr[i]); - } - printk("\n"); + ret = fs_write(&data_loc, temp_ptr, length); + // // printk("length is %d\n", length); + // printk("write data: "); + // for (int i = 0; i < length; i++) { + // printk("%d ",temp_ptr[i]); + // } + // printk("\n"); if(ret < 0) { printk("er %d\n",ret); - k_mutex_unlock(&audio_mutex); + return -1; } - fs_close(&data_filp); - k_mutex_unlock(&audio_mutex); + fs_close(&data_loc); + return 0; } - - -// fs_stat() check if dircetory exists + int initialize_audio_file(uint8_t num) { char *header = generate_new_audio_header(num); if (header == NULL) { @@ -270,26 +238,8 @@ int initialize_audio_file(uint8_t num) { return 0; } -// int close_audio_file() { -// printk("about to close\n"); -// k_msleep(10); -// fs_close(current_audio_file.file); -// k_free(current_audio_file.file); -// return 0; -// } - -int make_and_rebase_audio_file(uint8_t num) { - - - initialize_audio_file(num); - rebase_audio_file(num); - current_audio_file_number = num; - - return 0; -} - void print_directory_contents(struct fs_dir_t *zdp, struct fs_dirent *entry) { - // struct fs_dir_t *zip; + int rc = zdp->mp->fs->readdir(zdp, entry); printk("%s %d ",entry->name,entry->size); while (true) { @@ -306,5 +256,28 @@ void print_directory_contents(struct fs_dir_t *zdp, struct fs_dirent *entry) { if (rc < 0) { } printk("\n"); - return rc; + } + + + +char* generate_new_audio_header(uint8_t num) { + if (num > 99 ) return NULL; + char *ptr_ = k_malloc(14); + ptr_[0] = 'a'; + ptr_[1] = 'u'; + ptr_[2] = 'd'; + ptr_[3] = 'i'; + ptr_[4] = 'o'; + ptr_[5] = '/'; + ptr_[6] = 'a'; + ptr_[7] = 48 + (num / 10); + ptr_[8] = 48 + (num % 10); + ptr_[9] = '.'; + ptr_[10] = 't'; + ptr_[11] = 'x'; + ptr_[12] = 't'; + ptr_[13] = '\0'; + + return ptr_; +} \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.h b/Friend/firmware/firmware_v1.0/src/sdcard.h index 6bc42af64..cf001cfa0 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.h +++ b/Friend/firmware/firmware_v1.0/src/sdcard.h @@ -6,12 +6,7 @@ #include #include -static FATFS fat_fs; -typedef struct { - char *data; - uint16_t length; -} info_file_t; int mount_sd_card(void); @@ -21,10 +16,8 @@ char* generate_new_audio_header(uint8_t num); int initialize_audio_file(uint8_t num); int write_to_file(uint8_t *data,uint32_t length); int read_audio_data(uint8_t *buf, int amount,int offset); -int rebase_audio_file(uint8_t num); uint32_t get_file_size(uint8_t num); -int make_and_rebase_audio_file(uint8_t num); int move_read_pointer(uint8_t num); int move_write_pointer(uint8_t num); diff --git a/Friend/firmware/firmware_v1.0/src/storage.c b/Friend/firmware/firmware_v1.0/src/storage.c index ec72d08de..35cc5cacc 100644 --- a/Friend/firmware/firmware_v1.0/src/storage.c +++ b/Friend/firmware/firmware_v1.0/src/storage.c @@ -13,18 +13,25 @@ #include "sdcard.h" #include #include + +LOG_MODULE_REGISTER(storage, CONFIG_LOG_DEFAULT_LEVEL); + +#define MAX_PACKET_LENGTH 256 +#define OPUS_ENTRY_LENGTH 100 +#define FRAME_PREFIX_LENGTH 3 + static void storage_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value); static ssize_t storage_write_handler(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags); -static struct bt_uuid_128 storage_service_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x00001540, 0x1212, 0xEFDE, 0x1523, 0x785FEABCD123)); -static struct bt_uuid_128 storage_write_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x00001541, 0x1212, 0xEFDE, 0x1523, 0x785FEABCD123)); -static struct bt_uuid_128 storage_read_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x00001542, 0x1212, 0xEFDE, 0x1523, 0x785FEABCD123)); +static struct bt_uuid_128 storage_service_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x30295780, 0x4301, 0xEABD, 0x2904, 0x2849ADFEAE43)); +static struct bt_uuid_128 storage_write_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x30295781, 0x4301, 0xEABD, 0x2904, 0x2849ADFEAE43)); +static struct bt_uuid_128 storage_read_uuid = BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x30295782, 0x4301, 0xEABD, 0x2904, 0x2849ADFEAE43)); static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset); K_THREAD_STACK_DEFINE(storage_stack, 2048); static struct k_thread storage_thread; - +extern uint8_t file_count; void broadcast_storage_packet(struct k_work *work_item); K_WORK_DELAYABLE_DEFINE(storage_work, broadcast_storage_packet); @@ -40,114 +47,150 @@ static struct bt_gatt_attr storage_service_attr[] = { static struct bt_gatt_service storage_service = BT_GATT_SERVICE(storage_service_attr); - -static info_file_t info_file; -static char hello[256]; -static char num_buffer[32]; bool storage_is_on = false; static void storage_config_changed_handler(const struct bt_gatt_attr *attr, uint16_t value) { - printk("hoi \n"); - // snprintf(hello, sizeof(hello), "%d", get_file_size(5) ); storage_is_on = true; + if (value == BT_GATT_CCC_NOTIFY) + { + LOG_INF("Client subscribed for notifications"); + } + else if (value == 0) + { + LOG_INF("Client unsubscribed from notifications"); + } + else + { + LOG_ERR("Invalid CCC value: %u", value); + } } static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { - printk("hello\n"); k_msleep(10); - // printk("%d\n",get_file_size(5)); - // get_info_file_data_(); - ssize_t result = bt_gatt_attr_read(conn, attr, buf, len, offset, hello, 256); + char amount[1] = {file_count}; + + ssize_t result = bt_gatt_attr_read(conn, attr, buf, len, offset, amount, sizeof(amount)); return result; } +uint8_t transport_started = 0; - - -static uint32_t remaining_length = 0; -static bool transport_started = false; static ssize_t storage_write_handler(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags) { - - printk("%s\n",((char*)buf)[0]); - printk("about to schedule the storage\n"); + LOG_INF("about to schedule the storage"); + transport_started = 1; k_msleep(1000); - transport_started = true; + return len; } -static uint16_t packet_next_index = 0; +static uint16_t packet_next_index = 0; -//start num is assumed to be 2 -static uint8_t lowest_num = 2; static uint8_t storage_write_buffer[256]; static uint32_t offset = 0; static uint8_t index = 0; static uint8_t current_packet_size = 0; static uint8_t tx_buffer_size = 0; -bool storage_is_subscribed() { + +static uint8_t current_read_num = 2; +uint32_t remaining_length = 0; + +static void setup_storage_tx(void) { + transport_started= (uint8_t)0; + offset = 0; + + int res = move_read_pointer(current_read_num); + if (res) { + LOG_ERR("bad pointer"); + transport_started = 0; + current_read_num++; + remaining_length = 0; + } + else { + if ((uint32_t)get_file_size(current_read_num) == 0 ) { + LOG_ERR("bad file size, moving again..."); + current_read_num++; + move_read_pointer(current_read_num); + } + LOG_INF("current read ptr %d",current_read_num); + + remaining_length = get_file_size(current_read_num); + LOG_INF("remaining length: %d",remaining_length); + } + +} + + +static void write_to_gatt(struct bt_conn *conn) { + uint32_t id = packet_next_index++; + index = 0; + storage_write_buffer[0] = id & 0xFF; + storage_write_buffer[1] = (id >> 8) & 0xFF; + storage_write_buffer[2] = index; + + uint32_t packet_size = MIN(remaining_length,OPUS_ENTRY_LENGTH); + + int r = read_audio_data(storage_write_buffer+FRAME_PREFIX_LENGTH,packet_size,offset); + offset = offset + packet_size; + remaining_length = remaining_length - OPUS_ENTRY_LENGTH; + index++; - return bt_gatt_is_subscribed(get_current_connection(), &storage_service.attrs[1], BT_GATT_CCC_NOTIFY); + // printk("current remaining length: %d\n",remaining_length); + // for (int i = 0 ; i < 103; i ++) { + // printk("%d ",storage_write_buffer[i]); + // } + // printk("\n"); + int err = bt_gatt_notify(conn, &storage_service.attrs[1], &storage_write_buffer,packet_size+3); } -#define MAX_PACKET_LENGTH 256 -static uint8_t starting_num[2]; + + + void storage_write(void) { while (1) { - if ( transport_started) { - offset = 1; - index = 0; - move_read_pointer(7); - // remaining_length = (uint32_t)get_file_size(7); - remaining_length = 1000; - printk("remaining length: %d \n",remaining_length); - transport_started=false; - - read_audio_data(&starting_num,2,0); - tx_buffer_size = starting_num[0]; - printk("first number is %d\n",tx_buffer_size); + + if ( transport_started ) { + LOG_INF("transpor started in side : %d",transport_started); + setup_storage_tx(); } - // printk("hello\n"); - if(remaining_length > 0) { - uint32_t id = packet_next_index++; - - storage_write_buffer[0] = id & 0xFF; - storage_write_buffer[1] = (id >> 8) & 0xFF; - storage_write_buffer[2] = index; - printk("current buffer size is %d\n",tx_buffer_size); - uint32_t packet_size = MIN(remaining_length,tx_buffer_size+1); - - int r = read_audio_data(storage_write_buffer+3,packet_size,offset); - tx_buffer_size=storage_write_buffer[3+packet_size-1]; - // printk("next tx buffer os %d\n",tx_buffer_size); - offset = offset + packet_size; - remaining_length = MAX(remaining_length - packet_size,0); - index++; - - // printk("current offset: %d\n",offset); - printk("current reamining length: %d\n",remaining_length); + if(remaining_length > 0 ) { + struct bt_conn *conn = get_current_connection(); if (conn == NULL) { - printk("invalid connection\n"); - k_sleep(K_MSEC(10)); + LOG_ERR("invalid connection"); + k_yield(); } - int err = bt_gatt_notify(conn, &storage_service.attrs[1], &storage_write_buffer,packet_size+3-1); - - k_sleep(K_MSEC(10)); + write_to_gatt(conn); + + transport_started = 0; + if (remaining_length == 0) { + LOG_INF("done. attempting to download more files"); + // current_read_num++; + k_sleep(K_MSEC(10)); + // setup_storage_tx(); + } - // printk("hullo\n"); + + } + + k_yield(); } + } int storage_init() { + + bt_gatt_service_register(&storage_service); k_thread_create(&storage_thread, storage_stack, K_THREAD_STACK_SIZEOF(storage_stack), (k_thread_entry_t)storage_write, NULL, NULL, NULL, K_PRIO_PREEMPT(7), 0, K_NO_WAIT); + return 0; + } \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/storage.h b/Friend/firmware/firmware_v1.0/src/storage.h index 83399b034..c421a89fe 100644 --- a/Friend/firmware/firmware_v1.0/src/storage.h +++ b/Friend/firmware/firmware_v1.0/src/storage.h @@ -1,4 +1,4 @@ #pragma once #include -bool storage_is_subscribed(); + int storage_init(); \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/transport.c b/Friend/firmware/firmware_v1.0/src/transport.c index 0f508e2e5..96a2a8f66 100644 --- a/Friend/firmware/firmware_v1.0/src/transport.c +++ b/Friend/firmware/firmware_v1.0/src/transport.c @@ -22,6 +22,7 @@ LOG_MODULE_REGISTER(transport, CONFIG_LOG_DEFAULT_LEVEL); extern bool is_connected; extern bool storage_is_on; +extern uint8_t file_count; struct bt_conn *current_connection = NULL; uint16_t current_mtu = 0; uint16_t current_package_index = 0; @@ -327,6 +328,7 @@ void broadcast_battery_level(struct k_work *work_item) { static void _transport_connected(struct bt_conn *conn, uint8_t err) { struct bt_conn_info info = {0}; + storage_is_on = true; err = bt_conn_get_info(conn, &info); if (err) @@ -357,6 +359,7 @@ static void _transport_connected(struct bt_conn *conn, uint8_t err) static void _transport_disconnected(struct bt_conn *conn, uint8_t err) { is_connected = false; + storage_is_on = false; LOG_INF("Transport disconnected"); bt_conn_unref(conn); @@ -526,22 +529,24 @@ static bool push_to_gatt(struct bt_conn *conn) return true; } #define OPUS_PREFIX_LENGTH 1 - +#define OPUS_PADDED_LENGTH 100 static uint32_t offset = 0; + bool write_to_storage(void) { if (!read_from_tx_queue()) { return false; } - // printk("about to write to storage\n"); + uint8_t *buffer = tx_buffer+3; uint32_t packet_size = tx_buffer_size; + + memset(storage_temp_data, 0, OPUS_PADDED_LENGTH); + memcpy(storage_temp_data + OPUS_PREFIX_LENGTH, buffer, packet_size); storage_temp_data[0] = (uint8_t)tx_buffer_size; - memcpy(storage_temp_data+OPUS_PREFIX_LENGTH, buffer, packet_size); - uint8_t *b = (uint8_t*)storage_temp_data; - write_to_file(b,(uint32_t*)packet_size+OPUS_PREFIX_LENGTH); - // read_audio_data(pog,10,0); - // read_audio_data(storage_temp_data,packet_size,offset); + uint8_t *write_ptr = (uint8_t*)storage_temp_data; + write_to_file(write_ptr,OPUS_PADDED_LENGTH); + offset=offset+packet_size; return true; } @@ -568,7 +573,6 @@ void pusher(void) uint32_t offset = 0; int length = 1; - //FSM_STATE_T state_ = get_current_button_state(); if (conn) { conn = bt_conn_ref(conn); @@ -587,41 +591,33 @@ void pusher(void) valid = bt_gatt_is_subscribed(conn, &audio_service.attrs[1], BT_GATT_CCC_NOTIFY); // Check if subscribed } - // if (!valid && ( length < 100) && !storage_is_on) { + if (!valid && ( length < 100) && !storage_is_on) { - // bool result = write_to_storage(); + bool result = write_to_storage(); - // if (result) - // { - // // if (get_file_size(9) > MAX_AUDIO_FILE_SIZE) { - // // printk("Audio file size limit reached, making new file\n"); - // // // make_and_rebase_audio_file(get_info_file_length()+1); - // // } - // } - // else { - // k_sleep(K_MSEC(50)); - // } - // } - // k_yield(); - // ring_buf_reset(&ring_buf); - // k_sleep(K_MSEC(10)); - // If no valid mode exists - discard whole buffer + if (result) + { + // if (get_file_size(9) > MAX_AUDIO_FILE_SIZE) { + // printk("Audio file size limit reached, making new file\n"); + // // make_and_rebase_audio_file(get_info_file_length()+1); + // } + } + else { + k_sleep(K_MSEC(50)); + } + } // if (!valid) // { // ring_buf_reset(&ring_buf); // k_sleep(K_MSEC(10)); // } - - - // Handle GATT - // write_to_storage(); + if (use_gatt && valid) { - // printk("bt\n"); - // bool sent =write_to_storage(); - bool sent = push_to_gatt(conn); + + bool sent = push_to_gatt(conn); if (!sent) { k_sleep(K_MSEC(50)); diff --git a/Friend/firmware/testing/get_audio_file.py b/Friend/firmware/testing/get_audio_file.py index 818239604..26bbd69b0 100644 --- a/Friend/firmware/testing/get_audio_file.py +++ b/Friend/firmware/testing/get_audio_file.py @@ -11,8 +11,8 @@ audio_frames = [] decoder=opuslib.Decoder(16000, 1) device_id = "3CE1CE0A-A629-2E92-D708-E49E71045D07" #Please enter the id of your device (that is, the device id used to connect to your BT device here) -storage_uuid = "00001541-1212-EFDE-1523-785FEABCD123" #dont change this -storage_read_uuid = "00001542-1212-EFDE-1523-785FEABCD123" +storage_uuid = "30295781-4301-EABD-2904-2849ADFEAE43" #dont change this +storage_read_uuid = "30295782-4301-EABD-2904-2849ADFEAE43" count = 0 pcm_data=bytearray() done =False @@ -28,13 +28,18 @@ async def main(): with open("my_file.txt", "wb") as binary_file: result = bytearray() print('a') + + async def on_notify(sender: bleak.BleakGATTCharacteristic, data: bytearray): # Write bytes to file # binary_file.write(data) - audio_frames.append(data[3:]) + global count + global done + amount_to_append = data[3] + audio_frames.append(data[4:data[3]+4]) count +=1 - # print(np.frombuffer(data,dtype=np.uint8)) - if (count > 1000) and not done: + print(np.frombuffer(data[4:data[3]+4],dtype=np.uint8)) + if (count > 700) and not done: done=True for frame in audio_frames: try: @@ -46,7 +51,9 @@ async def on_notify(sender: bleak.BleakGATTCharacteristic, data: bytearray): wf.setnchannels(1) wf.setsampwidth(2) wf.setframerate(16000) - wf.writeframes(pcm_data) + wf.writeframes(pcm_data) + + stuff = await client.start_notify(storage_uuid, on_notify) print('b') # await client.read_gatt_char(storage_read_uuid) diff --git a/Friend/firmware/testing/get_info_list.py b/Friend/firmware/testing/get_info_list.py index ce6f4c75d..ae3d86fc9 100644 --- a/Friend/firmware/testing/get_info_list.py +++ b/Friend/firmware/testing/get_info_list.py @@ -10,7 +10,7 @@ load_dotenv() device_id = "3CE1CE0A-A629-2E92-D708-E49E71045D07" #Please enter the id of your device (that is, the device id used to connect to your BT device here) -storage_uuid = "00001542-1212-EFDE-1523-785FEABCD123" #dont change this +storage_uuid = "30295782-4301-EABD-2904-2849ADFEAE43" #dont change this async def main(): @@ -21,7 +21,7 @@ async def main(): while(True): await asyncio.sleep(2.0) - print(r) + print(np.frombuffer(r,dtype=np.uint8)) if __name__ == "__main__": From e9e6882e5dd60c0622c0b6524632510ebe27fd5a Mon Sep 17 00:00:00 2001 From: Brady Anthony-Brumfield Date: Tue, 3 Sep 2024 15:32:21 -0400 Subject: [PATCH 06/12] add workout-tracker --- community-plugins.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/community-plugins.json b/community-plugins.json index 9aabacd97..cbd6bc4f6 100644 --- a/community-plugins.json +++ b/community-plugins.json @@ -607,6 +607,20 @@ ], "deleted": false }, + { + "id": "workout-tracker", + "name": "Workout Tracker", + "author": "Brady Anthony-Brumfield", + "description": "Extracts & summarizes workout notes from transcripts & offers advice", + "prompt": "you are a strength trainer and physiology expert. parse this transcript for anything that sounds like verbal documentation of a workout, and if you find it then output a summary of the workout including each exercise, weight, and number of reps per set. then give an informed take on what kind of workout this constituted (which muscle groups, strength, hypertrophy, etc) and what kind results you can expect to see. then give feedback, if appropriate, based on other information about the workout, participant's goals, or the health of the participant given in the transcript. if you give feedback, quote the relevant information pulled from the transcript and give the feedback in a nested bullet point below it", + "image": "/plugins/logos/ronnie.jpg", + "memories": true, + "chat": false, + "capabilities": [ + "memories" + ], + "deleted": false + }, { "id": "nik-shevchenko", "name": "Nik Shevchenko", From 9d12a9bc35922686e28e55195ba9f44b437230e4 Mon Sep 17 00:00:00 2001 From: Brady Anthony-Brumfield Date: Tue, 3 Sep 2024 15:53:39 -0400 Subject: [PATCH 07/12] Update community-plugins.json --- community-plugins.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/community-plugins.json b/community-plugins.json index cbd6bc4f6..f87a563cb 100644 --- a/community-plugins.json +++ b/community-plugins.json @@ -598,7 +598,7 @@ "name": "Advanced Fact Checker", "author": "Brady Anthony-Brumfield", "description": "Searches the web and provides additional reading for contentious statements", - "prompt": "You will be given a transcription. First, understand that the transcription is of poor quality and if you see nonsensical text, infer the proper meaning. Then, check it for statements that need more evidence. For each of these statements, search the web for supporting and contradicting science-based evidence, and concisely summarize and link the evidence.", + "prompt": "You will be given a transcription. First, understand that the transcription is potentially of poor quality and if you see nonsensical text, infer the proper meaning. Then, check it for statements that aren't common knowledge and would benefit from more evidence. For each of these statements, search the web for supporting and contradicting science-based evidence, and concisely summarize and link the evidence.", "image": "/plugins/logos/source.jpg", "memories": true, "chat": false, @@ -612,7 +612,7 @@ "name": "Workout Tracker", "author": "Brady Anthony-Brumfield", "description": "Extracts & summarizes workout notes from transcripts & offers advice", - "prompt": "you are a strength trainer and physiology expert. parse this transcript for anything that sounds like verbal documentation of a workout, and if you find it then output a summary of the workout including each exercise, weight, and number of reps per set. then give an informed take on what kind of workout this constituted (which muscle groups, strength, hypertrophy, etc) and what kind results you can expect to see. then give feedback, if appropriate, based on other information about the workout, participant's goals, or the health of the participant given in the transcript. if you give feedback, quote the relevant information pulled from the transcript and give the feedback in a nested bullet point below it", + "prompt": "you are a strength trainer and physiology expert. You will be given a transcription. First, understand that the transcription is potentially of poor quality and if you see nonsensical text, infer the proper meaning. parse this transcript for anything that sounds like verbal documentation of a workout, and if you find it then output a summary of the workout including each exercise, weight, and number of reps per set. then give an informed take on what kind of workout this constituted (which muscle groups, strength, hypertrophy, etc) and what kind results you can expect to see. then give feedback, if appropriate, based on other information about the workout, participant's goals, or the health of the participant given in the transcript. if you give feedback, quote the relevant information pulled from the transcript and give the feedback in a nested bullet point below it", "image": "/plugins/logos/ronnie.jpg", "memories": true, "chat": false, From a732c8e23cd9b15a678255c640bb610938a06c28 Mon Sep 17 00:00:00 2001 From: Brady Anthony-Brumfield Date: Tue, 3 Sep 2024 15:57:20 -0400 Subject: [PATCH 08/12] Add files via upload --- plugins/logos/ozvs1a0l75421.jpg | Bin 0 -> 25316 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plugins/logos/ozvs1a0l75421.jpg diff --git a/plugins/logos/ozvs1a0l75421.jpg b/plugins/logos/ozvs1a0l75421.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3412cc478fed9c7c9ac949c56809bfb9716eebf0 GIT binary patch literal 25316 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 R%6*+Spl9G{1()2L{vV6|M124N literal 0 HcmV?d00001 From fc48cedeef301f07b9c8018c779d1d1f0e15ad01 Mon Sep 17 00:00:00 2001 From: Brady Anthony-Brumfield Date: Tue, 3 Sep 2024 15:57:51 -0400 Subject: [PATCH 09/12] Rename ozvs1a0l75421.jpg to ronnie.jpg --- plugins/logos/{ozvs1a0l75421.jpg => ronnie.jpg} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename plugins/logos/{ozvs1a0l75421.jpg => ronnie.jpg} (100%) diff --git a/plugins/logos/ozvs1a0l75421.jpg b/plugins/logos/ronnie.jpg similarity index 100% rename from plugins/logos/ozvs1a0l75421.jpg rename to plugins/logos/ronnie.jpg From 3f470f788477a75728925817077fdab03d0b0329 Mon Sep 17 00:00:00 2001 From: Brady Anthony-Brumfield Date: Tue, 3 Sep 2024 16:08:14 -0400 Subject: [PATCH 10/12] Update community-plugins.json --- community-plugins.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/community-plugins.json b/community-plugins.json index f87a563cb..b99efca2a 100644 --- a/community-plugins.json +++ b/community-plugins.json @@ -599,6 +599,7 @@ "author": "Brady Anthony-Brumfield", "description": "Searches the web and provides additional reading for contentious statements", "prompt": "You will be given a transcription. First, understand that the transcription is potentially of poor quality and if you see nonsensical text, infer the proper meaning. Then, check it for statements that aren't common knowledge and would benefit from more evidence. For each of these statements, search the web for supporting and contradicting science-based evidence, and concisely summarize and link the evidence.", + "memory_prompt": "You will be given a transcription. First, understand that the transcription is potentially of poor quality and if you see nonsensical text, infer the proper meaning. Then, check it for statements that aren't common knowledge and would benefit from more evidence. For each of these statements, search the web for supporting and contradicting science-based evidence, and concisely summarize and link the evidence.", "image": "/plugins/logos/source.jpg", "memories": true, "chat": false, @@ -608,11 +609,12 @@ "deleted": false }, { - "id": "workout-tracker", - "name": "Workout Tracker", + "id": "workout-buddy", + "name": "Workout Buddy", "author": "Brady Anthony-Brumfield", - "description": "Extracts & summarizes workout notes from transcripts & offers advice", + "description": "Extracts, summarizes, & gives feedback on workout notes from memories. You can also ", "prompt": "you are a strength trainer and physiology expert. You will be given a transcription. First, understand that the transcription is potentially of poor quality and if you see nonsensical text, infer the proper meaning. parse this transcript for anything that sounds like verbal documentation of a workout, and if you find it then output a summary of the workout including each exercise, weight, and number of reps per set. then give an informed take on what kind of workout this constituted (which muscle groups, strength, hypertrophy, etc) and what kind results you can expect to see. then give feedback, if appropriate, based on other information about the workout, participant's goals, or the health of the participant given in the transcript. if you give feedback, quote the relevant information pulled from the transcript and give the feedback in a nested bullet point below it", + "memory_prompt": "you are a strength trainer and physiology expert. You will be given a transcription. First, understand that the transcription is potentially of poor quality and if you see nonsensical text, infer the proper meaning. parse this transcript for anything that sounds like verbal documentation of a workout, and if you find it then output a summary of the workout including each exercise, weight, and number of reps per set. then give an informed take on what kind of workout this constituted (which muscle groups, strength, hypertrophy, etc) and what kind results you can expect to see. then give feedback, if appropriate, based on other information about the workout, participant's goals, or the health of the participant given in the transcript. if you give feedback, quote the relevant information pulled from the transcript and give the feedback in a nested bullet point below it", "image": "/plugins/logos/ronnie.jpg", "memories": true, "chat": false, From 33ff0965716661f67b3bd11a548694ff9279e502 Mon Sep 17 00:00:00 2001 From: kevvz Date: Tue, 3 Sep 2024 21:30:42 -0700 Subject: [PATCH 11/12] added option to check file count from bt --- Friend/firmware/firmware_v1.0/src/sdcard.c | 117 ++++++++++-------- Friend/firmware/firmware_v1.0/src/speaker.c | 9 +- Friend/firmware/firmware_v1.0/src/storage.c | 43 ++++--- Friend/firmware/firmware_v1.0/src/transport.c | 6 + Friend/firmware/testing/decode_audio.py | 39 ++++++ Friend/firmware/testing/get_audio_file.py | 18 +-- Friend/firmware/testing/get_info_list.py | 2 +- 7 files changed, 143 insertions(+), 91 deletions(-) create mode 100644 Friend/firmware/testing/decode_audio.py diff --git a/Friend/firmware/firmware_v1.0/src/sdcard.c b/Friend/firmware/firmware_v1.0/src/sdcard.c index 112bf8fdd..f0f6daea3 100644 --- a/Friend/firmware/firmware_v1.0/src/sdcard.c +++ b/Friend/firmware/firmware_v1.0/src/sdcard.c @@ -27,8 +27,6 @@ static char read_buffer[MAX_PATH_LENGTH]; static char write_buffer[MAX_PATH_LENGTH]; static const char *disk_mount_pt = "/SD:/"; - -//hehe... uint32_t get_file_size(uint8_t num){ char *ptr = generate_new_audio_header(num); snprintf(current_full_path, sizeof(current_full_path), "%s%s", disk_mount_pt, ptr); @@ -38,37 +36,11 @@ uint32_t get_file_size(uint8_t num){ return (uint32_t)entry.size; } - - -uint8_t get_directory_item_count(struct fs_dir_t *zdp, struct fs_dirent *entry) { - // struct fs_dir_t *zip; - uint8_t count = 0; - int rc = zdp->mp->fs->readdir(zdp, entry); - printk("%s %d ",entry->name,entry->size); - count++; - while (true) { - rc = zdp->mp->fs->readdir(zdp, entry); - count++; - if (rc < 0) { - break; - } - if (entry->name[0] == 0) { - break; - } - printk("%s %d ",entry->name,entry->size); - - } - if (rc < 0) { - // LOG_ERR("directory read error (%d)", rc); - } - printk("\n"); - return count; -} - int move_read_pointer(uint8_t num) { char *read_ptr = generate_new_audio_header(num); snprintf(read_buffer, sizeof(read_buffer), "%s%s", disk_mount_pt, read_ptr); - struct fs_dirent entry; //check if the info file exists. if not, generate new info file +// free(read_ptr); + struct fs_dirent entry; int res = fs_stat(&read_buffer,&entry); if (res) { printk("invalid file\n"); @@ -79,11 +51,21 @@ int move_read_pointer(uint8_t num) { } int move_write_pointer(uint8_t num) { - char *write_ptr = generate_new_audio_header(num); - snprintf(write_buffer, sizeof(write_buffer), "%s%s", disk_mount_pt, write_ptr); - return 0; + char *write_ptr = generate_new_audio_header(num); + snprintf(write_buffer, sizeof(write_buffer), "%s%s", disk_mount_pt, write_ptr); + struct fs_dirent entry; + int res = fs_stat(&write_buffer,&entry); + if (res) { + printk("invalid file\n"); + + return -1; + } + k_free(write_ptr); + return 0; } +uint32_t file_num_array[20]; + int mount_sd_card(void) { uint64_t memory_size_mb; @@ -92,11 +74,13 @@ int mount_sd_card(void) static const char *disk_pdrv = "SD"; int err = disk_access_init(disk_pdrv); printk("disk_access_init: %d\n", err); - if (err == -116) { + if (err) { k_msleep(2000); - disk_access_init(disk_pdrv); + err = disk_access_init(disk_pdrv); + if (err) { + return -1; + } } - mount_point.mnt_point = "/SD:"; int res = fs_mount(&mount_point); @@ -109,7 +93,6 @@ int mount_sd_card(void) res = fs_mkdir("/SD:/audio"); if (res == FR_OK) { printk("audio directory created successfully\n"); - initialize_audio_file(0); } else if (res == FR_EXIST) { printk("audio directory already exists\n"); @@ -120,27 +103,36 @@ int mount_sd_card(void) struct fs_dir_t zdp; fs_dir_t_init(&zdp); - res = fs_opendir(&zdp,"/SD:/audio"); - printk("result of opendir: %d\n",res); - - if (zdp.mp == NULL) { - printk("mp is null \n"); + err = fs_opendir(&zdp,"/SD:/audio"); + if (err) { + printk("error while opening directory \n",err); + return -1; } + printk("result of opendir: %d\n",err); struct fs_dirent entry_; - file_count = get_directory_item_count(&zdp,&entry_)-1; + + file_count =get_next_item(&zdp, &entry_); + if (file_count < 0) { + printk(" error getting file count\n"); + return -1; + } fs_closedir(&zdp); - - - printk("current num files: %d\n",file_count); file_count++; + printk("new num files: %d\n",file_count); initialize_audio_file(file_count); - - move_write_pointer(file_count); - move_read_pointer(file_count-1); - + err = move_write_pointer(file_count); + if (err) { + printk("erro while moving the write pointer\n"); + return -1; + } + move_read_pointer(file_count); + if (err) { + printk("error while moving the reader pointer\n"); + return -1; + } struct fs_dirent entry; //check if the info file exists. if not, generate new info file const char *info_path = "/SD:/info.txt"; @@ -234,6 +226,7 @@ int initialize_audio_file(uint8_t num) { if (header == NULL) { return -1; } + k_free(header); create_file(header); return 0; } @@ -280,4 +273,28 @@ char* generate_new_audio_header(uint8_t num) { ptr_[13] = '\0'; return ptr_; +} + +int get_next_item(struct fs_dir_t *zdp, struct fs_dirent *entry) { + if (zdp->mp->fs->readdir(zdp, entry) ) { + return -1; + } + if (entry->name[0] == 0) { + return 0; + } + int count = 0; + file_num_array[count] = entry->size; + printk("file numarray %d %d \n",count,file_num_array[count]); + printk("file name is %s \n", entry->name); + count++; + while (zdp->mp->fs->readdir(zdp, entry) == 0 ) { + if (entry->name[0] == 0 ) { + break; + } + file_num_array[count] = entry->size; + printk("file numarray %d %d \n",count,file_num_array[count]); + printk("file name is %s \n", entry->name); + count++; + } + return count; } \ No newline at end of file diff --git a/Friend/firmware/firmware_v1.0/src/speaker.c b/Friend/firmware/firmware_v1.0/src/speaker.c index 84a8d31f8..60c3a7b2a 100644 --- a/Friend/firmware/firmware_v1.0/src/speaker.c +++ b/Friend/firmware/firmware_v1.0/src/speaker.c @@ -27,10 +27,9 @@ static struct device *speaker; static uint16_t current_length; static uint16_t offset; int speaker_init() { - const struct device *mic = device_get_binding("I2S_0"); - speaker = mic; - if (!device_is_ready(mic)) { - LOG_ERR("Speaker device is not supported : %s", mic->name); + const struct device *speaker = device_get_binding("I2S_0"); + if (!device_is_ready(speaker)) { + LOG_ERR("Speaker device is not supported : %s", speaker->name); return 0; } struct i2s_config config = { @@ -44,7 +43,7 @@ int speaker_init() { .block_size = MAX_BLOCK_SIZE,/* size of ONE memory block in bytes */ .timeout = -1, /* Number of milliseconds to wait in case Tx queue is full or RX queue is empty, or 0, or SYS_FOREVER_MS */ }; - int err = i2s_configure(mic, I2S_DIR_TX, &config); + int err = i2s_configure(speaker, I2S_DIR_TX, &config); if (err < 0) { LOG_INF("Failed to configure Microphone (%d)", err); return 0; diff --git a/Friend/firmware/firmware_v1.0/src/storage.c b/Friend/firmware/firmware_v1.0/src/storage.c index 35cc5cacc..27e043839 100644 --- a/Friend/firmware/firmware_v1.0/src/storage.c +++ b/Friend/firmware/firmware_v1.0/src/storage.c @@ -6,10 +6,8 @@ #include #include #include -#include "config.h" #include "utils.h" #include "btutils.h" -#include "speaker.h" #include "sdcard.h" #include #include @@ -32,9 +30,8 @@ K_THREAD_STACK_DEFINE(storage_stack, 2048); static struct k_thread storage_thread; extern uint8_t file_count; - +extern uint32_t file_num_array[20]; void broadcast_storage_packet(struct k_work *work_item); -K_WORK_DELAYABLE_DEFINE(storage_work, broadcast_storage_packet); static struct bt_gatt_attr storage_service_attr[] = { BT_GATT_PRIMARY_SERVICE(&storage_service_uuid), @@ -70,9 +67,13 @@ static void storage_config_changed_handler(const struct bt_gatt_attr *attr, uint static ssize_t storage_read_characteristic(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { k_msleep(10); - char amount[1] = {file_count}; + // char amount[1] = {file_count}; + uint32_t amount[20] = {0}; + for (int i = 0; i < file_count; i++) { + amount[i] = file_num_array[i]; + } - ssize_t result = bt_gatt_attr_read(conn, attr, buf, len, offset, amount, sizeof(amount)); + ssize_t result = bt_gatt_attr_read(conn, attr, buf, len, offset, amount, file_count * sizeof(uint32_t)); return result; } @@ -98,31 +99,34 @@ static uint8_t current_packet_size = 0; static uint8_t tx_buffer_size = 0; -static uint8_t current_read_num = 2; +static uint8_t current_read_num = 1; uint32_t remaining_length = 0; -static void setup_storage_tx(void) { +static int setup_storage_tx(void) { transport_started= (uint8_t)0; offset = 0; int res = move_read_pointer(current_read_num); if (res) { - LOG_ERR("bad pointer"); + printk("bad pointer\n"); transport_started = 0; - current_read_num++; + // current_read_num++; + current_read_num = 1; remaining_length = 0; + return -1; } else { if ((uint32_t)get_file_size(current_read_num) == 0 ) { - LOG_ERR("bad file size, moving again..."); + // LOG_ERR("bad file size, moving again..."); current_read_num++; move_read_pointer(current_read_num); } - LOG_INF("current read ptr %d",current_read_num); + printk("current read ptr %d\n",current_read_num); remaining_length = get_file_size(current_read_num); LOG_INF("remaining length: %d",remaining_length); } + return 0; } @@ -140,12 +144,6 @@ static void write_to_gatt(struct bt_conn *conn) { offset = offset + packet_size; remaining_length = remaining_length - OPUS_ENTRY_LENGTH; index++; - - // printk("current remaining length: %d\n",remaining_length); - // for (int i = 0 ; i < 103; i ++) { - // printk("%d ",storage_write_buffer[i]); - // } - // printk("\n"); int err = bt_gatt_notify(conn, &storage_service.attrs[1], &storage_write_buffer,packet_size+3); } @@ -171,10 +169,15 @@ void storage_write(void) { transport_started = 0; if (remaining_length == 0) { - LOG_INF("done. attempting to download more files"); + printk("done. attempting to download more files\n"); + // current_read_num++; k_sleep(K_MSEC(10)); - // setup_storage_tx(); + // int res = setup_storage_tx(); + // if (res) { + + // printk("Error occuring while moving pointers. Exiting..\n"); + // } } diff --git a/Friend/firmware/firmware_v1.0/src/transport.c b/Friend/firmware/firmware_v1.0/src/transport.c index 96a2a8f66..16b91e090 100644 --- a/Friend/firmware/firmware_v1.0/src/transport.c +++ b/Friend/firmware/firmware_v1.0/src/transport.c @@ -23,6 +23,7 @@ LOG_MODULE_REGISTER(transport, CONFIG_LOG_DEFAULT_LEVEL); extern bool is_connected; extern bool storage_is_on; extern uint8_t file_count; +extern uint32_t file_num_array[20]; struct bt_conn *current_connection = NULL; uint16_t current_mtu = 0; uint16_t current_package_index = 0; @@ -30,6 +31,7 @@ uint16_t current_package_index = 0; // Internal // + static ssize_t audio_data_write_handler(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf, uint16_t len, uint16_t offset, uint8_t flags); static struct bt_conn_cb _callback_references; @@ -594,9 +596,13 @@ void pusher(void) if (!valid && ( length < 100) && !storage_is_on) { bool result = write_to_storage(); + file_num_array[file_count-1] = get_file_size(file_count); + printk("file size for file count %d %d\n",file_count,file_num_array[file_count-1]); + if (result) { + // if (get_file_size(9) > MAX_AUDIO_FILE_SIZE) { // printk("Audio file size limit reached, making new file\n"); // // make_and_rebase_audio_file(get_info_file_length()+1); diff --git a/Friend/firmware/testing/decode_audio.py b/Friend/firmware/testing/decode_audio.py new file mode 100644 index 000000000..2a0f1a967 --- /dev/null +++ b/Friend/firmware/testing/decode_audio.py @@ -0,0 +1,39 @@ +import opuslib +import numpy as np +import wave +opus_decoder = opuslib.Decoder(16000, 1) +pcm_data = bytearray() +f=[] +count = 0 +with open("my_file.txt", "rb") as binary_file: + info_char = binary_file.read() + # print(len(info_char)) + count = int(len(info_char) / 103) + + + for i in range(0,count): + sample_frame = info_char[i*103:(i+1)*103] + amount = int(sample_frame[3]) + frame_to_decode = bytes(list(sample_frame[4:4+amount])) + print(frame_to_decode) + print(len(frame_to_decode)) + f.append(frame_to_decode) + print(np.frombuffer(frame_to_decode,dtype=np.uint8)) + # print(i) + opus_frame = opus_decoder.decode(bytes(frame_to_decode), 160,decode_fec=False) + + + # for frame in f: + # try: + # decoded_frame = opus_decoder.decode(bytes(frame), 960) + # pcm_data.extend(decoded_frame) + # except Exception as e: + # print(f"Error decoding frame: {e}") + # count+=1 + + # with wave.open('decoded_audio.wav', 'wb') as wav_file: + # wav_file.setnchannels(1) # Mono + # wav_file.setsampwidth(2) # 16-bit + # wav_file.setframerate(16000) # Sample rate + # wav_file.writeframes(pcm_data) +# print(count) diff --git a/Friend/firmware/testing/get_audio_file.py b/Friend/firmware/testing/get_audio_file.py index 26bbd69b0..39988089b 100644 --- a/Friend/firmware/testing/get_audio_file.py +++ b/Friend/firmware/testing/get_audio_file.py @@ -32,26 +32,14 @@ async def main(): async def on_notify(sender: bleak.BleakGATTCharacteristic, data: bytearray): # Write bytes to file - # binary_file.write(data) + binary_file.write(data) global count global done + print(len(data)) amount_to_append = data[3] audio_frames.append(data[4:data[3]+4]) count +=1 - print(np.frombuffer(data[4:data[3]+4],dtype=np.uint8)) - if (count > 700) and not done: - done=True - for frame in audio_frames: - try: - decoded_frame = decoder.decode(bytes(frame), 320) - pcm_data.extend(decoded_frame) - except Exception as e: - print(f"Error decoding frame:{e} ") - with wave.open('out.wav', "wb") as wf: - wf.setnchannels(1) - wf.setsampwidth(2) - wf.setframerate(16000) - wf.writeframes(pcm_data) + print(np.frombuffer(data,dtype=np.uint8)) stuff = await client.start_notify(storage_uuid, on_notify) diff --git a/Friend/firmware/testing/get_info_list.py b/Friend/firmware/testing/get_info_list.py index ae3d86fc9..dce30550c 100644 --- a/Friend/firmware/testing/get_info_list.py +++ b/Friend/firmware/testing/get_info_list.py @@ -21,7 +21,7 @@ async def main(): while(True): await asyncio.sleep(2.0) - print(np.frombuffer(r,dtype=np.uint8)) + print(np.frombuffer(r,dtype=np.uint32)) if __name__ == "__main__": From e9cbfa7d4a31c8337db1a09f807ad31696f7abe9 Mon Sep 17 00:00:00 2001 From: kevvz Date: Tue, 3 Sep 2024 21:36:48 -0700 Subject: [PATCH 12/12] added zephyr file --- .../firmware_v1.0/storage_build/zephyr.uf2 | Bin 0 -> 520192 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Friend/firmware/firmware_v1.0/storage_build/zephyr.uf2 diff --git a/Friend/firmware/firmware_v1.0/storage_build/zephyr.uf2 b/Friend/firmware/firmware_v1.0/storage_build/zephyr.uf2 new file mode 100644 index 0000000000000000000000000000000000000000..dafd2052c7bacd38cf096b8bb41096465bc960bb GIT binary patch literal 520192 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 zℑ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≠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

Pu&)cl zpYla)*VYKk#RVmuTh)vBm7u!~mg%1_;+OMJuCBGrg~azf+Nc%tD%jjM>Kht450%*R z3-9`T{c6fX)x*|D?KPWqCn5JyyUof1RNp4l+Do#r$E*jZNV@;!s9C*e#BwuKnI*hi zu0UPk+ximhO?|Q@@1!9PDGOPCjZALK$ogZ(`lA_Hf1b1G1xkGq3eaZWv#E^fAX;63 z2Pa*rtZ1pFEm2dRMV*ozCUrkMcpNz-N;<9bB?ad0R~_@JP$9}p*D)?FyYpX1gm~+*X0T;=v5P~42$1xI`5n%%&R=2PC* zXP`%DkInBi!v~%1o{*RaJ@0{j2fwdNNrrmg>VL26qu7o7tahgcwLf?!mmN@ER}9GF zf56lKR{Q@z2>-2N_;0uLe*Ql6HIpyAH*m8Db~I#GF6k_YBoo>CcP-<-kij2#!o|Cs zpF#Sw@wfAtSQW;J9}X?&ab{aS&tzrt%$#xJ(V-^Gxq{AidC)#fCZG4|_?h7Lo(gdM zIUm~y-;b>Pk-Og*V&+siQ5g*HBK6Dp&~wL$uMWM7XI%aKbKkiFnq&AlY|M-;P0%hR zZZ3l87@O8!J+g0V+H#0`@N2-g2>b-GxnHJ#L6VuK@SKgQ&*TL@LA)^_KV*VW(jV}D zJDTLs4~*k?@ETO5WpT%(flHEh+nB-)1NT&VDV-#{wV+Nk(qLN)PftixlMzS(RC8ID-7M?wftg%@U z-g!LRv1%(bYgH{>$@;ttL>b;dfAhXRVtCTCK-4i$ba1HuN$(s}_z#8fe<2M2XAg(^ zrm;`sq&<^ao4GZF)e;XyYQIlkPWx$rs9+S+&SB1H)=u+M{fZeq8IIlUMLPb>!kiA; zT3^0E3)L@^E&YzcOZY9&*H>(a3{bT{-Avg5f znXvy0{A&b_86q zO?~&n6>8fN3wy3g+(N|T)e9dIS}YOg(#z*NUy)=dQStVS6MWMkGe{Oeqt#eyV&bm5_+3$tfm8e94w>UII_Ukt;a_ABjQ+Ry0U1ySfZ4aP&7_;kOT=)S>t8hxj#DZZ>Bt7pKQ}ds2LHxIc;lD$2nevYiF=9A#@!~?=*;Yw+h)Vdz z4G;G}ck_saYs;Q<-52P6GvM<@b$z6W^fQsBb!lQ;zl=An(~AG>Yoo|cp%|aR-d7ii zz7Eff#?w^iqHJjumCm_XzZuFGmS`7t329EsMH+a_zd2v~g6Cf(?$I$wv0dAA`f!;d zntwr3nw1_JarkJU#u;s^myVI;&ZxU}{C!TP_#3IaJk1&HS28Nyj)e>&(W+aNVk6EH zW3PvvkI-EY(vP)GPuIL45j(rivMzm5ey2?T4mibAH71@NTlAj^;r~(?{w(`~#F@0> z`d}s{twqj9c}zSJ%Z8|~HZd?>?CjULUe(2l(}x9KDNc~+3}-zWCyo89Zh0NDp;Fu# zJj-~9p&Jo`r%jB`n7>(aA%6U{sVj&9rQN&lK2lC+UlKpy($}!!1eWG-dEEgm3^Fw3 zHgE4EWQtH)LkzPoDstjIsvM)|f{W27RNqtms&vY4^JHB6L-_yXNPGte57Hj@roNW)_IPsG7(xUzLuT z5~>;fn415x5dJTR;V=J^nXAgV+Q#fg#TJpc_n}QY#>t;XzUPd5({prNfa6^?3h`Ow z`gME$>MN`JWkp$Yp!b#Gvbv|yr*!rm@l+JCn3D&6l{K7EGqs_Iob*UV**72hVD@_>uLO#D3#7VD#w&oxZ?itWW$^Tw{!{c!~aL zjDy!t~1ipbzP&^bhrjXy|nr_p862Wdn)>Q@JdzOwrI6~?IYu(*pkSXM{x z9(tF_WIIahNDj>jv#T!9dk?G?8+tCk`z>MsDPJ(A@aIDKZx6%&E%0A5LymnzPtUuy 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 literal 0 HcmV?d00001