From a80d66314623ea34bf183b7f419faeb5f3acbbf8 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Mon, 22 Jan 2024 17:27:30 +0800 Subject: [PATCH] update --- .vscode/settings.json | 6 +- app/app.uvoptx | 172 ++++++----- app/app.uvprojx | 30 +- app/main.c | 28 +- app/src/basic/board.c | 350 ++++++++++++++++++++++ app/src/basic/board.h | 67 +++++ app/src/basic/project_cfg.h | 3 + app/src/basic/version.h | 3 + app/src/basic/zble_module.c | 255 ++++++++++++++++ app/src/basic/zble_module.h | 20 ++ app/src/basic/zdatachannel_service.c | 217 ++++++++++++++ app/src/basic/zdatachannel_service.h | 89 ++++++ app/src/board.c | 350 ---------------------- app/src/board.h | 67 ----- app/src/one_conduction/one_conduction_board.c | 0 app/src/one_conduction/one_conduction_board.h | 4 + app/src/one_conduction/one_conduction_main.c | 73 +++++ app/src/one_conduction/one_conduction_main.h | 3 + app/src/project_cfg.h | 3 - app/src/three_conduction/three_conduction_board.c | 0 app/src/three_conduction/three_conduction_board.h | 0 app/src/three_conduction/three_conduction_main.c | 0 app/src/three_conduction/three_conduction_main.h | 0 app/src/version.h | 3 - app/src/zble_module.c | 255 ---------------- app/src/zble_module.h | 20 -- app/src/zdatachannel_service.c | 216 ------------- app/src/zdatachannel_service.h | 89 ------ libznordic | 2 +- 29 files changed, 1206 insertions(+), 1119 deletions(-) create mode 100644 app/src/basic/board.c create mode 100644 app/src/basic/board.h create mode 100644 app/src/basic/project_cfg.h create mode 100644 app/src/basic/version.h create mode 100644 app/src/basic/zble_module.c create mode 100644 app/src/basic/zble_module.h create mode 100644 app/src/basic/zdatachannel_service.c create mode 100644 app/src/basic/zdatachannel_service.h delete mode 100644 app/src/board.c delete mode 100644 app/src/board.h create mode 100644 app/src/one_conduction/one_conduction_board.c create mode 100644 app/src/one_conduction/one_conduction_board.h create mode 100644 app/src/one_conduction/one_conduction_main.c create mode 100644 app/src/one_conduction/one_conduction_main.h delete mode 100644 app/src/project_cfg.h create mode 100644 app/src/three_conduction/three_conduction_board.c create mode 100644 app/src/three_conduction/three_conduction_board.h create mode 100644 app/src/three_conduction/three_conduction_main.c create mode 100644 app/src/three_conduction/three_conduction_main.h delete mode 100644 app/src/version.h delete mode 100644 app/src/zble_module.c delete mode 100644 app/src/zble_module.h delete mode 100644 app/src/zdatachannel_service.c delete mode 100644 app/src/zdatachannel_service.h diff --git a/.vscode/settings.json b/.vscode/settings.json index a0adfb0..a1e24f1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -48,6 +48,10 @@ "nrf_drv_pwm.h": "c", "nrfx_config.h": "c", "nrf_drv_wdt.h": "c", - "app_sdcard.h": "c" + "app_sdcard.h": "c", + "diskio_blkdev.h": "c", + "three_conduction_main.h": "c", + "one_conduction_main.h": "c", + "one_conduction_board.h": "c" } } \ No newline at end of file diff --git a/app/app.uvoptx b/app/app.uvoptx index 43be657..72e05c0 100644 --- a/app/app.uvoptx +++ b/app/app.uvoptx @@ -177,7 +177,7 @@ 0 0 1 - .\src\board.c + D:\workspace\nordic_wp\conduction1_dynamic_electrocardiograph\app\src\board.c \\nrf52833_xxaa\src/board.c\275 @@ -193,7 +193,7 @@ 0 0 1 - .\src\board.c + D:\workspace\nordic_wp\conduction1_dynamic_electrocardiograph\app\src\board.c \\nrf52833_xxaa\src/board.c\279 @@ -447,7 +447,7 @@ 0 0 0 - .\src\zble_module.c + .\src\basic\zble_module.c zble_module.c 0 0 @@ -459,8 +459,8 @@ 0 0 0 - .\src\board.c - board.c + .\src\basic\zdatachannel_service.c + zdatachannel_service.c 0 0 @@ -471,8 +471,20 @@ 0 0 0 - .\src\zdatachannel_service.c - zdatachannel_service.c + .\src\one_conduction\one_conduction_board.c + one_conduction_board.c + 0 + 0 + + + 1 + 6 + 1 + 0 + 0 + 0 + .\src\one_conduction\one_conduction_main.c + one_conduction_main.c 0 0 @@ -486,7 +498,7 @@ 0 2 - 6 + 7 1 0 0 @@ -506,7 +518,7 @@ 0 3 - 7 + 8 1 0 0 @@ -518,7 +530,7 @@ 3 - 8 + 9 1 0 0 @@ -538,7 +550,7 @@ 0 4 - 9 + 10 1 0 0 @@ -558,7 +570,7 @@ 0 5 - 10 + 11 1 0 0 @@ -570,7 +582,7 @@ 5 - 11 + 12 1 0 0 @@ -582,7 +594,7 @@ 5 - 12 + 13 1 0 0 @@ -594,7 +606,7 @@ 5 - 13 + 14 1 0 0 @@ -606,7 +618,7 @@ 5 - 14 + 15 1 0 0 @@ -618,7 +630,7 @@ 5 - 15 + 16 1 0 0 @@ -630,7 +642,7 @@ 5 - 16 + 17 1 0 0 @@ -642,7 +654,7 @@ 5 - 17 + 18 1 0 0 @@ -662,7 +674,7 @@ 0 6 - 18 + 19 1 0 0 @@ -682,7 +694,7 @@ 0 7 - 19 + 20 1 0 0 @@ -694,7 +706,7 @@ 7 - 20 + 21 1 0 0 @@ -706,7 +718,7 @@ 7 - 21 + 22 1 0 0 @@ -718,7 +730,7 @@ 7 - 22 + 23 1 0 0 @@ -730,7 +742,7 @@ 7 - 23 + 24 1 0 0 @@ -742,7 +754,7 @@ 7 - 24 + 25 1 0 0 @@ -754,7 +766,7 @@ 7 - 25 + 26 1 0 0 @@ -766,7 +778,7 @@ 7 - 26 + 27 1 0 0 @@ -778,7 +790,7 @@ 7 - 27 + 28 1 0 0 @@ -790,7 +802,7 @@ 7 - 28 + 29 1 0 0 @@ -802,7 +814,7 @@ 7 - 29 + 30 1 0 0 @@ -814,7 +826,7 @@ 7 - 30 + 31 1 0 0 @@ -826,7 +838,7 @@ 7 - 31 + 32 1 0 0 @@ -838,7 +850,7 @@ 7 - 32 + 33 1 0 0 @@ -850,7 +862,7 @@ 7 - 33 + 34 1 0 0 @@ -862,7 +874,7 @@ 7 - 34 + 35 1 0 0 @@ -874,7 +886,7 @@ 7 - 35 + 36 1 0 0 @@ -886,7 +898,7 @@ 7 - 36 + 37 1 0 0 @@ -906,7 +918,7 @@ 0 8 - 37 + 38 1 0 0 @@ -918,7 +930,7 @@ 8 - 38 + 39 1 0 0 @@ -930,7 +942,7 @@ 8 - 39 + 40 1 0 0 @@ -942,7 +954,7 @@ 8 - 40 + 41 1 0 0 @@ -954,7 +966,7 @@ 8 - 41 + 42 1 0 0 @@ -966,7 +978,7 @@ 8 - 42 + 43 1 0 0 @@ -978,7 +990,7 @@ 8 - 43 + 44 1 0 0 @@ -990,7 +1002,7 @@ 8 - 44 + 45 1 0 0 @@ -1002,7 +1014,7 @@ 8 - 45 + 46 1 0 0 @@ -1014,7 +1026,7 @@ 8 - 46 + 47 1 0 0 @@ -1026,7 +1038,7 @@ 8 - 47 + 48 1 0 0 @@ -1038,7 +1050,7 @@ 8 - 48 + 49 1 0 0 @@ -1050,7 +1062,7 @@ 8 - 49 + 50 1 0 0 @@ -1062,7 +1074,7 @@ 8 - 50 + 51 1 0 0 @@ -1074,7 +1086,7 @@ 8 - 51 + 52 1 0 0 @@ -1086,7 +1098,7 @@ 8 - 52 + 53 1 0 0 @@ -1098,7 +1110,7 @@ 8 - 53 + 54 1 0 0 @@ -1110,7 +1122,7 @@ 8 - 54 + 55 1 0 0 @@ -1122,7 +1134,7 @@ 8 - 55 + 56 1 0 0 @@ -1134,7 +1146,7 @@ 8 - 56 + 57 1 0 0 @@ -1146,7 +1158,7 @@ 8 - 57 + 58 1 0 0 @@ -1158,7 +1170,7 @@ 8 - 58 + 59 1 0 0 @@ -1170,7 +1182,7 @@ 8 - 59 + 60 1 0 0 @@ -1182,7 +1194,7 @@ 8 - 60 + 61 1 0 0 @@ -1194,7 +1206,7 @@ 8 - 61 + 62 1 0 0 @@ -1206,7 +1218,7 @@ 8 - 62 + 63 1 0 0 @@ -1218,7 +1230,7 @@ 8 - 63 + 64 1 0 0 @@ -1238,7 +1250,7 @@ 0 9 - 64 + 65 1 0 0 @@ -1250,7 +1262,7 @@ 9 - 65 + 66 1 0 0 @@ -1262,7 +1274,7 @@ 9 - 66 + 67 1 0 0 @@ -1274,7 +1286,7 @@ 9 - 67 + 68 1 0 0 @@ -1286,7 +1298,7 @@ 9 - 68 + 69 1 0 0 @@ -1298,7 +1310,7 @@ 9 - 69 + 70 1 0 0 @@ -1318,7 +1330,7 @@ 0 10 - 70 + 71 1 0 0 @@ -1330,7 +1342,7 @@ 10 - 71 + 72 1 0 0 @@ -1342,7 +1354,7 @@ 10 - 72 + 73 1 0 0 @@ -1362,7 +1374,7 @@ 0 11 - 73 + 74 1 0 0 @@ -1374,7 +1386,7 @@ 11 - 74 + 75 1 0 0 @@ -1386,7 +1398,7 @@ 11 - 75 + 76 1 0 0 @@ -1406,7 +1418,7 @@ 0 12 - 76 + 77 1 0 0 @@ -1426,7 +1438,7 @@ 0 13 - 77 + 78 1 0 0 @@ -1438,7 +1450,7 @@ 13 - 78 + 79 1 0 0 diff --git a/app/app.uvprojx b/app/app.uvprojx index 445f198..98703d6 100644 --- a/app/app.uvprojx +++ b/app/app.uvprojx @@ -396,17 +396,22 @@ zble_module.c 1 - .\src\zble_module.c + .\src\basic\zble_module.c - board.c + zdatachannel_service.c 1 - .\src\board.c + .\src\basic\zdatachannel_service.c - zdatachannel_service.c + one_conduction_board.c + 1 + .\src\one_conduction\one_conduction_board.c + + + one_conduction_main.c 1 - .\src\zdatachannel_service.c + .\src\one_conduction\one_conduction_main.c @@ -4140,17 +4145,22 @@ zble_module.c 1 - .\src\zble_module.c + .\src\basic\zble_module.c - board.c + zdatachannel_service.c 1 - .\src\board.c + .\src\basic\zdatachannel_service.c - zdatachannel_service.c + one_conduction_board.c + 1 + .\src\one_conduction\one_conduction_board.c + + + one_conduction_main.c 1 - .\src\zdatachannel_service.c + .\src\one_conduction\one_conduction_main.c diff --git a/app/main.c b/app/main.c index 1c2a5d5..3a9bb5c 100644 --- a/app/main.c +++ b/app/main.c @@ -1,29 +1,9 @@ -#if 1 -#include "board.h" -#include "diskio_blkdev.h" -#include "ff.h" -#include "nrf_block_dev_sdc.h" -#include "nrf_delay.h" -#include "project_cfg.h" -#include "sys.h" -#include "version.h" -#include "zble_module.h" -#include "zdatachannel_service.h" -#include "diskio_blkdev.h" +#include "one_conduction/one_conduction_main.h" +#include "three_conduction/three_conduction_main.h" -#if 0 -void qingfengboard_test(void) { - // 测试LED - debug_light_init(15); - - // 测试BUTTON - // static uint8_t io_index[] = {ZPIN(0, 5), ZPIN(1, 9)}; - // zbsp_gpio_state_monitor(1000, (uint8_t*)io_index, ZARRAY_SIZE(io_index)); +int main(void) { one_conduction_main(); } - // 测试睡眠唤醒 - zbsp_enter_sleep(3000, 5, true); -} -#endif +#if 0 ZDATACHANNEL_DEF(m_zhrs, 2 /*回调事件优先级*/, 1 /*client num*/); APP_TIMER_DEF(m_test_tx_timer); diff --git a/app/src/basic/board.c b/app/src/basic/board.c new file mode 100644 index 0000000..b3df2c7 --- /dev/null +++ b/app/src/basic/board.c @@ -0,0 +1,350 @@ +#include "board.h" + +#include "app_timer.h" +#include "nrf_gpio.h" +#include "sys.h" +// +#include "diskio_blkdev.h" +#include "ff.h" +#include "nrf_block_dev_sdc.h" +#include "nrf_delay.h" +#include "nrf_drv_pwm.h" +#include "nrf_drv_wdt.h" + +static int16_t adc_channel_read_val(uint16_t channel) { + nrf_saadc_value_t value; + ret_code_t err_code; + err_code = nrfx_saadc_sample_convert(channel, &value); + if (err_code != NRF_SUCCESS) { + ZLOGE("nrfx_saadc_sample_convert(%d) fail err_code:%d", channel, err_code); + return 0; + } + return value; +} + +/******************************************************************************* + * DEBUG_LIGHT * + *******************************************************************************/ +APP_TIMER_DEF(m_debug_light_tmr); +static int32_t m_debug_light_io_index; +static void debug_light_tmr_cb_handler(void* p_context) { + static bool state = false; + if (state) { + nrf_gpio_pin_set(m_debug_light_io_index); + } else { + nrf_gpio_pin_clear(m_debug_light_io_index); + } + state = !state; +} + +void debug_light_init(int io_index) { + m_debug_light_io_index = io_index; + + nrf_gpio_cfg(m_debug_light_io_index, // + NRF_GPIO_PIN_DIR_OUTPUT, // + NRF_GPIO_PIN_INPUT_DISCONNECT, // + NRF_GPIO_PIN_PULLUP, // + NRF_GPIO_PIN_S0S1, // + NRF_GPIO_PIN_NOSENSE); + + ret_code_t err_code; + err_code = app_timer_create(&m_debug_light_tmr, APP_TIMER_MODE_REPEATED, debug_light_tmr_cb_handler); + APP_ERROR_CHECK(err_code); + + app_timer_start(m_debug_light_tmr, APP_TIMER_TICKS(100), NULL); +} +/******************************************************************************* + * zbsp_enter_sleep * + *******************************************************************************/ +APP_TIMER_DEF(enter_sleep_mode_tmr); +static int32_t m_wakeup_io_index; +static bool m_wakeup_io_mirror; +static void enter_sleep_tmr_cb(void* p_context) { + ZLOGI("enter sleep mode, wakeup io index: %d", m_wakeup_io_index); + + if (m_wakeup_io_mirror) { + nrf_gpio_cfg_sense_input(m_wakeup_io_index, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW); + nrf_gpio_cfg_sense_set(m_wakeup_io_index, NRF_GPIO_PIN_SENSE_LOW); + } else { + nrf_gpio_cfg_sense_input(m_wakeup_io_index, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_HIGH); + nrf_gpio_cfg_sense_set(m_wakeup_io_index, NRF_GPIO_PIN_SENSE_HIGH); + } + + // Go to system-off mode (this function will not return; wakeup will cause a reset). + ret_code_t err_code; + err_code = sd_power_system_off(); + if (err_code != NRF_SUCCESS) { + ZLOGE("sd_power_system_off err_code: %x", err_code); + } +} +void zbsp_enter_sleep(int32_t after_ms, int32_t wakeup_io_index, bool mirror) { + m_wakeup_io_index = wakeup_io_index; + m_wakeup_io_mirror = mirror; + ret_code_t err_code; + APP_ERROR_CHECK(app_timer_create(&enter_sleep_mode_tmr, APP_TIMER_MODE_SINGLE_SHOT, enter_sleep_tmr_cb)); + APP_ERROR_CHECK(app_timer_start(enter_sleep_mode_tmr, APP_TIMER_TICKS(after_ms), NULL)); + + ZLOGI("enter sleep mode after %d ms", after_ms); +} + +/******************************************************************************* + * gpio_io_state_monitor * + *******************************************************************************/ +APP_TIMER_DEF(gpio_io_state_monitor_tmr); +static uint8_t* m_io_index; +static int32_t m_nio; +static void gpio_io_state_monitor_tmr_cb(void* p_context) { + // ioindex:state ioindex:state ioindex:state + if (m_nio == 1) { + ZLOGI("iostate %d:%d ", m_io_index[0], nrf_gpio_pin_read(m_io_index[0])); + } else if (m_nio == 2) { + ZLOGI("iostate %d:%d %d:%d", m_io_index[0], nrf_gpio_pin_read(m_io_index[0]), // + m_io_index[1], nrf_gpio_pin_read(m_io_index[1])); + } else if (m_nio >= 3) { + ZLOGI("iostate %d:%d %d:%d %d:%d", m_io_index[0], nrf_gpio_pin_read(m_io_index[0]), // + m_io_index[1], nrf_gpio_pin_read(m_io_index[1]), // + m_io_index[2], nrf_gpio_pin_read(m_io_index[2])); + } +} + +void zbsp_gpio_state_monitor_without_initio(int dumpstate_period, uint8_t* io_index, int32_t nio) { + m_io_index = io_index; + m_nio = nio; + APP_ERROR_CHECK(app_timer_create(&gpio_io_state_monitor_tmr, APP_TIMER_MODE_REPEATED, gpio_io_state_monitor_tmr_cb)); + APP_ERROR_CHECK(app_timer_start(gpio_io_state_monitor_tmr, APP_TIMER_TICKS(dumpstate_period), NULL)); +} +void zbsp_gpio_state_monitor(int dumpstate_period, uint8_t* io_index, int32_t nio) { + m_io_index = io_index; + m_nio = nio; + for (int i = 0; i < nio; i++) { + nrf_gpio_cfg_input(io_index[i], NRF_GPIO_PIN_PULLUP); + } + zbsp_gpio_state_monitor_without_initio(dumpstate_period, io_index, nio); +} + +void board_init() {} + +/******************************************************************************* + * ADC * + *******************************************************************************/ + +static void saadc_callback(nrf_drv_saadc_evt_t const* p_event) { + if (p_event->type == NRF_DRV_SAADC_EVT_DONE) { + } +} + +void adc_module_init() { + nrf_drv_saadc_config_t adccfg = NRFX_SAADC_DEFAULT_CONFIG; + adccfg.resolution = NRF_SAADC_RESOLUTION_12BIT; // 4096 等于满采样率 + ZERROR_CHECK(nrf_drv_saadc_init(&adccfg, saadc_callback)); +} + +void adc_module_battery_channel_init(nrf_saadc_input_t channelpin) { + nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(channelpin); + ZERROR_CHECK(nrfx_saadc_channel_init(0, &channel_config)); +} +int16_t adc_module_battery_channel_read_val() { return adc_channel_read_val(0); } + +void adc_module_heart_elect_channel_init(nrf_saadc_input_t channelpin) { + nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(channelpin); + channel_config.acq_time = NRF_SAADC_ACQTIME_40US; + ZERROR_CHECK(nrfx_saadc_channel_init(1, &channel_config)); +} +int16_t adc_module_heart_elect_channel_read_val() { return adc_channel_read_val(1); } +/******************************************************************************* + * SPI * + *******************************************************************************/ +#define SPI_MISO_PIN 31 +#define SPI_SS_PIN 20 +#define SPI_SCK_PIN 29 +#define SPI_MOSI_PIN 30 +static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(0); /**< SPI instance. */ + +// static volatile bool m_spi_translate_done = false; +// static void spi_event_handler(nrf_drv_spi_evt_t const* p_event, void* p_context) { m_spi_translate_done = true; } +void board_spi_init() { + nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; + spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; // NRF_DRV_SPI_PIN_NOT_USED + spi_config.miso_pin = SPI_MISO_PIN; + spi_config.mosi_pin = SPI_MOSI_PIN; + spi_config.sck_pin = SPI_SCK_PIN; + spi_config.frequency = NRF_DRV_SPI_FREQ_1M; + ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); +} +ret_code_t board_spi_transfer(uint8_t const* p_tx_buffer, uint8_t tx_buffer_length, uint8_t* p_rx_buffer, uint8_t rx_buffer_length) { + // m_spi_translate_done = false; + ZERROR_CHECK(nrf_drv_spi_transfer(&spi, p_tx_buffer, tx_buffer_length, p_rx_buffer, rx_buffer_length)); + // while (!m_spi_translate_done) + // ; + return NRF_SUCCESS; +} + +ret_code_t board_spi_transfer_test() { + uint8_t tx_data[] = {0x01, 0x02, 0x03}; + uint8_t rx_data[3]; + ZERROR_CHECK(board_spi_transfer(tx_data, 3, rx_data, 3)); +} + +void screen_init() {} +void screen_spi_translate_onebyte() {} + +static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0); +static nrf_pwm_values_individual_t m_demo1_seq_values; + +void pwm_trigger() { + nrf_drv_pwm_config_t const config0 = { + .output_pins = {11}, + .irq_priority = APP_IRQ_PRIORITY_LOWEST, + .base_clock = NRF_PWM_CLK_125kHz, + .count_mode = NRF_PWM_MODE_UP, + .top_value = 10, + .load_mode = NRF_PWM_LOAD_INDIVIDUAL, + .step_mode = NRF_PWM_STEP_AUTO, + }; + APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL)); + + static nrf_pwm_sequence_t const m_demo1_seq = { + .values.p_individual = &m_demo1_seq_values, + .length = NRF_PWM_VALUES_LENGTH(m_demo1_seq_values), + .repeats = 0, + .end_delay = 0, + }; + + m_demo1_seq_values.channel_0 = 8; + m_demo1_seq_values.channel_1 = 0; + m_demo1_seq_values.channel_2 = 0; + m_demo1_seq_values.channel_3 = 0; + + (void)nrf_drv_pwm_simple_playback(&m_pwm0, &m_demo1_seq, 1, NRF_DRV_PWM_FLAG_LOOP); +} + +/******************************************************************************* + * I2C * + *******************************************************************************/ + +#define TWI_SCL_M 30 // I2C SCL引脚 +#define TWI_SDA_M 31 // I2C SDA引脚 +static const nrf_drv_twi_t m_twi_master = NRF_DRV_TWI_INSTANCE(1); + +void board_i2c_init() { + const nrf_drv_twi_config_t config = { + .scl = TWI_SCL_M, + .sda = TWI_SDA_M, + .frequency = NRF_DRV_TWI_FREQ_100K, + .interrupt_priority = APP_IRQ_PRIORITY_HIGH, + .clear_bus_init = false, + }; + + ZERROR_CHECK(nrf_drv_twi_init(&m_twi_master, &config, NULL, NULL)); + + nrf_drv_twi_enable(&m_twi_master); +} + +void board_i2c_write(uint8_t addr, uint8_t* data, uint8_t len) { nrf_drv_twi_tx(&m_twi_master, addr, data, len, false); } + +#define FILE_NAME "NORDIC.TXT" +#define TEST_STRING "SD card example." + +// #define SPI_MISO_PIN 31 +// #define SPI_SS_PIN 20 +// #define SPI_SCK_PIN 29 +// #define SPI_MOSI_PIN 30 + +#define SDC_SCK_PIN 29 ///< SDC serial clock (SCK) pin. +#define SDC_MOSI_PIN 30 ///< SDC serial data in (DI) pin. +#define SDC_MISO_PIN 31 ///< SDC serial data out (DO) pin. +#define SDC_CS_PIN 20 ///< SDC chip select (CS) pin. + +NRF_BLOCK_DEV_SDC_DEFINE(m_block_dev_sdc, NRF_BLOCK_DEV_SDC_CONFIG(SDC_SECTOR_SIZE, APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN)), NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")); +void fatfs_init() { + // // Initialize FATFS disk I/O interface by providing the block device. + static diskio_blkdev_t drives[] = {DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)}; + + diskio_blockdev_register(drives, ARRAY_SIZE(drives)); + fatfs_test_write(); +} +void fatfs_test_write() { + static FATFS fs; + static DIR dir; + static FILINFO fno; + static FIL file; + + uint32_t bytes_written; + FRESULT ff_result; + DSTATUS disk_state = STA_NOINIT; + + for (uint32_t retries = 3; retries && disk_state; --retries) { + disk_state = disk_initialize(0); + } + if (disk_state) { + NRF_LOG_INFO("Disk initialization failed. %d", disk_state); + return; + } + return; + // NRF_LOG_INFO("Initializing disk 0 (SDC)..."); + + uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size; + uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb; + NRF_LOG_INFO("Capacity: %d MB", capacity); + + NRF_LOG_INFO("Mounting volume..."); + ff_result = f_mount(&fs, "", 1); + if (ff_result) { + NRF_LOG_INFO("Mount failed."); + return; + } + + NRF_LOG_INFO("\r\n Listing directory: /"); + ff_result = f_opendir(&dir, "/"); + if (ff_result) { + NRF_LOG_INFO("Directory listing failed!"); + return; + } + + do { + ff_result = f_readdir(&dir, &fno); + if (ff_result != FR_OK) { + NRF_LOG_INFO("Directory read failed."); + return; + } + + if (fno.fname[0]) { + if (fno.fattrib & AM_DIR) { + NRF_LOG_RAW_INFO(" %s", (uint32_t)fno.fname); + } else { + NRF_LOG_RAW_INFO("%9lu %s", fno.fsize, (uint32_t)fno.fname); + } + } + } while (fno.fname[0]); + NRF_LOG_RAW_INFO(""); + + NRF_LOG_INFO("Writing to file " FILE_NAME "..."); + ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND); + if (ff_result != FR_OK) { + NRF_LOG_INFO("Unable to open or create file: " FILE_NAME "."); + return; + } + + ff_result = f_write(&file, TEST_STRING, sizeof(TEST_STRING) - 1, (UINT*)&bytes_written); + if (ff_result != FR_OK) { + NRF_LOG_INFO("Write failed\r\n."); + } else { + NRF_LOG_INFO("%d bytes written.", bytes_written); + } + + (void)f_close(&file); + return; +} +nrf_drv_wdt_channel_id m_channel_id; + +void wd_init() { + // WDT_CONFIG_RELOAD_VALUE 修改这个数值修改喂狗周期,单位ms + nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG; + config.reload_value = WDT_CONFIG_RELOAD_VALUE; + ret_code_t err_code = nrf_drv_wdt_init(&config, NULL); + ZERROR_CHECK(err_code); + err_code = nrf_drv_wdt_channel_alloc(&m_channel_id); + ZERROR_CHECK(err_code); + nrf_drv_wdt_enable(); +} +void wd_feed() { nrfx_wdt_feed(); } \ No newline at end of file diff --git a/app/src/basic/board.h b/app/src/basic/board.h new file mode 100644 index 0000000..e36e8fb --- /dev/null +++ b/app/src/basic/board.h @@ -0,0 +1,67 @@ +#pragma once +#include + +#include "nrf_drv_saadc.h" +#include "nrf_drv_twi.h" +#include "sys.h" + +/******************************************************************************* + * DEBUG_LIGHT * + *******************************************************************************/ +void debug_light_init(int io_index); + +/******************************************************************************* + * zbsp_enter_sleep * + *******************************************************************************/ + +/** + * @brief 调用此方法前,需要确保底层协议栈已经初始化 + * + * @param after_ms + * @param wakeup_io_index + */ +void zbsp_enter_sleep(int32_t after_ms, int32_t wakeup_io_index, bool mirror); + +/******************************************************************************* + * gpio_io_state_monitor * + *******************************************************************************/ +void zbsp_gpio_state_monitor(int dumpstate_period, uint8_t* io_index, int32_t nio); +void zbsp_gpio_state_monitor_without_initio(int dumpstate_period, uint8_t* io_index, int32_t nio); + +void board_init(); + +/******************************************************************************* + * ADC * + *******************************************************************************/ + +void adc_module_init(); + +void adc_module_battery_channel_init(nrf_saadc_input_t channelpin); +int16_t adc_module_battery_channel_read_val(); + +void adc_module_heart_elect_channel_init(nrf_saadc_input_t channelpin); +int16_t adc_module_heart_elect_channel_read_val(); + +/******************************************************************************* + * SPI * + *******************************************************************************/ + +void board_spi_init(); +ret_code_t board_spi_transfer(uint8_t const* p_tx_buffer, uint8_t tx_buffer_length, uint8_t* p_rx_buffer, uint8_t rx_buffer_length); +ret_code_t board_spi_transfer_test(); + +void board_i2c_init(); +void board_i2c_write(uint8_t addr, uint8_t* data, uint8_t len); + +void screen_init(); +void screen_spi_translate_onebyte(); + +/******************************************************************************* + * FATFS * + *******************************************************************************/ +void fatfs_init(); +void fatfs_test_write(); +void pwm_trigger(); + +void wd_init(); +void wd_feed(); \ No newline at end of file diff --git a/app/src/basic/project_cfg.h b/app/src/basic/project_cfg.h new file mode 100644 index 0000000..a0ece75 --- /dev/null +++ b/app/src/basic/project_cfg.h @@ -0,0 +1,3 @@ +#pragma once + +#define DEBUG_LIGHT_IO_INDEX 13 \ No newline at end of file diff --git a/app/src/basic/version.h b/app/src/basic/version.h new file mode 100644 index 0000000..0c3edf1 --- /dev/null +++ b/app/src/basic/version.h @@ -0,0 +1,3 @@ +#pragma once +#define VERSION 1 +#define MANUFACTURER_NAME "iflytop" \ No newline at end of file diff --git a/app/src/basic/zble_module.c b/app/src/basic/zble_module.c new file mode 100644 index 0000000..26c36bf --- /dev/null +++ b/app/src/basic/zble_module.c @@ -0,0 +1,255 @@ + + +#include "zble_module.h" + +#include +#include + +#include "sys.h" +/******************************************************************************* + * 广播包配置 * + *******************************************************************************/ +#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */ +#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */ +#define SLAVE_LATENCY 0 /**< Slave latency. */ +#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */ +#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */ +static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ + {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; +#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */ +#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ +BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ + +/******************************************************************************* + * GATT配置 * + *******************************************************************************/ +NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ + +/******************************************************************************* + * 连接参数配置 * + *******************************************************************************/ +#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ +#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ +#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ + +/******************************************************************************* + * CODE * + *******************************************************************************/ + +static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< 当前连接句柄 */ +static uint16_t m_mtu_size = BLE_GATT_ATT_MTU_DEFAULT - 3; + +/**@brief Function for putting the chip into sleep mode. + * + * @note This function will not return. + */ +static void sleep_mode_enter(void) { +#if 0 + uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); + ZERROR_CHECK(err_code); + + // Prepare wakeup buttons. + err_code = bsp_btn_ble_sleep_mode_prepare(); + ZERROR_CHECK(err_code); + + // Go to system-off mode (this function will not return; wakeup will cause a reset). + err_code = sd_power_system_off(); + ZERROR_CHECK(err_code); +#endif +} + +static void ble_evt_handler(ble_evt_t const* p_ble_evt, void* p_context) { + uint32_t err_code; + switch (p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + break; + + case BLE_GAP_EVT_DISCONNECTED: + m_conn_handle = BLE_CONN_HANDLE_INVALID; + break; + + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { + NRF_LOG_DEBUG("PHY update request."); + ble_gap_phys_t const phys = { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); + ZERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + // Pairing not supported + err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + // No system attributes have been stored. + err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTC_EVT_TIMEOUT: + // Disconnect on GATT Client timeout event. + err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTS_EVT_TIMEOUT: + // Disconnect on GATT Server timeout event. + err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + ZERROR_CHECK(err_code); + break; + + default: + // No implementation needed. + break; + } +} +static void gatt_evt_handler(nrf_ble_gatt_t* p_gatt, nrf_ble_gatt_evt_t const* p_evt) { + /******************************************************************************* + * MTU SIZE 更新 * + *******************************************************************************/ + if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { + m_mtu_size = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; + NRF_LOG_DEBUG("ATT MTU exchange completed. central %d peripheral %d", p_gatt->att_mtu_desired_central, p_gatt->att_mtu_desired_periph); + } +} +static void on_conn_params_evt(ble_conn_params_evt_t* p_evt) { + uint32_t err_code; + if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { + err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); + ZERROR_CHECK(err_code); + } +} +static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } +static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { + uint32_t err_code; + switch (ble_adv_evt) { + case BLE_ADV_EVT_FAST: + // err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); + // ZERROR_CHECK(err_code); + break; + case BLE_ADV_EVT_IDLE: + // sleep_mode_enter(); + break; + default: + break; + } +} + +void zble_module_start_adv() { + uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); + ZERROR_CHECK(err_code); +} +void zble_module_stop_adv() { + uint32_t err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle); + ZERROR_CHECK(err_code); +} + +/******************************************************************************* + * INIT * + *******************************************************************************/ +void zble_module_init(zble_module_cfg_t* cfg) { + /** + * @brief + * 初始化蓝牙协议栈,并注册蓝牙事件处理函数,固定代码,勿修改 + */ + { NRF_SDH_BLE_OBSERVER(m_ble_observer, 3, ble_evt_handler, NULL); } + /******************************************************************************* + * GAP初始化 * + *******************************************************************************/ + { + uint32_t err_code; + ble_gap_conn_params_t gap_conn_params; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t*)cfg->deviceName, strlen(cfg->deviceName)); + ZERROR_CHECK(err_code); + + memset(&gap_conn_params, 0, sizeof(gap_conn_params)); + + gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; + gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; + gap_conn_params.slave_latency = SLAVE_LATENCY; + gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; + + err_code = sd_ble_gap_ppcp_set(&gap_conn_params); + ZERROR_CHECK(err_code); + } + + /******************************************************************************* + * GATT 初始化 * + *******************************************************************************/ + { + ret_code_t err_code; + + err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); + ZERROR_CHECK(err_code); + + err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); + ZERROR_CHECK(err_code); + } + + /******************************************************************************* + * 蓝牙服务初始化 * + *******************************************************************************/ + { + if (cfg->on_service_init) cfg->on_service_init(); + } + + /******************************************************************************* + * 广播初始化 * + *******************************************************************************/ + { + uint32_t err_code; + ble_advertising_init_t init; + + memset(&init, 0, sizeof(init)); + + init.advdata.name_type = BLE_ADVDATA_FULL_NAME; + init.advdata.include_appearance = false; + // init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; + init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + + init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); + init.srdata.uuids_complete.p_uuids = m_adv_uuids; + + init.config.ble_adv_fast_enabled = true; + init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; + init.config.ble_adv_fast_timeout = 0; + init.evt_handler = on_adv_evt; + + err_code = ble_advertising_init(&m_advertising, &init); + ZERROR_CHECK(err_code); + + ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); + } + /******************************************************************************* + * 连接参数初始化 * + *******************************************************************************/ + { + uint32_t err_code; + ble_conn_params_init_t cp_init; + + memset(&cp_init, 0, sizeof(cp_init)); + + cp_init.p_conn_params = NULL; + cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; + cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; + cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; + cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; + cp_init.disconnect_on_fail = false; + cp_init.evt_handler = on_conn_params_evt; + cp_init.error_handler = conn_params_error_handler; + + err_code = ble_conn_params_init(&cp_init); + ZERROR_CHECK(err_code); + } + + // zble_module_start_adv(); +} \ No newline at end of file diff --git a/app/src/basic/zble_module.h b/app/src/basic/zble_module.h new file mode 100644 index 0000000..a630a0a --- /dev/null +++ b/app/src/basic/zble_module.h @@ -0,0 +1,20 @@ +#pragma once +#include + +/** + * @brief + */ + +typedef void (*on_service_init_t)(void); + +typedef struct { + const char* deviceName; + on_service_init_t on_service_init; +} zble_module_cfg_t; + +void zble_module_init(zble_module_cfg_t* cfg); + +void zble_module_start_adv(); +void zble_module_stop_adv(); + +void zble_module_is_connected(); diff --git a/app/src/basic/zdatachannel_service.c b/app/src/basic/zdatachannel_service.c new file mode 100644 index 0000000..876d8cf --- /dev/null +++ b/app/src/basic/zdatachannel_service.c @@ -0,0 +1,217 @@ +#include "zdatachannel_service.h" + +#include "ble.h" +#include "ble_srv_common.h" +#include "nrf_log.h" +#include "sdk_common.h" +#include "sys.h" + +#define ZDATACHANNEL_UUID_NUS_SERVICE 0x0001 /**< The UUID of the Nordic UART Service. */ +#define ZDATACHANNEL_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */ +#define ZDATACHANNEL_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */ +#define ZDATACHANNEL_DATABLOCK_TX_CHARACTERISTIC 0x0004 /**< The UUID of the RX Characteristic. */ + +#define ZDATACHANNEL_MAX_RX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ +#define ZDATACHANNEL_MAX_TX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ +#define ZDATACHANNEL_DATABLOCK_TX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ + +#define NUS_BASE_UUID \ + { \ + { 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E } \ + } /**< Used vendor specific UUID. */ + +static zdatachannel_t *p_datachannel; + +static bool notification_enable(uint16_t conn_handle, uint16_t cccd_handle) { + ret_code_t err_code; + ble_gatts_value_t gatts_val; + uint8_t cccd_value[2]; + memset(&gatts_val, 0, sizeof(ble_gatts_value_t)); + gatts_val.p_value = cccd_value; + gatts_val.len = sizeof(cccd_value); + gatts_val.offset = 0; + err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &gatts_val); + if ((err_code == NRF_SUCCESS) && ble_srv_is_notification_enabled(gatts_val.p_value)) { + return true; + } + return false; +} + +/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_write(zdatachannel_t *p_nus, ble_evt_t const *p_ble_evt) { + zdatachannel_evt_t evt; + ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + memset(&evt, 0, sizeof(zdatachannel_evt_t)); + + if ((p_evt_write->handle == p_nus->cmd_tx_handles.cccd_handle) && (p_evt_write->len == 2)) { + if (ble_srv_is_notification_enabled(p_evt_write->data)) { + p_nus->cmd_tx_channel_is_notification_enabled = true; + } else { + p_nus->cmd_tx_channel_is_notification_enabled = false; + } + } else if ((p_evt_write->handle == p_nus->datablock_tx_handles.cccd_handle) && (p_evt_write->len == 2)) { + if (ble_srv_is_notification_enabled(p_evt_write->data)) { + p_nus->datablock_tx_channel_is_notification_enabled = true; + } else { + p_nus->datablock_tx_channel_is_notification_enabled = false; + } + } else if ((p_evt_write->handle == p_nus->cmd_rx_handles.value_handle) && (p_nus->data_handler != NULL)) { + evt.type = ZDATACHANNEL_EVT_RX_DATA; + evt.params.rx_data.p_data = p_evt_write->data; + evt.params.rx_data.length = p_evt_write->len; + + p_nus->data_handler(&evt); + } else { + // Do Nothing. This event is not relevant for this service. + } +} + +void zdatachannel_on_ble_evt(ble_evt_t const *p_ble_evt, void *p_context) { + if ((p_context == NULL) || (p_ble_evt == NULL)) { + return; + } + + zdatachannel_t *p_nus = (zdatachannel_t *)p_context; + + switch (p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + p_nus->conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + p_nus->cmd_tx_channel_is_notification_enabled = notification_enable(p_ble_evt->evt.gap_evt.conn_handle, p_nus->cmd_tx_handles.cccd_handle); + p_nus->datablock_tx_channel_is_notification_enabled = notification_enable(p_ble_evt->evt.gap_evt.conn_handle, p_nus->cmd_tx_handles.cccd_handle); + break; + case BLE_GAP_EVT_DISCONNECTED: + p_nus->conn_handle = BLE_CONN_HANDLE_INVALID; + break; + case BLE_GATTS_EVT_WRITE: + on_write(p_nus, p_ble_evt); + break; + default: + // No implementation needed. + break; + } +} + +uint32_t zdatachannel_init(zdatachannel_t *p_nus, zdatachannel_init_t const *p_nus_init) { + p_datachannel = p_nus; + ret_code_t err_code; + ble_uuid_t ble_uuid; + ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; + ble_add_char_params_t add_char_params; + + VERIFY_PARAM_NOT_NULL(p_nus); + VERIFY_PARAM_NOT_NULL(p_nus_init); + + // Initialize the service structure. + p_nus->data_handler = p_nus_init->data_handler; + + /**@snippet [Adding proprietary Service to the SoftDevice] */ + // Add a custom base UUID. + err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); + VERIFY_SUCCESS(err_code); + + ble_uuid.type = p_nus->uuid_type; + ble_uuid.uuid = ZDATACHANNEL_UUID_NUS_SERVICE; + + // Add the service. + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_nus->service_handle); + /**@snippet [Adding proprietary Service to the SoftDevice] */ + VERIFY_SUCCESS(err_code); + + // Add the RX Characteristic. + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = ZDATACHANNEL_RX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = ZDATACHANNEL_MAX_RX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.write = 1; + add_char_params.char_props.write_wo_resp = 1; + + add_char_params.read_access = SEC_NO_ACCESS; + add_char_params.write_access = SEC_OPEN; + + VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->cmd_rx_handles)); + + // Add the TX Characteristic. + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = ZDATACHANNEL_TX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = ZDATACHANNEL_MAX_TX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.cccd_write_access = SEC_OPEN; + + VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->cmd_tx_handles)); + + // Add the TX Characteristic. + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = ZDATACHANNEL_DATABLOCK_TX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = ZDATACHANNEL_DATABLOCK_TX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.cccd_write_access = SEC_OPEN; + + VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->datablock_tx_handles)); + + return NRF_SUCCESS; + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ +} + +uint32_t zdatachannel_data_send(uint8_t *p_data, uint16_t *p_length) { + ret_code_t err_code; + ble_gatts_hvx_params_t hvx_params; + + if (!p_datachannel->cmd_tx_channel_is_notification_enabled) { + return NRF_ERROR_INVALID_STATE; + } + + if (*p_length > ZDATACHANNEL_MAX_DATA_LEN) { + return NRF_ERROR_INVALID_PARAM; + } + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_datachannel->cmd_tx_handles.value_handle; + hvx_params.p_data = p_data; + hvx_params.p_len = p_length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + + return sd_ble_gatts_hvx(p_datachannel->conn_handle, &hvx_params); +} + +uint32_t zdatachannel_block_data_send(uint8_t *p_data, uint16_t *p_length) { + ret_code_t err_code; + ble_gatts_hvx_params_t hvx_params; + + if (!p_datachannel->datablock_tx_channel_is_notification_enabled) { + return NRF_ERROR_INVALID_STATE; + } + + if (*p_length > ZDATACHANNEL_MAX_DATA_LEN) { + return NRF_ERROR_INVALID_PARAM; + } + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_datachannel->datablock_tx_handles.value_handle; + hvx_params.p_data = p_data; + hvx_params.p_len = p_length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + + return sd_ble_gatts_hvx(p_datachannel->conn_handle, &hvx_params); +} diff --git a/app/src/basic/zdatachannel_service.h b/app/src/basic/zdatachannel_service.h new file mode 100644 index 0000000..7941ed7 --- /dev/null +++ b/app/src/basic/zdatachannel_service.h @@ -0,0 +1,89 @@ +#ifndef ZDATACHANNEL_H__ +#define ZDATACHANNEL_H__ + +#include +#include + +#include "ble.h" +#include "ble_link_ctx_manager.h" +#include "ble_srv_common.h" +#include "nrf_sdh_ble.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a ble_nus instance. + * + * @param _name Name of the instance. + * @param[in] _nus_max_clients Maximum number of NUS clients connected at a time. + * @hideinitializer + */ +#define ZDATACHANNEL_DEF(_name, _ble_observer_prio, _nus_max_clients) \ + static zdatachannel_t _name; \ + NRF_SDH_BLE_OBSERVER(_name##_obs, _ble_observer_prio, zdatachannel_on_ble_evt, &_name) + +#define OPCODE_LENGTH 1 +#define HANDLE_LENGTH 2 + +/**@brief Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */ +#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0) +#define ZDATACHANNEL_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH) +#else +#define ZDATACHANNEL_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH) +#warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined. +#endif + +/**@brief Nordic UART Service event types. */ +typedef enum { + ZDATACHANNEL_EVT_RX_DATA, /**< Data received. */ +} zdatachannel_evt_type_t; + +typedef struct zdatachannel_s zdatachannel_t; + +typedef struct { + uint8_t const* p_data; /**< A pointer to the buffer with received data. */ + uint16_t length; /**< Length of received data. */ +} zdatachannel_evt_rx_data_t; + +typedef struct { + zdatachannel_evt_type_t type; /**< Event type. */ + union { + zdatachannel_evt_rx_data_t rx_data; /**< @ref ZDATACHANNEL_EVT_RX_DATA event data. */ + } params; +} zdatachannel_evt_t; + +typedef void (*zdatachannel_data_handler_t)(zdatachannel_evt_t* p_evt); + +typedef struct { + zdatachannel_data_handler_t data_handler; +} zdatachannel_init_t; + +struct zdatachannel_s { + uint8_t uuid_type; /**< UUID type for Nordic UART Service Base UUID. */ + uint16_t service_handle; /**< Handle of Nordic UART Service (as provided by the SoftDevice). */ + ble_gatts_char_handles_t cmd_tx_handles; /**< 指令发送句柄 */ + ble_gatts_char_handles_t cmd_rx_handles; /**< 指令接收句柄 */ + ble_gatts_char_handles_t datablock_tx_handles; /**< 数据块发送句柄 */ + zdatachannel_data_handler_t data_handler; /**< Event handler to be called for handling received data. */ + + // 状态 + int16_t conn_handle; + bool cmd_tx_channel_is_notification_enabled; + bool datablock_tx_channel_is_notification_enabled; +}; + +uint32_t zdatachannel_init(zdatachannel_t* p_nus, zdatachannel_init_t const* p_nus_init); +void zdatachannel_on_ble_evt(ble_evt_t const* p_ble_evt, void* p_context); + +uint32_t zdatachannel_data_send(uint8_t* p_data, uint16_t* p_length); +uint32_t zdatachannel_block_data_send(uint8_t* p_data, uint16_t* p_length); + +#ifdef __cplusplus +} +#endif + +#endif // ZDATACHANNEL_H__ + +/** @} */ diff --git a/app/src/board.c b/app/src/board.c deleted file mode 100644 index b3df2c7..0000000 --- a/app/src/board.c +++ /dev/null @@ -1,350 +0,0 @@ -#include "board.h" - -#include "app_timer.h" -#include "nrf_gpio.h" -#include "sys.h" -// -#include "diskio_blkdev.h" -#include "ff.h" -#include "nrf_block_dev_sdc.h" -#include "nrf_delay.h" -#include "nrf_drv_pwm.h" -#include "nrf_drv_wdt.h" - -static int16_t adc_channel_read_val(uint16_t channel) { - nrf_saadc_value_t value; - ret_code_t err_code; - err_code = nrfx_saadc_sample_convert(channel, &value); - if (err_code != NRF_SUCCESS) { - ZLOGE("nrfx_saadc_sample_convert(%d) fail err_code:%d", channel, err_code); - return 0; - } - return value; -} - -/******************************************************************************* - * DEBUG_LIGHT * - *******************************************************************************/ -APP_TIMER_DEF(m_debug_light_tmr); -static int32_t m_debug_light_io_index; -static void debug_light_tmr_cb_handler(void* p_context) { - static bool state = false; - if (state) { - nrf_gpio_pin_set(m_debug_light_io_index); - } else { - nrf_gpio_pin_clear(m_debug_light_io_index); - } - state = !state; -} - -void debug_light_init(int io_index) { - m_debug_light_io_index = io_index; - - nrf_gpio_cfg(m_debug_light_io_index, // - NRF_GPIO_PIN_DIR_OUTPUT, // - NRF_GPIO_PIN_INPUT_DISCONNECT, // - NRF_GPIO_PIN_PULLUP, // - NRF_GPIO_PIN_S0S1, // - NRF_GPIO_PIN_NOSENSE); - - ret_code_t err_code; - err_code = app_timer_create(&m_debug_light_tmr, APP_TIMER_MODE_REPEATED, debug_light_tmr_cb_handler); - APP_ERROR_CHECK(err_code); - - app_timer_start(m_debug_light_tmr, APP_TIMER_TICKS(100), NULL); -} -/******************************************************************************* - * zbsp_enter_sleep * - *******************************************************************************/ -APP_TIMER_DEF(enter_sleep_mode_tmr); -static int32_t m_wakeup_io_index; -static bool m_wakeup_io_mirror; -static void enter_sleep_tmr_cb(void* p_context) { - ZLOGI("enter sleep mode, wakeup io index: %d", m_wakeup_io_index); - - if (m_wakeup_io_mirror) { - nrf_gpio_cfg_sense_input(m_wakeup_io_index, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW); - nrf_gpio_cfg_sense_set(m_wakeup_io_index, NRF_GPIO_PIN_SENSE_LOW); - } else { - nrf_gpio_cfg_sense_input(m_wakeup_io_index, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_HIGH); - nrf_gpio_cfg_sense_set(m_wakeup_io_index, NRF_GPIO_PIN_SENSE_HIGH); - } - - // Go to system-off mode (this function will not return; wakeup will cause a reset). - ret_code_t err_code; - err_code = sd_power_system_off(); - if (err_code != NRF_SUCCESS) { - ZLOGE("sd_power_system_off err_code: %x", err_code); - } -} -void zbsp_enter_sleep(int32_t after_ms, int32_t wakeup_io_index, bool mirror) { - m_wakeup_io_index = wakeup_io_index; - m_wakeup_io_mirror = mirror; - ret_code_t err_code; - APP_ERROR_CHECK(app_timer_create(&enter_sleep_mode_tmr, APP_TIMER_MODE_SINGLE_SHOT, enter_sleep_tmr_cb)); - APP_ERROR_CHECK(app_timer_start(enter_sleep_mode_tmr, APP_TIMER_TICKS(after_ms), NULL)); - - ZLOGI("enter sleep mode after %d ms", after_ms); -} - -/******************************************************************************* - * gpio_io_state_monitor * - *******************************************************************************/ -APP_TIMER_DEF(gpio_io_state_monitor_tmr); -static uint8_t* m_io_index; -static int32_t m_nio; -static void gpio_io_state_monitor_tmr_cb(void* p_context) { - // ioindex:state ioindex:state ioindex:state - if (m_nio == 1) { - ZLOGI("iostate %d:%d ", m_io_index[0], nrf_gpio_pin_read(m_io_index[0])); - } else if (m_nio == 2) { - ZLOGI("iostate %d:%d %d:%d", m_io_index[0], nrf_gpio_pin_read(m_io_index[0]), // - m_io_index[1], nrf_gpio_pin_read(m_io_index[1])); - } else if (m_nio >= 3) { - ZLOGI("iostate %d:%d %d:%d %d:%d", m_io_index[0], nrf_gpio_pin_read(m_io_index[0]), // - m_io_index[1], nrf_gpio_pin_read(m_io_index[1]), // - m_io_index[2], nrf_gpio_pin_read(m_io_index[2])); - } -} - -void zbsp_gpio_state_monitor_without_initio(int dumpstate_period, uint8_t* io_index, int32_t nio) { - m_io_index = io_index; - m_nio = nio; - APP_ERROR_CHECK(app_timer_create(&gpio_io_state_monitor_tmr, APP_TIMER_MODE_REPEATED, gpio_io_state_monitor_tmr_cb)); - APP_ERROR_CHECK(app_timer_start(gpio_io_state_monitor_tmr, APP_TIMER_TICKS(dumpstate_period), NULL)); -} -void zbsp_gpio_state_monitor(int dumpstate_period, uint8_t* io_index, int32_t nio) { - m_io_index = io_index; - m_nio = nio; - for (int i = 0; i < nio; i++) { - nrf_gpio_cfg_input(io_index[i], NRF_GPIO_PIN_PULLUP); - } - zbsp_gpio_state_monitor_without_initio(dumpstate_period, io_index, nio); -} - -void board_init() {} - -/******************************************************************************* - * ADC * - *******************************************************************************/ - -static void saadc_callback(nrf_drv_saadc_evt_t const* p_event) { - if (p_event->type == NRF_DRV_SAADC_EVT_DONE) { - } -} - -void adc_module_init() { - nrf_drv_saadc_config_t adccfg = NRFX_SAADC_DEFAULT_CONFIG; - adccfg.resolution = NRF_SAADC_RESOLUTION_12BIT; // 4096 等于满采样率 - ZERROR_CHECK(nrf_drv_saadc_init(&adccfg, saadc_callback)); -} - -void adc_module_battery_channel_init(nrf_saadc_input_t channelpin) { - nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(channelpin); - ZERROR_CHECK(nrfx_saadc_channel_init(0, &channel_config)); -} -int16_t adc_module_battery_channel_read_val() { return adc_channel_read_val(0); } - -void adc_module_heart_elect_channel_init(nrf_saadc_input_t channelpin) { - nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(channelpin); - channel_config.acq_time = NRF_SAADC_ACQTIME_40US; - ZERROR_CHECK(nrfx_saadc_channel_init(1, &channel_config)); -} -int16_t adc_module_heart_elect_channel_read_val() { return adc_channel_read_val(1); } -/******************************************************************************* - * SPI * - *******************************************************************************/ -#define SPI_MISO_PIN 31 -#define SPI_SS_PIN 20 -#define SPI_SCK_PIN 29 -#define SPI_MOSI_PIN 30 -static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(0); /**< SPI instance. */ - -// static volatile bool m_spi_translate_done = false; -// static void spi_event_handler(nrf_drv_spi_evt_t const* p_event, void* p_context) { m_spi_translate_done = true; } -void board_spi_init() { - nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; - spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; // NRF_DRV_SPI_PIN_NOT_USED - spi_config.miso_pin = SPI_MISO_PIN; - spi_config.mosi_pin = SPI_MOSI_PIN; - spi_config.sck_pin = SPI_SCK_PIN; - spi_config.frequency = NRF_DRV_SPI_FREQ_1M; - ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); -} -ret_code_t board_spi_transfer(uint8_t const* p_tx_buffer, uint8_t tx_buffer_length, uint8_t* p_rx_buffer, uint8_t rx_buffer_length) { - // m_spi_translate_done = false; - ZERROR_CHECK(nrf_drv_spi_transfer(&spi, p_tx_buffer, tx_buffer_length, p_rx_buffer, rx_buffer_length)); - // while (!m_spi_translate_done) - // ; - return NRF_SUCCESS; -} - -ret_code_t board_spi_transfer_test() { - uint8_t tx_data[] = {0x01, 0x02, 0x03}; - uint8_t rx_data[3]; - ZERROR_CHECK(board_spi_transfer(tx_data, 3, rx_data, 3)); -} - -void screen_init() {} -void screen_spi_translate_onebyte() {} - -static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0); -static nrf_pwm_values_individual_t m_demo1_seq_values; - -void pwm_trigger() { - nrf_drv_pwm_config_t const config0 = { - .output_pins = {11}, - .irq_priority = APP_IRQ_PRIORITY_LOWEST, - .base_clock = NRF_PWM_CLK_125kHz, - .count_mode = NRF_PWM_MODE_UP, - .top_value = 10, - .load_mode = NRF_PWM_LOAD_INDIVIDUAL, - .step_mode = NRF_PWM_STEP_AUTO, - }; - APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL)); - - static nrf_pwm_sequence_t const m_demo1_seq = { - .values.p_individual = &m_demo1_seq_values, - .length = NRF_PWM_VALUES_LENGTH(m_demo1_seq_values), - .repeats = 0, - .end_delay = 0, - }; - - m_demo1_seq_values.channel_0 = 8; - m_demo1_seq_values.channel_1 = 0; - m_demo1_seq_values.channel_2 = 0; - m_demo1_seq_values.channel_3 = 0; - - (void)nrf_drv_pwm_simple_playback(&m_pwm0, &m_demo1_seq, 1, NRF_DRV_PWM_FLAG_LOOP); -} - -/******************************************************************************* - * I2C * - *******************************************************************************/ - -#define TWI_SCL_M 30 // I2C SCL引脚 -#define TWI_SDA_M 31 // I2C SDA引脚 -static const nrf_drv_twi_t m_twi_master = NRF_DRV_TWI_INSTANCE(1); - -void board_i2c_init() { - const nrf_drv_twi_config_t config = { - .scl = TWI_SCL_M, - .sda = TWI_SDA_M, - .frequency = NRF_DRV_TWI_FREQ_100K, - .interrupt_priority = APP_IRQ_PRIORITY_HIGH, - .clear_bus_init = false, - }; - - ZERROR_CHECK(nrf_drv_twi_init(&m_twi_master, &config, NULL, NULL)); - - nrf_drv_twi_enable(&m_twi_master); -} - -void board_i2c_write(uint8_t addr, uint8_t* data, uint8_t len) { nrf_drv_twi_tx(&m_twi_master, addr, data, len, false); } - -#define FILE_NAME "NORDIC.TXT" -#define TEST_STRING "SD card example." - -// #define SPI_MISO_PIN 31 -// #define SPI_SS_PIN 20 -// #define SPI_SCK_PIN 29 -// #define SPI_MOSI_PIN 30 - -#define SDC_SCK_PIN 29 ///< SDC serial clock (SCK) pin. -#define SDC_MOSI_PIN 30 ///< SDC serial data in (DI) pin. -#define SDC_MISO_PIN 31 ///< SDC serial data out (DO) pin. -#define SDC_CS_PIN 20 ///< SDC chip select (CS) pin. - -NRF_BLOCK_DEV_SDC_DEFINE(m_block_dev_sdc, NRF_BLOCK_DEV_SDC_CONFIG(SDC_SECTOR_SIZE, APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN)), NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")); -void fatfs_init() { - // // Initialize FATFS disk I/O interface by providing the block device. - static diskio_blkdev_t drives[] = {DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)}; - - diskio_blockdev_register(drives, ARRAY_SIZE(drives)); - fatfs_test_write(); -} -void fatfs_test_write() { - static FATFS fs; - static DIR dir; - static FILINFO fno; - static FIL file; - - uint32_t bytes_written; - FRESULT ff_result; - DSTATUS disk_state = STA_NOINIT; - - for (uint32_t retries = 3; retries && disk_state; --retries) { - disk_state = disk_initialize(0); - } - if (disk_state) { - NRF_LOG_INFO("Disk initialization failed. %d", disk_state); - return; - } - return; - // NRF_LOG_INFO("Initializing disk 0 (SDC)..."); - - uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size; - uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb; - NRF_LOG_INFO("Capacity: %d MB", capacity); - - NRF_LOG_INFO("Mounting volume..."); - ff_result = f_mount(&fs, "", 1); - if (ff_result) { - NRF_LOG_INFO("Mount failed."); - return; - } - - NRF_LOG_INFO("\r\n Listing directory: /"); - ff_result = f_opendir(&dir, "/"); - if (ff_result) { - NRF_LOG_INFO("Directory listing failed!"); - return; - } - - do { - ff_result = f_readdir(&dir, &fno); - if (ff_result != FR_OK) { - NRF_LOG_INFO("Directory read failed."); - return; - } - - if (fno.fname[0]) { - if (fno.fattrib & AM_DIR) { - NRF_LOG_RAW_INFO(" %s", (uint32_t)fno.fname); - } else { - NRF_LOG_RAW_INFO("%9lu %s", fno.fsize, (uint32_t)fno.fname); - } - } - } while (fno.fname[0]); - NRF_LOG_RAW_INFO(""); - - NRF_LOG_INFO("Writing to file " FILE_NAME "..."); - ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND); - if (ff_result != FR_OK) { - NRF_LOG_INFO("Unable to open or create file: " FILE_NAME "."); - return; - } - - ff_result = f_write(&file, TEST_STRING, sizeof(TEST_STRING) - 1, (UINT*)&bytes_written); - if (ff_result != FR_OK) { - NRF_LOG_INFO("Write failed\r\n."); - } else { - NRF_LOG_INFO("%d bytes written.", bytes_written); - } - - (void)f_close(&file); - return; -} -nrf_drv_wdt_channel_id m_channel_id; - -void wd_init() { - // WDT_CONFIG_RELOAD_VALUE 修改这个数值修改喂狗周期,单位ms - nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG; - config.reload_value = WDT_CONFIG_RELOAD_VALUE; - ret_code_t err_code = nrf_drv_wdt_init(&config, NULL); - ZERROR_CHECK(err_code); - err_code = nrf_drv_wdt_channel_alloc(&m_channel_id); - ZERROR_CHECK(err_code); - nrf_drv_wdt_enable(); -} -void wd_feed() { nrfx_wdt_feed(); } \ No newline at end of file diff --git a/app/src/board.h b/app/src/board.h deleted file mode 100644 index e36e8fb..0000000 --- a/app/src/board.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include - -#include "nrf_drv_saadc.h" -#include "nrf_drv_twi.h" -#include "sys.h" - -/******************************************************************************* - * DEBUG_LIGHT * - *******************************************************************************/ -void debug_light_init(int io_index); - -/******************************************************************************* - * zbsp_enter_sleep * - *******************************************************************************/ - -/** - * @brief 调用此方法前,需要确保底层协议栈已经初始化 - * - * @param after_ms - * @param wakeup_io_index - */ -void zbsp_enter_sleep(int32_t after_ms, int32_t wakeup_io_index, bool mirror); - -/******************************************************************************* - * gpio_io_state_monitor * - *******************************************************************************/ -void zbsp_gpio_state_monitor(int dumpstate_period, uint8_t* io_index, int32_t nio); -void zbsp_gpio_state_monitor_without_initio(int dumpstate_period, uint8_t* io_index, int32_t nio); - -void board_init(); - -/******************************************************************************* - * ADC * - *******************************************************************************/ - -void adc_module_init(); - -void adc_module_battery_channel_init(nrf_saadc_input_t channelpin); -int16_t adc_module_battery_channel_read_val(); - -void adc_module_heart_elect_channel_init(nrf_saadc_input_t channelpin); -int16_t adc_module_heart_elect_channel_read_val(); - -/******************************************************************************* - * SPI * - *******************************************************************************/ - -void board_spi_init(); -ret_code_t board_spi_transfer(uint8_t const* p_tx_buffer, uint8_t tx_buffer_length, uint8_t* p_rx_buffer, uint8_t rx_buffer_length); -ret_code_t board_spi_transfer_test(); - -void board_i2c_init(); -void board_i2c_write(uint8_t addr, uint8_t* data, uint8_t len); - -void screen_init(); -void screen_spi_translate_onebyte(); - -/******************************************************************************* - * FATFS * - *******************************************************************************/ -void fatfs_init(); -void fatfs_test_write(); -void pwm_trigger(); - -void wd_init(); -void wd_feed(); \ No newline at end of file diff --git a/app/src/one_conduction/one_conduction_board.c b/app/src/one_conduction/one_conduction_board.c new file mode 100644 index 0000000..e69de29 diff --git a/app/src/one_conduction/one_conduction_board.h b/app/src/one_conduction/one_conduction_board.h new file mode 100644 index 0000000..95300f1 --- /dev/null +++ b/app/src/one_conduction/one_conduction_board.h @@ -0,0 +1,4 @@ +#pragma once +#define VERSION 1 +#define MANUFACTURER_NAME "iflytop" +#define BLE_NAME "iflytop_test" \ No newline at end of file diff --git a/app/src/one_conduction/one_conduction_main.c b/app/src/one_conduction/one_conduction_main.c new file mode 100644 index 0000000..d4955c4 --- /dev/null +++ b/app/src/one_conduction/one_conduction_main.c @@ -0,0 +1,73 @@ +#include "basic/zble_module.h" +#include "basic/zdatachannel_service.h" +#include "one_conduction_board.h" +#include "sys.h" + +ZDATACHANNEL_DEF(m_zhrs, 2 /*回调事件优先级*/, 1 /*client num*/); + +/******************************************************************************* + * TOOLS * + *******************************************************************************/ +static const char* hex2str(const uint8_t* data, int32_t len) { + static char rx[64] = {0}; + memset(rx, 0, sizeof(rx)); + for (int32_t i = 0; i < len; i++) { + sprintf(rx + i * 2, "%02X", data[i]); + } + return rx; +} + +/******************************************************************************* + * CB * + *******************************************************************************/ + +// static void ble_evt_handler(ble_evt_t const* p_ble_evt, void* p_context) { +// switch (p_ble_evt->header.evt_id) { +// case BLE_GAP_EVT_CONNECTED: +// ZLOGI("Connected"); +// break; + +// case BLE_GAP_EVT_DISCONNECTED: +// ZLOGI("Disconnected"); +// break; +// } +// } + +void zdatachannel_data_handler(zdatachannel_evt_t* p_evt) { + /** + * @brief 接收到指令数据 + */ + if (p_evt->type == ZDATACHANNEL_EVT_RX_DATA) { + ZLOGI("rx:%s", hex2str(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length)); + } +} +/******************************************************************************* + * INIT * + *******************************************************************************/ +void on_service_init(void) { + /** + * @brief 数据通道初始化 + */ + ZLOGI("init zdatachannel service"); + zdatachannel_init_t zdatachannle_init; + memset(&zdatachannle_init, 0, sizeof(zdatachannle_init)); + zdatachannle_init.data_handler = zdatachannel_data_handler; + ZERROR_CHECK(zdatachannel_init(&m_zhrs, &zdatachannle_init)); +} + +void one_conduction_main() { + zsys_init(); + NRF_LOG_INFO("compile time :%s", __TIME__); + NRF_LOG_INFO("Version :%d", VERSION); + NRF_LOG_INFO("Manufacturer :%s", MANUFACTURER_NAME); + + static zble_module_cfg_t cfg = // + { + .deviceName = BLE_NAME, + .on_service_init = on_service_init, + }; + zble_module_init(&cfg); + + zble_module_start_adv(); + zsys_loop(); +} diff --git a/app/src/one_conduction/one_conduction_main.h b/app/src/one_conduction/one_conduction_main.h new file mode 100644 index 0000000..92c6329 --- /dev/null +++ b/app/src/one_conduction/one_conduction_main.h @@ -0,0 +1,3 @@ +#pragma once + +void one_conduction_main(); \ No newline at end of file diff --git a/app/src/project_cfg.h b/app/src/project_cfg.h deleted file mode 100644 index a0ece75..0000000 --- a/app/src/project_cfg.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#define DEBUG_LIGHT_IO_INDEX 13 \ No newline at end of file diff --git a/app/src/three_conduction/three_conduction_board.c b/app/src/three_conduction/three_conduction_board.c new file mode 100644 index 0000000..e69de29 diff --git a/app/src/three_conduction/three_conduction_board.h b/app/src/three_conduction/three_conduction_board.h new file mode 100644 index 0000000..e69de29 diff --git a/app/src/three_conduction/three_conduction_main.c b/app/src/three_conduction/three_conduction_main.c new file mode 100644 index 0000000..e69de29 diff --git a/app/src/three_conduction/three_conduction_main.h b/app/src/three_conduction/three_conduction_main.h new file mode 100644 index 0000000..e69de29 diff --git a/app/src/version.h b/app/src/version.h deleted file mode 100644 index 0c3edf1..0000000 --- a/app/src/version.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -#define VERSION 1 -#define MANUFACTURER_NAME "iflytop" \ No newline at end of file diff --git a/app/src/zble_module.c b/app/src/zble_module.c deleted file mode 100644 index 26c36bf..0000000 --- a/app/src/zble_module.c +++ /dev/null @@ -1,255 +0,0 @@ - - -#include "zble_module.h" - -#include -#include - -#include "sys.h" -/******************************************************************************* - * 广播包配置 * - *******************************************************************************/ -#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */ -#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */ -#define SLAVE_LATENCY 0 /**< Slave latency. */ -#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */ -#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */ -static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ - {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; -#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */ -#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ -BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ - -/******************************************************************************* - * GATT配置 * - *******************************************************************************/ -NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ - -/******************************************************************************* - * 连接参数配置 * - *******************************************************************************/ -#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ -#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ -#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ - -/******************************************************************************* - * CODE * - *******************************************************************************/ - -static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< 当前连接句柄 */ -static uint16_t m_mtu_size = BLE_GATT_ATT_MTU_DEFAULT - 3; - -/**@brief Function for putting the chip into sleep mode. - * - * @note This function will not return. - */ -static void sleep_mode_enter(void) { -#if 0 - uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); - ZERROR_CHECK(err_code); - - // Prepare wakeup buttons. - err_code = bsp_btn_ble_sleep_mode_prepare(); - ZERROR_CHECK(err_code); - - // Go to system-off mode (this function will not return; wakeup will cause a reset). - err_code = sd_power_system_off(); - ZERROR_CHECK(err_code); -#endif -} - -static void ble_evt_handler(ble_evt_t const* p_ble_evt, void* p_context) { - uint32_t err_code; - switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - break; - - case BLE_GAP_EVT_DISCONNECTED: - m_conn_handle = BLE_CONN_HANDLE_INVALID; - break; - - case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { - NRF_LOG_DEBUG("PHY update request."); - ble_gap_phys_t const phys = { - .rx_phys = BLE_GAP_PHY_AUTO, - .tx_phys = BLE_GAP_PHY_AUTO, - }; - err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); - ZERROR_CHECK(err_code); - } break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - // Pairing not supported - err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); - ZERROR_CHECK(err_code); - break; - - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - // No system attributes have been stored. - err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); - ZERROR_CHECK(err_code); - break; - - case BLE_GATTC_EVT_TIMEOUT: - // Disconnect on GATT Client timeout event. - err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); - ZERROR_CHECK(err_code); - break; - - case BLE_GATTS_EVT_TIMEOUT: - // Disconnect on GATT Server timeout event. - err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); - ZERROR_CHECK(err_code); - break; - - default: - // No implementation needed. - break; - } -} -static void gatt_evt_handler(nrf_ble_gatt_t* p_gatt, nrf_ble_gatt_evt_t const* p_evt) { - /******************************************************************************* - * MTU SIZE 更新 * - *******************************************************************************/ - if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { - m_mtu_size = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; - NRF_LOG_DEBUG("ATT MTU exchange completed. central %d peripheral %d", p_gatt->att_mtu_desired_central, p_gatt->att_mtu_desired_periph); - } -} -static void on_conn_params_evt(ble_conn_params_evt_t* p_evt) { - uint32_t err_code; - if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { - err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); - ZERROR_CHECK(err_code); - } -} -static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } -static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { - uint32_t err_code; - switch (ble_adv_evt) { - case BLE_ADV_EVT_FAST: - // err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); - // ZERROR_CHECK(err_code); - break; - case BLE_ADV_EVT_IDLE: - // sleep_mode_enter(); - break; - default: - break; - } -} - -void zble_module_start_adv() { - uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); - ZERROR_CHECK(err_code); -} -void zble_module_stop_adv() { - uint32_t err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle); - ZERROR_CHECK(err_code); -} - -/******************************************************************************* - * INIT * - *******************************************************************************/ -void zble_module_init(zble_module_cfg_t* cfg) { - /** - * @brief - * 初始化蓝牙协议栈,并注册蓝牙事件处理函数,固定代码,勿修改 - */ - { NRF_SDH_BLE_OBSERVER(m_ble_observer, 3, ble_evt_handler, NULL); } - /******************************************************************************* - * GAP初始化 * - *******************************************************************************/ - { - uint32_t err_code; - ble_gap_conn_params_t gap_conn_params; - ble_gap_conn_sec_mode_t sec_mode; - - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - - err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t*)cfg->deviceName, strlen(cfg->deviceName)); - ZERROR_CHECK(err_code); - - memset(&gap_conn_params, 0, sizeof(gap_conn_params)); - - gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; - gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; - gap_conn_params.slave_latency = SLAVE_LATENCY; - gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; - - err_code = sd_ble_gap_ppcp_set(&gap_conn_params); - ZERROR_CHECK(err_code); - } - - /******************************************************************************* - * GATT 初始化 * - *******************************************************************************/ - { - ret_code_t err_code; - - err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); - ZERROR_CHECK(err_code); - - err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); - ZERROR_CHECK(err_code); - } - - /******************************************************************************* - * 蓝牙服务初始化 * - *******************************************************************************/ - { - if (cfg->on_service_init) cfg->on_service_init(); - } - - /******************************************************************************* - * 广播初始化 * - *******************************************************************************/ - { - uint32_t err_code; - ble_advertising_init_t init; - - memset(&init, 0, sizeof(init)); - - init.advdata.name_type = BLE_ADVDATA_FULL_NAME; - init.advdata.include_appearance = false; - // init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; - init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; - - init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); - init.srdata.uuids_complete.p_uuids = m_adv_uuids; - - init.config.ble_adv_fast_enabled = true; - init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; - init.config.ble_adv_fast_timeout = 0; - init.evt_handler = on_adv_evt; - - err_code = ble_advertising_init(&m_advertising, &init); - ZERROR_CHECK(err_code); - - ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); - } - /******************************************************************************* - * 连接参数初始化 * - *******************************************************************************/ - { - uint32_t err_code; - ble_conn_params_init_t cp_init; - - memset(&cp_init, 0, sizeof(cp_init)); - - cp_init.p_conn_params = NULL; - cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; - cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; - cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; - cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; - cp_init.disconnect_on_fail = false; - cp_init.evt_handler = on_conn_params_evt; - cp_init.error_handler = conn_params_error_handler; - - err_code = ble_conn_params_init(&cp_init); - ZERROR_CHECK(err_code); - } - - // zble_module_start_adv(); -} \ No newline at end of file diff --git a/app/src/zble_module.h b/app/src/zble_module.h deleted file mode 100644 index a630a0a..0000000 --- a/app/src/zble_module.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include - -/** - * @brief - */ - -typedef void (*on_service_init_t)(void); - -typedef struct { - const char* deviceName; - on_service_init_t on_service_init; -} zble_module_cfg_t; - -void zble_module_init(zble_module_cfg_t* cfg); - -void zble_module_start_adv(); -void zble_module_stop_adv(); - -void zble_module_is_connected(); diff --git a/app/src/zdatachannel_service.c b/app/src/zdatachannel_service.c deleted file mode 100644 index 7a9e2af..0000000 --- a/app/src/zdatachannel_service.c +++ /dev/null @@ -1,216 +0,0 @@ -#include "zdatachannel_service.h" - -#include "ble.h" -#include "ble_srv_common.h" -#include "nrf_log.h" -#include "sdk_common.h" - -#define ZDATACHANNEL_UUID_NUS_SERVICE 0x0001 /**< The UUID of the Nordic UART Service. */ -#define ZDATACHANNEL_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */ -#define ZDATACHANNEL_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */ -#define ZDATACHANNEL_DATABLOCK_TX_CHARACTERISTIC 0x0004 /**< The UUID of the RX Characteristic. */ - -#define ZDATACHANNEL_MAX_RX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ -#define ZDATACHANNEL_MAX_TX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ -#define ZDATACHANNEL_DATABLOCK_TX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ - -#define NUS_BASE_UUID \ - { \ - { 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E } \ - } /**< Used vendor specific UUID. */ - -static zdatachannel_t *p_datachannel; - -static bool notification_enable(uint16_t conn_handle, uint16_t cccd_handle) { - ret_code_t err_code; - ble_gatts_value_t gatts_val; - uint8_t cccd_value[2]; - memset(&gatts_val, 0, sizeof(ble_gatts_value_t)); - gatts_val.p_value = cccd_value; - gatts_val.len = sizeof(cccd_value); - gatts_val.offset = 0; - err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &gatts_val); - if ((err_code == NRF_SUCCESS) && ble_srv_is_notification_enabled(gatts_val.p_value)) { - return true; - } - return false; -} - -/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. - * - * @param[in] p_nus Nordic UART Service structure. - * @param[in] p_ble_evt Pointer to the event received from BLE stack. - */ -static void on_write(zdatachannel_t *p_nus, ble_evt_t const *p_ble_evt) { - zdatachannel_evt_t evt; - ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; - - memset(&evt, 0, sizeof(zdatachannel_evt_t)); - - if ((p_evt_write->handle == p_nus->cmd_tx_handles.cccd_handle) && (p_evt_write->len == 2)) { - if (ble_srv_is_notification_enabled(p_evt_write->data)) { - p_nus->cmd_tx_channel_is_notification_enabled = true; - } else { - p_nus->cmd_tx_channel_is_notification_enabled = false; - } - } else if ((p_evt_write->handle == p_nus->datablock_tx_handles.cccd_handle) && (p_evt_write->len == 2)) { - if (ble_srv_is_notification_enabled(p_evt_write->data)) { - p_nus->datablock_tx_channel_is_notification_enabled = true; - } else { - p_nus->datablock_tx_channel_is_notification_enabled = false; - } - } else if ((p_evt_write->handle == p_nus->cmd_tx_handles.value_handle) && (p_nus->data_handler != NULL)) { - evt.type = ZDATACHANNEL_EVT_RX_DATA; - evt.params.rx_data.p_data = p_evt_write->data; - evt.params.rx_data.length = p_evt_write->len; - - p_nus->data_handler(&evt); - } else { - // Do Nothing. This event is not relevant for this service. - } -} - -void zdatachannel_on_ble_evt(ble_evt_t const *p_ble_evt, void *p_context) { - if ((p_context == NULL) || (p_ble_evt == NULL)) { - return; - } - - zdatachannel_t *p_nus = (zdatachannel_t *)p_context; - - switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - p_nus->conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - p_nus->cmd_tx_channel_is_notification_enabled = notification_enable(p_ble_evt->evt.gap_evt.conn_handle, p_nus->cmd_tx_handles.cccd_handle); - p_nus->datablock_tx_channel_is_notification_enabled = notification_enable(p_ble_evt->evt.gap_evt.conn_handle, p_nus->cmd_tx_handles.cccd_handle); - break; - case BLE_GAP_EVT_DISCONNECTED: - p_nus->conn_handle = BLE_CONN_HANDLE_INVALID; - break; - case BLE_GATTS_EVT_WRITE: - on_write(p_nus, p_ble_evt); - break; - default: - // No implementation needed. - break; - } -} - -uint32_t zdatachannel_init(zdatachannel_t *p_nus, zdatachannel_init_t const *p_nus_init) { - p_datachannel = p_nus; - ret_code_t err_code; - ble_uuid_t ble_uuid; - ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; - ble_add_char_params_t add_char_params; - - VERIFY_PARAM_NOT_NULL(p_nus); - VERIFY_PARAM_NOT_NULL(p_nus_init); - - // Initialize the service structure. - p_nus->data_handler = p_nus_init->data_handler; - - /**@snippet [Adding proprietary Service to the SoftDevice] */ - // Add a custom base UUID. - err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); - VERIFY_SUCCESS(err_code); - - ble_uuid.type = p_nus->uuid_type; - ble_uuid.uuid = ZDATACHANNEL_UUID_NUS_SERVICE; - - // Add the service. - err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_nus->service_handle); - /**@snippet [Adding proprietary Service to the SoftDevice] */ - VERIFY_SUCCESS(err_code); - - // Add the RX Characteristic. - memset(&add_char_params, 0, sizeof(add_char_params)); - add_char_params.uuid = ZDATACHANNEL_RX_CHARACTERISTIC; - add_char_params.uuid_type = p_nus->uuid_type; - add_char_params.max_len = ZDATACHANNEL_MAX_RX_CHAR_LEN; - add_char_params.init_len = sizeof(uint8_t); - add_char_params.is_var_len = true; - add_char_params.char_props.write = 1; - add_char_params.char_props.write_wo_resp = 1; - - add_char_params.read_access = SEC_NO_ACCESS; - add_char_params.write_access = SEC_OPEN; - - VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->cmd_rx_handles)); - - // Add the TX Characteristic. - /**@snippet [Adding proprietary characteristic to the SoftDevice] */ - memset(&add_char_params, 0, sizeof(add_char_params)); - add_char_params.uuid = ZDATACHANNEL_TX_CHARACTERISTIC; - add_char_params.uuid_type = p_nus->uuid_type; - add_char_params.max_len = ZDATACHANNEL_MAX_TX_CHAR_LEN; - add_char_params.init_len = sizeof(uint8_t); - add_char_params.is_var_len = true; - add_char_params.char_props.notify = 1; - - add_char_params.read_access = SEC_OPEN; - add_char_params.write_access = SEC_OPEN; - add_char_params.cccd_write_access = SEC_OPEN; - - VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->cmd_tx_handles)); - - // Add the TX Characteristic. - /**@snippet [Adding proprietary characteristic to the SoftDevice] */ - memset(&add_char_params, 0, sizeof(add_char_params)); - add_char_params.uuid = ZDATACHANNEL_DATABLOCK_TX_CHARACTERISTIC; - add_char_params.uuid_type = p_nus->uuid_type; - add_char_params.max_len = ZDATACHANNEL_DATABLOCK_TX_CHAR_LEN; - add_char_params.init_len = sizeof(uint8_t); - add_char_params.is_var_len = true; - add_char_params.char_props.notify = 1; - - add_char_params.read_access = SEC_OPEN; - add_char_params.write_access = SEC_OPEN; - add_char_params.cccd_write_access = SEC_OPEN; - - VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->datablock_tx_handles)); - - return NRF_SUCCESS; - /**@snippet [Adding proprietary characteristic to the SoftDevice] */ -} - -uint32_t zdatachannel_data_send(uint8_t *p_data, uint16_t *p_length) { - ret_code_t err_code; - ble_gatts_hvx_params_t hvx_params; - - if (!p_datachannel->cmd_tx_channel_is_notification_enabled) { - return NRF_ERROR_INVALID_STATE; - } - - if (*p_length > ZDATACHANNEL_MAX_DATA_LEN) { - return NRF_ERROR_INVALID_PARAM; - } - - memset(&hvx_params, 0, sizeof(hvx_params)); - - hvx_params.handle = p_datachannel->cmd_tx_handles.value_handle; - hvx_params.p_data = p_data; - hvx_params.p_len = p_length; - hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - - return sd_ble_gatts_hvx(p_datachannel->conn_handle, &hvx_params); -} - -uint32_t zdatachannel_block_data_send(uint8_t *p_data, uint16_t *p_length) { - ret_code_t err_code; - ble_gatts_hvx_params_t hvx_params; - - if (!p_datachannel->datablock_tx_channel_is_notification_enabled) { - return NRF_ERROR_INVALID_STATE; - } - - if (*p_length > ZDATACHANNEL_MAX_DATA_LEN) { - return NRF_ERROR_INVALID_PARAM; - } - memset(&hvx_params, 0, sizeof(hvx_params)); - - hvx_params.handle = p_datachannel->datablock_tx_handles.value_handle; - hvx_params.p_data = p_data; - hvx_params.p_len = p_length; - hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - - return sd_ble_gatts_hvx(p_datachannel->conn_handle, &hvx_params); -} diff --git a/app/src/zdatachannel_service.h b/app/src/zdatachannel_service.h deleted file mode 100644 index 7941ed7..0000000 --- a/app/src/zdatachannel_service.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef ZDATACHANNEL_H__ -#define ZDATACHANNEL_H__ - -#include -#include - -#include "ble.h" -#include "ble_link_ctx_manager.h" -#include "ble_srv_common.h" -#include "nrf_sdh_ble.h" -#include "sdk_config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Macro for defining a ble_nus instance. - * - * @param _name Name of the instance. - * @param[in] _nus_max_clients Maximum number of NUS clients connected at a time. - * @hideinitializer - */ -#define ZDATACHANNEL_DEF(_name, _ble_observer_prio, _nus_max_clients) \ - static zdatachannel_t _name; \ - NRF_SDH_BLE_OBSERVER(_name##_obs, _ble_observer_prio, zdatachannel_on_ble_evt, &_name) - -#define OPCODE_LENGTH 1 -#define HANDLE_LENGTH 2 - -/**@brief Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */ -#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0) -#define ZDATACHANNEL_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH) -#else -#define ZDATACHANNEL_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH) -#warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined. -#endif - -/**@brief Nordic UART Service event types. */ -typedef enum { - ZDATACHANNEL_EVT_RX_DATA, /**< Data received. */ -} zdatachannel_evt_type_t; - -typedef struct zdatachannel_s zdatachannel_t; - -typedef struct { - uint8_t const* p_data; /**< A pointer to the buffer with received data. */ - uint16_t length; /**< Length of received data. */ -} zdatachannel_evt_rx_data_t; - -typedef struct { - zdatachannel_evt_type_t type; /**< Event type. */ - union { - zdatachannel_evt_rx_data_t rx_data; /**< @ref ZDATACHANNEL_EVT_RX_DATA event data. */ - } params; -} zdatachannel_evt_t; - -typedef void (*zdatachannel_data_handler_t)(zdatachannel_evt_t* p_evt); - -typedef struct { - zdatachannel_data_handler_t data_handler; -} zdatachannel_init_t; - -struct zdatachannel_s { - uint8_t uuid_type; /**< UUID type for Nordic UART Service Base UUID. */ - uint16_t service_handle; /**< Handle of Nordic UART Service (as provided by the SoftDevice). */ - ble_gatts_char_handles_t cmd_tx_handles; /**< 指令发送句柄 */ - ble_gatts_char_handles_t cmd_rx_handles; /**< 指令接收句柄 */ - ble_gatts_char_handles_t datablock_tx_handles; /**< 数据块发送句柄 */ - zdatachannel_data_handler_t data_handler; /**< Event handler to be called for handling received data. */ - - // 状态 - int16_t conn_handle; - bool cmd_tx_channel_is_notification_enabled; - bool datablock_tx_channel_is_notification_enabled; -}; - -uint32_t zdatachannel_init(zdatachannel_t* p_nus, zdatachannel_init_t const* p_nus_init); -void zdatachannel_on_ble_evt(ble_evt_t const* p_ble_evt, void* p_context); - -uint32_t zdatachannel_data_send(uint8_t* p_data, uint16_t* p_length); -uint32_t zdatachannel_block_data_send(uint8_t* p_data, uint16_t* p_length); - -#ifdef __cplusplus -} -#endif - -#endif // ZDATACHANNEL_H__ - -/** @} */ diff --git a/libznordic b/libznordic index dea8cb2..e20cb4c 160000 --- a/libznordic +++ b/libznordic @@ -1 +1 @@ -Subproject commit dea8cb28511e92e1566da73974a24f74ec9bcab6 +Subproject commit e20cb4c21a5a95b8b60d76d29156faba65246b67