From fc1c3bce2696214c6c065be853be846cc2a2b792 Mon Sep 17 00:00:00 2001 From: Miller Puckette Date: Sat, 10 Jul 2021 21:37:02 -0700 Subject: [PATCH] pd working using low-level i2s audio driver, output only so far. --- CMakeLists.txt | 2 +- README.rst | 17 +-- main/CMakeLists.txt | 10 +- main/espd.c | 317 +++++++++++++++++++++++++++++++++++++++ main/fifostream.c | 200 ------------------------- main/fifostream.h | 57 ------- main/pdmain.c | 98 ++++++++---- main/weasel.c | 354 -------------------------------------------- 8 files changed, 395 insertions(+), 660 deletions(-) create mode 100644 main/espd.c delete mode 100644 main/fifostream.c delete mode 100644 main/fifostream.h delete mode 100644 main/weasel.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 36858b7..2919c57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,4 +4,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{ADF_PATH}/CMakeLists.txt) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(bt_spp_acceptor_demo) +project(espd) diff --git a/README.rst b/README.rst index 816fcbb..2cadca2 100644 --- a/README.rst +++ b/README.rst @@ -1,16 +1,3 @@ -qESP-IDF BT-SPP-ACCEPTOR demo -====================== +enter menuconfig "Component config", choose "Bluetooth" +enter menu Bluetooth, choose "Classic Bluetooth" and "SPP Profile" -Demo of SPP acceptor role - -This is the demo for user to use ESP_APIs to create a SPP acceptor. - -Options choose step: - 1. make menuconfig. - 2. enter menuconfig "Component config", choose "Bluetooth" - 3. enter menu Bluetooth, choose "Classic Bluetooth" and "SPP Profile" - 4. choose your options. - -Then set SPP_SHOW_MODE as SPP_SHOW_DATA or SPP_SHOW_SPEED in code(should be same with bt_spp_initator). - -After the program started, bt_spp_initator will connect it and send data. diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 18fc33b..70d3dd0 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,4 +1,4 @@ -set(COMPONENT_SRCS "weasel.c fifostream.c pdmain.c \ +set(COMPONENT_SRCS "espd.c pdmain.c \ ../pd/src/g_canvas.c \ ../pd/src/g_graph.c \ ../pd/src/g_text.c \ @@ -25,7 +25,12 @@ set(COMPONENT_SRCS "weasel.c fifostream.c pdmain.c \ ../pd/src/d_osc.c \ ../pd/src/d_ctl.c \ ../pd/src/d_arithmetic.c \ +../pd/src/d_array.c \ ../pd/src/d_dac.c \ +../pd/src/d_delay.c \ +../pd/src/d_filter.c \ +../pd/src/d_math.c \ +../pd/src/d_misc.c \ ../pd/src/x_arithmetic.c \ ../pd/src/x_connective.c \ ../pd/src/x_interface.c \ @@ -37,6 +42,9 @@ set(COMPONENT_SRCS "weasel.c fifostream.c pdmain.c \ ../pd/src/x_scalar.c \ ../pd/src/x_text.c \ ../pd/src/x_list.c \ +../pd/src/x_vexp.c \ +../pd/src/x_vexp_fun.c \ +../pd/src/x_vexp_if.c \ ") diff --git a/main/espd.c b/main/espd.c new file mode 100644 index 0000000..f60e26e --- /dev/null +++ b/main/espd.c @@ -0,0 +1,317 @@ +/* + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "esp_log.h" +#include "audio_element.h" +#include "audio_pipeline.h" +#include "audio_event_iface.h" +#include "audio_mem.h" +#include "audio_common.h" +#include "i2s_stream.h" +#include "mp3_decoder.h" +#include "filter_resample.h" +#include "board.h" +#include "esp_bt.h" +#include "esp_bt_main.h" +#include "esp_gap_bt_api.h" +#include "esp_bt_device.h" +#include "esp_spp_api.h" +#include "esp_peripherals.h" +#include "periph_sdcard.h" +#include "nvs.h" +#include "nvs_flash.h" + +static const char *TAG = "ESPD"; +#define TEST_I2S_NUM I2S_NUM_0 + +extern void pdmain_tick( void); +void pdmain_init( void); + +void bt_init( void); +void sd_init( void); + +#define INCHANS 1 +#define OUTCHANS 1 +#define BLKSIZE 64 +float soundin[OUTCHANS * BLKSIZE], soundout[OUTCHANS * BLKSIZE]; + +void senddacs( void) +{ + int i, ret; + size_t written; + short poodle[OUTCHANS * BLKSIZE]; + + for (i = 0; i < BLKSIZE; i+= OUTCHANS) + { + int ch1 = 32767*soundout[i]; + if (ch1 > 32767) + ch1 = 32767; + else if (ch1 < -32768) + ch1 = -32768; + poodle[i] = ch1; + /* + ch1 = 32767*soundout[BLKSIZE+i]; + if (ch1 > 32767) + ch1 = 32767; + else if (ch1 < -32768) + ch1 = -32768; + poodle[i+1] = ch2; */ + + soundout[i] = 0; + } + + ret = i2s_write(TEST_I2S_NUM, poodle, sizeof(poodle), &written, + portMAX_DELAY); + if (ret != ESP_OK) + ESP_LOGE(TAG, "error writing"); +} + +void pdmain_print( const char *s) +{ + char y[80]; + strncpy(y, s, 79); + y[79]=0; + ESP_LOGI(TAG, "%s", y); +} + +void trymem(int foo); + +void app_main(void) +{ + i2s_config_t i2s_cfg = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX, + .sample_rate = 48000, + .bits_per_sample = 16, + /* .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, */ + .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, + .communication_format = I2S_COMM_FORMAT_I2S, + .dma_buf_count = 3, + .dma_buf_len = 300, + .use_apll = 1, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2, + }; + i2s_pin_config_t i2s_pin_cfg = {0}; + int zz = 0, ret; + + pdmain_init(); + + esp_log_level_set("*", ESP_LOG_WARN); + esp_log_level_set(TAG, ESP_LOG_INFO); + ESP_LOGI(TAG, "[ 1 ] Start audio codec chip"); + + audio_board_handle_t board_handle = audio_board_init(); + audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START); + + i2s_driver_install(I2S_NUM_0, &i2s_cfg, 0, NULL); + get_i2s_pins(I2S_NUM_0, &i2s_pin_cfg); + i2s_set_pin(I2S_NUM_0, &i2s_pin_cfg); + i2s_mclk_gpio_select(I2S_NUM_0, GPIO_NUM_0); + + bt_init(); + sd_init(); + + ESP_LOGI(TAG, "[ 2 ] now write some shit"); + + while (1) + { + /* if (!((zz++)%1000)) + { + trymem(5); + ESP_LOGI(TAG, "tick"); + } */ + pdmain_tick(); + senddacs(); + } + +} + +/* -------------------- bluetooth and SD card ------------------ */ + +void pd_dispatch_bt(char *data, size_t size); + +static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_CB; +static const esp_spp_sec_t sec_mask = ESP_SPP_SEC_AUTHENTICATE; +static const esp_spp_role_t role_slave = ESP_SPP_ROLE_SLAVE; + +static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) +{ + switch (event) { + case ESP_SPP_INIT_EVT: + ESP_LOGI(TAG, "ESP_SPP_INIT_EVT"); + esp_bt_dev_set_device_name("pure_data"); + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); + esp_spp_start_srv(sec_mask,role_slave, 0, "pd_server"); + break; + case ESP_SPP_DISCOVERY_COMP_EVT: + ESP_LOGI(TAG, "ESP_SPP_DISCOVERY_COMP_EVT"); + break; + case ESP_SPP_OPEN_EVT: + ESP_LOGI(TAG, "ESP_SPP_OPEN_EVT"); + break; + case ESP_SPP_CLOSE_EVT: + ESP_LOGI(TAG, "ESP_SPP_CLOSE_EVT"); + break; + case ESP_SPP_START_EVT: + ESP_LOGI(TAG, "ESP_SPP_START_EVT"); + break; + case ESP_SPP_CL_INIT_EVT: + ESP_LOGI(TAG, "ESP_SPP_CL_INIT_EVT"); + break; + case ESP_SPP_DATA_IND_EVT: + + if (param->data_ind.len > 2) + ESP_LOGI(TAG, "ESP_SPP_DATA_IND_EVT len=%d handle=%d", + param->data_ind.len, param->data_ind.handle); + + pd_dispatch_bt((char *)(param->data_ind.data), param->data_ind.len); + + break; + case ESP_SPP_CONG_EVT: + ESP_LOGI(TAG, "ESP_SPP_CONG_EVT"); + break; + case ESP_SPP_WRITE_EVT: + ESP_LOGI(TAG, "ESP_SPP_WRITE_EVT"); + break; + case ESP_SPP_SRV_OPEN_EVT: + ESP_LOGI(TAG, "ESP_SPP_SRV_OPEN_EVT"); + break; + default: + break; + } +} + +void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + switch (event) { + case ESP_BT_GAP_AUTH_CMPL_EVT:{ + if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { + ESP_LOGI(TAG, "authentication success: %s", param->auth_cmpl.device_name); + esp_log_buffer_hex(TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); + } else { + ESP_LOGE(TAG, "authentication failed, status:%d", param->auth_cmpl.stat); + } + break; + } + case ESP_BT_GAP_PIN_REQ_EVT:{ + ESP_LOGI(TAG, "ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit); + if (param->pin_req.min_16_digit) { + ESP_LOGI(TAG, "Input pin code: 0000 0000 0000 0000"); + esp_bt_pin_code_t pin_code = {0}; + esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code); + } else { + ESP_LOGI(TAG, "Input pin code: 1234"); + esp_bt_pin_code_t pin_code; + pin_code[0] = '1'; + pin_code[1] = '2'; + pin_code[2] = '3'; + pin_code[3] = '4'; + esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code); + } + break; + } + +#if (CONFIG_BT_SSP_ENABLED == true) + case ESP_BT_GAP_CFM_REQ_EVT: + ESP_LOGI(TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); + esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); + break; + case ESP_BT_GAP_KEY_NOTIF_EVT: + ESP_LOGI(TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); + break; + case ESP_BT_GAP_KEY_REQ_EVT: + ESP_LOGI(TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); + break; +#endif + + default: { + ESP_LOGI(TAG, "event: %d", event); + break; + } + } + return; +} + +void bt_init( void) +{ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK( ret ); + + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE)); + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { + ESP_LOGE(TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { + ESP_LOGE(TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bluedroid_init()) != ESP_OK) { + ESP_LOGE(TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bluedroid_enable()) != ESP_OK) { + ESP_LOGE(TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bt_gap_register_callback(esp_bt_gap_cb)) != ESP_OK) { + ESP_LOGE(TAG, "%s gap register failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + + if ((ret = esp_spp_register_callback(esp_spp_cb)) != ESP_OK) { + ESP_LOGE(TAG, "%s spp register failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + + if ((ret = esp_spp_init(esp_spp_mode)) != ESP_OK) { + ESP_LOGE(TAG, "%s spp init failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + +#if (CONFIG_BT_SSP_ENABLED == true) + /* Set default parameters for Secure Simple Pairing */ + esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; + esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; + esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); +#endif + + /* + * Set default parameters for Legacy Pairing + * Use variable pin, input pin code when pairing + */ + esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; + esp_bt_pin_code_t pin_code; + esp_bt_gap_set_pin(pin_type, 0, pin_code); +} + +void sd_init( void) +{ + /* initialize SD card */ + ESP_LOGI(TAG, "[ 1 ] Mount sdcard"); + // Initialize peripherals management + esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG(); + esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg); + + // Initialize SD Card peripheral + audio_board_sdcard_init(set, SD_MODE_1_LINE); +} diff --git a/main/fifostream.c b/main/fifostream.c deleted file mode 100644 index 283a45b..0000000 --- a/main/fifostream.c +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// All rights reserved. - -#include -#include "esp_log.h" -#include "audio_error.h" -#include "audio_mem.h" -#include "audio_element.h" -#include "fifostream.h" -#include "audio_type_def.h" -static const char *TAG = "fifostream"; - -#define CHANS 2 -#define INCHANS CHANS -#define OUTCHANS CHANS -#define BLKSIZE 64 -#define BLK_BYTES (BLKSIZE*CHANS*sizeof(short)) - -extern void pdmain_tick( void); - -typedef struct fifostream { - int samplerate; - int channel; - short *s_buf; - int byte_num; - int at_eof; -} fifostream_t; - -static esp_err_t fifostream_destroy(audio_element_handle_t self) -{ - fifostream_t *fifostream = (fifostream_t *)audio_element_getdata(self); - audio_free(fifostream); - return ESP_OK; -} - -static esp_err_t fifostream_open(audio_element_handle_t self) -{ - ESP_LOGD(TAG, "fifostream_open"); - fifostream_t *fifostream = (fifostream_t *)audio_element_getdata(self); - audio_element_info_t info = {0}; - audio_element_getinfo(self, &info); - if (info.sample_rates - && info.channels) { - fifostream->samplerate = info.sample_rates; - fifostream->channel = info.channels; - } - fifostream->at_eof = 0; - fifostream->s_buf = (short *)calloc(sizeof(short), BLK_BYTES/sizeof(short)); - if (fifostream->s_buf == NULL) { - ESP_LOGE(TAG, "calloc buffer failed. (line %d)", __LINE__); - return ESP_ERR_NO_MEM; - } - memset(fifostream->s_buf, 0, BLK_BYTES); - - return ESP_OK; -} - -static esp_err_t fifostream_close(audio_element_handle_t self) -{ - ESP_LOGD(TAG, "fifostream_close"); - fifostream_t *fifostream = (fifostream_t *)audio_element_getdata(self); - if (fifostream->s_buf == NULL) { - audio_free(fifostream->s_buf); - fifostream->s_buf = NULL; - } - return ESP_OK; -} - -float soundin[OUTCHANS * BLKSIZE], soundout[OUTCHANS * BLKSIZE]; - -#if 0 /* better one that doesn't work for some reason */ -static int fifostream_process(audio_element_handle_t self, char *in_buffer, - int in_len) -{ - static int cumsamps = 0; - fifostream_t *fifostream = (fifostream_t *)audio_element_getdata(self); - int ret = 0; - int r_size = (fifostream->at_eof ? 0 : - audio_element_input(self, (char *)fifostream->s_buf, BLK_BYTES)); - if (r_size >= BLK_BYTES) - { - int i, nsamps = BLKSIZE; - fifostream->byte_num += BLK_BYTES; - - for (i = 0; i < BLKSIZE; i+= 2) - { - soundin[i] = fifostream->s_buf[i]/32768;; - soundin[BLKSIZE+i] = fifostream->s_buf[i+1]/32768; - } - pdmain_tick(); - for (i = 0; i < BLKSIZE; i+= 2) - { - int ch1 = 32767*soundout[i], ch2 = 32767*soundout[BLKSIZE+i]; - if (ch1 > 32767) - ch1 = 32767; - else if (ch1 < -32768) - ch1 = -32768; - if (ch2 > 32767) - ch2 = 32767; - else if (ch2 < -32768) - ch2 = -32768; - fifostream->s_buf[i] = (short)ch1; - fifostream->s_buf[i+1] = (short)ch2; - } - ret = audio_element_output(self, (char *)fifostream->s_buf, BLK_BYTES); - } - else - { - fifostream->at_eof = 1; - ret = 0; - } - return ret; -} -#endif - -#if 1 -static int fifostream_process(audio_element_handle_t self, char *in_buffer, int in_len) -{ - static int cumsamps = 0; - fifostream_t *fifostream = (fifostream_t *)audio_element_getdata(self); - int ret = 0; - int r_size = 0; - if (fifostream->at_eof == 0) { - r_size = audio_element_input(self, (char *)fifostream->s_buf, BLK_BYTES); - } - if (r_size > 0) { - if (r_size != BLK_BYTES) { - fifostream->at_eof = 1; - } - fifostream->byte_num += r_size; - { - int i, nsamps = r_size/(2*sizeof(short)); - static int phase; - if (nsamps * 2 * sizeof(short) != r_size) - ESP_LOGE("WOMBAT", "odd sample frame size %d", r_size); - for (i = 0; i < nsamps; i++) - { - int ch1 = 32767*soundout[i], ch2 = 32767*soundout[BLKSIZE+i]; - if (ch1 > 32767) - ch1 = 32767; - else if (ch1 < -32768) - ch1 = -32768; - if (ch2 > 32767) - ch2 = 32767; - else if (ch2 < -32768) - ch2 = -32768; - soundin[phase] = fifostream->s_buf[2*i]/32768; - fifostream->s_buf[2*i] = ch1; - soundin[BLKSIZE+phase] = fifostream->s_buf[2*i+1]/32768; - fifostream->s_buf[2*i+1] = ch2; - phase++; - if (phase == BLKSIZE) - { - pdmain_tick(); - phase = 0; - } - } - } - ret = audio_element_output(self, (char *)fifostream->s_buf, BLK_BYTES); - } else { - ret = r_size; - } - return ret; -} -#endif - -audio_element_handle_t fifostream_init(fifostream_cfg_t *config) -{ - if (config == NULL) { - ESP_LOGE(TAG, "config is NULL. (line %d)", __LINE__); - return NULL; - } - fifostream_t *fifostream = audio_calloc(1, sizeof(fifostream_t)); - AUDIO_MEM_CHECK(TAG, fifostream, return NULL); - if (fifostream == NULL) { - ESP_LOGE(TAG, "audio_calloc failed for fifostream. (line %d)", __LINE__); - return NULL; - } - audio_element_cfg_t cfg = DEFAULT_AUDIO_ELEMENT_CONFIG(); - cfg.destroy = fifostream_destroy; - cfg.process = fifostream_process; - cfg.open = fifostream_open; - cfg.close = fifostream_close; - cfg.buffer_len = 0; - cfg.tag = "fifostream"; - cfg.task_stack = config->task_stack; - cfg.task_prio = config->task_prio; - cfg.task_core = config->task_core; - cfg.out_rb_size = config->out_rb_size; - cfg.stack_in_ext = config->stack_in_ext; - audio_element_handle_t el = audio_element_init(&cfg); - AUDIO_MEM_CHECK(TAG, el, {audio_free(fifostream); return NULL;}); - fifostream->samplerate = config->samplerate; - fifostream->channel = config->channel; - audio_element_setdata(el, fifostream); - audio_element_info_t info = {0}; - audio_element_setinfo(el, &info); - ESP_LOGD(TAG, "fifostream_init"); - return el; -} diff --git a/main/fifostream.h b/main/fifostream.h deleted file mode 100644 index 3697daa..0000000 --- a/main/fifostream.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// All rights reserved. - -#ifndef _FIFOSTREAM_H_ -#define _FIFOSTREAM_H_ - -#include "esp_err.h" -#include "audio_element.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * @brief Configuration - */ -typedef struct fifostream_cfg { - int samplerate; /*!< Audio sample rate (in Hz)*/ - int channel; /*!< Number of audio channels (Mono=1, Dual=2) */ - int *set_gain; /*!< Equalizer gain */ - int out_rb_size; /*!< Size of output ring buffer */ - int task_stack; /*!< Task stack size */ - int task_core; /*!< Task running in core...*/ - int task_prio; /*!< Task priority*/ - bool stack_in_ext; /*!< Try to allocate stack in external memory */ -} fifostream_cfg_t; - -#define FIFOSTREAM_TASK_STACK (20000) -#define FIFOSTREAM_TASK_CORE (0) -#define FIFOSTREAM_TASK_PRIO (5) -#define FIFOSTREAM_RINGBUFFER_SIZE (8 * 1024) - -/** -* @note `set_value_gain` is defined in c file. -* values is {-13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13}; -*/ -extern int set_value_gain[]; - -#define DEFAULT_FIFOSTREAM_CONFIG() { \ - .samplerate = 48000, \ - .channel = 1, \ - .set_gain = set_value_gain, \ - .out_rb_size = FIFOSTREAM_RINGBUFFER_SIZE, \ - .task_stack = FIFOSTREAM_TASK_STACK, \ - .task_core = FIFOSTREAM_TASK_CORE, \ - .task_prio = FIFOSTREAM_TASK_PRIO, \ - .stack_in_ext = true, \ - } - -audio_element_handle_t fifostream_init(fifostream_cfg_t *config); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/main/pdmain.c b/main/pdmain.c index ebd4eeb..446923f 100644 --- a/main/pdmain.c +++ b/main/pdmain.c @@ -10,6 +10,7 @@ #include #include #include +#include void pd_init(void); void glob_open(t_pd *ignore, t_symbol *name, t_symbol *dir, t_floatarg f); @@ -29,22 +30,18 @@ canvas 274 279 752 643 12;\n\ #endif static const char patchfile[] = "\ -canvas 0 50 604 482 12;\n\ -#X obj 179 99 r foo;\n\ -#X obj 179 124 osc~ 880;\n\ -#X obj 179 149 dac~ 1;\n\ -#X obj 257 127 osc~ 880;\n\ -#X obj 257 102 r foo2;\n\ -#X obj 257 151 dac~ 2;\n\ +canvas 0 50 450 300 12;\n\ +#X obj 190 104 loadbang;\n\ +#X msg 190 129 \; pd dsp 1;\n\ +#X obj 118 123 dac~ 1;\n\ +#X obj 118 98 osc~ 440;\n\ #X connect 0 0 1 0;\n\ -#X connect 1 0 2 0;\n\ -#X connect 3 0 5 0;\n\ -#X connect 4 0 3 0;\n\ +#X connect 3 0 2 0;\n\ "; -static void trymem(int foo) +void trymem(int foo) { -#if 0 +#if 1 int i; char msg[80]; for (i = 1; i < 500; i++) @@ -74,10 +71,19 @@ void pd_dispatch_bt(char *data, size_t size) void pd_poll_bt( void) { + int lastchar; static t_binbuf *b; if (!b) + { b = binbuf_new(); - if (pd_bt_size) + post("new binbuf %x", b); + } + /* only interpret this text if terminated by a semicolon */ + lastchar = pd_bt_size-1; + while (lastchar >= 0 && isspace((int)(pd_bt_buf[lastchar]))) + lastchar--; + if (lastchar >= 3 && pd_bt_buf[lastchar] == ';' && + pd_bt_buf[lastchar-1] != '\\') { binbuf_text(b, pd_bt_buf, pd_bt_size); binbuf_eval(b, 0, 0, 0); @@ -87,41 +93,35 @@ void pd_poll_bt( void) } extern float soundin[], soundout[]; - +void canvas_start_dsp( void); void pdmain_init( void) { t_binbuf *b; sys_printhook = pdmain_print; - trymem(1); // 111 + trymem(1); pd_init(); - trymem(2); // 47 + trymem(2); STUFF->st_dacsr = sys_getsr(); STUFF->st_soundout = soundout; STUFF->st_soundin = soundin; - +#if 0 b = binbuf_new(); glob_setfilename(0, gensym("main-patch"), gensym(".")); binbuf_text(b, patchfile, strlen(patchfile)); binbuf_eval(b, &pd_canvasmaker, 0, 0); canvas_loadbang((t_canvas *)s__X.s_thing); vmess(s__X.s_thing, gensym("pop"), "i", 0); - glob_setfilename(0, &s_, &s_); binbuf_free(b); +#endif } void pdmain_tick( void) { - static int initted; - if (!initted) - { - pdmain_init(); - initted = 1; - } - memset(soundout, 0, 128*sizeof(float)); + memset(soundout, 0, 64*sizeof(float)); pd_poll_bt(); sched_tick(); } @@ -132,9 +132,34 @@ t_class *glob_pdobject; static void glob_foo(void *dummy, t_floatarg f) { - post("foo %f", f); + trymem(0); } +static void glob_beginnew(void *dummy, t_symbol *pname, t_symbol *pdir) +{ + glob_setfilename(0, pname, pdir); + pd_bind(&pd_canvasmaker, &s__N); +} + +static void glob_endnew(void *dummy) +{ + pd_unbind(&pd_canvasmaker, &s__N); + if ((t_canvas *)s__X.s_thing) + { + canvas_loadbang((t_canvas *)s__X.s_thing); + vmess(s__X.s_thing, gensym("pop"), "i", 0); + } + glob_setfilename(0, &s_, &s_); +} + +static void glob_close(void *dummy, t_symbol *pname) +{ + t_pd *c = pd_findbyclass(pname, canvas_class); + if (c) + pd_free(c); + } + + void glob_dsp(void *dummy, t_symbol *s, int argc, t_atom *argv); void glob_init( void) @@ -145,6 +170,12 @@ void glob_init( void) A_GIMME, 0); class_addmethod(glob_pdobject, (t_method)glob_foo, gensym("foo"), A_DEFFLOAT, 0); + class_addmethod(glob_pdobject, (t_method)glob_beginnew, gensym("begin-new"), + A_SYMBOL, A_SYMBOL, 0); + class_addmethod(glob_pdobject, (t_method)glob_close, gensym("close"), + A_SYMBOL, 0); + class_addmethod(glob_pdobject, (t_method)glob_endnew, gensym("end-new"), + 0); pd_bind(&glob_pdobject, gensym("pd")); } @@ -209,7 +240,6 @@ void conf_init(void) g_guiconnect_setup(); g_scalar_setup(); g_template_setup(); - clone_setup(); m_pd_setup(); x_acoustics_setup(); x_interface_setup(); @@ -228,23 +258,25 @@ void conf_init(void) d_dac_setup(); d_ctl_setup(); d_osc_setup(); - trymem(11); -} - -/* d_arithmetic_setup(); d_array_setup(); + clone_setup(); d_delay_setup(); d_filter_setup(); d_math_setup(); d_misc_setup(); + expr_setup(); + trymem(11); +} + +/* g_traversal_setup(); */ /* ------- STUBS that do nothing ------------- */ int sys_get_outchannels(void) {return(2); } int sys_get_inchannels(void) {return(2); } -float sys_getsr( void) {return (44100);} +float sys_getsr( void) {return (48000);} int sys_getblksize(void) { return (DEFDACBLKSIZE); } int pd_compatibilitylevel = 100; @@ -323,6 +355,8 @@ void x_midi_newpdinstance( void) {} t_symbol *iemgui_raute2dollar(t_symbol *s) {return(s);} t_symbol *iemgui_dollar2raute(t_symbol *s) {return(s);} +t_class *clone_class; + /* --------------- m_sched.c -------------------- */ #define TIMEUNITPERMSEC (32. * 441.) #define TIMEUNITPERSECOND (TIMEUNITPERMSEC * 1000.) diff --git a/main/weasel.c b/main/weasel.c deleted file mode 100644 index 1d43a67..0000000 --- a/main/weasel.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include "nvs.h" -#include "nvs_flash.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "audio_pipeline.h" -#include "i2s_stream.h" -#include "board.h" -#include "fifostream.h" -#include "esp_bt.h" -#include "esp_bt_main.h" -#include "esp_gap_bt_api.h" -#include "esp_bt_device.h" -#include "esp_spp_api.h" - -#include "time.h" -#include "sys/time.h" - - -#define SPP_TAG "WOMBAT" -#define SPP_SERVER_NAME "SPP_SERVER" -#define EXCAMPLE_DEVICE_NAME "ESP_SPP_ACCEPTOR" -#define SPP_SHOW_DATA 0 -#define SPP_SHOW_SPEED 1 -#define SPP_SHOW_MODE SPP_SHOW_DATA /*Choose show mode: show data or speed*/ - -void pdmain_print( const char *s) -{ - ESP_LOGI("PD", "%s" , s); -} - -static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_CB; - -static struct timeval time_new, time_old; -static long data_num = 0; - -static const esp_spp_sec_t sec_mask = ESP_SPP_SEC_AUTHENTICATE; -static const esp_spp_role_t role_slave = ESP_SPP_ROLE_SLAVE; - -static void print_speed(void) -{ - float time_old_s = time_old.tv_sec + time_old.tv_usec / 1000000.0; - float time_new_s = time_new.tv_sec + time_new.tv_usec / 1000000.0; - float time_interval = time_new_s - time_old_s; - float speed = data_num * 8 / time_interval / 1000.0; - ESP_LOGI(SPP_TAG, "speed(%fs ~ %fs): %f kbit/s" , time_old_s, time_new_s, speed); - data_num = 0; - time_old.tv_sec = time_new.tv_sec; - time_old.tv_usec = time_new.tv_usec; -} - -extern int phaseinc; -void pd_dispatch_bt(char *data, size_t size); - -static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) -{ - switch (event) { - case ESP_SPP_INIT_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_INIT_EVT"); - esp_bt_dev_set_device_name(EXCAMPLE_DEVICE_NAME); - esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); - esp_spp_start_srv(sec_mask,role_slave, 0, SPP_SERVER_NAME); - break; - case ESP_SPP_DISCOVERY_COMP_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_DISCOVERY_COMP_EVT"); - break; - case ESP_SPP_OPEN_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_OPEN_EVT"); - break; - case ESP_SPP_CLOSE_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_CLOSE_EVT"); - break; - case ESP_SPP_START_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_START_EVT"); - break; - case ESP_SPP_CL_INIT_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_CL_INIT_EVT"); - break; - case ESP_SPP_DATA_IND_EVT: - - ESP_LOGI(SPP_TAG, "ESP_SPP_DATA_IND_EVT len=%d handle=%d", - param->data_ind.len, param->data_ind.handle); - esp_log_buffer_hex("",param->data_ind.data,param->data_ind.len); - { -#if 1 - pd_dispatch_bt((char *)(param->data_ind.data), - param->data_ind.len); -#else - char foo[80]; - int nfoo = (param->data_ind.len > 78 ? 78 : param->data_ind.len), i; - for (i = 0; i < nfoo; i++) - foo[i] = param->data_ind.data[i]; - foo[i] = 0; - ESP_LOGI(SPP_TAG, "%s", foo); - sscanf(foo, "%d%d", &i, &phaseinc); -#endif - } - - break; - case ESP_SPP_CONG_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_CONG_EVT"); - break; - case ESP_SPP_WRITE_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_WRITE_EVT"); - break; - case ESP_SPP_SRV_OPEN_EVT: - ESP_LOGI(SPP_TAG, "ESP_SPP_SRV_OPEN_EVT"); - gettimeofday(&time_old, NULL); - break; - default: - break; - } -} - -void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) -{ - switch (event) { - case ESP_BT_GAP_AUTH_CMPL_EVT:{ - if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { - ESP_LOGI(SPP_TAG, "authentication success: %s", param->auth_cmpl.device_name); - esp_log_buffer_hex(SPP_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); - } else { - ESP_LOGE(SPP_TAG, "authentication failed, status:%d", param->auth_cmpl.stat); - } - break; - } - case ESP_BT_GAP_PIN_REQ_EVT:{ - ESP_LOGI(SPP_TAG, "ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit); - if (param->pin_req.min_16_digit) { - ESP_LOGI(SPP_TAG, "Input pin code: 0000 0000 0000 0000"); - esp_bt_pin_code_t pin_code = {0}; - esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code); - } else { - ESP_LOGI(SPP_TAG, "Input pin code: 1234"); - esp_bt_pin_code_t pin_code; - pin_code[0] = '1'; - pin_code[1] = '2'; - pin_code[2] = '3'; - pin_code[3] = '4'; - esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code); - } - break; - } - -#if (CONFIG_BT_SSP_ENABLED == true) - case ESP_BT_GAP_CFM_REQ_EVT: - ESP_LOGI(SPP_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); - esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); - break; - case ESP_BT_GAP_KEY_NOTIF_EVT: - ESP_LOGI(SPP_TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); - break; - case ESP_BT_GAP_KEY_REQ_EVT: - ESP_LOGI(SPP_TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); - break; -#endif - - default: { - ESP_LOGI(SPP_TAG, "event: %d", event); - break; - } - } - return; -} -void audio_main(void) -{ - audio_pipeline_handle_t pipeline; - audio_element_handle_t i2s_stream_writer, i2s_stream_reader, fifostream; - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set(SPP_TAG, ESP_LOG_DEBUG); - - - ESP_LOGI(SPP_TAG, "[ 1 ] Start codec chip"); - audio_board_handle_t board_handle = audio_board_init(); - - audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START); - - - ESP_LOGI(SPP_TAG, "[ 2 ] Create audio pipeline for playback"); - audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG(); - pipeline = audio_pipeline_init(&pipeline_cfg); - - ESP_LOGI(SPP_TAG, "[3.1] Create i2s stream to write data to codec chip"); - i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT(); - i2s_cfg.type = AUDIO_STREAM_WRITER; - i2s_stream_writer = i2s_stream_init(&i2s_cfg); - - - ESP_LOGI(SPP_TAG, "[3.1b] fifostream"); - fifostream_cfg_t eq_cfg = DEFAULT_FIFOSTREAM_CONFIG(); - int set_gain[] = {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, - 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,}; - eq_cfg.set_gain = set_gain; - fifostream = fifostream_init(&eq_cfg); - - ESP_LOGI(SPP_TAG, "[3.2] Create i2s stream to read data from codec chip"); - i2s_stream_cfg_t i2s_cfg_read = I2S_STREAM_CFG_DEFAULT(); - i2s_cfg_read.type = AUDIO_STREAM_READER; - i2s_stream_reader = i2s_stream_init(&i2s_cfg_read); - - ESP_LOGI(SPP_TAG, "[3.3] Register all elements to audio pipeline"); - audio_pipeline_register(pipeline, i2s_stream_reader, "i2s_read"); - audio_pipeline_register(pipeline, fifostream, "wombat"); - audio_pipeline_register(pipeline, i2s_stream_writer, "i2s_write"); - - ESP_LOGI(SPP_TAG, "[3.4] Link it together [codec_chip]-->i2s_stream_reader-->i2s_stream_writer-->[codec_chip]"); - const char *link_tag[3] = {"i2s_read", "wombat", "i2s_write"}; - audio_pipeline_link(pipeline, &link_tag[0], 3); - - ESP_LOGI(SPP_TAG, "[ 4 ] Set up event listener"); - audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG(); - audio_event_iface_handle_t evt = audio_event_iface_init(&evt_cfg); - - ESP_LOGI(SPP_TAG, "[4.1] Listening event from all elements of pipeline"); - audio_pipeline_set_listener(pipeline, evt); - - ESP_LOGI(SPP_TAG, "[ 5 ] Start audio_pipeline"); - audio_pipeline_run(pipeline); - - ESP_LOGI(SPP_TAG, "[ 7 ] Listen for all pipeline events"); - while (1) { - audio_event_iface_msg_t msg; - esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY); - if (ret != ESP_OK) { - ESP_LOGE(SPP_TAG, "[ * ] Event interface error : %d", ret); - continue; - } - - /* Stop when the last pipeline element (i2s_stream_writer in this case) receives stop event */ - if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void *) i2s_stream_writer - && msg.cmd == AEL_MSG_CMD_REPORT_STATUS - && (((int)msg.data == AEL_STATUS_STATE_STOPPED) || ((int)msg.data == AEL_STATUS_STATE_FINISHED))) { - ESP_LOGW(SPP_TAG, "[ * ] Stop event received"); - break; - } - } - - ESP_LOGI(SPP_TAG, "[ 8 ] Stop audio_pipeline"); - audio_pipeline_stop(pipeline); - audio_pipeline_wait_for_stop(pipeline); - audio_pipeline_terminate(pipeline); - - audio_pipeline_unregister(pipeline, i2s_stream_reader); - audio_pipeline_unregister(pipeline, i2s_stream_writer); - - /* Terminate the pipeline before removing the listener */ - audio_pipeline_remove_listener(pipeline); - - /* Make sure audio_pipeline_remove_listener & audio_event_iface_remove_listener are called before destroying event_iface */ - audio_event_iface_destroy(evt); - - /* Release all resources */ - audio_pipeline_deinit(pipeline); - audio_element_deinit(i2s_stream_reader); - audio_element_deinit(i2s_stream_writer); -} - -void app_main() -{ - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK( ret ); - - ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE)); - - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { - ESP_LOGE(SPP_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - - if ((ret = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { - ESP_LOGE(SPP_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - - if ((ret = esp_bluedroid_init()) != ESP_OK) { - ESP_LOGE(SPP_TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - - if ((ret = esp_bluedroid_enable()) != ESP_OK) { - ESP_LOGE(SPP_TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - - if ((ret = esp_bt_gap_register_callback(esp_bt_gap_cb)) != ESP_OK) { - ESP_LOGE(SPP_TAG, "%s gap register failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - - if ((ret = esp_spp_register_callback(esp_spp_cb)) != ESP_OK) { - ESP_LOGE(SPP_TAG, "%s spp register failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - - if ((ret = esp_spp_init(esp_spp_mode)) != ESP_OK) { - ESP_LOGE(SPP_TAG, "%s spp init failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - -#if (CONFIG_BT_SSP_ENABLED == true) - /* Set default parameters for Secure Simple Pairing */ - esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; - esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; - esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); -#endif - - /* - * Set default parameters for Legacy Pairing - * Use variable pin, input pin code when pairing - */ - esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; - esp_bt_pin_code_t pin_code; - esp_bt_gap_set_pin(pin_type, 0, pin_code); - - audio_main(); -} - -#if 0 /* this will be more work than I thought */ -void gettaskinfo(char *where) -{ - TaskStatus_t xTaskDetails; - vTaskGetInfo( /* The handle of the task being queried. */ - 0, - /* The TaskStatus_t structure to complete with information - on xTask. */ - &xTaskDetails, - /* Include the stack high water mark value in the - TaskStatus_t structure. */ - pdTRUE, - /* Include the task state in the TaskStatus_t structure. */ - eInvalid ); - ESP_LOGE("PROC", "where: proc %s: %d %d", xTaskDetails.pcTaskName, - (int)((char *)(&xTaskDetails) - (char *)(pxStackBase)), - (int)usStackHighWaterMark); -} -#endif