43 changed files with 25878 additions and 0 deletions
-
11.gitignore
-
18.gitmodules
-
245.vscode/c_cpp_properties.json
-
114.vscode/settings.json
-
379app/RTE/Device/nRF52833_xxAA/arm_startup_nrf52833.s
-
329app/RTE/Device/nRF52833_xxAA/system_nrf52.c
-
1660app/app.uvoptx
-
7882app/app.uvprojx
-
12168app/config/sdk_config.h
-
369app/src/ads1293_simple_tester.c
-
537app/src/app_ble_service.c
-
15app/src/app_ble_service.h
-
52app/src/app_event.h
-
23app/src/app_event_distribute.c
-
15app/src/app_event_distribute.h
-
129app/src/basic/ads1293/ads1293.c
-
142app/src/basic/ads1293/ads1293.h
-
3app/src/basic/version.h
-
0app/src/board/board.c
-
72app/src/board/board.h
-
36app/src/board/board_battery_state.c
-
14app/src/board/board_battery_state.h
-
102app/src/board/board_beep_ctrl.c
-
24app/src/board/board_beep_ctrl.h
-
34app/src/board/board_button.c
-
23app/src/board/board_button.h
-
79app/src/board/board_light_ctrl.c
-
23app/src/board/board_light_ctrl.h
-
172app/src/board/board_sdcard_driver.c
-
19app/src/board/board_sdcard_driver.h
-
357app/src/device_ctrl_service.c
-
44app/src/device_ctrl_service.h
-
455app/src/heart_wave_sample_service.c
-
35app/src/heart_wave_sample_service.h
-
43app/src/main.c
-
171app/src/sample_data_manager_service.c
-
78app/src/sample_data_manager_service.h
-
1bootloader
-
1dynamic_electrocardiograph_ble_server
-
1ify_hrs_protocol
-
1libznordic
-
1pemkey
-
1sdk
@ -0,0 +1,11 @@ |
|||||
|
_build |
||||
|
app.uvguix.* |
||||
|
JLinkLog.txt |
||||
|
JLinkSettings.ini |
||||
|
RTE_Components.h |
||||
|
EventRecorderStub.scvd |
||||
|
app/.vscode |
||||
|
.vscode/uv4.log.lock |
||||
|
.vscode/keil-assistant.log |
||||
|
bin2/bl_temp.hex |
||||
|
bin2/settings.hex |
@ -0,0 +1,18 @@ |
|||||
|
[submodule "sdk"] |
||||
|
path = sdk |
||||
|
url = zwsd@192.168.1.3:p_dynamic_electrocardiograph/nrf5_sdk_17_1_0.git |
||||
|
[submodule "bootloader"] |
||||
|
path = bootloader |
||||
|
url = zwsd@192.168.1.3:p_dynamic_electrocardiograph/bootloader.git |
||||
|
[submodule "pemkey"] |
||||
|
path = pemkey |
||||
|
url = zwsd@192.168.1.3:p_dynamic_electrocardiograph/pemkey.git |
||||
|
[submodule "dynamic_electrocardiograph_ble_server"] |
||||
|
path = dynamic_electrocardiograph_ble_server |
||||
|
url = zwsd@192.168.1.3:p_dynamic_electrocardiograph/dynamic_electrocardiograph_ble_server.git |
||||
|
[submodule "libznordic"] |
||||
|
path = libznordic |
||||
|
url = zwsd@192.168.1.3:p_dynamic_electrocardiograph/libznordic.git |
||||
|
[submodule "ify_hrs_protocol"] |
||||
|
path = ify_hrs_protocol |
||||
|
url = zwsd@192.168.1.3:p_dynamic_electrocardiograph/ify_hrs_protocol.git |
@ -0,0 +1,245 @@ |
|||||
|
{ |
||||
|
"configurations": [ |
||||
|
{ |
||||
|
"name": "nrf52833_xxaa", |
||||
|
"includePath": [ |
||||
|
"libznordic\\include", |
||||
|
"sdk/external/fatfs/src/", |
||||
|
"sdk/external/fatfs/src/", |
||||
|
"sdk/external/fatfs/port/", |
||||
|
"sdk/components/libraries/block_dev/sdc/", |
||||
|
"sdk/components/libraries/block_dev/", |
||||
|
"sdk\\config", |
||||
|
"app\\src", |
||||
|
"sdk\\components", |
||||
|
"sdk\\components\\ble\\ble_advertising", |
||||
|
"sdk\\components\\ble\\ble_dtm", |
||||
|
"sdk\\components\\ble\\ble_link_ctx_manager", |
||||
|
"sdk\\components\\ble\\ble_racp", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_ancs_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_ans_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_bas", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_bas_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_cscs", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_cts_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_dfu", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_dis", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_gls", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_hids", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_hrs", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_hrs_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_hts", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_ias", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_ias_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_lbs", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_lbs_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_lls", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_nus", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_nus_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_rscs", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_rscs_c", |
||||
|
"sdk\\components\\ble\\ble_services\\ble_tps", |
||||
|
"sdk\\components\\ble\\common", |
||||
|
"sdk\\components\\ble\\nrf_ble_gatt", |
||||
|
"sdk\\components\\ble\\nrf_ble_qwr", |
||||
|
"sdk\\components\\ble\\peer_manager", |
||||
|
"sdk\\components\\boards", |
||||
|
"sdk\\components\\libraries\\atomic", |
||||
|
"sdk\\components\\libraries\\atomic_fifo", |
||||
|
"sdk\\components\\libraries\\atomic_flags", |
||||
|
"sdk\\components\\libraries\\balloc", |
||||
|
"sdk\\components\\libraries\\bootloader\\ble_dfu", |
||||
|
"sdk\\components\\libraries\\bsp", |
||||
|
"sdk\\components\\libraries\\button", |
||||
|
"sdk\\components\\libraries\\cli", |
||||
|
"sdk\\components\\libraries\\crc16", |
||||
|
"sdk\\components\\libraries\\crc32", |
||||
|
"sdk\\components\\libraries\\crypto", |
||||
|
"sdk\\components\\libraries\\csense", |
||||
|
"sdk\\components\\libraries\\csense_drv", |
||||
|
"sdk\\components\\libraries\\delay", |
||||
|
"sdk\\components\\libraries\\ecc", |
||||
|
"sdk\\components\\libraries\\experimental_section_vars", |
||||
|
"sdk\\components\\libraries\\experimental_task_manager", |
||||
|
"sdk\\components\\libraries\\fds", |
||||
|
"sdk\\components\\libraries\\fifo", |
||||
|
"sdk\\components\\libraries\\fstorage", |
||||
|
"sdk\\components\\libraries\\gfx", |
||||
|
"sdk\\components\\libraries\\gpiote", |
||||
|
"sdk\\components\\libraries\\hardfault", |
||||
|
"sdk\\components\\libraries\\hci", |
||||
|
"sdk\\components\\libraries\\led_softblink", |
||||
|
"sdk\\components\\libraries\\log", |
||||
|
"sdk\\components\\libraries\\log\\src", |
||||
|
"sdk\\components\\libraries\\low_power_pwm", |
||||
|
"sdk\\components\\libraries\\mem_manager", |
||||
|
"sdk\\components\\libraries\\memobj", |
||||
|
"sdk\\components\\libraries\\mpu", |
||||
|
"sdk\\components\\libraries\\mutex", |
||||
|
"sdk\\components\\libraries\\pwm", |
||||
|
"sdk\\components\\libraries\\pwr_mgmt", |
||||
|
"sdk\\components\\libraries\\queue", |
||||
|
"sdk\\components\\libraries\\ringbuf", |
||||
|
"sdk\\components\\libraries\\scheduler", |
||||
|
"sdk\\components\\libraries\\sdcard", |
||||
|
"sdk\\components\\libraries\\slip", |
||||
|
"sdk\\components\\libraries\\sortlist", |
||||
|
"sdk\\components\\libraries\\spi_mngr", |
||||
|
"sdk\\components\\libraries\\stack_guard", |
||||
|
"sdk\\components\\libraries\\strerror", |
||||
|
"sdk\\components\\libraries\\svc", |
||||
|
"sdk\\components\\libraries\\timer", |
||||
|
"sdk\\components\\libraries\\twi_mngr", |
||||
|
"sdk\\components\\libraries\\twi_sensor", |
||||
|
"sdk\\components\\libraries\\uart", |
||||
|
"sdk\\components\\libraries\\usbd", |
||||
|
"sdk\\components\\libraries\\usbd\\class\\audio", |
||||
|
"sdk\\components\\libraries\\usbd\\class\\cdc", |
||||
|
"sdk\\components\\libraries\\usbd\\class\\cdc\\acm", |
||||
|
"sdk\\components\\libraries\\usbd\\class\\hid", |
||||
|
"sdk\\components\\libraries\\usbd\\class\\hid\\generic", |
||||
|
"sdk\\components\\libraries\\usbd\\class\\hid\\kbd", |
||||
|
"sdk\\components\\libraries\\usbd\\class\\hid\\mouse", |
||||
|
"sdk\\components\\libraries\\usbd\\class\\msc", |
||||
|
"sdk\\components\\libraries\\util", |
||||
|
"sdk\\components\\nfc\\ndef\\conn_hand_parser", |
||||
|
"sdk\\components\\nfc\\ndef\\conn_hand_parser\\ac_rec_parser", |
||||
|
"sdk\\components\\nfc\\ndef\\conn_hand_parser\\ble_oob_advdata_parser", |
||||
|
"sdk\\components\\nfc\\ndef\\conn_hand_parser\\le_oob_rec_parser", |
||||
|
"sdk\\components\\nfc\\ndef\\connection_handover\\ac_rec", |
||||
|
"sdk\\components\\nfc\\ndef\\connection_handover\\ble_oob_advdata", |
||||
|
"sdk\\components\\nfc\\ndef\\connection_handover\\ble_pair_lib", |
||||
|
"sdk\\components\\nfc\\ndef\\connection_handover\\ble_pair_msg", |
||||
|
"sdk\\components\\nfc\\ndef\\connection_handover\\common", |
||||
|
"sdk\\components\\nfc\\ndef\\connection_handover\\ep_oob_rec", |
||||
|
"sdk\\components\\nfc\\ndef\\connection_handover\\hs_rec", |
||||
|
"sdk\\components\\nfc\\ndef\\connection_handover\\le_oob_rec", |
||||
|
"sdk\\components\\nfc\\ndef\\generic\\message", |
||||
|
"sdk\\components\\nfc\\ndef\\generic\\record", |
||||
|
"sdk\\components\\nfc\\ndef\\launchapp", |
||||
|
"sdk\\components\\nfc\\ndef\\parser\\message", |
||||
|
"sdk\\components\\nfc\\ndef\\parser\\record", |
||||
|
"sdk\\components\\nfc\\ndef\\text", |
||||
|
"sdk\\components\\nfc\\ndef\\uri", |
||||
|
"sdk\\components\\nfc\\platform", |
||||
|
"sdk\\components\\nfc\\t2t_lib", |
||||
|
"sdk\\components\\nfc\\t2t_parser", |
||||
|
"sdk\\components\\nfc\\t4t_lib", |
||||
|
"sdk\\components\\nfc\\t4t_parser\\apdu", |
||||
|
"sdk\\components\\nfc\\t4t_parser\\cc_file", |
||||
|
"sdk\\components\\nfc\\t4t_parser\\hl_detection_procedure", |
||||
|
"sdk\\components\\nfc\\t4t_parser\\tlv", |
||||
|
"sdk\\components\\softdevice\\common", |
||||
|
"sdk\\components\\softdevice\\s140\\headers", |
||||
|
"sdk\\components\\softdevice\\s140\\headers\\nrf52", |
||||
|
"sdk\\external\\fprintf", |
||||
|
"sdk\\external\\segger_rtt", |
||||
|
"sdk\\external\\utf_converter", |
||||
|
"sdk\\integration\\nrfx", |
||||
|
"sdk\\integration\\nrfx\\legacy", |
||||
|
"sdk\\modules\\nrfx", |
||||
|
"sdk\\modules\\nrfx\\drivers\\include", |
||||
|
"sdk\\modules\\nrfx\\hal", |
||||
|
"app\\config\\", |
||||
|
"app\\config", |
||||
|
"app", |
||||
|
"sdk\\modules\\nrfx\\soc", |
||||
|
"sdk\\modules\\nrfx\\drivers\\src", |
||||
|
"sdk\\modules\\nrfx\\drivers\\src\\prs", |
||||
|
"sdk\\modules\\nrfx\\mdk\\", |
||||
|
"sdk\\components\\toolchain\\cmsis\\include\\", |
||||
|
"sdk\\components\\libraries\\bootloader\\" |
||||
|
], |
||||
|
"defines": [ |
||||
|
"BL_SETTINGS_ACCESS_ONLY", |
||||
|
"NRF_DFU_SVCI_ENABLED", |
||||
|
"NRF_DFU_TRANSPORT_BLE=1", |
||||
|
"CONFIG_NFCT_PINS_AS_GPIOS", |
||||
|
"APP_TIMER_V2", |
||||
|
"APP_TIMER_V2_RTC1_ENABLED", |
||||
|
"BOARD_PCA10100", |
||||
|
"FLOAT_ABI_HARD", |
||||
|
"NRF52833_XXAA", |
||||
|
"NRF_SD_BLE_API_VERSION=7", |
||||
|
"S140", |
||||
|
"SOFTDEVICE_PRESENT", |
||||
|
"__HEAP_SIZE=2048", |
||||
|
"__STACK_SIZE=4096", |
||||
|
"__CC_ARM", |
||||
|
"__arm__", |
||||
|
"__align(x)=", |
||||
|
"__ALIGNOF__(x)=", |
||||
|
"__alignof__(x)=", |
||||
|
"__asm(x)=", |
||||
|
"__forceinline=", |
||||
|
"__restrict=", |
||||
|
"__global_reg(n)=", |
||||
|
"__inline=", |
||||
|
"__int64=long long", |
||||
|
"__INTADDR__(expr)=0", |
||||
|
"__irq=", |
||||
|
"__packed=", |
||||
|
"__pure=", |
||||
|
"__smc(n)=", |
||||
|
"__svc(n)=", |
||||
|
"__svc_indirect(n)=", |
||||
|
"__svc_indirect_r7(n)=", |
||||
|
"__value_in_regs=", |
||||
|
"__weak=", |
||||
|
"__writeonly=", |
||||
|
"__declspec(x)=", |
||||
|
"__attribute__(x)=", |
||||
|
"__nonnull__(x)=", |
||||
|
"__register=", |
||||
|
"__breakpoint(x)=", |
||||
|
"__cdp(x,y,z)=", |
||||
|
"__clrex()=", |
||||
|
"__clz(x)=0U", |
||||
|
"__current_pc()=0U", |
||||
|
"__current_sp()=0U", |
||||
|
"__disable_fiq()=", |
||||
|
"__disable_irq()=", |
||||
|
"__dmb(x)=", |
||||
|
"__dsb(x)=", |
||||
|
"__enable_fiq()=", |
||||
|
"__enable_irq()=", |
||||
|
"__fabs(x)=0.0", |
||||
|
"__fabsf(x)=0.0f", |
||||
|
"__force_loads()=", |
||||
|
"__force_stores()=", |
||||
|
"__isb(x)=", |
||||
|
"__ldrex(x)=0U", |
||||
|
"__ldrexd(x)=0U", |
||||
|
"__ldrt(x)=0U", |
||||
|
"__memory_changed()=", |
||||
|
"__nop()=", |
||||
|
"__pld(...)=", |
||||
|
"__pli(...)=", |
||||
|
"__qadd(x,y)=0", |
||||
|
"__qdbl(x)=0", |
||||
|
"__qsub(x,y)=0", |
||||
|
"__rbit(x)=0U", |
||||
|
"__rev(x)=0U", |
||||
|
"__return_address()=0U", |
||||
|
"__ror(x,y)=0U", |
||||
|
"__schedule_barrier()=", |
||||
|
"__semihost(x,y)=0", |
||||
|
"__sev()=", |
||||
|
"__sqrt(x)=0.0", |
||||
|
"__sqrtf(x)=0.0f", |
||||
|
"__ssat(x,y)=0", |
||||
|
"__strex(x,y)=0U", |
||||
|
"__strexd(x,y)=0", |
||||
|
"__strt(x,y)=", |
||||
|
"__swp(x,y)=0U", |
||||
|
"__usat(x,y)=0U", |
||||
|
"__wfe()=", |
||||
|
"__wfi()=", |
||||
|
"__yield()=", |
||||
|
"__vfp_status(x,y)=0" |
||||
|
], |
||||
|
"intelliSenseMode": "${default}" |
||||
|
} |
||||
|
], |
||||
|
"version": 4 |
||||
|
} |
@ -0,0 +1,114 @@ |
|||||
|
{ |
||||
|
"files.associations": { |
||||
|
"*.hpp": "cpp", |
||||
|
"ble_hci.h": "c", |
||||
|
"ble_advdata.h": "c", |
||||
|
"ble_advertising.h": "c", |
||||
|
"ble_conn_params.h": "c", |
||||
|
"nrf_sdh.h": "c", |
||||
|
"nrf_sdh_soc.h": "c", |
||||
|
"nrf_sdh_ble.h": "c", |
||||
|
"nrf_ble_gatt.h": "c", |
||||
|
"nrf_ble_qwr.h": "c", |
||||
|
"app_timer.h": "c", |
||||
|
"nordic_common.h": "c", |
||||
|
"nrf.h": "c", |
||||
|
"nrf52833.h": "c", |
||||
|
"nrf52833_bitfields.h": "c", |
||||
|
"system_nrf52833.h": "c", |
||||
|
"app_util_platform.h": "c", |
||||
|
"string.h": "c", |
||||
|
"ble_nus.h": "c", |
||||
|
"app_uart.h": "c", |
||||
|
"bsp_btn_ble.h": "c", |
||||
|
"nrf_pwr_mgmt.h": "c", |
||||
|
"core_cm4.h": "c", |
||||
|
"nrf52_to_nrf52833.h": "c", |
||||
|
"compare": "c", |
||||
|
"type_traits": "c", |
||||
|
"stdint.h": "c", |
||||
|
"sys.h": "c", |
||||
|
"nrf_log.h": "c", |
||||
|
"version.h": "c", |
||||
|
"zble_module.h": "c", |
||||
|
"pca10112.h": "c", |
||||
|
"pca10100.h": "c", |
||||
|
"board.h": "c", |
||||
|
"stdio.h": "c", |
||||
|
"nrf_log_ctrl.h": "c", |
||||
|
"nrf_log_default_backends.h": "c", |
||||
|
"nrf_delay.h": "c", |
||||
|
"zhrs_service.h": "c", |
||||
|
"ble_srv_common.h": "c", |
||||
|
"zdatachannel_service.h": "c", |
||||
|
"ble_link_ctx_manager.h": "c", |
||||
|
"nrf_drv_saadc.h": "c", |
||||
|
"project_cfg.h": "c", |
||||
|
"nrf_block_dev_sdc.h": "c", |
||||
|
"nrf_drv_pwm.h": "c", |
||||
|
"nrfx_config.h": "c", |
||||
|
"nrf_drv_wdt.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", |
||||
|
"driver_ssd1306.h": "c", |
||||
|
"driver_ssd1306_font.h": "c", |
||||
|
"driver_ssd1306_basic.h": "c", |
||||
|
"driver_ssd1306_interface.h": "c", |
||||
|
"three_lead_board.h": "c", |
||||
|
"znordic.h": "c", |
||||
|
"ads1293.h": "c", |
||||
|
"app_scheduler.h": "c", |
||||
|
"stdbool.h": "c", |
||||
|
"stdlib.h": "c", |
||||
|
"zble_nus_c.h": "c", |
||||
|
"ble.h": "c", |
||||
|
"ble_gattc.h": "c", |
||||
|
"ble_gatt.h": "c", |
||||
|
"ble_gap.h": "c", |
||||
|
"sdk_common.h": "c", |
||||
|
"app_error.h": "c", |
||||
|
"ble_gatts.h": "c", |
||||
|
"sdk_macros.h": "c", |
||||
|
"app_util.h": "c", |
||||
|
"ble_types.h": "c", |
||||
|
"ble_db_discovery.h": "c", |
||||
|
"ble_gatt_db.h": "c", |
||||
|
"nrf_ble_gq.h": "c", |
||||
|
"ti_ads1293_register_settings.h": "c", |
||||
|
"typeinfo": "c", |
||||
|
"fontlib.h": "c", |
||||
|
"font.h": "c", |
||||
|
"display_manager.h": "c", |
||||
|
"wave_drawer.h": "c", |
||||
|
"sample_data_manager.h": "c", |
||||
|
"zeeprom_fs.h": "c", |
||||
|
"config.h": "c", |
||||
|
"stdarg.h": "c", |
||||
|
"nrf_uarte.h": "c", |
||||
|
"heart_rate_sensor_protocol.h": "c", |
||||
|
"ble_cmd_process_service.h": "c", |
||||
|
"heart_wave_sample_service.h": "c", |
||||
|
"znordic_device_info_mgr.h": "c", |
||||
|
"nrf_uart.h": "c", |
||||
|
"ads_cfg.h": "c", |
||||
|
"sdk_config.h": "c", |
||||
|
"app_ble_service.h": "c", |
||||
|
"nrfx_timer.h": "c", |
||||
|
"app_button.h": "c", |
||||
|
"nrf_drv_gpiote.h": "c", |
||||
|
"device_ctrl_service.h": "c", |
||||
|
"board_battery_state.h": "c", |
||||
|
"board_sdcard_driver.h": "c", |
||||
|
"board_button.h": "c", |
||||
|
"app_event_distribute.h": "c", |
||||
|
"board_beep_ctrl.h": "c", |
||||
|
"nrf_soc.h": "c", |
||||
|
"sample_data_manager_service.h": "c", |
||||
|
"app_event.h": "c", |
||||
|
"compiler_abstraction.h": "c" |
||||
|
}, |
||||
|
"files.encoding": "gbk" |
||||
|
} |
@ -0,0 +1,379 @@ |
|||||
|
; Copyright (c) 2009-2021 ARM Limited. All rights reserved. |
||||
|
; |
||||
|
; SPDX-License-Identifier: Apache-2.0 |
||||
|
; |
||||
|
; Licensed under the Apache License, Version 2.0 (the License); you may |
||||
|
; not use this file except in compliance with the License. |
||||
|
; You may obtain a copy of the License at |
||||
|
; |
||||
|
; www.apache.org/licenses/LICENSE-2.0 |
||||
|
; |
||||
|
; Unless required by applicable law or agreed to in writing, software |
||||
|
; distributed under the License is distributed on an AS IS BASIS, WITHOUT |
||||
|
; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
; See the License for the specific language governing permissions and |
||||
|
; limitations under the License. |
||||
|
; |
||||
|
; NOTICE: This file has been modified by Nordic Semiconductor ASA. |
||||
|
|
||||
|
IF :DEF: __STARTUP_CONFIG |
||||
|
#ifdef __STARTUP_CONFIG |
||||
|
#include "startup_config.h" |
||||
|
#ifndef __STARTUP_CONFIG_STACK_ALIGNEMENT |
||||
|
#define __STARTUP_CONFIG_STACK_ALIGNEMENT 3 |
||||
|
#endif |
||||
|
#endif |
||||
|
ENDIF |
||||
|
|
||||
|
IF :DEF: __STARTUP_CONFIG |
||||
|
Stack_Size EQU __STARTUP_CONFIG_STACK_SIZE |
||||
|
ELIF :DEF: __STACK_SIZE |
||||
|
Stack_Size EQU __STACK_SIZE |
||||
|
ELSE |
||||
|
Stack_Size EQU 8192 |
||||
|
ENDIF |
||||
|
|
||||
|
IF :DEF: __STARTUP_CONFIG |
||||
|
Stack_Align EQU __STARTUP_CONFIG_STACK_ALIGNEMENT |
||||
|
ELSE |
||||
|
Stack_Align EQU 3 |
||||
|
ENDIF |
||||
|
|
||||
|
AREA STACK, NOINIT, READWRITE, ALIGN=Stack_Align |
||||
|
Stack_Mem SPACE Stack_Size |
||||
|
__initial_sp |
||||
|
|
||||
|
IF :DEF: __STARTUP_CONFIG |
||||
|
Heap_Size EQU __STARTUP_CONFIG_HEAP_SIZE |
||||
|
ELIF :DEF: __HEAP_SIZE |
||||
|
Heap_Size EQU __HEAP_SIZE |
||||
|
ELSE |
||||
|
Heap_Size EQU 8192 |
||||
|
ENDIF |
||||
|
|
||||
|
AREA HEAP, NOINIT, READWRITE, ALIGN=3 |
||||
|
__heap_base |
||||
|
Heap_Mem SPACE Heap_Size |
||||
|
__heap_limit |
||||
|
|
||||
|
PRESERVE8 |
||||
|
THUMB |
||||
|
|
||||
|
; Vector Table Mapped to Address 0 at Reset |
||||
|
|
||||
|
AREA RESET, DATA, READONLY |
||||
|
EXPORT __Vectors |
||||
|
EXPORT __Vectors_End |
||||
|
EXPORT __Vectors_Size |
||||
|
|
||||
|
__Vectors DCD __initial_sp ; Top of Stack |
||||
|
DCD Reset_Handler |
||||
|
DCD NMI_Handler |
||||
|
DCD HardFault_Handler |
||||
|
DCD MemoryManagement_Handler |
||||
|
DCD BusFault_Handler |
||||
|
DCD UsageFault_Handler |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD SVC_Handler |
||||
|
DCD DebugMon_Handler |
||||
|
DCD 0 ; Reserved |
||||
|
DCD PendSV_Handler |
||||
|
DCD SysTick_Handler |
||||
|
|
||||
|
; External Interrupts |
||||
|
DCD POWER_CLOCK_IRQHandler |
||||
|
DCD RADIO_IRQHandler |
||||
|
DCD UARTE0_UART0_IRQHandler |
||||
|
DCD SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler |
||||
|
DCD SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler |
||||
|
DCD NFCT_IRQHandler |
||||
|
DCD GPIOTE_IRQHandler |
||||
|
DCD SAADC_IRQHandler |
||||
|
DCD TIMER0_IRQHandler |
||||
|
DCD TIMER1_IRQHandler |
||||
|
DCD TIMER2_IRQHandler |
||||
|
DCD RTC0_IRQHandler |
||||
|
DCD TEMP_IRQHandler |
||||
|
DCD RNG_IRQHandler |
||||
|
DCD ECB_IRQHandler |
||||
|
DCD CCM_AAR_IRQHandler |
||||
|
DCD WDT_IRQHandler |
||||
|
DCD RTC1_IRQHandler |
||||
|
DCD QDEC_IRQHandler |
||||
|
DCD COMP_LPCOMP_IRQHandler |
||||
|
DCD SWI0_EGU0_IRQHandler |
||||
|
DCD SWI1_EGU1_IRQHandler |
||||
|
DCD SWI2_EGU2_IRQHandler |
||||
|
DCD SWI3_EGU3_IRQHandler |
||||
|
DCD SWI4_EGU4_IRQHandler |
||||
|
DCD SWI5_EGU5_IRQHandler |
||||
|
DCD TIMER3_IRQHandler |
||||
|
DCD TIMER4_IRQHandler |
||||
|
DCD PWM0_IRQHandler |
||||
|
DCD PDM_IRQHandler |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD MWU_IRQHandler |
||||
|
DCD PWM1_IRQHandler |
||||
|
DCD PWM2_IRQHandler |
||||
|
DCD SPIM2_SPIS2_SPI2_IRQHandler |
||||
|
DCD RTC2_IRQHandler |
||||
|
DCD I2S_IRQHandler |
||||
|
DCD FPU_IRQHandler |
||||
|
DCD USBD_IRQHandler |
||||
|
DCD UARTE1_IRQHandler |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD PWM3_IRQHandler |
||||
|
DCD 0 ; Reserved |
||||
|
DCD SPIM3_IRQHandler |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
DCD 0 ; Reserved |
||||
|
|
||||
|
__Vectors_End |
||||
|
|
||||
|
__Vectors_Size EQU __Vectors_End - __Vectors |
||||
|
|
||||
|
AREA |.text|, CODE, READONLY |
||||
|
|
||||
|
; Reset Handler |
||||
|
|
||||
|
|
||||
|
Reset_Handler PROC |
||||
|
EXPORT Reset_Handler [WEAK] |
||||
|
IMPORT SystemInit |
||||
|
IMPORT __main |
||||
|
|
||||
|
|
||||
|
LDR R0, =SystemInit |
||||
|
BLX R0 |
||||
|
LDR R0, =__main |
||||
|
BX R0 |
||||
|
ENDP |
||||
|
|
||||
|
; Dummy Exception Handlers (infinite loops which can be modified) |
||||
|
|
||||
|
NMI_Handler PROC |
||||
|
EXPORT NMI_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
HardFault_Handler\ |
||||
|
PROC |
||||
|
EXPORT HardFault_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
MemoryManagement_Handler\ |
||||
|
PROC |
||||
|
EXPORT MemoryManagement_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
BusFault_Handler\ |
||||
|
PROC |
||||
|
EXPORT BusFault_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
UsageFault_Handler\ |
||||
|
PROC |
||||
|
EXPORT UsageFault_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
SVC_Handler PROC |
||||
|
EXPORT SVC_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
DebugMon_Handler\ |
||||
|
PROC |
||||
|
EXPORT DebugMon_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
PendSV_Handler PROC |
||||
|
EXPORT PendSV_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
SysTick_Handler PROC |
||||
|
EXPORT SysTick_Handler [WEAK] |
||||
|
B . |
||||
|
ENDP |
||||
|
|
||||
|
Default_Handler PROC |
||||
|
|
||||
|
EXPORT POWER_CLOCK_IRQHandler [WEAK] |
||||
|
EXPORT RADIO_IRQHandler [WEAK] |
||||
|
EXPORT UARTE0_UART0_IRQHandler [WEAK] |
||||
|
EXPORT SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler [WEAK] |
||||
|
EXPORT SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler [WEAK] |
||||
|
EXPORT NFCT_IRQHandler [WEAK] |
||||
|
EXPORT GPIOTE_IRQHandler [WEAK] |
||||
|
EXPORT SAADC_IRQHandler [WEAK] |
||||
|
EXPORT TIMER0_IRQHandler [WEAK] |
||||
|
EXPORT TIMER1_IRQHandler [WEAK] |
||||
|
EXPORT TIMER2_IRQHandler [WEAK] |
||||
|
EXPORT RTC0_IRQHandler [WEAK] |
||||
|
EXPORT TEMP_IRQHandler [WEAK] |
||||
|
EXPORT RNG_IRQHandler [WEAK] |
||||
|
EXPORT ECB_IRQHandler [WEAK] |
||||
|
EXPORT CCM_AAR_IRQHandler [WEAK] |
||||
|
EXPORT WDT_IRQHandler [WEAK] |
||||
|
EXPORT RTC1_IRQHandler [WEAK] |
||||
|
EXPORT QDEC_IRQHandler [WEAK] |
||||
|
EXPORT COMP_LPCOMP_IRQHandler [WEAK] |
||||
|
EXPORT SWI0_EGU0_IRQHandler [WEAK] |
||||
|
EXPORT SWI1_EGU1_IRQHandler [WEAK] |
||||
|
EXPORT SWI2_EGU2_IRQHandler [WEAK] |
||||
|
EXPORT SWI3_EGU3_IRQHandler [WEAK] |
||||
|
EXPORT SWI4_EGU4_IRQHandler [WEAK] |
||||
|
EXPORT SWI5_EGU5_IRQHandler [WEAK] |
||||
|
EXPORT TIMER3_IRQHandler [WEAK] |
||||
|
EXPORT TIMER4_IRQHandler [WEAK] |
||||
|
EXPORT PWM0_IRQHandler [WEAK] |
||||
|
EXPORT PDM_IRQHandler [WEAK] |
||||
|
EXPORT MWU_IRQHandler [WEAK] |
||||
|
EXPORT PWM1_IRQHandler [WEAK] |
||||
|
EXPORT PWM2_IRQHandler [WEAK] |
||||
|
EXPORT SPIM2_SPIS2_SPI2_IRQHandler [WEAK] |
||||
|
EXPORT RTC2_IRQHandler [WEAK] |
||||
|
EXPORT I2S_IRQHandler [WEAK] |
||||
|
EXPORT FPU_IRQHandler [WEAK] |
||||
|
EXPORT USBD_IRQHandler [WEAK] |
||||
|
EXPORT UARTE1_IRQHandler [WEAK] |
||||
|
EXPORT PWM3_IRQHandler [WEAK] |
||||
|
EXPORT SPIM3_IRQHandler [WEAK] |
||||
|
POWER_CLOCK_IRQHandler |
||||
|
RADIO_IRQHandler |
||||
|
UARTE0_UART0_IRQHandler |
||||
|
SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler |
||||
|
SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler |
||||
|
NFCT_IRQHandler |
||||
|
GPIOTE_IRQHandler |
||||
|
SAADC_IRQHandler |
||||
|
TIMER0_IRQHandler |
||||
|
TIMER1_IRQHandler |
||||
|
TIMER2_IRQHandler |
||||
|
RTC0_IRQHandler |
||||
|
TEMP_IRQHandler |
||||
|
RNG_IRQHandler |
||||
|
ECB_IRQHandler |
||||
|
CCM_AAR_IRQHandler |
||||
|
WDT_IRQHandler |
||||
|
RTC1_IRQHandler |
||||
|
QDEC_IRQHandler |
||||
|
COMP_LPCOMP_IRQHandler |
||||
|
SWI0_EGU0_IRQHandler |
||||
|
SWI1_EGU1_IRQHandler |
||||
|
SWI2_EGU2_IRQHandler |
||||
|
SWI3_EGU3_IRQHandler |
||||
|
SWI4_EGU4_IRQHandler |
||||
|
SWI5_EGU5_IRQHandler |
||||
|
TIMER3_IRQHandler |
||||
|
TIMER4_IRQHandler |
||||
|
PWM0_IRQHandler |
||||
|
PDM_IRQHandler |
||||
|
MWU_IRQHandler |
||||
|
PWM1_IRQHandler |
||||
|
PWM2_IRQHandler |
||||
|
SPIM2_SPIS2_SPI2_IRQHandler |
||||
|
RTC2_IRQHandler |
||||
|
I2S_IRQHandler |
||||
|
FPU_IRQHandler |
||||
|
USBD_IRQHandler |
||||
|
UARTE1_IRQHandler |
||||
|
PWM3_IRQHandler |
||||
|
SPIM3_IRQHandler |
||||
|
B . |
||||
|
ENDP |
||||
|
ALIGN |
||||
|
|
||||
|
; User Initial Stack & Heap |
||||
|
|
||||
|
IF :DEF:__MICROLIB |
||||
|
|
||||
|
EXPORT __initial_sp |
||||
|
EXPORT __heap_base |
||||
|
EXPORT __heap_limit |
||||
|
|
||||
|
ELSE |
||||
|
|
||||
|
IMPORT __use_two_region_memory |
||||
|
EXPORT __user_initial_stackheap |
||||
|
|
||||
|
__user_initial_stackheap PROC |
||||
|
|
||||
|
LDR R0, = Heap_Mem |
||||
|
LDR R1, = (Stack_Mem + Stack_Size) |
||||
|
LDR R2, = (Heap_Mem + Heap_Size) |
||||
|
LDR R3, = Stack_Mem |
||||
|
BX LR |
||||
|
ENDP |
||||
|
|
||||
|
ALIGN |
||||
|
|
||||
|
ENDIF |
||||
|
|
||||
|
END |
@ -0,0 +1,329 @@ |
|||||
|
/* |
||||
|
|
||||
|
Copyright (c) 2009-2021 ARM Limited. All rights reserved. |
||||
|
|
||||
|
SPDX-License-Identifier: Apache-2.0 |
||||
|
|
||||
|
Licensed under the Apache License, Version 2.0 (the License); you may |
||||
|
not use this file except in compliance with the License. |
||||
|
You may obtain a copy of the License at |
||||
|
|
||||
|
www.apache.org/licenses/LICENSE-2.0 |
||||
|
|
||||
|
Unless required by applicable law or agreed to in writing, software |
||||
|
distributed under the License is distributed on an AS IS BASIS, WITHOUT |
||||
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
See the License for the specific language governing permissions and |
||||
|
limitations under the License. |
||||
|
|
||||
|
NOTICE: This file has been modified by Nordic Semiconductor ASA. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
/* NOTE: Template files (including this one) are application specific and therefore expected to |
||||
|
be copied into the application project folder prior to its use! */ |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
#include <stdbool.h> |
||||
|
#include "nrf.h" |
||||
|
#include "nrf_peripherals.h" |
||||
|
#include "nrf52_erratas.h" |
||||
|
#include "system_nrf52.h" |
||||
|
#include "system_nrf52_approtect.h" |
||||
|
|
||||
|
#define __SYSTEM_CLOCK_64M (64000000UL) |
||||
|
|
||||
|
|
||||
|
#if defined ( __CC_ARM ) |
||||
|
uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_64M; |
||||
|
#elif defined ( __ICCARM__ ) |
||||
|
__root uint32_t SystemCoreClock = __SYSTEM_CLOCK_64M; |
||||
|
#elif defined ( __GNUC__ ) |
||||
|
uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_64M; |
||||
|
#endif |
||||
|
|
||||
|
/* Select correct reset pin */ |
||||
|
/* Handle DEVELOP_IN-targets first as they take precedence over the later macros */ |
||||
|
#if defined (DEVELOP_IN_NRF52805) \ |
||||
|
|| defined (DEVELOP_IN_NRF52810) \ |
||||
|
|| defined (DEVELOP_IN_NRF52811) \ |
||||
|
|| defined (DEVELOP_IN_NRF52832) |
||||
|
#define RESET_PIN 21 |
||||
|
#elif defined (DEVELOP_IN_NRF52820) \ |
||||
|
|| defined (DEVELOP_IN_NRF52833) \ |
||||
|
|| defined (DEVELOP_IN_NRF52840) |
||||
|
#define RESET_PIN 18 |
||||
|
#elif defined (NRF52805_XXAA) \ |
||||
|
|| defined (NRF52810_XXAA) \ |
||||
|
|| defined (NRF52811_XXAA) \ |
||||
|
|| defined (NRF52832_XXAA) \ |
||||
|
|| defined (NRF52832_XXAB) |
||||
|
#define RESET_PIN 21 |
||||
|
#elif defined (NRF52820_XXAA) \ |
||||
|
|| defined (NRF52833_XXAA) \ |
||||
|
|| defined (NRF52840_XXAA) |
||||
|
#define RESET_PIN 18 |
||||
|
#else |
||||
|
#error "A supported device macro must be defined." |
||||
|
#endif |
||||
|
|
||||
|
/* -- NVMC utility functions -- */ |
||||
|
/* Waits until NVMC is done with the current pending action */ |
||||
|
void nvmc_wait(void) |
||||
|
{ |
||||
|
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} |
||||
|
} |
||||
|
|
||||
|
/* Configure the NVMC to "mode". |
||||
|
Mode must be an enumerator of field NVMC_CONFIG_WEN */ |
||||
|
void nvmc_config(uint32_t mode) |
||||
|
{ |
||||
|
NRF_NVMC->CONFIG = mode << NVMC_CONFIG_WEN_Pos; |
||||
|
nvmc_wait(); |
||||
|
} |
||||
|
|
||||
|
void SystemCoreClockUpdate(void) |
||||
|
{ |
||||
|
SystemCoreClock = __SYSTEM_CLOCK_64M; |
||||
|
} |
||||
|
|
||||
|
void SystemInit(void) |
||||
|
{ |
||||
|
/* Enable SWO trace functionality. If ENABLE_SWO is not defined, SWO pin will be used as GPIO (see Product |
||||
|
Specification to see which one). */ |
||||
|
#if defined (ENABLE_SWO) && defined(CLOCK_TRACECONFIG_TRACEMUX_Pos) |
||||
|
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; |
||||
|
NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Serial << CLOCK_TRACECONFIG_TRACEMUX_Pos; |
||||
|
NRF_P0->PIN_CNF[18] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); |
||||
|
#endif |
||||
|
|
||||
|
/* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product |
||||
|
Specification to see which ones). */ |
||||
|
#if defined (ENABLE_TRACE) && defined(CLOCK_TRACECONFIG_TRACEMUX_Pos) |
||||
|
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; |
||||
|
NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Parallel << CLOCK_TRACECONFIG_TRACEMUX_Pos; |
||||
|
NRF_P0->PIN_CNF[14] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); |
||||
|
NRF_P0->PIN_CNF[15] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); |
||||
|
NRF_P0->PIN_CNF[16] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); |
||||
|
NRF_P0->PIN_CNF[18] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); |
||||
|
NRF_P0->PIN_CNF[20] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_12_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 12 "COMP: Reference ladder not correctly calibrated" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_12()){ |
||||
|
*(volatile uint32_t *)0x40013540 = (*(uint32_t *)0x10000324 & 0x00001F00) >> 8; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_16_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 16 "System: RAM may be corrupt on wakeup from CPU IDLE" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_16()){ |
||||
|
*(volatile uint32_t *)0x4007C074 = 3131961357ul; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_31_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 31 "CLOCK: Calibration values are not correctly loaded from FICR at reset" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_31()){ |
||||
|
*(volatile uint32_t *)0x4000053C = ((*(volatile uint32_t *)0x10000244) & 0x0000E000) >> 13; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_32_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 32 "DIF: Debug session automatically enables TracePort pins" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_32()){ |
||||
|
CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_36_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 36 "CLOCK: Some registers are not reset when expected" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_36()){ |
||||
|
NRF_CLOCK->EVENTS_DONE = 0; |
||||
|
NRF_CLOCK->EVENTS_CTTO = 0; |
||||
|
NRF_CLOCK->CTIV = 0; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_37_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 37 "RADIO: Encryption engine is slow by default" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_37()){ |
||||
|
*(volatile uint32_t *)0x400005A0 = 0x3; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_57_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 57 "NFCT: NFC Modulation amplitude" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_57()){ |
||||
|
*(volatile uint32_t *)0x40005610 = 0x00000005; |
||||
|
*(volatile uint32_t *)0x40005688 = 0x00000001; |
||||
|
*(volatile uint32_t *)0x40005618 = 0x00000000; |
||||
|
*(volatile uint32_t *)0x40005614 = 0x0000003F; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_66_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 66 "TEMP: Linearity specification not met with default settings" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_66()){ |
||||
|
NRF_TEMP->A0 = NRF_FICR->TEMP.A0; |
||||
|
NRF_TEMP->A1 = NRF_FICR->TEMP.A1; |
||||
|
NRF_TEMP->A2 = NRF_FICR->TEMP.A2; |
||||
|
NRF_TEMP->A3 = NRF_FICR->TEMP.A3; |
||||
|
NRF_TEMP->A4 = NRF_FICR->TEMP.A4; |
||||
|
NRF_TEMP->A5 = NRF_FICR->TEMP.A5; |
||||
|
NRF_TEMP->B0 = NRF_FICR->TEMP.B0; |
||||
|
NRF_TEMP->B1 = NRF_FICR->TEMP.B1; |
||||
|
NRF_TEMP->B2 = NRF_FICR->TEMP.B2; |
||||
|
NRF_TEMP->B3 = NRF_FICR->TEMP.B3; |
||||
|
NRF_TEMP->B4 = NRF_FICR->TEMP.B4; |
||||
|
NRF_TEMP->B5 = NRF_FICR->TEMP.B5; |
||||
|
NRF_TEMP->T0 = NRF_FICR->TEMP.T0; |
||||
|
NRF_TEMP->T1 = NRF_FICR->TEMP.T1; |
||||
|
NRF_TEMP->T2 = NRF_FICR->TEMP.T2; |
||||
|
NRF_TEMP->T3 = NRF_FICR->TEMP.T3; |
||||
|
NRF_TEMP->T4 = NRF_FICR->TEMP.T4; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_98_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 98 "NFCT: Not able to communicate with the peer" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_98()){ |
||||
|
*(volatile uint32_t *)0x4000568Cul = 0x00038148ul; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_103_ENABLE_WORKAROUND && defined(CCM_MAXPACKETSIZE_MAXPACKETSIZE_Pos) |
||||
|
/* Workaround for Errata 103 "CCM: Wrong reset value of CCM MAXPACKETSIZE" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_103()){ |
||||
|
NRF_CCM->MAXPACKETSIZE = 0xFBul; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_108_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 108 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_108()){ |
||||
|
*(volatile uint32_t *)0x40000EE4ul = *(volatile uint32_t *)0x10000258ul & 0x0000004Ful; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_115_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 115 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_115()){ |
||||
|
*(volatile uint32_t *)0x40000EE4 = (*(volatile uint32_t *)0x40000EE4 & 0xFFFFFFF0) | (*(uint32_t *)0x10000258 & 0x0000000F); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_120_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 120 "QSPI: Data read or written is corrupted" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_120()){ |
||||
|
*(volatile uint32_t *)0x40029640ul = 0x200ul; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_136_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 136 "System: Bits in RESETREAS are set when they should not be" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_136()){ |
||||
|
if (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk){ |
||||
|
NRF_POWER->RESETREAS = ~POWER_RESETREAS_RESETPIN_Msk; |
||||
|
} |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_182_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 182 "RADIO: Fixes for anomalies #102, #106, and #107 do not take effect" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_182()){ |
||||
|
*(volatile uint32_t *) 0x4000173C |= (0x1 << 10); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if NRF52_ERRATA_217_ENABLE_WORKAROUND |
||||
|
/* Workaround for Errata 217 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document |
||||
|
for your device located at https://infocenter.nordicsemi.com/index.jsp */ |
||||
|
if (nrf52_errata_217()){ |
||||
|
*(volatile uint32_t *)0x40000EE4ul |= 0x0000000Ful; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
/* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the |
||||
|
* compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit |
||||
|
* operations are not used in your code. */ |
||||
|
#if (__FPU_USED == 1) |
||||
|
SCB->CPACR |= (3UL << 20) | (3UL << 22); |
||||
|
__DSB(); |
||||
|
__ISB(); |
||||
|
#endif |
||||
|
|
||||
|
nrf52_handle_approtect(); |
||||
|
|
||||
|
#if NRF52_CONFIGURATION_249_ENABLE && (defined(NRF52805_XXAA) || defined(NRF52810_XXAA) || defined(NRF52811_XXAA)) |
||||
|
if (nrf52_configuration_249() && (NRF_UICR->NRFMDK[0] == 0xFFFFFFFF || NRF_UICR->NRFMDK[1] == 0xFFFFFFFF)) |
||||
|
{ |
||||
|
nvmc_config(NVMC_CONFIG_WEN_Wen); |
||||
|
NRF_UICR->NRFMDK[0] = 0; |
||||
|
nvmc_wait(); |
||||
|
NRF_UICR->NRFMDK[1] = 0; |
||||
|
nvmc_wait(); |
||||
|
nvmc_config(NVMC_CONFIG_WEN_Ren); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
/* Configure NFCT pins as GPIOs if NFCT is not to be used in your code. If CONFIG_NFCT_PINS_AS_GPIOS is not defined, |
||||
|
two GPIOs (see Product Specification to see which ones) will be reserved for NFC and will not be available as |
||||
|
normal GPIOs. */ |
||||
|
#if defined (CONFIG_NFCT_PINS_AS_GPIOS) && defined(NFCT_PRESENT) |
||||
|
if ((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)){ |
||||
|
nvmc_config(NVMC_CONFIG_WEN_Wen); |
||||
|
NRF_UICR->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk; |
||||
|
nvmc_wait(); |
||||
|
nvmc_config(NVMC_CONFIG_WEN_Ren); |
||||
|
NVIC_SystemReset(); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
/* Configure GPIO pads as pPin Reset pin if Pin Reset capabilities desired. If CONFIG_GPIO_AS_PINRESET is not |
||||
|
defined, pin reset will not be available. One GPIO (see Product Specification to see which one) will then be |
||||
|
reserved for PinReset and not available as normal GPIO. */ |
||||
|
#if defined (CONFIG_GPIO_AS_PINRESET) |
||||
|
if (((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) || |
||||
|
((NRF_UICR->PSELRESET[1] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))){ |
||||
|
nvmc_config(NVMC_CONFIG_WEN_Wen); |
||||
|
NRF_UICR->PSELRESET[0] = RESET_PIN; |
||||
|
nvmc_wait(); |
||||
|
NRF_UICR->PSELRESET[1] = RESET_PIN; |
||||
|
nvmc_wait(); |
||||
|
nvmc_config(NVMC_CONFIG_WEN_Ren); |
||||
|
NVIC_SystemReset(); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
/* When developing for nRF52810 on an nRF52832, or nRF52811 on an nRF52840, |
||||
|
make sure NFC pins are mapped as GPIO. */ |
||||
|
#if defined (DEVELOP_IN_NRF52832) && defined(NRF52810_XXAA) \ |
||||
|
|| defined (DEVELOP_IN_NRF52840) && defined(NRF52811_XXAA) |
||||
|
if ((*((uint32_t *)0x1000120C) & (1 << 0)) != 0){ |
||||
|
nvmc_config(NVMC_CONFIG_WEN_Wen); |
||||
|
*((uint32_t *)0x1000120C) = 0; |
||||
|
nvmc_wait(); |
||||
|
nvmc_config(NVMC_CONFIG_WEN_Ren); |
||||
|
NVIC_SystemReset(); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
SystemCoreClockUpdate(); |
||||
|
} |
1660
app/app.uvoptx
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
7882
app/app.uvprojx
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
12168
app/config/sdk_config.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,369 @@ |
|||||
|
#include "znordic.h" |
||||
|
// |
||||
|
#include <stdarg.h> |
||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
// |
||||
|
#include "app_ble_service.h" |
||||
|
#include "app_event_distribute.h" |
||||
|
#include "basic/ads1293/ads1293.h" |
||||
|
#include "board/board.h" |
||||
|
#include "device_ctrl_service.h" |
||||
|
#include "nrf_drv_gpiote.h" |
||||
|
#include "sample_data_manager_service.h" |
||||
|
#include "zble_module.h" |
||||
|
#include "zdatachannel_service.h" |
||||
|
#include "znordic_device_info_mgr.h" |
||||
|
// |
||||
|
ZDATACHANNEL_DEF(m_zhrs, 2 /*优先级*/, 1 /*client num*/); |
||||
|
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(ADS1293_SPI_INSTANCE); /**< SPI instance. */ |
||||
|
static ads1293_t m_ads1293_0; // U2 |
||||
|
static ads1293_t m_ads1293_1; |
||||
|
typedef struct { |
||||
|
uint8_t add; |
||||
|
uint8_t data; |
||||
|
} adscfg_t; |
||||
|
|
||||
|
static adscfg_t m_prvads0cfg_cache[65]; |
||||
|
static adscfg_t m_prvads1cfg_cache[65]; |
||||
|
|
||||
|
static void zdatachannel_data_handler(zdatachannel_evt_t* p_evt) {} |
||||
|
void blechannel_service_init() { |
||||
|
ZLOGI("init zdatachannel service"); |
||||
|
static 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)); |
||||
|
} |
||||
|
static void ads1293_spi_tx_rx_0(uint8_t* tx, uint8_t* rx, uint8_t len) { |
||||
|
nrf_gpio_pin_clear(ADS1293_SPI_CS0_PIN); |
||||
|
nrf_drv_spi_transfer(&spi, tx, len, rx, len); |
||||
|
nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); |
||||
|
} |
||||
|
static void ads1293_spi_tx_rx_1(uint8_t* tx, uint8_t* rx, uint8_t len) { |
||||
|
nrf_gpio_pin_clear(ADS1293_SPI_CS1_PIN); |
||||
|
nrf_drv_spi_transfer(&spi, tx, len, rx, len); |
||||
|
nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); |
||||
|
} |
||||
|
static void ads1293_spi_writereg_and_check(ads1293_t* ads, uint8_t addr, uint8_t data) { |
||||
|
uint8_t readbak = 0; |
||||
|
// readonly add |
||||
|
readbak = data; |
||||
|
if (addr >= 0x18 && addr <= 0x1E) { |
||||
|
return; |
||||
|
} |
||||
|
if (addr >= 0x30 && addr <= 0x3f) { |
||||
|
return; |
||||
|
} |
||||
|
if (addr == 0x40) { |
||||
|
return; |
||||
|
} |
||||
|
if (addr == 0x50) { |
||||
|
return; |
||||
|
} |
||||
|
ads1293_spi_writereg_and_readbak(ads, addr, data, &readbak); |
||||
|
if (readbak != data) { |
||||
|
ZLOGE("ads_%d write %x failed,w:%x readbak:%x\n", ads->id, addr, data, readbak); |
||||
|
} |
||||
|
} |
||||
|
static void tryloadcfg_from_fatfs(const char* file, adscfg_t* cfg, uint16_t cfgsize, uint16_t* cfg_ret_size) { |
||||
|
// |
||||
|
*cfg_ret_size = 0; |
||||
|
|
||||
|
static FIL fd; |
||||
|
FRESULT ff_result = f_open(&fd, (const TCHAR*)file, FA_READ); |
||||
|
if (ff_result != FR_OK) { |
||||
|
ZLOGE("open %s failed\n", file); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
char line[128]; |
||||
|
int niterm = 0; |
||||
|
f_gets(line, 128, &fd); |
||||
|
|
||||
|
while (f_gets(line, 128, &fd)) { |
||||
|
uint32_t addr; |
||||
|
uint32_t value; |
||||
|
sscanf(line, "%x,%x", &addr, &value); |
||||
|
cfg[niterm].add = addr; |
||||
|
cfg[niterm].data = value; |
||||
|
niterm++; |
||||
|
|
||||
|
if (niterm >= cfgsize) { |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
*cfg_ret_size = niterm; |
||||
|
ZLOGI("load %s cfg size:%d\n", file, niterm); |
||||
|
f_close(&fd); |
||||
|
} |
||||
|
|
||||
|
uint32_t get_ready_pin_state_get() { return nrf_gpio_pin_read(ADS1293_READY_PIN); } |
||||
|
|
||||
|
static adscfg_t m_prvads0cfg[] = // |
||||
|
{ |
||||
|
{0x00, 0x00}, {0x01, 0x19}, {0x02, 0x11}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x0f}, {0x08, 0xff}, {0x09, 0x00}, {0x0a, 0x07}, {0x0b, 0x07}, {0x0c, 0x74}, {0x0d, 0x01}, {0x0e, 0x02}, {0x0f, 0x03}, {0x10, 0x04}, |
||||
|
{0x11, 0x00}, {0x12, 0x05}, {0x13, 0x39}, {0x14, 0x36}, {0x15, 0x06}, {0x16, 0x00}, {0x17, 0x05}, {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00}, {0x1c, 0x00}, {0x1d, 0x00}, {0x21, 0x01}, {0x22, 0x20}, {0x23, 0x20}, {0x24, 0x02}, |
||||
|
{0x25, 0x00}, {0x26, 0x00}, {0x27, 0x08}, {0x28, 0x08}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00}, {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x33}, {0x2f, 0x30}, {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0x00}, {0x35, 0x00}, |
||||
|
{0x36, 0x00}, {0x37, 0x00}, {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00}, {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00}, {0x40, 0xff}, {0x50, 0x00}, {0x60, 0x00}, {0x62, 0x00}, |
||||
|
}; |
||||
|
|
||||
|
static adscfg_t m_prvads1cfg[] = // |
||||
|
{ |
||||
|
{0x00, 0x00}, {0x01, 0x0c}, {0x02, 0x14}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x0f}, {0x08, 0xff}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x07}, {0x0c, 0x78}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00}, {0x10, 0x04}, |
||||
|
{0x11, 0x00}, {0x12, 0x07}, {0x13, 0x3b}, {0x14, 0x24}, {0x15, 0x04}, {0x16, 0x00}, {0x17, 0x05}, {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00}, {0x1c, 0x00}, {0x1d, 0x00}, {0x21, 0x01}, {0x22, 0x20}, {0x23, 0x20}, {0x24, 0x02}, |
||||
|
{0x25, 0x00}, {0x26, 0x00}, {0x27, 0x08}, {0x28, 0x40}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00}, {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x33}, {0x2f, 0x30}, {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0x00}, {0x35, 0x00}, |
||||
|
{0x36, 0x00}, {0x37, 0x00}, {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00}, {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00}, {0x40, 0xff}, {0x50, 0x00}, {0x60, 0x00}, {0x62, 0x00}, |
||||
|
}; |
||||
|
|
||||
|
static void ads1293_init() { |
||||
|
/******************************************************************************* |
||||
|
* SPI初始化 * |
||||
|
*******************************************************************************/ |
||||
|
static 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 = ADS1293_SPI_MISO_PIN; |
||||
|
spi_config.mosi_pin = ADS1293_SPI_MOSI_PIN; |
||||
|
spi_config.sck_pin = ADS1293_SPI_SCK_PIN; |
||||
|
spi_config.frequency = NRF_DRV_SPI_FREQ_8M; |
||||
|
spi_config.mode = NRF_DRV_SPI_MODE_3; |
||||
|
// spi_config.mode = |
||||
|
ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); |
||||
|
|
||||
|
znrf_gpio_cfg_output(ADS1293_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL); |
||||
|
znrf_gpio_cfg_output(ADS1293_SPI_CS1_PIN, NRF_GPIO_PIN_NOPULL); |
||||
|
nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); |
||||
|
nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); |
||||
|
|
||||
|
m_ads1293_0.spi_tx_rx = ads1293_spi_tx_rx_0; |
||||
|
m_ads1293_0.id = 0; |
||||
|
m_ads1293_1.spi_tx_rx = ads1293_spi_tx_rx_1; |
||||
|
m_ads1293_1.id = 1; |
||||
|
|
||||
|
ads1293_spi_init(&m_ads1293_0, ads1293_spi_tx_rx_0); |
||||
|
ads1293_spi_init(&m_ads1293_1, ads1293_spi_tx_rx_1); |
||||
|
|
||||
|
uint8_t revid = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_REVID_REG); |
||||
|
ZLOGI("ads1293_0 revid: %d\n", revid); |
||||
|
revid = ads1293_spi_readreg(&m_ads1293_1, TI_ADS1293_REVID_REG); |
||||
|
ZLOGI("ads1293_1 revid: %d\n", revid); |
||||
|
|
||||
|
ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0); |
||||
|
|
||||
|
uint16_t cfgsize = 0; |
||||
|
tryloadcfg_from_fatfs("0.cfg", m_prvads0cfg_cache, ZARRAY_SIZE(m_prvads0cfg_cache), &cfgsize); |
||||
|
if (cfgsize > 0) { |
||||
|
ZLOGI("load 0.cfg from fatfs\n"); |
||||
|
|
||||
|
if (memcmp(m_prvads0cfg_cache, m_prvads0cfg, sizeof(m_prvads0cfg)) != 0) { |
||||
|
ZLOGI("0.cfg is different from default\n"); |
||||
|
} else { |
||||
|
ZLOGI("0.cfg is same as default\n"); |
||||
|
} |
||||
|
|
||||
|
for (uint16_t i = 0; i < cfgsize; i++) { |
||||
|
ads1293_spi_writereg_and_check(&m_ads1293_0, m_prvads0cfg_cache[i].add, m_prvads0cfg_cache[i].data); |
||||
|
} |
||||
|
} else { |
||||
|
for (uint16_t i = 0; i < ZARRAY_SIZE(m_prvads0cfg); i++) { |
||||
|
ads1293_spi_writereg_and_check(&m_ads1293_0, m_prvads0cfg[i].add, m_prvads0cfg[i].data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
tryloadcfg_from_fatfs("1.cfg", m_prvads1cfg_cache, ZARRAY_SIZE(m_prvads1cfg_cache), &cfgsize); |
||||
|
if (cfgsize > 0) { |
||||
|
ZLOGI("load 1.cfg from fatfs\n"); |
||||
|
|
||||
|
if (memcmp(m_prvads1cfg_cache, m_prvads1cfg, sizeof(m_prvads1cfg)) != 0) { |
||||
|
ZLOGI("1.cfg is different from default\n"); |
||||
|
} else { |
||||
|
ZLOGI("1.cfg is same as default\n"); |
||||
|
} |
||||
|
|
||||
|
for (uint16_t i = 0; i < cfgsize; i++) { |
||||
|
ads1293_spi_writereg_and_check(&m_ads1293_1, m_prvads1cfg_cache[i].add, m_prvads1cfg_cache[i].data); |
||||
|
} |
||||
|
} else { |
||||
|
for (uint16_t i = 0; i < ZARRAY_SIZE(m_prvads1cfg); i++) { |
||||
|
ads1293_spi_writereg_and_check(&m_ads1293_1, m_prvads1cfg[i].add, m_prvads1cfg[i].data); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static void onServiceInitCB() { |
||||
|
ZLOGI("init zdatachannel service"); |
||||
|
static 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 setup(); |
||||
|
int main() { |
||||
|
APP_SCHED_INIT(APP_MAX_EVEN_SIZE, APP_EVENT_QUEUE_SIZE); |
||||
|
znordic_init(); |
||||
|
NRF_LOG_INFO("compile time :%s", __TIME__); |
||||
|
ZLOGI("CUSTOMER :%d", NRF_UICR->CUSTOMER[0]); |
||||
|
/******************************************************************************* |
||||
|
* 蓝牙服务初始化 * |
||||
|
*******************************************************************************/ |
||||
|
static zble_module_cfg_t cfg; |
||||
|
cfg.deviceName = "ADS1293_TESTER"; |
||||
|
cfg.on_service_init = onServiceInitCB; |
||||
|
zble_module_init(&cfg); |
||||
|
AppBleService_init(); |
||||
|
|
||||
|
setup(); |
||||
|
} |
||||
|
|
||||
|
static ads1293_error_t error0; |
||||
|
static ads1293_error_t error1; |
||||
|
static uint8_t txcache[128]; |
||||
|
|
||||
|
void send_ads1293_error_state(ads1293_error_t* e0, ads1293_error_t* e1) { // |
||||
|
|
||||
|
txcache[0] = 0xA1; |
||||
|
txcache[1] = 0x01; |
||||
|
memcpy(txcache + 2, e0, sizeof(ads1293_error_t)); |
||||
|
memcpy(txcache + 2 + sizeof(ads1293_error_t), e1, sizeof(ads1293_error_t)); |
||||
|
|
||||
|
zdatachannel_data_send2(txcache, 2 + sizeof(ads1293_error_t) * 2); |
||||
|
} |
||||
|
|
||||
|
void capture_error_state() { |
||||
|
ads1293_read_error(&m_ads1293_0, &error0); |
||||
|
ads1293_read_error(&m_ads1293_1, &error1); |
||||
|
|
||||
|
#if 0 |
||||
|
error0.estatus =1; |
||||
|
error0.error_range1 =2; |
||||
|
error0.error_range2 =3; |
||||
|
error0.error_range3 =4; |
||||
|
error0.error_sync =5; |
||||
|
error0.error_misc =6; |
||||
|
|
||||
|
error1.estatus =21; |
||||
|
error1.error_range1 =22; |
||||
|
error1.error_range2 =23; |
||||
|
error1.error_range3 =24; |
||||
|
error1.error_sync =25; |
||||
|
error1.error_misc =26; |
||||
|
#endif |
||||
|
|
||||
|
send_ads1293_error_state(&error0, &error1); |
||||
|
} |
||||
|
#pragma pack(1) |
||||
|
typedef struct { |
||||
|
uint32_t sample0; |
||||
|
} one_ch_cache_t; |
||||
|
typedef struct { |
||||
|
uint8_t h1; |
||||
|
uint8_t h2; |
||||
|
one_ch_cache_t data[3]; |
||||
|
uint8_t e1; |
||||
|
uint8_t e2; |
||||
|
} one_frame_cache_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
one_frame_cache_t frame[8]; |
||||
|
} one_packet_t; |
||||
|
|
||||
|
#pragma unpack() |
||||
|
|
||||
|
one_packet_t txpacket; |
||||
|
int cache_data_size = 0; |
||||
|
|
||||
|
void trigger_capture() { |
||||
|
static uint32_t sample[6]; |
||||
|
static uint8_t readystatus[2] = {0}; |
||||
|
ads1293_read_ecgs(&m_ads1293_0, &sample[0]); |
||||
|
ads1293_read_ecgs(&m_ads1293_1, &sample[3]); |
||||
|
|
||||
|
// static int i = 0; |
||||
|
// static int j = 0; |
||||
|
// i++; |
||||
|
// if (i % 8 == 0) { |
||||
|
// j++; |
||||
|
// } |
||||
|
// sample[0] = j; |
||||
|
// sample[3] = j; |
||||
|
// sample[4] = j; |
||||
|
|
||||
|
// TI_ADS1293_DATA_STATUS_REG |
||||
|
// readystatus[0] = ads1293_read_ready_status(&m_ads1293_0); |
||||
|
// readystatus[1] = ads1293_read_ready_status(&m_ads1293_1); |
||||
|
|
||||
|
{ |
||||
|
txpacket.frame[cache_data_size].h1 = 0xA2; |
||||
|
txpacket.frame[cache_data_size].h2 = 0x2; |
||||
|
txpacket.frame[cache_data_size].data[0].sample0 = sample[0]; |
||||
|
txpacket.frame[cache_data_size].data[1].sample0 = sample[3]; |
||||
|
txpacket.frame[cache_data_size].data[2].sample0 = sample[4]; |
||||
|
txpacket.frame[cache_data_size].e1 = 0x2; |
||||
|
txpacket.frame[cache_data_size].e2 = 0xA2; |
||||
|
|
||||
|
cache_data_size++; |
||||
|
if (cache_data_size == 8) { |
||||
|
zdatachannel_data_send2((uint8_t*)&txpacket, sizeof(one_packet_t)); |
||||
|
cache_data_size = 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
uint32_t m_changecount = 0; |
||||
|
static void ads1293_ready_pin_irq(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { // |
||||
|
m_changecount++; |
||||
|
trigger_capture(); |
||||
|
} |
||||
|
|
||||
|
void setup() { |
||||
|
// |
||||
|
|
||||
|
zble_module_start_adv(); |
||||
|
SampleDataMgr_init(); |
||||
|
SampleDataMgr_changeToLocalMode(); |
||||
|
ads1293_init(); |
||||
|
SampleDataMgr_changeToExtMode(); |
||||
|
|
||||
|
ads1293_start_conversion(&m_ads1293_0); |
||||
|
ads1293_start_conversion(&m_ads1293_1); |
||||
|
|
||||
|
nrf_gpio_cfg_input(ADS1293_READY_PIN, NRF_GPIO_PIN_PULLUP); |
||||
|
|
||||
|
{ |
||||
|
nrf_gpio_cfg_input(ADS1293_READY_PIN, NRF_GPIO_PIN_PULLUP); |
||||
|
ZERROR_CHECK(nrfx_gpiote_init()); |
||||
|
nrf_drv_gpiote_in_config_t inConfig = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); // 双边沿中断触发 |
||||
|
inConfig.pull = NRF_GPIO_PIN_PULLUP; // 默认上拉 |
||||
|
inConfig.sense = NRF_GPIOTE_POLARITY_HITOLO; // 下降沿触发 |
||||
|
ZERROR_CHECK(nrfx_gpiote_in_init(ADS1293_READY_PIN, &inConfig, ads1293_ready_pin_irq)); |
||||
|
nrfx_gpiote_in_event_enable(ADS1293_READY_PIN, true); |
||||
|
} |
||||
|
|
||||
|
while (true) { |
||||
|
app_sched_execute(); |
||||
|
NRF_LOG_PROCESS(); |
||||
|
|
||||
|
static bool state = false; |
||||
|
static uint32_t last_ticket = 0; |
||||
|
|
||||
|
bool now = get_ready_pin_state_get(); |
||||
|
uint32_t nowticket = znordic_getpower_on_s(); |
||||
|
|
||||
|
// if (state != now) { |
||||
|
// state = now; |
||||
|
// m_changecount++; |
||||
|
// if (now) { |
||||
|
// // trigger_capture(); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
if (last_ticket != nowticket) { |
||||
|
last_ticket = nowticket; |
||||
|
ZLOGI("%d changecount:%d\n", znordic_getpower_on_ms(), m_changecount); |
||||
|
|
||||
|
capture_error_state(); |
||||
|
m_changecount = 0; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,537 @@ |
|||||
|
#include "app_ble_service.h" |
||||
|
|
||||
|
#include "../../ify_hrs_protocol/heart_rate_sensor_protocol.h" |
||||
|
#include "app_event.h" |
||||
|
#include "app_event_distribute.h" |
||||
|
#include "app_scheduler.h" |
||||
|
#include "board/board.h" |
||||
|
#include "board/board_battery_state.h" |
||||
|
#include "device_ctrl_service.h" |
||||
|
#include "heart_wave_sample_service.h" |
||||
|
#include "sample_data_manager_service.h" |
||||
|
#include "zble_module.h" |
||||
|
#include "zdatachannel_service.h" |
||||
|
#include "znordic.h" |
||||
|
#include "znordic_device_info_mgr.h" |
||||
|
|
||||
|
static uint8_t rxbufcache[256]; |
||||
|
static bool is_rxbufcache_used = false; // 接收到的消息是否正在被处理中 |
||||
|
static bool m_realtime_report_state = false; // 实时上报状态 |
||||
|
|
||||
|
static uint8_t m_txbuf[256]; |
||||
|
static uint8_t m_reportbuf[256]; |
||||
|
|
||||
|
APP_TIMER_DEF(m_record_upload_tmr); // 数据上报定时器 |
||||
|
APP_TIMER_DEF(m_record_upload_finish_packet_report_tmr); // 数据上报完成上报定时器 |
||||
|
|
||||
|
static void prvf_process_ble_rx_data(void* p_event_data, uint16_t event_size); |
||||
|
static void process_ble_rx_data(void* p_event_data, uint16_t event_size); |
||||
|
static void RecordUpload_tmr_cb(void* p_context); |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 蓝牙服务注册 * |
||||
|
*******************************************************************************/ |
||||
|
ZDATACHANNEL_DEF(m_zhrs, 2 /*优先级*/, 1 /*client num*/); |
||||
|
/** |
||||
|
* @brief 蓝牙消息回调 |
||||
|
*/ |
||||
|
static void zdatachannel_data_handler(zdatachannel_evt_t* p_evt) { |
||||
|
if (p_evt->type != ZDATACHANNEL_EVT_RX_DATA) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 消息正在被处理中,丢弃新来的消息 |
||||
|
if (is_rxbufcache_used) return; |
||||
|
if (p_evt->params.rx_data.length > sizeof(rxbufcache)) return; |
||||
|
|
||||
|
memcpy(rxbufcache, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); |
||||
|
uint32_t suc = app_sched_event_put(rxbufcache, p_evt->params.rx_data.length, process_ble_rx_data); |
||||
|
if (suc == 0) { |
||||
|
is_rxbufcache_used = true; |
||||
|
} |
||||
|
} |
||||
|
/******************************************************************************* |
||||
|
* UTILS * |
||||
|
*******************************************************************************/ |
||||
|
int ble_start_realtime_report() { |
||||
|
m_realtime_report_state = true; |
||||
|
return 0; |
||||
|
} |
||||
|
int ble_stop_realtime_report() { |
||||
|
m_realtime_report_state = false; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
static void send_error_receipt(ify_hrs_packet_t* rxpacket, int32_t errorcode) { |
||||
|
ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)m_txbuf; |
||||
|
error_receipt_t* receipt = (error_receipt_t*)txheader->data; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(error_receipt_t); |
||||
|
|
||||
|
txheader->cmd = rxpacket->cmd; |
||||
|
txheader->frame_index = rxpacket->frame_index; |
||||
|
txheader->frame_type = kifyhrs_pt_error_receipt; |
||||
|
|
||||
|
txheader->frame_type = kifyhrs_pt_error_receipt; |
||||
|
receipt->errorcode = kifyhrs_ecode_cmd_not_support; |
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
} |
||||
|
|
||||
|
static void send_success_receipt(ify_hrs_packet_t* rxpacket, int32_t emptydatasize) { |
||||
|
ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)m_txbuf; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + emptydatasize; |
||||
|
|
||||
|
txheader->cmd = rxpacket->cmd; |
||||
|
txheader->frame_index = rxpacket->frame_index; |
||||
|
txheader->frame_type = kifyhrs_pt_cmd_receipt; |
||||
|
|
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
} |
||||
|
|
||||
|
static void prvf_try_report_sensor_drop_event(uint8_t dropstate0, uint8_t dropstate1) { |
||||
|
sensor_drop_event_report_packet_t* reportpacket = (sensor_drop_event_report_packet_t*)m_reportbuf; |
||||
|
reportpacket->cmd = ify_hrs_report_sensor_drop_detect; |
||||
|
reportpacket->frame_index = 0; |
||||
|
reportpacket->frame_type = kifyhrs_pt_report; |
||||
|
reportpacket->drop_state0 = dropstate0; |
||||
|
reportpacket->drop_state1 = dropstate1; |
||||
|
|
||||
|
uint16_t sendlen = sizeof(sensor_drop_event_report_packet_t); |
||||
|
zdatachannel_data_send2(m_reportbuf, sendlen); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
static void prvf_try_report_sample_end_event() { |
||||
|
ify_hrs_packet_t* reportpacket = (ify_hrs_packet_t*)m_reportbuf; |
||||
|
reportpacket->cmd = ify_hrs_report_sample_finish_end; |
||||
|
reportpacket->frame_index = 0; |
||||
|
reportpacket->frame_type = kifyhrs_pt_report; |
||||
|
|
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t); |
||||
|
zdatachannel_data_send2(m_reportbuf, sendlen); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
void prvf_report_sample_data(uint32_t frameIndex, one_frame_data_t* data, int32_t ndata) { |
||||
|
if (!m_realtime_report_state) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
heartrate_report_packet_t* reportpacket = (heartrate_report_packet_t*)m_reportbuf; |
||||
|
reportpacket->cmd = ify_hrs_report_heartrate_data; |
||||
|
reportpacket->frame_index = 0; |
||||
|
reportpacket->frame_type = kifyhrs_pt_report; |
||||
|
reportpacket->sample_data_index = frameIndex; |
||||
|
|
||||
|
/** |
||||
|
* @brief 第一导联数据 |
||||
|
*/ |
||||
|
for (int i = 0; i < ndata; i++) { |
||||
|
|
||||
|
reportpacket->data[i * 9 + 0] = ((data[i].data0)) >> 0; |
||||
|
reportpacket->data[i * 9 + 1] = ((data[i].data0)) >> 8; |
||||
|
reportpacket->data[i * 9 + 2] = ((data[i].data0)) >> 16; |
||||
|
|
||||
|
reportpacket->data[i * 9 + 3] = ((data[i].data1)) >> 0; |
||||
|
reportpacket->data[i * 9 + 4] = ((data[i].data1)) >> 8; |
||||
|
reportpacket->data[i * 9 + 5] = ((data[i].data1)) >> 16; |
||||
|
|
||||
|
reportpacket->data[i * 9 + 6] = ((data[i].data2)) >> 0; |
||||
|
reportpacket->data[i * 9 + 7] = ((data[i].data2)) >> 8; |
||||
|
reportpacket->data[i * 9 + 8] = ((data[i].data2)) >> 16; |
||||
|
} |
||||
|
uint16_t sendlen = sizeof(heartrate_report_packet_t) + ndata * 9; |
||||
|
zdatachannel_data_send2(m_reportbuf, sendlen); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 记录读取服务 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
static int m_upload_fd; |
||||
|
static uint8_t m_datacache[256]; |
||||
|
static int m_remaindatalen = 0; |
||||
|
static uint32_t m_report_data_sumcheckcode = 0; |
||||
|
static bool m_isupload_data_state = false; |
||||
|
|
||||
|
void RecordUpload_report_finish_event(uint32_t sumcheckcode) { |
||||
|
ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)m_txbuf; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + 4; |
||||
|
|
||||
|
txheader->cmd = ify_hrs_report_record_upload_end; // 6A |
||||
|
txheader->frame_index = 0; |
||||
|
txheader->frame_type = kifyhrs_pt_report; |
||||
|
|
||||
|
// txheader->data[0] = errorcode; |
||||
|
*(uint32_t*)txheader->data = sumcheckcode; |
||||
|
|
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
int RecordUpload_ble_stop_upload_record() { |
||||
|
m_isupload_data_state = false; |
||||
|
app_timer_stop(m_record_upload_tmr); |
||||
|
return 0; |
||||
|
} |
||||
|
/** |
||||
|
* @brief 数据上报定时器回调 |
||||
|
* |
||||
|
* @param p_context |
||||
|
*/ |
||||
|
static void RecordUpload_finish_packet_report_tmr_cb(void* p_context) { // |
||||
|
RecordUpload_report_finish_event(m_report_data_sumcheckcode); |
||||
|
} |
||||
|
|
||||
|
static void RecordUpload_tmr_cb(void* p_context) { // |
||||
|
|
||||
|
if (!m_isupload_data_state) return; |
||||
|
|
||||
|
// sample_data_mgr_read |
||||
|
if (m_remaindatalen == 0) { |
||||
|
memset(m_datacache, 0, sizeof(m_datacache)); |
||||
|
int32_t rdsize = SampleDataMgr_read(m_upload_fd, m_datacache, sizeof(m_datacache)); |
||||
|
if (rdsize <= 0) { |
||||
|
ZLOGI("read file end,stop upload"); |
||||
|
ZERROR_CHECK(app_timer_start(m_record_upload_finish_packet_report_tmr, APP_TIMER_TICKS(30), (void*)m_report_data_sumcheckcode)); |
||||
|
RecordUpload_ble_stop_upload_record(); |
||||
|
return; |
||||
|
} |
||||
|
m_remaindatalen = rdsize; |
||||
|
} |
||||
|
if (m_remaindatalen == 0) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
int32_t mtusize = zble_module_get_mtu_size(); |
||||
|
mtusize = mtusize < 128 ? mtusize : 128; |
||||
|
|
||||
|
uint8_t* data = m_datacache + (sizeof(m_datacache) - m_remaindatalen); |
||||
|
int len = m_remaindatalen > mtusize ? mtusize : m_remaindatalen; |
||||
|
|
||||
|
ZLOGI("upload %d %d %d", len, m_remaindatalen, mtusize); |
||||
|
if (!zdatachannel_is_connected()) { |
||||
|
ZLOGI("ble is disconnected,stop upload"); |
||||
|
RecordUpload_ble_stop_upload_record(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
uint32_t suc = zdatachannel_block_data_send2(data, len); |
||||
|
if (suc != NRF_SUCCESS) { |
||||
|
if (suc == NRF_ERROR_INVALID_STATE) { |
||||
|
// 未使能notify |
||||
|
ZLOGI("ble unenable notify,stop upload"); |
||||
|
RecordUpload_ble_stop_upload_record(); |
||||
|
return; |
||||
|
} else if (suc == NRF_ERROR_BUSY || suc == NRF_ERROR_RESOURCES) { |
||||
|
// 等待下次发送 |
||||
|
return; |
||||
|
} else { |
||||
|
ZLOGI("ble send error,stop upload %x", suc); |
||||
|
RecordUpload_ble_stop_upload_record(); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
for (uint32_t i = 0; i < len; i++) { |
||||
|
m_report_data_sumcheckcode += data[i]; |
||||
|
} |
||||
|
m_remaindatalen -= len; |
||||
|
} |
||||
|
|
||||
|
int RecordUpload_start(sample_data_filename_t* recordid) { |
||||
|
// |
||||
|
// 启动 |
||||
|
// |
||||
|
SampleDataMgr_changeToLocalMode(); |
||||
|
|
||||
|
m_upload_fd = SampleDataMgr_open(recordid, kwrflag_read_only); |
||||
|
if (m_upload_fd <= 0) { |
||||
|
return kifyhrs_ecode_no_record_find; |
||||
|
} |
||||
|
|
||||
|
ZERROR_CHECK(app_timer_start(m_record_upload_tmr, APP_TIMER_TICKS(2), NULL)); |
||||
|
m_isupload_data_state = true; |
||||
|
m_remaindatalen = 0; |
||||
|
m_report_data_sumcheckcode = 0; |
||||
|
return 0; |
||||
|
} |
||||
|
int RecordUpload_stop_upload() { |
||||
|
m_isupload_data_state = false; |
||||
|
SampleDataMgr_changeToExtMode(); |
||||
|
app_timer_stop(m_record_upload_tmr); |
||||
|
return 0; |
||||
|
} |
||||
|
bool RecordUpload_is_uploading() { return m_isupload_data_state; } |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 消息处理 * |
||||
|
*******************************************************************************/ |
||||
|
static void process_ble_rx_data(void* p_event_data, uint16_t event_size) { // |
||||
|
prvf_process_ble_rx_data(p_event_data, event_size); |
||||
|
is_rxbufcache_used = false; |
||||
|
} |
||||
|
|
||||
|
static void prvf_process_ble_rx_data(void* p_event_data, uint16_t len) { |
||||
|
ify_hrs_packet_t* rxheader = (ify_hrs_packet_t*)p_event_data; |
||||
|
ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)m_txbuf; |
||||
|
ify_hrs_cmd_t cmd = (ify_hrs_cmd_t)rxheader->cmd; |
||||
|
memset(m_txbuf, 0, sizeof(m_txbuf)); |
||||
|
|
||||
|
ZLOGI("rx cmd:%d index:%d datalen:%d", cmd, rxheader->frame_index, len - sizeof(ify_hrs_packet_t)); |
||||
|
NRF_LOG_HEXDUMP_INFO(p_event_data, len); |
||||
|
|
||||
|
txheader->cmd = rxheader->cmd; |
||||
|
txheader->frame_index = rxheader->frame_index; |
||||
|
txheader->frame_type = kifyhrs_pt_cmd_receipt; |
||||
|
|
||||
|
if (cmd == ify_hrs_cmd_read_device_version) { |
||||
|
device_version_info_receipt_t* receipt = (device_version_info_receipt_t*)txheader->data; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_version_info_receipt_t); |
||||
|
|
||||
|
receipt->blestack_version = device_info_read_blestack_version(); |
||||
|
receipt->bootloader_version = device_info_read_bootloader_version(); |
||||
|
receipt->firmware_version = device_info_read_firmware_version(); |
||||
|
receipt->hardware_version = device_info_read_hardware_version(); |
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_read_sensor_info) { |
||||
|
sensor_info_receipt_t* receipt = (sensor_info_receipt_t*)txheader->data; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(sensor_info_receipt_t); |
||||
|
|
||||
|
receipt->sensor_num = APP_SENSOR_NUM; |
||||
|
receipt->sensor_precision = SAMPLE_PRECISION; |
||||
|
receipt->sensor_sample_rate = SAMPLE_RATE / 10; |
||||
|
receipt->sensor0_pos = kifyhrs_sensor_pos_II; |
||||
|
receipt->sensor1_pos = kifyhrs_sensor_pos_V1; |
||||
|
receipt->sensor2_pos = kifyhrs_sensor_pos_V5; |
||||
|
|
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_read_device_state) { |
||||
|
device_state_receipt_t* receipt = (device_state_receipt_t*)txheader->data; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_state_receipt_t); |
||||
|
|
||||
|
receipt->drop_state0 = hwss_get_drop_state0(); |
||||
|
receipt->drop_state1 = hwss_get_drop_state1(); |
||||
|
|
||||
|
receipt->drop_state1 = 0x00; |
||||
|
receipt->device_state0.sampling_state = (DeviceCtrl_now_state() == kdevice_state_sampling); |
||||
|
receipt->device_state0.report_state = m_realtime_report_state; |
||||
|
receipt->device_state0.low_battery = (BoardBattery_get_battery_level() < 20); |
||||
|
receipt->device_state0.full_storge = (SampleDataMgr_storageIsFull()); |
||||
|
|
||||
|
receipt->device_state1 = 0; |
||||
|
receipt->powerlevel = BoardBattery_get_battery_level(); |
||||
|
receipt->storage_item_num = SampleDataMgr_getFileNum(); |
||||
|
|
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_read_time) { |
||||
|
read_time_receipt_t* receipt = (read_time_receipt_t*)txheader->data; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_time_receipt_t); |
||||
|
static ztm_t ztm; |
||||
|
znordic_rtc_gettime(&ztm); |
||||
|
|
||||
|
receipt->year = (ztm.tm_year + 1900 - 2000); |
||||
|
receipt->month = ztm.tm_mon + 1; |
||||
|
receipt->day = ztm.tm_mday; |
||||
|
receipt->hour = ztm.tm_hour; |
||||
|
receipt->minute = ztm.tm_min; |
||||
|
receipt->second = ztm.tm_sec; |
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_sync_time) { |
||||
|
sync_time_cmd_t* cmd = (sync_time_cmd_t*)rxheader->data; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t); |
||||
|
|
||||
|
znordic_rtc_settime(cmd->year + 2000, cmd->month, cmd->day, cmd->hour, cmd->minute, cmd->second); |
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_start_capture) { |
||||
|
// hwss_start_capture(); |
||||
|
|
||||
|
if (RecordUpload_is_uploading()) { |
||||
|
ZLOGI("uploading,can not start capture"); |
||||
|
send_error_receipt(rxheader, kifyhrs_ecode_device_busy); |
||||
|
} |
||||
|
|
||||
|
DeviceCtrl_startSample(); |
||||
|
send_success_receipt(rxheader, 0); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_stop_capture) { |
||||
|
// hwss_stop_capture(); |
||||
|
DeviceCtrl_stopSample(); |
||||
|
send_success_receipt(rxheader, 0); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_start_realtime_report) { |
||||
|
// unsupport cmd |
||||
|
int ecode = ble_start_realtime_report(); |
||||
|
if (ecode == 0) { |
||||
|
send_success_receipt(rxheader, 8); // 凑8个字节,使这个回执的字节长度同上报包长度一致,方便调试 |
||||
|
} else { |
||||
|
send_error_receipt(rxheader, ecode); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_stop_realtime_report) { |
||||
|
int ecode = ble_stop_realtime_report(); |
||||
|
if (ecode == 0) { |
||||
|
send_success_receipt(rxheader, 0); |
||||
|
} else { |
||||
|
send_error_receipt(rxheader, ecode); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_read_records_info) { |
||||
|
// 指令 10-读取采样记录头部信息 |
||||
|
read_record_info_cmd_t* cmd = (read_record_info_cmd_t*)rxheader->data; |
||||
|
read_record_info_receipt_t* receipt = (read_record_info_receipt_t*)txheader->data; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_record_info_receipt_t); |
||||
|
|
||||
|
uint8_t recordoff = cmd->record_index; |
||||
|
|
||||
|
// 采样时不支持 |
||||
|
if (hwss_is_capturing()) { |
||||
|
send_error_receipt(rxheader, kifyhrs_ecode_device_busy); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
sample_data_fileinfo_list_t* recordlist = SampleDataMgr_getFileinfoList(); |
||||
|
if (recordoff >= recordlist->count) { |
||||
|
send_error_receipt(rxheader, kifyhrs_ecode_no_record_find); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
sample_data_fileinfo_t* fileinfo = recordlist->fileinfo[recordoff]; |
||||
|
memcpy(receipt->record_id, fileinfo->filename, 6); |
||||
|
receipt->frameNum = fileinfo->size / APP_BYTE_EACH_FRAME; |
||||
|
receipt->dataSize = fileinfo->size; |
||||
|
receipt->sensorNum = APP_SENSOR_NUM; |
||||
|
receipt->captureRate = SAMPLE_RATE / 10; |
||||
|
receipt->capturePrecision = SAMPLE_PRECISION; |
||||
|
receipt->compressAlgorithm = 0; |
||||
|
|
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_del_record) { |
||||
|
// 指令 11-删除采样记录 |
||||
|
del_record_cmd_t* cmd = (del_record_cmd_t*)rxheader->data; |
||||
|
|
||||
|
static sample_data_filename_t filename; |
||||
|
memset(&filename, 0, sizeof(filename)); |
||||
|
memcpy(&filename, cmd->record_id, sizeof(cmd->record_id)); |
||||
|
|
||||
|
send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_start_upload_record) { |
||||
|
// 指令 12-上传采集记录 |
||||
|
// send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); |
||||
|
|
||||
|
start_upload_record_cmd_t* cmd = (start_upload_record_cmd_t*)rxheader->data; |
||||
|
|
||||
|
static sample_data_filename_t filename; |
||||
|
memset(&filename, 0, sizeof(filename)); |
||||
|
memcpy(&filename, cmd->record_id, sizeof(cmd->record_id)); |
||||
|
|
||||
|
// 采样时不支持 |
||||
|
if (DeviceCtrl_now_state() != kdevice_state_ready) { |
||||
|
send_error_receipt(rxheader, kifyhrs_ecode_device_busy); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
int ecode = RecordUpload_start(&filename); |
||||
|
if (0 == 0) { |
||||
|
send_success_receipt(rxheader, 0); |
||||
|
} else { |
||||
|
send_error_receipt(rxheader, 0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_stop_upload_record) { |
||||
|
RecordUpload_stop_upload(); |
||||
|
send_success_receipt(rxheader, 0); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_enter_ota) { |
||||
|
send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_read_sn) { |
||||
|
read_sn_receipt_t* receipt = (read_sn_receipt_t*)txheader->data; |
||||
|
uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_sn_receipt_t); |
||||
|
device_info_read_sn((sn_t*)&receipt->sn); |
||||
|
zdatachannel_data_send2(m_txbuf, sendlen); |
||||
|
} |
||||
|
|
||||
|
else if (cmd == ify_hrs_cmd_reset) { |
||||
|
NVIC_SystemReset(); |
||||
|
} |
||||
|
// |
||||
|
else { |
||||
|
send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); |
||||
|
} |
||||
|
} |
||||
|
static const char* dropstate(uint8_t drop0, uint8_t drop1) { |
||||
|
static char state[128]; |
||||
|
sprintf(state, "drop0:%d%d%d%d-%d%d%d%d drop1:%d%d%d%d-%d%d%d%d", // |
||||
|
drop0 & 0x80 ? 1 : 0, drop0 & 0x40 ? 1 : 0, drop0 & 0x20 ? 1 : 0, drop0 & 0x10 ? 1 : 0, // |
||||
|
drop0 & 0x08 ? 1 : 0, drop0 & 0x04 ? 1 : 0, drop0 & 0x02 ? 1 : 0, drop0 & 0x01 ? 1 : 0, // |
||||
|
drop1 & 0x80 ? 1 : 0, drop1 & 0x40 ? 1 : 0, drop1 & 0x20 ? 1 : 0, drop1 & 0x10 ? 1 : 0, // |
||||
|
drop1 & 0x08 ? 1 : 0, drop1 & 0x04 ? 1 : 0, drop1 & 0x02 ? 1 : 0, drop1 & 0x01 ? 1 : 0 // |
||||
|
); |
||||
|
return state; |
||||
|
} |
||||
|
void AppBleService_onServiceInitCB() { |
||||
|
ZLOGI("init zdatachannel service"); |
||||
|
static 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)); |
||||
|
} |
||||
|
|
||||
|
static void app_event_listener(void* p_event_data, uint16_t event_size) { // |
||||
|
app_event_t* event = (app_event_t*)p_event_data; |
||||
|
if (event->eventType == kevent_sensor_drop) { |
||||
|
prvf_try_report_sensor_drop_event(event->val.sensor_drop.drop0, event->val.sensor_drop.drop1); |
||||
|
} else if (event->eventType == kevent_tmr_scheduler) { |
||||
|
static int cnt = 0; |
||||
|
cnt++; |
||||
|
if (DeviceCtrl_now_state() == kdevice_state_sampling && cnt % 10 == 0) { |
||||
|
// uint8_t drop0 = hwss_get_drop_state0(); |
||||
|
// uint8_t drop1 = hwss_get_drop_state1(); |
||||
|
// ZLOGI("[%d] drop %s", znordic_getpower_on_ms(), dropstate(drop0, drop1)); |
||||
|
// prvf_try_report_sensor_drop_event(drop0, drop1); |
||||
|
} |
||||
|
|
||||
|
} else if (event->eventType == kevent_sample_stop_event) { |
||||
|
prvf_try_report_sample_end_event(); |
||||
|
} else if (event->eventType == kevent_capture_little_data_block_event) { |
||||
|
// 上报采样数据 |
||||
|
if (m_realtime_report_state) { |
||||
|
// 上报采样数据 |
||||
|
prvf_report_sample_data(event->val.little_data_block.frameIndex, // |
||||
|
event->val.little_data_block.data, LITTLE_DATA_BLOCK_FRAME_NUM); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool m_ble_cmder_is_inited = false; |
||||
|
void AppBleService_init() { |
||||
|
AppEvent_regListener(app_event_listener); |
||||
|
|
||||
|
if (!m_ble_cmder_is_inited) { |
||||
|
ZERROR_CHECK(app_timer_create(&m_record_upload_tmr, APP_TIMER_MODE_REPEATED, RecordUpload_tmr_cb)); |
||||
|
ZERROR_CHECK(app_timer_create(&m_record_upload_finish_packet_report_tmr, APP_TIMER_MODE_SINGLE_SHOT, RecordUpload_finish_packet_report_tmr_cb)); |
||||
|
} |
||||
|
m_ble_cmder_is_inited = true; |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
#pragma once |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
/** |
||||
|
* @brief |
||||
|
* zble_module_init 方法将此回调注册进去 |
||||
|
*/ |
||||
|
void AppBleService_onServiceInitCB(); |
||||
|
|
||||
|
void AppBleService_init(); |
||||
|
void AppBleService_uninit(); |
||||
|
|
||||
|
void AppBleService_try_report_one_sample_data(uint32_t frameIndex, uint16_t data); |
||||
|
void AppBleService_try_report_sensor_drop_event(uint8_t dropstate0, uint8_t dropstate1); |
||||
|
void AppBleService_report_sample_finish_event(); |
@ -0,0 +1,52 @@ |
|||||
|
#pragma once |
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
#include "board/board.h" |
||||
|
|
||||
|
|
||||
|
typedef enum { |
||||
|
kevent_sensor_drop = 0, // 导联连接事件 |
||||
|
kevent_tmr_scheduler, // 定时器调度事件 |
||||
|
kevent_capture_data_block_event, // 每采集一定数据后回调一次 |
||||
|
kevent_capture_little_data_block_event, // 传感器小数据块回调事件 |
||||
|
kevent_button_push_event, // 按键按下事件 |
||||
|
kevent_button_release_event, // 按键释放事件 |
||||
|
|
||||
|
kevent_start_sample_cmd_event, // 开始采集事件 |
||||
|
kevent_stop_sample_cmd_event, // 停止采集事件 |
||||
|
|
||||
|
kevent_sample_start_event, // 开始采集事件 |
||||
|
kevent_sample_stop_event, // 停止采集事件 |
||||
|
|
||||
|
kevent_ble_connect_event, // 蓝牙连接事件 |
||||
|
kevent_ble_disconnect_event, // 蓝牙断开事件 |
||||
|
|
||||
|
} app_event_type_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
uint32_t data0; |
||||
|
uint32_t data1; |
||||
|
uint32_t data2; |
||||
|
} one_frame_data_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
app_event_type_t eventType; |
||||
|
union { |
||||
|
struct { |
||||
|
uint32_t frameIndex; |
||||
|
one_frame_data_t data[LITTLE_DATA_BLOCK_FRAME_NUM]; |
||||
|
} little_data_block; |
||||
|
|
||||
|
struct { |
||||
|
uint8_t* data; // 不保证数据对齐 |
||||
|
int len; |
||||
|
} block_sensor_data; |
||||
|
|
||||
|
struct { |
||||
|
uint8_t drop0; |
||||
|
uint8_t drop1; |
||||
|
} sensor_drop; |
||||
|
} val; |
||||
|
} app_event_t; |
||||
|
|
||||
|
void app_event_process_cb(void* p_event_data, uint16_t event_size); |
@ -0,0 +1,23 @@ |
|||||
|
#include "app_event_distribute.h" |
||||
|
|
||||
|
#include "app_event.h" |
||||
|
#include "app_scheduler.h" |
||||
|
|
||||
|
static AppEventListener m_listener[10]; |
||||
|
static int m_listener_num = 0; |
||||
|
|
||||
|
static void app_event_process_cb(void* p_event_data, uint16_t event_size) { |
||||
|
for (int i = 0; i < m_listener_num; i++) { |
||||
|
if (m_listener[i].cbfunc) { |
||||
|
m_listener[i].cbfunc(p_event_data, event_size); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void AppEvent_regListener(app_event_listener_t listener) { // |
||||
|
m_listener[m_listener_num++].cbfunc = listener; |
||||
|
} |
||||
|
|
||||
|
void AppEvent_pushEvent(app_event_t* event) { // |
||||
|
app_sched_event_put(event, sizeof(app_event_t), app_event_process_cb); |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
#pragma once |
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#include "app_event.h" |
||||
|
|
||||
|
|
||||
|
typedef void (*app_event_listener_t)(void* p_event_data, uint16_t event_size); |
||||
|
|
||||
|
typedef struct { |
||||
|
app_event_listener_t cbfunc; |
||||
|
} AppEventListener; |
||||
|
|
||||
|
void AppEvent_regListener(app_event_listener_t listener); |
||||
|
void AppEvent_pushEvent(app_event_t* event); |
@ -0,0 +1,129 @@ |
|||||
|
/* |
||||
|
* ADS1293.h |
||||
|
* |
||||
|
* Created on: Jun 6, 2022 |
||||
|
* Author: Hans Hüttmann |
||||
|
*/ |
||||
|
#include "ads1293.h" |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
static uint8_t txcache[256]; |
||||
|
static uint8_t rxcache[256]; |
||||
|
|
||||
|
void ads1293_spi_init(ads1293_t* ads, ads1293_spi_tx_rx_t spi_tx_rx) { ads->spi_tx_rx = spi_tx_rx; } |
||||
|
|
||||
|
void ads1293_spi_writereg(ads1293_t* ads, uint8_t addr, uint8_t data) { |
||||
|
uint8_t txcache[2]; |
||||
|
txcache[0] = ADS1293_WRITE_BIT & addr; |
||||
|
txcache[1] = data; |
||||
|
ads->spi_tx_rx(txcache, NULL, 2); |
||||
|
} |
||||
|
uint8_t ads1293_spi_readreg(ads1293_t* ads, uint8_t addr) { |
||||
|
uint8_t txcache[2]; |
||||
|
txcache[0] = ADS1293_READ_BIT | addr; |
||||
|
txcache[1] = 0; |
||||
|
uint8_t rxcache[2]; |
||||
|
ads->spi_tx_rx(txcache, rxcache, 2); |
||||
|
return rxcache[1]; |
||||
|
} |
||||
|
void ads1293_spi_writereg_and_readbak(ads1293_t* ads, uint8_t addr, uint8_t data, uint8_t* readbak) { |
||||
|
ads1293_spi_writereg(ads, addr, data); |
||||
|
*readbak = ads1293_spi_readreg(ads, addr); |
||||
|
} |
||||
|
|
||||
|
void ads1293_spi_autoinc_writereg(ads1293_t* ads, uint8_t addr, uint8_t* data, uint8_t len) { // |
||||
|
len = len > 255 ? 255 : len; |
||||
|
uint8_t addbyte = ADS1293_WRITE_BIT & addr; |
||||
|
|
||||
|
txcache[0] = addbyte; |
||||
|
memcpy(txcache + 1, data, len); |
||||
|
|
||||
|
ads->spi_tx_rx(txcache, NULL, len + 1); |
||||
|
} |
||||
|
void ads1293_spi_autoinc_readreg(ads1293_t* ads, uint8_t addr, uint8_t* data, uint8_t len) { |
||||
|
len = len > 255 ? 255 : len; |
||||
|
uint8_t addbyte = ADS1293_READ_BIT | addr; |
||||
|
|
||||
|
txcache[0] = addbyte; |
||||
|
memset(txcache + 1, 0, len); |
||||
|
|
||||
|
ads->spi_tx_rx(txcache, rxcache, len + 1); |
||||
|
|
||||
|
memcpy(data, rxcache + 1, len); |
||||
|
} |
||||
|
void ads1293_spi_stream_readreg(ads1293_t* ads, uint8_t* data, uint8_t len) { |
||||
|
len = len > 255 ? 255 : len; |
||||
|
|
||||
|
memset(txcache, 0, len); |
||||
|
memset(rxcache, 0, len); |
||||
|
|
||||
|
uint8_t addbyte = ADS1293_READ_BIT | TI_ADS1293_DATA_LOOP_REG; |
||||
|
|
||||
|
ads->spi_tx_rx(&addbyte, rxcache, len); |
||||
|
memcpy(data, rxcache, len); |
||||
|
} |
||||
|
|
||||
|
void ads1293_read_ecg(ads1293_t* ads, uint32_t ch, uint32_t* data) { |
||||
|
uint8_t add = 0; |
||||
|
if (ch == 1) { |
||||
|
add = TI_ADS1293_DATA_CH1_ECG_H_REG; |
||||
|
} else if (ch == 2) { |
||||
|
add = TI_ADS1293_DATA_CH2_ECG_H_REG; |
||||
|
} else if (ch == 3) { |
||||
|
add = TI_ADS1293_DATA_CH3_ECG_H_REG; |
||||
|
} else { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
uint8_t readbak[3] = {0}; |
||||
|
ads1293_spi_autoinc_readreg(ads, add, readbak, 3); |
||||
|
|
||||
|
*data = 0; |
||||
|
*data = ((uint32_t)readbak[0] << 16) + ((uint32_t)readbak[1] << 8) + ((uint32_t)readbak[2] << 0); |
||||
|
} |
||||
|
|
||||
|
void ads1293_read_ecgs(ads1293_t* ads, uint32_t* data /*3*/) { |
||||
|
uint8_t add = 0; |
||||
|
add = TI_ADS1293_DATA_CH1_ECG_H_REG; |
||||
|
uint8_t readbak[9] = {0}; |
||||
|
ads1293_spi_autoinc_readreg(ads, add, readbak, 9); |
||||
|
|
||||
|
data[0] = ((uint32_t)readbak[0] << 16) + ((uint32_t)readbak[1] << 8) + ((uint32_t)readbak[2] << 0); |
||||
|
data[1] = ((uint32_t)readbak[3] << 16) + ((uint32_t)readbak[4] << 8) + ((uint32_t)readbak[5] << 0); |
||||
|
data[2] = ((uint32_t)readbak[6] << 16) + ((uint32_t)readbak[7] << 8) + ((uint32_t)readbak[8] << 0); |
||||
|
} |
||||
|
|
||||
|
void ads1293_read_error(ads1293_t* ads, ads1293_error_t* error) { |
||||
|
error->lod = 0; |
||||
|
error->estatus = 0; |
||||
|
error->error_range1 = 0; |
||||
|
error->error_range2 = 0; |
||||
|
error->error_range3 = 0; |
||||
|
error->error_sync = 0; |
||||
|
error->error_misc = 0; |
||||
|
|
||||
|
ads1293_spi_autoinc_readreg(ads, TI_ADS1293_ERROR_LOD_REG, (uint8_t*)error, 7); |
||||
|
} |
||||
|
|
||||
|
void ads1293_start_conversion(ads1293_t* ads) { |
||||
|
uint8_t data = 0; |
||||
|
data = 0x01; |
||||
|
ads1293_spi_writereg(ads, TI_ADS1293_CONFIG_REG, data); |
||||
|
} |
||||
|
void ads1293_stop_conversion(ads1293_t* ads) { |
||||
|
uint8_t data = 0; |
||||
|
data = 0x04; |
||||
|
ads1293_spi_writereg(ads, TI_ADS1293_CONFIG_REG, data); |
||||
|
} |
||||
|
void ads1293_start_power_off(ads1293_t* ads) { |
||||
|
uint8_t data = 0; |
||||
|
data |= 0x01 << 2; |
||||
|
ads1293_spi_writereg(ads, TI_ADS1293_CONFIG_REG, data); |
||||
|
} |
||||
|
|
||||
|
uint8_t ads1293_read_error_lod(ads1293_t* ads) { return ads1293_spi_readreg(ads, TI_ADS1293_ERROR_LOD_REG); } |
||||
|
|
||||
|
uint8_t ads1293_read_ready_status(ads1293_t* ads) { return ads1293_spi_readreg(ads, TI_ADS1293_DATA_STATUS_REG); } |
@ -0,0 +1,142 @@ |
|||||
|
//---------------------------------------------------------------------------- |
||||
|
// Description: This file contains definitions specific to the ADS1293. |
||||
|
// All the ADS1293 registers are defined as well as some common masks |
||||
|
// for these registers. |
||||
|
// |
||||
|
// MSP430/ADS1293 Interface Code Library v1.0 |
||||
|
// |
||||
|
// Vishy Natarajan |
||||
|
// Texas Instruments Inc. |
||||
|
// April 2013 |
||||
|
// Built with IAR Embedded Workbench Version: 5.5x |
||||
|
//------------------------------------------------------------------------------ |
||||
|
// Change Log: |
||||
|
//------------------------------------------------------------------------------ |
||||
|
// Version: 1.00 |
||||
|
// Comments: Initial Release Version |
||||
|
//------------------------------------------------------------------------------ |
||||
|
#ifndef HEADER_FILE_TI_ADS1293_H |
||||
|
|
||||
|
#define HEADER_FILE_TI_ADS1293_H |
||||
|
|
||||
|
#include <stdint.h> |
||||
|
|
||||
|
/************************************************************ |
||||
|
* TI ADS1293 REGISTER SET ADDRESSES |
||||
|
************************************************************/ |
||||
|
|
||||
|
#define TI_ADS1293_CONFIG_REG (0x00) /* Main Configuration */ |
||||
|
|
||||
|
#define TI_ADS1293_FLEX_CH1_CN_REG (0x01) /* Flex Routing Swich Control for Channel 1 */ |
||||
|
#define TI_ADS1293_FLEX_CH2_CN_REG (0x02) /* Flex Routing Swich Control for Channel 2 */ |
||||
|
#define TI_ADS1293_FLEX_CH3_CN_REG (0x03) /* Flex Routing Swich Control for Channel 3 */ |
||||
|
#define TI_ADS1293_FLEX_PACE_CN_REG (0x04) /* Flex Routing Swich Control for Pace Channel */ |
||||
|
#define TI_ADS1293_FLEX_VBAT_CN_REG (0x05) /* Flex Routing Swich Control for Battery Monitoriing */ |
||||
|
|
||||
|
#define TI_ADS1293_LOD_CN_REG (0x06) /* Lead Off Detect Control */ |
||||
|
#define TI_ADS1293_LOD_EN_REG (0x07) /* Lead Off Detect Enable */ |
||||
|
#define TI_ADS1293_LOD_CURRENT_REG (0x08) /* Lead Off Detect Current */ |
||||
|
#define TI_ADS1293_LOD_AC_CN_REG (0x09) /* AC Lead Off Detect Current */ |
||||
|
|
||||
|
#define TI_ADS1293_CMDET_EN_REG (0x0A) /* Common Mode Detect Enable */ |
||||
|
#define TI_ADS1293_CMDET_CN_REG (0x0B) /* Commond Mode Detect Control */ |
||||
|
#define TI_ADS1293_RLD_CN_REG (0x0C) /* Right Leg Drive Control */ |
||||
|
|
||||
|
#define TI_ADS1293_WILSON_EN1_REG (0x0D) /* Wilson Reference Input one Selection */ |
||||
|
#define TI_ADS1293_WILSON_EN2_REG (0x0E) /* Wilson Reference Input two Selection */ |
||||
|
#define TI_ADS1293_WILSON_EN3_REG (0x0F) /* Wilson Reference Input three Selection */ |
||||
|
#define TI_ADS1293_WILSON_CN_REG (0x10) /* Wilson Reference Input Control */ |
||||
|
|
||||
|
#define TI_ADS1293_REF_CN_REG (0x11) /* Internal Reference Voltage Control */ |
||||
|
|
||||
|
#define TI_ADS1293_OSC_CN_REG (0x12) /* Clock Source and Output Clock Control */ |
||||
|
|
||||
|
#define TI_ADS1293_AFE_RES_REG (0x13) /* Analog Front-End Frequency and Resolution */ |
||||
|
#define TI_ADS1293_AFE_SHDN_CN_REG (0x14) /* Analog Front-End Shutdown Control */ |
||||
|
#define TI_ADS1293_AFE_FAULT_CN_REG (0x15) /* Analog Front-End Fault Detection Control */ |
||||
|
#define TI_ADS1293_AFE_DITHER_EN_REG (0x16) /* Enable Dithering in Signma-Delta */ |
||||
|
#define TI_ADS1293_AFE_PACE_CN_REG (0x17) /* Analog Pace Channel Output Routing Control */ |
||||
|
|
||||
|
#define TI_ADS1293_ERROR_LOD_REG (0x18) /* Lead Off Detect Error Status */ |
||||
|
#define TI_ADS1293_ERROR_STATUS_REG (0x19) /* Other Error Status */ |
||||
|
#define TI_ADS1293_ERROR_RANGE1_REG (0x1A) /* Channel 1 Amplifier Out of Range Status */ |
||||
|
#define TI_ADS1293_ERROR_RANGE2_REG (0x1B) /* Channel 1 Amplifier Out of Range Status */ |
||||
|
#define TI_ADS1293_ERROR_RANGE3_REG (0x1C) /* Channel 1 Amplifier Out of Range Status */ |
||||
|
#define TI_ADS1293_ERROR_SYNC_REG (0x1D) /* Synchronization Error */ |
||||
|
|
||||
|
#define TI_ADS1293_R2_RATE_REG (0x21) /* R2 Decimation Rate */ |
||||
|
#define TI_ADS1293_R3_RATE1_REG (0x22) /* R3 Decimation Rate for Channel 1 */ |
||||
|
#define TI_ADS1293_R3_RATE2_REG (0x23) /* R3 Decimation Rate for Channel 2 */ |
||||
|
#define TI_ADS1293_R3_RATE3_REG (0x24) /* R3 Decimation Rate for Channel 3 */ |
||||
|
#define TI_ADS1293_P_DRATE_REG (0x25) /* 2x Pace Data Rate */ |
||||
|
#define TI_ADS1293_DIS_EFILTER_REG (0x26) /* ECG Filter Disable */ |
||||
|
#define TI_ADS1293_DRDYB_SRC_REG (0x27) /* Data Ready Pin Source */ |
||||
|
#define TI_ADS1293_SYNCOUTB_SRC_REG (0x28) /* Sync Out Pin Source */ |
||||
|
#define TI_ADS1293_MASK_DRDYB_REG (0x29) /* Optional Mask Control for DRDYB Output */ |
||||
|
#define TI_ADS1293_MASK_ERR_REG (0x2A) /* Mask Error on ALARMB Pin */ |
||||
|
|
||||
|
#define TI_ADS1293_ALARM_FILTER_REG (0x2E) /* Digital Filter for Analog Alarm Signals */ |
||||
|
#define TI_ADS1293_CH_CNFG_REG (0x2F) /* Configure Channel for Loop Read Back Mode */ |
||||
|
|
||||
|
#define TI_ADS1293_DATA_STATUS_REG (0x30) /* ECG and Pace Data Ready Status */ |
||||
|
#define TI_ADS1293_DATA_CH1_PACE_H_REG (0x31) /* Channel1 Pace Data High [15:8] */ |
||||
|
#define TI_ADS1293_DATA_CH1_PACE_L_REG (0x32) /* Channel1 Pace Data Low [7:0] */ |
||||
|
#define TI_ADS1293_DATA_CH2_PACE_H_REG (0x33) /* Channel2 Pace Data High [15:8] */ |
||||
|
#define TI_ADS1293_DATA_CH2_PACE_L_REG (0x34) /* Channel2 Pace Data Low [7:0] */ |
||||
|
#define TI_ADS1293_DATA_CH3_PACE_H_REG (0x35) /* Channel3 Pace Data High [15:8] */ |
||||
|
#define TI_ADS1293_DATA_CH3_PACE_L_REG (0x36) /* Channel3 Pace Data Low [7:0] */ |
||||
|
#define TI_ADS1293_DATA_CH1_ECG_H_REG (0x37) /* Channel1 ECG Data High [23:16] */ |
||||
|
#define TI_ADS1293_DATA_CH1_ECG_M_REG (0x38) /* Channel1 ECG Data Medium [15:8] */ |
||||
|
#define TI_ADS1293_DATA_CH1_ECG_L_REG (0x39) /* Channel1 ECG Data Low [7:0] */ |
||||
|
#define TI_ADS1293_DATA_CH2_ECG_H_REG (0x3A) /* Channel2 ECG Data High [23:16] */ |
||||
|
#define TI_ADS1293_DATA_CH2_ECG_M_REG (0x3B) /* Channel2 ECG Data Medium [15:8] */ |
||||
|
#define TI_ADS1293_DATA_CH2_ECG_L_REG (0x3C) /* Channel2 ECG Data Low [7:0] */ |
||||
|
#define TI_ADS1293_DATA_CH3_ECG_H_REG (0x3D) /* Channel3 ECG Data High [23:16] */ |
||||
|
#define TI_ADS1293_DATA_CH3_ECG_M_REG (0x3E) /* Channel3 ECG Data Medium [15:8] */ |
||||
|
#define TI_ADS1293_DATA_CH3_ECG_L_REG (0x3F) /* Channel3 ECG Data Low [7:0] */ |
||||
|
|
||||
|
#define TI_ADS1293_REVID_REG (0x40) /* Revision ID */ |
||||
|
#define TI_ADS1293_DATA_LOOP_REG (0x50) /* Loop Read Back Address */ |
||||
|
|
||||
|
// Useful definitions |
||||
|
#define ADS1293_READ_BIT (0x80) |
||||
|
#define ADS1293_WRITE_BIT (0x7F) |
||||
|
|
||||
|
typedef void (*ads1293_spi_tx_rx_t)(uint8_t* tx, uint8_t* rx, uint8_t len); |
||||
|
typedef struct { |
||||
|
ads1293_spi_tx_rx_t spi_tx_rx; |
||||
|
int id; |
||||
|
} ads1293_t; |
||||
|
|
||||
|
void ads1293_spi_init(ads1293_t* ads, ads1293_spi_tx_rx_t spi_tx_rx); |
||||
|
|
||||
|
void ads1293_spi_writereg_and_readbak(ads1293_t* ads, uint8_t addr, uint8_t data, uint8_t* readbak); |
||||
|
void ads1293_spi_writereg(ads1293_t* ads, uint8_t addr, uint8_t data); |
||||
|
uint8_t ads1293_spi_readreg(ads1293_t* ads, uint8_t addr); |
||||
|
|
||||
|
void ads1293_spi_autoinc_writereg(ads1293_t* ads, uint8_t addr, uint8_t* data, uint8_t len); |
||||
|
void ads1293_spi_autoinc_readreg(ads1293_t* ads, uint8_t addr, uint8_t* data, uint8_t len); |
||||
|
void ads1293_spi_stream_readreg(ads1293_t* ads, uint8_t* data, uint8_t len); |
||||
|
|
||||
|
void ads1293_read_ecg(ads1293_t* ads, uint32_t ch, uint32_t* data); |
||||
|
void ads1293_read_ecgs(ads1293_t* ads, uint32_t* data /*3*/); |
||||
|
|
||||
|
uint8_t ads1293_read_error_lod(ads1293_t* ads); |
||||
|
|
||||
|
void ads1293_start_conversion(ads1293_t* ads); |
||||
|
void ads1293_stop_conversion(ads1293_t* ads); |
||||
|
|
||||
|
uint8_t ads1293_read_ready_status(ads1293_t* ads); |
||||
|
|
||||
|
typedef struct { |
||||
|
uint8_t lod; |
||||
|
uint8_t estatus; |
||||
|
uint8_t error_range1; |
||||
|
uint8_t error_range2; |
||||
|
uint8_t error_range3; |
||||
|
uint8_t error_sync; |
||||
|
uint8_t error_misc; |
||||
|
} ads1293_error_t; |
||||
|
void ads1293_read_error(ads1293_t* ads, ads1293_error_t* error); |
||||
|
|
||||
|
#endif // HEADER_FILE_TI_ADS1293_H |
@ -0,0 +1,3 @@ |
|||||
|
#pragma once |
||||
|
#define VERSION 1 |
||||
|
#define MANUFACTURER_NAME "iflytop" |
@ -0,0 +1,72 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* ADS * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
#define ADS1293_SPI_SCK_PIN (32 + 9) |
||||
|
#define ADS1293_SPI_MOSI_PIN 15 |
||||
|
#define ADS1293_SPI_MISO_PIN 20 |
||||
|
#define ADS1293_SPI_CS0_PIN 3 |
||||
|
#define ADS1293_SPI_CS1_PIN 29 |
||||
|
#define ADS1293_READY_PIN 31 |
||||
|
#define LINE_DET_PIN 10 |
||||
|
|
||||
|
/** |
||||
|
* @brief SDCARD |
||||
|
*/ |
||||
|
#define SDCARD_SPI_SCK_PIN 4 // SDCARD SCK CLK |
||||
|
#define SDCARD_SPI_CS_PIN 5 // SDCARD CS DATA3 |
||||
|
#define SDCARD_SPI_MISO_PIN 11 // SDCARD MISO DATA0 |
||||
|
#define SDCARD_SPI_MOSI_PIN 17 // SDCARD MOSI CMD |
||||
|
|
||||
|
#define SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN 1 // flash连接控制引脚 |
||||
|
#define SDCARD_USBDRIVER_IC_RESET_PIN 28 // flash复位引脚 |
||||
|
#define SDCARD_POWER_CTRL_PIN 30 // flash供电控制引脚 |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 外设分配 * |
||||
|
*******************************************************************************/ |
||||
|
#define ADS1293_SPI_INSTANCE 2 |
||||
|
#define BEEP_PWM_INSTANCE 0 |
||||
|
#define BATTERY_ADC_CHANNEL 1 // 不重复即可 |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* LIGHT * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
#define LED_GREEN_PIN 9 |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 按键 * |
||||
|
*******************************************************************************/ |
||||
|
#define BUTTON_PIN 18 |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 蜂鸣器 * |
||||
|
*******************************************************************************/ |
||||
|
#define BEEP_PIN 0 |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 电池电量 * |
||||
|
*******************************************************************************/ |
||||
|
#define BATTERY_ADC_PIN NRF_SAADC_INPUT_AIN0 |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 应用程序配置 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
#define HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE (3 * 3 * 256) |
||||
|
#define FILE_MAX_COUNT 1 |
||||
|
#define SDCARD_MAX_FILE_SIZE (uint32_t)(3.5 * 1024 * 1024 * 1024) |
||||
|
// |
||||
|
#define SAMPLE_RATE 400 |
||||
|
#define LITTLE_DATA_BLOCK_FRAME_NUM 4 // 每两帧回调一次,对应100HZ |
||||
|
#define SAMPLE_PRECISION 24 |
||||
|
|
||||
|
#define APP_MAX_EVEN_SIZE MAX(APP_TIMER_SCHED_EVENT_DATA_SIZE, sizeof(app_event_t)) |
||||
|
#define APP_EVENT_QUEUE_SIZE 100 |
||||
|
|
||||
|
#define APP_AUTO_SLEEP_TIMEOUT_MS (10 * 1000) |
||||
|
#define APP_BYTE_EACH_FRAME 9 |
||||
|
#define APP_SENSOR_NUM 3 |
@ -0,0 +1,36 @@ |
|||||
|
|
||||
|
#include "board_battery_state.h" |
||||
|
|
||||
|
void BoardBattery_init() {} |
||||
|
void BoardBattery_load() { |
||||
|
nrf_drv_saadc_config_t adccfg = NRFX_SAADC_DEFAULT_CONFIG; |
||||
|
adccfg.resolution = NRF_SAADC_RESOLUTION_12BIT; // 4096 等于满采样率 |
||||
|
ZERROR_CHECK(nrf_drv_saadc_init(&adccfg, NULL)); |
||||
|
|
||||
|
nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(BATTERY_ADC_PIN); |
||||
|
channel_config.acq_time = NRF_SAADC_ACQTIME_20US; |
||||
|
ZERROR_CHECK(nrfx_saadc_channel_init(BATTERY_ADC_CHANNEL, &channel_config)); |
||||
|
} |
||||
|
void BoardBattery_unload() { nrf_drv_saadc_uninit(); } |
||||
|
|
||||
|
int16_t BoardBattery_get_adc_val() { |
||||
|
int16_t val = znrf_adc_channel_read_val(BATTERY_ADC_CHANNEL); |
||||
|
return val; |
||||
|
} |
||||
|
int16_t BoardBattery_get_battery_level() { |
||||
|
static const float maxv = 4.0; |
||||
|
static const float minv = 3.3; |
||||
|
|
||||
|
float voltage = BoardBattery_get_adc_val() / 4096.0 * 3.3 / 2.0 * 3; |
||||
|
if (voltage > maxv) voltage = maxv; |
||||
|
if (voltage < minv) voltage = minv; |
||||
|
|
||||
|
float percent = (voltage - minv) / (maxv - minv) * 100 + (float)0.1 /*加0.1是为了避免999.999时显示电量为90*/; |
||||
|
int16_t percent_int = (int16_t)percent; |
||||
|
if (percent_int < 10 && percent_int != 0) { |
||||
|
percent_int = 3; |
||||
|
} else { |
||||
|
percent_int = percent_int / 10 * 10; |
||||
|
} |
||||
|
return percent_int; |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#include "board/board.h" |
||||
|
#include "znordic.h" |
||||
|
|
||||
|
void BoardBattery_init(); |
||||
|
void BoardBattery_load(); |
||||
|
void BoardBattery_unload(); |
||||
|
|
||||
|
int16_t BoardBattery_get_adc_val(); |
||||
|
int16_t BoardBattery_get_battery_level(); // 0->100 |
@ -0,0 +1,102 @@ |
|||||
|
#include "board_beep_ctrl.h" |
||||
|
#define BEEP_TIMER_INTERVAL (150) |
||||
|
|
||||
|
APP_TIMER_DEF(m_beep_tmr); // |
||||
|
static nrf_drv_pwm_t m_beep_pwm0 = NRF_DRV_PWM_INSTANCE(BEEP_PWM_INSTANCE); |
||||
|
static nrf_pwm_values_individual_t m_beep_pwm0_seq_values = {0}; |
||||
|
static nrf_pwm_sequence_t const m_beep_pwm0_seq = { |
||||
|
.values.p_individual = &m_beep_pwm0_seq_values, |
||||
|
.length = NRF_PWM_VALUES_LENGTH(m_beep_pwm0_seq_values), |
||||
|
.repeats = 0, |
||||
|
.end_delay = 0, |
||||
|
}; |
||||
|
static nrf_drv_pwm_config_t const m_beep_pwm0_config0 = { |
||||
|
.output_pins = |
||||
|
{ |
||||
|
BEEP_PIN | NRF_DRV_PWM_PIN_INVERTED, // |
||||
|
NRF_DRV_PWM_PIN_NOT_USED, |
||||
|
NRF_DRV_PWM_PIN_NOT_USED, |
||||
|
NRF_DRV_PWM_PIN_NOT_USED, |
||||
|
}, |
||||
|
.irq_priority = APP_IRQ_PRIORITY_LOWEST, |
||||
|
.base_clock = NRF_PWM_CLK_125kHz, |
||||
|
.count_mode = NRF_PWM_MODE_UP, |
||||
|
.top_value = 46, // 125kHz / 46 = 2.717k |
||||
|
.load_mode = NRF_PWM_LOAD_INDIVIDUAL, |
||||
|
.step_mode = NRF_PWM_STEP_AUTO, |
||||
|
}; |
||||
|
BoardBeepEffect_t m_beep_effect = kBoardBeepEffect_none; |
||||
|
static uint32_t m_beep_cnt = 0; |
||||
|
|
||||
|
static void beep_tmr_handler(void *context) { |
||||
|
if (m_beep_effect == kBoardBeepEffect_none) { |
||||
|
BoardBeepCtrl_set(false); |
||||
|
} else if (m_beep_effect == kBoardBeepEffect_oneShortBeep) { |
||||
|
if (m_beep_cnt == 0) { |
||||
|
BoardBeepCtrl_set(true); |
||||
|
} else if (m_beep_cnt >= 1) { |
||||
|
BoardBeepCtrl_set(false); |
||||
|
app_timer_stop(m_beep_tmr); |
||||
|
m_beep_effect = kBoardBeepEffect_none; |
||||
|
} |
||||
|
} else if (m_beep_effect == kBoardBeepEffect_threeShortBeep) { |
||||
|
if (m_beep_cnt < 6) { |
||||
|
if (m_beep_cnt % 2 == 0) { |
||||
|
BoardBeepCtrl_set(true); |
||||
|
} else if (m_beep_cnt % 2 == 1) { |
||||
|
BoardBeepCtrl_set(false); |
||||
|
} |
||||
|
} else { |
||||
|
BoardBeepCtrl_set(false); |
||||
|
app_timer_stop(m_beep_tmr); |
||||
|
m_beep_effect = kBoardBeepEffect_none; |
||||
|
} |
||||
|
|
||||
|
} else if (m_beep_effect == kBoardBeepEffect_continuousShortBeep) { |
||||
|
// 每隔1秒响三声 |
||||
|
if (m_beep_cnt < 6) { |
||||
|
if (m_beep_cnt % 2 == 0) { |
||||
|
BoardBeepCtrl_set(true); |
||||
|
} else if (m_beep_cnt % 2 == 1) { |
||||
|
BoardBeepCtrl_set(false); |
||||
|
} |
||||
|
} else { |
||||
|
if (BEEP_TIMER_INTERVAL * m_beep_cnt >= 10000) { |
||||
|
m_beep_cnt = 0; |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
m_beep_cnt++; |
||||
|
} |
||||
|
|
||||
|
void BoardBeepCtrl_init(void) { app_timer_create(&m_beep_tmr, APP_TIMER_MODE_REPEATED, beep_tmr_handler); } |
||||
|
void BoardBeepCtrl_load() { APP_ERROR_CHECK(nrfx_pwm_init(&m_beep_pwm0, &m_beep_pwm0_config0, NULL)); } |
||||
|
|
||||
|
void BoardBeepCtrl_unload() { |
||||
|
BoardBeepCtrl_set(0); |
||||
|
nrfx_pwm_uninit(&m_beep_pwm0); |
||||
|
} |
||||
|
|
||||
|
void BoardBeepCtrl_set(uint8_t state) { |
||||
|
if (state) { |
||||
|
m_beep_pwm0_seq_values.channel_0 = m_beep_pwm0_config0.top_value / 2; // 设置占空比,数值最大不超过 top_value |
||||
|
nrfx_pwm_simple_playback(&m_beep_pwm0, &m_beep_pwm0_seq, 1, NRF_DRV_PWM_FLAG_LOOP); |
||||
|
} else { |
||||
|
nrfx_pwm_stop(&m_beep_pwm0, true); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void BoardBeepCtrl_setEffect(BoardBeepEffect_t effect) { |
||||
|
m_beep_effect = effect; |
||||
|
|
||||
|
app_timer_stop(m_beep_tmr); |
||||
|
m_beep_cnt = 0; |
||||
|
if (m_beep_effect == kBoardBeepEffect_none) { |
||||
|
BoardBeepCtrl_set(false); |
||||
|
} |
||||
|
|
||||
|
else { |
||||
|
app_timer_start(m_beep_tmr, APP_TIMER_TICKS(BEEP_TIMER_INTERVAL), NULL); |
||||
|
} |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#include "board/board.h" |
||||
|
#include "znordic.h" |
||||
|
|
||||
|
typedef enum { |
||||
|
kBoardBeepEffect_none = 0, |
||||
|
// 响一声 |
||||
|
kBoardBeepEffect_oneShortBeep, |
||||
|
// 响三声 |
||||
|
kBoardBeepEffect_threeShortBeep, |
||||
|
// 持续短鸣报警 |
||||
|
kBoardBeepEffect_continuousShortBeep, |
||||
|
} BoardBeepEffect_t; |
||||
|
|
||||
|
void BoardBeepCtrl_init(void); |
||||
|
void BoardBeepCtrl_load(); |
||||
|
void BoardBeepCtrl_unload(); |
||||
|
|
||||
|
void BoardBeepCtrl_set(uint8_t beep); |
||||
|
void BoardBeepCtrl_setEffect(BoardBeepEffect_t effect); |
@ -0,0 +1,34 @@ |
|||||
|
#include "board_button.h" |
||||
|
|
||||
|
#include "app_button.h" |
||||
|
#include "board.h" |
||||
|
#include "znordic.h" |
||||
|
|
||||
|
#define BUTTON_DETECTION_DELAY APP_TIMER_TICKS(50) |
||||
|
static board_button_cb_t m_cb; |
||||
|
// |
||||
|
void button_process_handler(uint8_t pin_no, uint8_t button_action) { |
||||
|
if (m_cb) { |
||||
|
m_cb(kButton_mainButton, (ButtonAction_t)button_action); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static app_button_cfg_t buttons[] = { |
||||
|
{BUTTON_PIN, true, NRF_GPIO_PIN_PULLUP, button_process_handler}, |
||||
|
}; |
||||
|
void BoardButton_Init(board_button_cb_t cb) { // |
||||
|
m_cb = cb; |
||||
|
// ZERROR_CHECK(app_button_init(buttons, ARRAY_SIZE(buttons), BUTTON_DETECTION_DELAY)); |
||||
|
} |
||||
|
void BoardButton_load() { |
||||
|
// ZERROR_CHECK(app_button_enable()); |
||||
|
} |
||||
|
void BoardButton_unload() { |
||||
|
// ZERROR_CHECK(app_button_disable()); |
||||
|
} |
||||
|
|
||||
|
void BoardButton_enable_sense() { |
||||
|
// app_button_disable(); |
||||
|
nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); |
||||
|
// nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH); |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#include "board/board.h" |
||||
|
|
||||
|
typedef enum { |
||||
|
kButton_mainButton, |
||||
|
} ButtonIndex_t; |
||||
|
|
||||
|
typedef enum { |
||||
|
kButtonAction_push = 1, |
||||
|
kButtonAction_release = 0, |
||||
|
} ButtonAction_t; |
||||
|
|
||||
|
typedef void (*board_button_cb_t)(ButtonIndex_t pin_no, ButtonAction_t button_action); |
||||
|
|
||||
|
void BoardButton_Init(board_button_cb_t cb); // main中初始化一遍 |
||||
|
void BoardButton_load(); |
||||
|
void BoardButton_unload(); |
||||
|
|
||||
|
void BoardButton_enable_sense(); // 低功耗睡眠前调用该方法 |
@ -0,0 +1,79 @@ |
|||||
|
#include "board_light_ctrl.h" |
||||
|
|
||||
|
#include "board.h" |
||||
|
#include "znordic.h" |
||||
|
|
||||
|
#define BLINK_CNT 1 |
||||
|
#define BLINK_PERIOD_MS (100) |
||||
|
|
||||
|
static LightEffect m_light_effect; |
||||
|
static bool m_led_green_light_state; |
||||
|
static int m_blink_cnt; |
||||
|
APP_TIMER_DEF(m_green_light_effect_tmr); |
||||
|
|
||||
|
static void BoardLight_effect_tmr_handler(void *p_context) { // |
||||
|
if (m_light_effect == kLightEffect_close) { |
||||
|
if (m_led_green_light_state) { |
||||
|
BoardLight_setGreenLightState(false); |
||||
|
} |
||||
|
} else if (m_light_effect == kLightEffect_open) { |
||||
|
if (!m_led_green_light_state) { |
||||
|
BoardLight_setGreenLightState(true); |
||||
|
} |
||||
|
} else if (m_light_effect == kLightEffect_slowFlash) { |
||||
|
if (m_blink_cnt < 2) { |
||||
|
if (m_blink_cnt % 2 == 0) { |
||||
|
BoardLight_setGreenLightState(true); |
||||
|
} else if (m_blink_cnt % 2 == 1) { |
||||
|
BoardLight_setGreenLightState(false); |
||||
|
} |
||||
|
} else { |
||||
|
if (BLINK_PERIOD_MS * m_blink_cnt >= 1000) { |
||||
|
m_blink_cnt = 0; |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
m_blink_cnt++; |
||||
|
} |
||||
|
|
||||
|
void BoardLight_Init() { |
||||
|
znrf_gpio_cfg_output(LED_GREEN_PIN, NRF_GPIO_PIN_NOPULL); |
||||
|
|
||||
|
ZERROR_CHECK(app_timer_create(&m_green_light_effect_tmr, APP_TIMER_MODE_REPEATED, BoardLight_effect_tmr_handler)); |
||||
|
} |
||||
|
void BoardLight_load() {} |
||||
|
void BoardLight_unload() {} |
||||
|
|
||||
|
void BoardLight_setGreenLightState(bool state) { |
||||
|
if (state) { |
||||
|
nrf_gpio_pin_set(LED_GREEN_PIN); |
||||
|
m_led_green_light_state = true; |
||||
|
} else { |
||||
|
nrf_gpio_pin_clear(LED_GREEN_PIN); |
||||
|
m_led_green_light_state = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void BoardLight_toggleGreenLightState() { nrf_gpio_pin_toggle(LED_GREEN_PIN); } |
||||
|
|
||||
|
void BoardLight_setGreenLightEffect(LightEffect effect) { |
||||
|
m_light_effect = effect; |
||||
|
|
||||
|
switch (effect) { |
||||
|
case kLightEffect_close: |
||||
|
app_timer_stop(m_green_light_effect_tmr); |
||||
|
BoardLight_setGreenLightState(false); |
||||
|
break; |
||||
|
case kLightEffect_open: |
||||
|
app_timer_stop(m_green_light_effect_tmr); |
||||
|
BoardLight_setGreenLightState(true); |
||||
|
break; |
||||
|
case kLightEffect_slowFlash: |
||||
|
app_timer_start(m_green_light_effect_tmr, APP_TIMER_TICKS(BLINK_PERIOD_MS), NULL); |
||||
|
break; |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
return; |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#include "board/board.h" |
||||
|
|
||||
|
typedef enum { |
||||
|
|
||||
|
kLightEffect_close, |
||||
|
kLightEffect_open, |
||||
|
kLightEffect_slowFlash, |
||||
|
|
||||
|
} LightEffect; |
||||
|
|
||||
|
void BoardLight_Init(); // main中初始化一遍 |
||||
|
void BoardLight_load(); |
||||
|
void BoardLight_unload(); |
||||
|
|
||||
|
void BoardLight_setGreenLightState(bool state); // 尽量不要直接使用该函数 |
||||
|
void BoardLight_toggleGreenLightState(); // 尽量不要直接使用该函数 |
||||
|
|
||||
|
void BoardLight_setGreenLightEffect(LightEffect effect); |
@ -0,0 +1,172 @@ |
|||||
|
#include "board/board_sdcard_driver.h" |
||||
|
|
||||
|
#include "board/board.h" |
||||
|
#include "znordic.h" |
||||
|
/******************************************************************************* |
||||
|
* 结构体定义 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
FATFS m_fs; |
||||
|
BoardSdcardConnectTo_t m_connectTo = kConnectToNone; |
||||
|
static bool m_sdcard_inited; |
||||
|
|
||||
|
NRF_BLOCK_DEV_SDC_DEFINE( // |
||||
|
m_block_dev_sdc, // |
||||
|
NRF_BLOCK_DEV_SDC_CONFIG(SDC_SECTOR_SIZE, // |
||||
|
APP_SDCARD_CONFIG(SDCARD_SPI_MOSI_PIN, // |
||||
|
SDCARD_SPI_MISO_PIN, // |
||||
|
SDCARD_SPI_SCK_PIN, // |
||||
|
SDCARD_SPI_CS_PIN)), |
||||
|
NFR_BLOCK_DEV_INFO_CONFIG("IFLYTOP", "SDC", "1.00")); |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @warning: |
||||
|
* SD卡和单片机是一直连接着的,SD卡和读卡器是通过一个电子开关隔离开的的。 |
||||
|
* 所以如果SD卡切换到读卡器,单片机需要先将SPI引脚初始化成输入高阻,然后再切换到读卡器。避免引脚竞争。 |
||||
|
* 此处代码需要谨慎修改,容易造成硬件损坏。 |
||||
|
* |
||||
|
* SDCARD_POWER_CTRL_PIN:低电平有效 |
||||
|
* SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN:0:连接读卡器 1:连接单片机 |
||||
|
* |
||||
|
*/ |
||||
|
void Board_sdcardInit() { |
||||
|
if (m_sdcard_inited) return; |
||||
|
/** |
||||
|
* @brief SDCARD SPI 引脚初始化 |
||||
|
*/ |
||||
|
nrf_gpio_cfg_sense_input(SDCARD_SPI_CS_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); |
||||
|
nrf_gpio_cfg_sense_input(SDCARD_SPI_MISO_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); |
||||
|
nrf_gpio_cfg_sense_input(SDCARD_SPI_MOSI_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); |
||||
|
nrf_gpio_cfg_sense_input(SDCARD_SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); |
||||
|
/** |
||||
|
* @brief SD卡 USB读卡器IC复位引脚 |
||||
|
* 引脚一直配置成高即可 |
||||
|
*/ |
||||
|
znrf_gpio_cfg_output(SDCARD_USBDRIVER_IC_RESET_PIN, NRF_GPIO_PIN_PULLUP); |
||||
|
nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 1); |
||||
|
/** |
||||
|
* @brief 初始化 SD卡连接切换引脚 |
||||
|
*/ |
||||
|
znrf_gpio_cfg_output(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, NRF_GPIO_PIN_PULLUP); |
||||
|
nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 0); // OE = 0 |
||||
|
/** |
||||
|
* @brief SDCARD电源控制引脚 |
||||
|
*/ |
||||
|
znrf_gpio_cfg_output(SDCARD_POWER_CTRL_PIN, NRF_GPIO_PIN_PULLUP); |
||||
|
nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // POWER = 0 打开电源 |
||||
|
m_connectTo = kConnectToNone; |
||||
|
|
||||
|
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)); |
||||
|
m_sdcard_inited = true; |
||||
|
} |
||||
|
|
||||
|
void Board_sdcardConnectToExt() { |
||||
|
/** |
||||
|
* @brief |
||||
|
*/ |
||||
|
if (m_connectTo == kConnectToExt) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief |
||||
|
* 0. 卸载文件系统 |
||||
|
* 2. 配置SPI引脚成输入 |
||||
|
* 3. 切换引脚连接 |
||||
|
* 4. 通过给SD卡重启上电,复位SD卡状态 |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* @brief 卸载文件系统 |
||||
|
* |
||||
|
* PS:这里会自动卸载SPI驱动 |
||||
|
*/ |
||||
|
|
||||
|
f_mount(NULL, "", 1); // 卸载文件系统 |
||||
|
disk_uninitialize(0); // 卸载磁盘驱动 |
||||
|
|
||||
|
/** |
||||
|
* @brief 配置SPI引脚成输入 |
||||
|
*/ |
||||
|
nrf_gpio_cfg_sense_input(SDCARD_SPI_CS_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); |
||||
|
nrf_gpio_cfg_sense_input(SDCARD_SPI_MISO_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); |
||||
|
nrf_gpio_cfg_sense_input(SDCARD_SPI_MOSI_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); |
||||
|
nrf_gpio_cfg_sense_input(SDCARD_SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); |
||||
|
|
||||
|
/** |
||||
|
* @brief 关闭SD卡电源 |
||||
|
*/ |
||||
|
nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 1); |
||||
|
nrf_delay_ms(100); // 让SD卡通过断电复位一会 |
||||
|
nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // 开 |
||||
|
/** |
||||
|
* @brief 切换引脚连接 |
||||
|
*/ |
||||
|
nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 0); |
||||
|
|
||||
|
nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 0); |
||||
|
nrf_delay_ms(30); |
||||
|
nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 1); |
||||
|
|
||||
|
m_connectTo = kConnectToExt; |
||||
|
} |
||||
|
void Board_sdcardConnectToInternal() { |
||||
|
if (m_connectTo == kConnectToInternal) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief |
||||
|
* 0. 断开SD卡电源 |
||||
|
* 1. 断开SD卡与读卡器的连接 |
||||
|
* 2. 打开SD电源 |
||||
|
* 3. 挂载SD卡 |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* @brief 断开SD卡电源 |
||||
|
*/ |
||||
|
nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 1); |
||||
|
|
||||
|
/** |
||||
|
* @brief 断开SD卡与读卡器的连接 |
||||
|
*/ |
||||
|
nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 1); |
||||
|
|
||||
|
/** |
||||
|
* @brief 打开SD电源 |
||||
|
*/ |
||||
|
nrf_delay_ms(30); // 让SD卡通过断电复位一会 |
||||
|
nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // 开 |
||||
|
|
||||
|
/** |
||||
|
* @brief 挂载SD卡 |
||||
|
*/ |
||||
|
DSTATUS disk_state = STA_NOINIT; |
||||
|
for (uint32_t retries = 10; retries && disk_state; --retries) { |
||||
|
disk_state = disk_initialize(0); |
||||
|
} |
||||
|
if (disk_state != 0) { |
||||
|
NRF_LOG_INFO("Disk initialization failed. %d", disk_state); |
||||
|
ZASSERT(0); |
||||
|
} |
||||
|
NRF_LOG_INFO("Disk initialization succeeded."); |
||||
|
FRESULT ff_result; |
||||
|
ff_result = f_mount(&m_fs, "", 1); |
||||
|
if (ff_result) { |
||||
|
NRF_LOG_INFO("Mount failed."); |
||||
|
ZASSERT(0); |
||||
|
} |
||||
|
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; |
||||
|
|
||||
|
ZLOGI("Mount success"); |
||||
|
NRF_LOG_INFO("Capacity: %d MB", capacity); |
||||
|
|
||||
|
m_connectTo = kConnectToInternal; |
||||
|
} |
||||
|
|
||||
|
BoardSdcardConnectTo_t Board_sdcardGetConnectTo() { return m_connectTo; } |
@ -0,0 +1,19 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#include "board/board.h" |
||||
|
|
||||
|
typedef enum { |
||||
|
kConnectToNone = 0, |
||||
|
kConnectToInternal, |
||||
|
kConnectToExt, |
||||
|
} BoardSdcardConnectTo_t; |
||||
|
|
||||
|
void Board_sdcardInit(); // main中初始化一遍 |
||||
|
|
||||
|
void Board_sdcardConnectToExt(); // SD卡连接到外部SD卡读卡器 |
||||
|
void Board_sdcardConnectToInternal(); // SD卡连接到单片机 |
||||
|
|
||||
|
BoardSdcardConnectTo_t Board_sdcardGetConnectTo(); |
@ -0,0 +1,357 @@ |
|||||
|
#include "device_ctrl_service.h" |
||||
|
|
||||
|
#include "app_event_distribute.h" |
||||
|
#include "board/board_battery_state.h" |
||||
|
#include "board/board_beep_ctrl.h" |
||||
|
#include "board/board_button.h" |
||||
|
#include "board/board_light_ctrl.h" |
||||
|
#include "board/board_sdcard_driver.h" |
||||
|
#include "heart_wave_sample_service.h" |
||||
|
#include "sample_data_manager_service.h" |
||||
|
#include "zble_module.h" |
||||
|
#include "zdatachannel_service.h" |
||||
|
// |
||||
|
APP_TIMER_DEF(m_state_machine_driver_tmr); // 状态机驱动定时器 |
||||
|
static device_state_t m_device_state = kdevice_state_standby; // 设备状态 |
||||
|
static uint32_t m_change_to_cur_state_tp = 0; // 切换到当前状态的时间戳 |
||||
|
static int m_sample_data_fd = -1; // 采集数据文件描述符 |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 函数列表 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
void DeviceCtrl_change_to_state(device_state_t state); |
||||
|
uint32_t DeviceCtrl_cur_state_haspassed_ms(); |
||||
|
device_state_t DeviceCtrl_now_state(); |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 事件路由 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
static void state_machine_driver_tmr_cb(void* p_context) { // |
||||
|
static app_event_t appevent; |
||||
|
appevent.eventType = kevent_tmr_scheduler; |
||||
|
AppEvent_pushEvent(&appevent); |
||||
|
} |
||||
|
/** |
||||
|
* @brief 按键事件处理 |
||||
|
*/ |
||||
|
static void board_button_cb(ButtonIndex_t pin_no, ButtonAction_t button_action) { // |
||||
|
static app_event_t event; |
||||
|
event.eventType = button_action == kButtonAction_push ? kevent_button_push_event : kevent_button_release_event; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
|
||||
|
static void zble_event_listener(zble_event_t* ble_event) { // |
||||
|
static app_event_t event; |
||||
|
if (ble_event->eventType == kzble_event_connected) { |
||||
|
event.eventType = kevent_ble_connect_event; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} else if (ble_event->eventType == kzble_event_disconnected) { |
||||
|
event.eventType = kevent_ble_disconnect_event; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 事件处理 * |
||||
|
*******************************************************************************/ |
||||
|
static bool m_ispoweron = false; |
||||
|
// static bool m_drop_state_triggered = false; |
||||
|
static void poweroff() { |
||||
|
if (!m_ispoweron) return; |
||||
|
BoardBeepCtrl_unload(); |
||||
|
BoardLight_unload(); |
||||
|
BoardBattery_unload(); |
||||
|
BoardButton_unload(); |
||||
|
SampleDataMgr_unloadDriver(); |
||||
|
// hwss_unload(); |
||||
|
DeviceCtrl_change_to_state(kdevice_state_standby); |
||||
|
zble_module_stop_adv(); |
||||
|
BoardLight_setGreenLightEffect(kLightEffect_close); |
||||
|
|
||||
|
// 进入深度睡眠前,使能唤醒引脚 |
||||
|
BoardButton_enable_sense(); |
||||
|
app_timer_stop_all(); |
||||
|
// 系统进入深度睡眠 |
||||
|
sd_power_system_off(); |
||||
|
NVIC_SystemReset(); |
||||
|
m_ispoweron = false; |
||||
|
} |
||||
|
static void poweron() { |
||||
|
if (m_ispoweron) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
BoardBeepCtrl_load(); |
||||
|
BoardLight_load(); |
||||
|
BoardBattery_load(); |
||||
|
BoardButton_load(); |
||||
|
SampleDataMgr_loadDriver(); |
||||
|
DeviceCtrl_change_to_state(kdevice_state_ready); |
||||
|
zble_module_start_adv(); |
||||
|
BoardLight_setGreenLightEffect(kLightEffect_slowFlash); |
||||
|
m_ispoweron = true; |
||||
|
} |
||||
|
|
||||
|
static sample_data_filename_t* cratefilename() { |
||||
|
static ztm_t tm; |
||||
|
static sample_data_filename_t sampledata_file_name; |
||||
|
memset(&sampledata_file_name, 0, sizeof(sampledata_file_name)); |
||||
|
znordic_rtc_gettime(&tm); |
||||
|
|
||||
|
sampledata_file_name.year = tm.tm_year + 1900 - 2000; |
||||
|
sampledata_file_name.month = tm.tm_mon + 1; |
||||
|
sampledata_file_name.day = tm.tm_mday; |
||||
|
sampledata_file_name.hour = tm.tm_hour; |
||||
|
sampledata_file_name.min = tm.tm_min; |
||||
|
sampledata_file_name.sec = tm.tm_sec; |
||||
|
return &sampledata_file_name; |
||||
|
} |
||||
|
|
||||
|
static void prvf_change_to_standby_state() { |
||||
|
poweroff(); |
||||
|
DeviceCtrl_change_to_state(kdevice_state_standby); |
||||
|
} |
||||
|
static void prvf_change_to_ready_state() { |
||||
|
poweron(); |
||||
|
DeviceCtrl_change_to_state(kdevice_state_ready); |
||||
|
BoardBeepCtrl_setEffect(kBoardBeepEffect_threeShortBeep); |
||||
|
} |
||||
|
#if 0 |
||||
|
static const char* dropstate(uint8_t drop0, uint8_t drop1) { |
||||
|
static char state[128]; |
||||
|
sprintf(state, "drop0:%d%d%d%d-%d%d%d%d drop1:%d%d%d%d-%d%d%d%d", // |
||||
|
drop0 & 0x80 ? 1 : 0, drop0 & 0x40 ? 1 : 0, drop0 & 0x20 ? 1 : 0, drop0 & 0x10 ? 1 : 0, // |
||||
|
drop0 & 0x08 ? 1 : 0, drop0 & 0x04 ? 1 : 0, drop0 & 0x02 ? 1 : 0, drop0 & 0x01 ? 1 : 0, // |
||||
|
drop1 & 0x80 ? 1 : 0, drop1 & 0x40 ? 1 : 0, drop1 & 0x20 ? 1 : 0, drop1 & 0x10 ? 1 : 0, // |
||||
|
drop1 & 0x08 ? 1 : 0, drop1 & 0x04 ? 1 : 0, drop1 & 0x02 ? 1 : 0, drop1 & 0x01 ? 1 : 0 // |
||||
|
); |
||||
|
return state; |
||||
|
} |
||||
|
#endif |
||||
|
static void prvf_change_to_sample_state() { // |
||||
|
if (m_device_state == kdevice_state_sampling) { |
||||
|
return; |
||||
|
} |
||||
|
DeviceCtrl_change_to_state(kdevice_state_sampling); |
||||
|
} |
||||
|
|
||||
|
static void app_event_listener(void* p_event_data, uint16_t event_size) { // |
||||
|
app_event_t* event = (app_event_t*)p_event_data; |
||||
|
// static bool inited; |
||||
|
// if (!inited) { |
||||
|
// nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_NOPULL); |
||||
|
// inited = true; |
||||
|
// } |
||||
|
// ZLOGI("button %d", nrf_gpio_pin_read(BUTTON_PIN)); |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 状态无关事件处理 * |
||||
|
*******************************************************************************/ |
||||
|
if (event->eventType == kevent_ble_connect_event) { |
||||
|
BoardLight_setGreenLightEffect(kLightEffect_open); |
||||
|
return; |
||||
|
} else if (event->eventType == kevent_ble_disconnect_event) { |
||||
|
BoardLight_setGreenLightEffect(kLightEffect_slowFlash); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 状态机 * |
||||
|
*******************************************************************************/ |
||||
|
// ZLOGI("state %d", m_device_state); |
||||
|
if (m_device_state == kdevice_state_standby) { |
||||
|
// 休眠模式现在是深度睡眠,所以永远不会触发这个回调 |
||||
|
} |
||||
|
|
||||
|
// |
||||
|
else if (m_device_state == kdevice_state_ready) { |
||||
|
/******************************************************************************* |
||||
|
* 永不休眠 * |
||||
|
*******************************************************************************/ |
||||
|
#if 0 |
||||
|
if (!zble_module_is_connected() && DeviceCtrl_cur_state_haspassed_ms() > APP_AUTO_SLEEP_TIMEOUT_MS) { |
||||
|
ZLOGI("auto sleep"); |
||||
|
prvf_change_to_standby_state(); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
if (event->eventType == kevent_start_sample_cmd_event) { |
||||
|
ZLOGI("start sample"); |
||||
|
// SD卡连接到单片机 |
||||
|
SampleDataMgr_changeToLocalMode(); |
||||
|
hwss_load(); |
||||
|
// 创建文件 |
||||
|
m_sample_data_fd = SampleDataMgr_open(cratefilename(), kwrflag_write_only); |
||||
|
ZASSERT(m_sample_data_fd > 0); |
||||
|
// 切换到采集状态 |
||||
|
prvf_change_to_sample_state(); |
||||
|
// 开始采集 |
||||
|
hwss_start_capture(); |
||||
|
|
||||
|
{ |
||||
|
static app_event_t event; |
||||
|
event.eventType = kevent_sample_start_event; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
|
||||
|
BoardBeepCtrl_setEffect(kBoardBeepEffect_oneShortBeep); |
||||
|
} |
||||
|
} |
||||
|
// |
||||
|
else if (m_device_state == kdevice_state_sampling) { |
||||
|
// 采集的字节长度超过最大字节长度,停止采集 |
||||
|
|
||||
|
if (event->eventType == kevent_capture_data_block_event) { |
||||
|
SampleDataMgr_write(m_sample_data_fd, (uint8_t*)event->val.block_sensor_data.data, event->val.block_sensor_data.len); |
||||
|
} |
||||
|
|
||||
|
uint8_t drop0 = hwss_get_drop_state0(); |
||||
|
uint8_t drop1 = hwss_get_drop_state1(); |
||||
|
|
||||
|
if ((drop0 || drop1) && event->eventType == kevent_tmr_scheduler) { |
||||
|
// ZLOGI("[%d] drop %s", znordic_getpower_on_ms(), dropstate(drop0, drop1)); |
||||
|
} |
||||
|
|
||||
|
bool stopcapture = false; |
||||
|
if (SampleDataMgr_getFileSizeByFd(m_sample_data_fd) > SDCARD_MAX_FILE_SIZE) { |
||||
|
ZLOGI("stop sample because file size is too large"); |
||||
|
stopcapture = true; |
||||
|
} else if (event->eventType == kevent_stop_sample_cmd_event) { |
||||
|
ZLOGI("stop sample because stop sample event"); |
||||
|
stopcapture = true; |
||||
|
} |
||||
|
|
||||
|
if (stopcapture) { |
||||
|
// 关闭文件 |
||||
|
SampleDataMgr_close(m_sample_data_fd); |
||||
|
// SD卡连接到外部typec |
||||
|
SampleDataMgr_changeToExtMode(); |
||||
|
// 停止采集 |
||||
|
hwss_stop_capture(); |
||||
|
// 卸载心电采集服务 |
||||
|
hwss_unload(); |
||||
|
// 切换到待机状态 |
||||
|
prvf_change_to_ready_state(); |
||||
|
|
||||
|
{ |
||||
|
static app_event_t event; |
||||
|
event.eventType = kevent_sample_stop_event; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void DeviceCtrl_startSample() { |
||||
|
ZLOGI("start sample"); |
||||
|
static app_event_t event; |
||||
|
event.eventType = kevent_start_sample_cmd_event; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
void DeviceCtrl_stopSample() { |
||||
|
ZLOGI("stop sample"); |
||||
|
static app_event_t event; |
||||
|
event.eventType = kevent_stop_sample_cmd_event; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* EXTERN * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
void DeviceCtrl_init() { |
||||
|
// 蜂鸣器初始化 |
||||
|
BoardBeepCtrl_init(); |
||||
|
// 板载指示灯初始化 |
||||
|
BoardLight_Init(); |
||||
|
// 按键初始化 |
||||
|
BoardButton_Init(board_button_cb); |
||||
|
// 电池初始化 |
||||
|
BoardBattery_init(); |
||||
|
// SD卡初始化 |
||||
|
SampleDataMgr_init(); |
||||
|
// 心电采集服务初始化 |
||||
|
hwss_init(); |
||||
|
// 注册事件监听 |
||||
|
AppEvent_regListener(app_event_listener); |
||||
|
// 监听蓝牙事件 |
||||
|
zble_module_reglistener(zble_event_listener); |
||||
|
// 切换到待机状态 |
||||
|
prvf_change_to_ready_state(); |
||||
|
|
||||
|
|
||||
|
// BoardBeepCtrl_init(); |
||||
|
// BoardBeepCtrl_load(); |
||||
|
// BoardBeepCtrl_setEffect(kBoardBeepEffect_continuousShortBeep); |
||||
|
|
||||
|
ZERROR_CHECK(app_timer_create(&m_state_machine_driver_tmr, APP_TIMER_MODE_REPEATED, state_machine_driver_tmr_cb)); |
||||
|
ZERROR_CHECK(app_timer_start(m_state_machine_driver_tmr, APP_TIMER_TICKS(100), NULL)); // 200HZ采样 |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* UTILS * |
||||
|
*******************************************************************************/ |
||||
|
void DeviceCtrl_change_to_state(device_state_t state) { |
||||
|
ZLOGI("change state from %s to %s", ds2str(m_device_state), ds2str(state)); |
||||
|
m_device_state = state; |
||||
|
m_change_to_cur_state_tp = znordic_getpower_on_ms(); |
||||
|
} |
||||
|
uint32_t DeviceCtrl_cur_state_haspassed_ms() { return znordic_haspassed_ms(m_change_to_cur_state_tp); } |
||||
|
device_state_t DeviceCtrl_now_state() { return m_device_state; } |
||||
|
|
||||
|
#if 0 |
||||
|
static void DeviceCtrl_test() { |
||||
|
/** |
||||
|
* @brief |
||||
|
* 1. 测试蜂鸣器 |
||||
|
* 2. 测试按键 |
||||
|
* 3. 测试LED |
||||
|
* 4. 测试指示灯 |
||||
|
* . SD卡 |
||||
|
* 5. 测试电池电量采集 |
||||
|
*/ |
||||
|
#if 0 |
||||
|
//蜂鸣器测试 |
||||
|
BoardBeepCtrl_init(); |
||||
|
BoardBeepCtrl_load(); |
||||
|
BoardBeepCtrl_setEffect(kBoardBeepEffect_continuousShortBeep); |
||||
|
#endif |
||||
|
|
||||
|
#if 1 |
||||
|
// BoardButton_Init(board_button_cb); |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
#if 0 |
||||
|
BoardLight_Init(); |
||||
|
BoardLight_load(); |
||||
|
BoardLight_setGreenLightEffect(kLightEffect_slowFlash); |
||||
|
#endif |
||||
|
#if 0 |
||||
|
Board_sdcardInit(); |
||||
|
Board_sdcardConnectToInternal(); |
||||
|
Board_sdcardConnectToExt(); |
||||
|
|
||||
|
Board_sdcardConnectToInternal(); |
||||
|
Board_sdcardConnectToExt(); |
||||
|
|
||||
|
#endif |
||||
|
#if 0 |
||||
|
sample_data_mgr_init(); |
||||
|
sample_data_mgr_loadDriver(); |
||||
|
sample_data_mgr_change_to_local_mode(); |
||||
|
|
||||
|
sample_data_filename_t filename; |
||||
|
int fd = sample_data_mgr_open(&filename, kwrflag_write_only); |
||||
|
sample_data_mgr_write(fd, "123456", 6); |
||||
|
sample_data_mgr_close(fd); |
||||
|
sample_data_mgr_change_to_ext_mode(); |
||||
|
#endif |
||||
|
#if 1 |
||||
|
// 蜂鸣器测试 |
||||
|
|
||||
|
#endif |
||||
|
} |
||||
|
#endif |
@ -0,0 +1,44 @@ |
|||||
|
/** |
||||
|
* @file device_ctrl_service.h |
||||
|
* @author zhaohe (h_zhaohe@domain.com) |
||||
|
* @brief É豸¿ØÖÆ·þÎñ |
||||
|
* @version 0.1 |
||||
|
* @date 2024-02-01 |
||||
|
* |
||||
|
* @copyright Copyright (c) 2024 |
||||
|
* |
||||
|
*/ |
||||
|
#pragma once |
||||
|
#include "znordic.h" |
||||
|
|
||||
|
typedef enum { |
||||
|
// ´ý»ú |
||||
|
kdevice_state_standby = 0, |
||||
|
// Ready |
||||
|
kdevice_state_ready = 1, |
||||
|
// sample |
||||
|
kdevice_state_sampling = 2, |
||||
|
} device_state_t; |
||||
|
|
||||
|
static const char* ds2str(device_state_t ds) { |
||||
|
switch (ds) { |
||||
|
case kdevice_state_standby: |
||||
|
return "standby"; |
||||
|
case kdevice_state_ready: |
||||
|
return "ready"; |
||||
|
case kdevice_state_sampling: |
||||
|
return "sampling"; |
||||
|
default: |
||||
|
return "unknown"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void DeviceCtrl_change_to_state(device_state_t state); |
||||
|
uint32_t DeviceCtrl_cur_state_haspassed_ms(); |
||||
|
device_state_t DeviceCtrl_now_state(); |
||||
|
|
||||
|
void DeviceCtrl_startSample(); |
||||
|
void DeviceCtrl_stopSample(); |
||||
|
void DeviceCtrl_schdeule(); |
||||
|
|
||||
|
void DeviceCtrl_init() ; |
@ -0,0 +1,455 @@ |
|||||
|
#include "heart_wave_sample_service.h" |
||||
|
// |
||||
|
#include "znordic.h" |
||||
|
// |
||||
|
#include "app_button.h" |
||||
|
#include "app_event.h" |
||||
|
#include "app_event_distribute.h" |
||||
|
#include "basic/ads1293/ads1293.h" |
||||
|
#include "nrf_drv_gpiote.h" |
||||
|
#include "nrfx_timer.h" |
||||
|
|
||||
|
#define SENSOR0_ID 0 |
||||
|
#define SENSOR1_ID 3 |
||||
|
#define SENSOR2_ID 4 |
||||
|
static const nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(1); /**< Timer used for channel sweeps and tx with duty cycle. */ |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* STRUCT * |
||||
|
*******************************************************************************/ |
||||
|
typedef struct { |
||||
|
uint8_t add; |
||||
|
uint8_t data; |
||||
|
} adscfg_t; |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* CONFIG * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
static adscfg_t m_prvads0cfg[] = // |
||||
|
{ |
||||
|
{0x00, 0x00}, {0x01, 0x19}, {0x02, 0x11}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x0f}, {0x08, 0xff}, {0x09, 0x00}, {0x0a, 0x07}, {0x0b, 0x07}, {0x0c, 0x74}, {0x0d, 0x01}, {0x0e, 0x02}, {0x0f, 0x03}, {0x10, 0x04}, |
||||
|
{0x11, 0x00}, {0x12, 0x05}, {0x13, 0x39}, {0x14, 0x36}, {0x15, 0x06}, {0x16, 0x00}, {0x17, 0x05}, {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00}, {0x1c, 0x00}, {0x1d, 0x00}, {0x21, 0x01}, {0x22, 0x20}, {0x23, 0x20}, {0x24, 0x02}, |
||||
|
{0x25, 0x00}, {0x26, 0x00}, {0x27, 0x08}, {0x28, 0x08}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00}, {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x33}, {0x2f, 0x30}, {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0x00}, {0x35, 0x00}, |
||||
|
{0x36, 0x00}, {0x37, 0x00}, {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00}, {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00}, {0x40, 0xff}, {0x50, 0x00}, {0x60, 0x00}, {0x62, 0x00}, |
||||
|
}; |
||||
|
|
||||
|
static adscfg_t m_prvads1cfg[] = // |
||||
|
{ |
||||
|
{0x00, 0x00}, {0x01, 0x0c}, {0x02, 0x14}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x0f}, {0x08, 0xff}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x07}, {0x0c, 0x78}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00}, {0x10, 0x04}, |
||||
|
{0x11, 0x00}, {0x12, 0x07}, {0x13, 0x3b}, {0x14, 0x24}, {0x15, 0x04}, {0x16, 0x00}, {0x17, 0x05}, {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00}, {0x1c, 0x00}, {0x1d, 0x00}, {0x21, 0x01}, {0x22, 0x20}, {0x23, 0x20}, {0x24, 0x02}, |
||||
|
{0x25, 0x00}, {0x26, 0x00}, {0x27, 0x08}, {0x28, 0x40}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00}, {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x33}, {0x2f, 0x30}, {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0x00}, {0x35, 0x00}, |
||||
|
{0x36, 0x00}, {0x37, 0x00}, {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00}, {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00}, {0x40, 0xff}, {0x50, 0x00}, {0x60, 0x00}, {0x62, 0x00}, |
||||
|
}; |
||||
|
|
||||
|
static adscfg_t m_prvads0cfg_cache[65]; |
||||
|
static adscfg_t m_prvads1cfg_cache[65]; |
||||
|
/******************************************************************************* |
||||
|
* VARIABLE * |
||||
|
*******************************************************************************/ |
||||
|
static ads1293_t m_ads1293_0; // U2 |
||||
|
static ads1293_t m_ads1293_1; // U3 |
||||
|
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(ADS1293_SPI_INSTANCE); /**< SPI instance. */ |
||||
|
static bool m_ads1293_driver_is_inited = false; |
||||
|
static uint32_t m_frame_index; |
||||
|
static uint32_t m_frame_filter_index; |
||||
|
static bool m_work_flag; |
||||
|
|
||||
|
#define FRAME_FILTER_INDEX_NUM 10 |
||||
|
|
||||
|
static uint8_t m_frame_buffer_a[HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE]; |
||||
|
static uint8_t m_frame_buffer_b[HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE]; |
||||
|
static uint8_t* m_frame_buffer; |
||||
|
static int32_t m_frame_buffer_index; |
||||
|
|
||||
|
static one_frame_data_t m_sensor_little_frame_cache[LITTLE_DATA_BLOCK_FRAME_NUM]; |
||||
|
static uint32_t m_little_frame_index; |
||||
|
|
||||
|
static uint8_t m_lodstate0; |
||||
|
static uint8_t m_lodstate1; |
||||
|
|
||||
|
volatile static bool m_drop_state_triggered = false; |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 函数声明 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
// READY_PIN 中断回调函数 |
||||
|
// static void ads1293_ready_pin_irq(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action); |
||||
|
// 缓冲区切换BUFFER |
||||
|
static void prvf_buffer_switch(void); |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* FUNCTION * |
||||
|
*******************************************************************************/ |
||||
|
static void prvf_buffer_switch(void) { |
||||
|
if (m_frame_buffer == m_frame_buffer_a) { |
||||
|
m_frame_buffer = m_frame_buffer_b; |
||||
|
m_frame_buffer_index = 0; |
||||
|
} else { |
||||
|
m_frame_buffer = m_frame_buffer_a; |
||||
|
m_frame_buffer_index = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static inline bool prvf_buffer_is_full(void) { |
||||
|
if (m_frame_buffer_index >= HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE) { |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
static inline void prvf_buffer_push_one_byte(uint8_t byte) { |
||||
|
if (m_frame_buffer_index >= HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE) { |
||||
|
return; |
||||
|
} |
||||
|
m_frame_buffer[m_frame_buffer_index] = byte; |
||||
|
m_frame_buffer_index++; |
||||
|
} |
||||
|
|
||||
|
static inline void prvf_trigger_capture_data_block_event(uint8_t* data, int datalen) { |
||||
|
static app_event_t event; |
||||
|
event.eventType = kevent_capture_data_block_event; |
||||
|
event.val.block_sensor_data.data = data; |
||||
|
event.val.block_sensor_data.len = datalen; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
|
||||
|
static inline void prvf_little_block_cache_push_one_frame(uint32_t data0, uint32_t data1, uint32_t data2) { |
||||
|
if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) { |
||||
|
return; |
||||
|
} |
||||
|
m_sensor_little_frame_cache[m_little_frame_index].data0 = data0; |
||||
|
m_sensor_little_frame_cache[m_little_frame_index].data1 = data1; |
||||
|
m_sensor_little_frame_cache[m_little_frame_index].data2 = data2; |
||||
|
m_little_frame_index++; |
||||
|
} |
||||
|
|
||||
|
static inline bool prvf_light_block_cache_is_full(void) { |
||||
|
if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) { |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
static inline void prvf_light_block_cache_clear(void) { m_little_frame_index = 0; } |
||||
|
static inline void prvf_light_block_trigger_event() { |
||||
|
static app_event_t event; |
||||
|
event.eventType = kevent_capture_little_data_block_event; |
||||
|
// memcpy(event.val.little_data_block.data, m_sensor_little_frame_cache, LITTLE_DATA_BLOCK_FRAME_NUM * sizeof(one_frame_data_t)); |
||||
|
|
||||
|
for (uint32_t i = 0; i < LITTLE_DATA_BLOCK_FRAME_NUM; i++) { |
||||
|
event.val.little_data_block.data[i].data0 = m_sensor_little_frame_cache[i].data0; |
||||
|
event.val.little_data_block.data[i].data1 = m_sensor_little_frame_cache[i].data1; |
||||
|
event.val.little_data_block.data[i].data2 = m_sensor_little_frame_cache[i].data2; |
||||
|
// event.val.little_data_block.data[0].data0 = 1111111111; |
||||
|
// event.val.little_data_block.data[0].data1 = 2222222222; |
||||
|
// event.val.little_data_block.data[0].data2 = 3333333333; |
||||
|
} |
||||
|
|
||||
|
event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
|
||||
|
static inline void prvf_trigger_sensor_drop_event(uint8_t drop0, uint8_t drop1) { |
||||
|
static app_event_t event; |
||||
|
event.eventType = kevent_sensor_drop; |
||||
|
event.val.sensor_drop.drop0 = drop0; |
||||
|
event.val.sensor_drop.drop1 = drop1; |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
|
||||
|
static void ads1293_spi_tx_rx_0(uint8_t* tx, uint8_t* rx, uint8_t len) { |
||||
|
if (!m_ads1293_driver_is_inited) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
nrf_gpio_pin_clear(ADS1293_SPI_CS0_PIN); |
||||
|
nrf_drv_spi_transfer(&spi, tx, len, rx, len); |
||||
|
nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); |
||||
|
} |
||||
|
static void ads1293_spi_tx_rx_1(uint8_t* tx, uint8_t* rx, uint8_t len) { |
||||
|
if (!m_ads1293_driver_is_inited) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
nrf_gpio_pin_clear(ADS1293_SPI_CS1_PIN); |
||||
|
nrf_drv_spi_transfer(&spi, tx, len, rx, len); |
||||
|
nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); |
||||
|
} |
||||
|
|
||||
|
static void ads1293_spi_writereg_and_check(ads1293_t* ads, uint8_t addr, uint8_t data) { |
||||
|
uint8_t readbak = 0; |
||||
|
// readonly add |
||||
|
readbak = data; |
||||
|
if (addr >= 0x18 && addr <= 0x1E) { |
||||
|
return; |
||||
|
} |
||||
|
if (addr >= 0x30 && addr <= 0x3f) { |
||||
|
return; |
||||
|
} |
||||
|
if (addr == 0x40) { |
||||
|
return; |
||||
|
} |
||||
|
if (addr == 0x50) { |
||||
|
return; |
||||
|
} |
||||
|
ads1293_spi_writereg_and_readbak(ads, addr, data, &readbak); |
||||
|
if (readbak != data) { |
||||
|
ZLOGE("ads_%d write %x failed,w:%x readbak:%x\n", ads->id, addr, data, readbak); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static void tryloadcfg_from_fatfs(const char* file, adscfg_t* cfg, uint16_t cfgsize, uint16_t* cfg_ret_size) { |
||||
|
// |
||||
|
*cfg_ret_size = 0; |
||||
|
|
||||
|
static FIL fd; |
||||
|
FRESULT ff_result = f_open(&fd, (const TCHAR*)file, FA_READ); |
||||
|
if (ff_result != FR_OK) { |
||||
|
ZLOGE("open %s failed\n", file); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
char line[128]; |
||||
|
int niterm = 0; |
||||
|
f_gets(line, 128, &fd); |
||||
|
|
||||
|
while (f_gets(line, 128, &fd)) { |
||||
|
uint32_t addr; |
||||
|
uint32_t value; |
||||
|
sscanf(line, "%x,%x", &addr, &value); |
||||
|
cfg[niterm].add = addr; |
||||
|
cfg[niterm].data = value; |
||||
|
niterm++; |
||||
|
|
||||
|
if (niterm >= cfgsize) { |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
*cfg_ret_size = niterm; |
||||
|
ZLOGI("load %s cfg size:%d\n", file, niterm); |
||||
|
f_close(&fd); |
||||
|
} |
||||
|
|
||||
|
static void ads1293_init() { |
||||
|
/******************************************************************************* |
||||
|
* SPI初始化 * |
||||
|
*******************************************************************************/ |
||||
|
static 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 = ADS1293_SPI_MISO_PIN; |
||||
|
spi_config.mosi_pin = ADS1293_SPI_MOSI_PIN; |
||||
|
spi_config.sck_pin = ADS1293_SPI_SCK_PIN; |
||||
|
spi_config.frequency = NRF_DRV_SPI_FREQ_8M; |
||||
|
spi_config.mode = NRF_DRV_SPI_MODE_3; |
||||
|
// spi_config.mode = |
||||
|
ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); |
||||
|
|
||||
|
znrf_gpio_cfg_output(ADS1293_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL); |
||||
|
znrf_gpio_cfg_output(ADS1293_SPI_CS1_PIN, NRF_GPIO_PIN_NOPULL); |
||||
|
nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); |
||||
|
nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); |
||||
|
|
||||
|
m_ads1293_0.spi_tx_rx = ads1293_spi_tx_rx_0; |
||||
|
m_ads1293_0.id = 0; |
||||
|
m_ads1293_1.spi_tx_rx = ads1293_spi_tx_rx_1; |
||||
|
m_ads1293_1.id = 1; |
||||
|
|
||||
|
ads1293_spi_init(&m_ads1293_0, ads1293_spi_tx_rx_0); |
||||
|
ads1293_spi_init(&m_ads1293_1, ads1293_spi_tx_rx_1); |
||||
|
|
||||
|
m_ads1293_driver_is_inited = true; |
||||
|
|
||||
|
uint8_t revid = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_REVID_REG); |
||||
|
ZLOGI("ads1293_0 revid: %d\n", revid); |
||||
|
revid = ads1293_spi_readreg(&m_ads1293_1, TI_ADS1293_REVID_REG); |
||||
|
ZLOGI("ads1293_1 revid: %d\n", revid); |
||||
|
|
||||
|
ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0); |
||||
|
|
||||
|
uint16_t cfgsize = 0; |
||||
|
tryloadcfg_from_fatfs("0.cfg", m_prvads0cfg_cache, ZARRAY_SIZE(m_prvads0cfg_cache), &cfgsize); |
||||
|
if (cfgsize > 0) { |
||||
|
ZLOGI("load 0.cfg from fatfs\n"); |
||||
|
|
||||
|
if (memcmp(m_prvads0cfg_cache, m_prvads0cfg, sizeof(m_prvads0cfg)) != 0) { |
||||
|
ZLOGI("0.cfg is different from default\n"); |
||||
|
} else { |
||||
|
ZLOGI("0.cfg is same as default\n"); |
||||
|
} |
||||
|
|
||||
|
for (uint16_t i = 0; i < cfgsize; i++) { |
||||
|
ads1293_spi_writereg_and_check(&m_ads1293_0, m_prvads0cfg_cache[i].add, m_prvads0cfg_cache[i].data); |
||||
|
} |
||||
|
} else { |
||||
|
for (uint16_t i = 0; i < ZARRAY_SIZE(m_prvads0cfg); i++) { |
||||
|
ads1293_spi_writereg_and_check(&m_ads1293_0, m_prvads0cfg[i].add, m_prvads0cfg[i].data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
tryloadcfg_from_fatfs("1.cfg", m_prvads1cfg_cache, ZARRAY_SIZE(m_prvads1cfg_cache), &cfgsize); |
||||
|
if (cfgsize > 0) { |
||||
|
ZLOGI("load 1.cfg from fatfs\n"); |
||||
|
|
||||
|
if (memcmp(m_prvads1cfg_cache, m_prvads1cfg, sizeof(m_prvads1cfg)) != 0) { |
||||
|
ZLOGI("1.cfg is different from default\n"); |
||||
|
} else { |
||||
|
ZLOGI("1.cfg is same as default\n"); |
||||
|
} |
||||
|
|
||||
|
for (uint16_t i = 0; i < cfgsize; i++) { |
||||
|
ads1293_spi_writereg_and_check(&m_ads1293_1, m_prvads1cfg_cache[i].add, m_prvads1cfg_cache[i].data); |
||||
|
} |
||||
|
} else { |
||||
|
for (uint16_t i = 0; i < ZARRAY_SIZE(m_prvads1cfg); i++) { |
||||
|
ads1293_spi_writereg_and_check(&m_ads1293_1, m_prvads1cfg[i].add, m_prvads1cfg[i].data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief READY引脚中断初始化 |
||||
|
*/ |
||||
|
{ |
||||
|
// nrf_gpio_cfg_input(ADS1293_READY_PIN, NRF_GPIO_PIN_PULLUP); |
||||
|
// ZERROR_CHECK(nrfx_gpiote_init()); |
||||
|
// nrf_drv_gpiote_in_config_t inConfig = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); // 双边沿中断触发 |
||||
|
// inConfig.pull = NRF_GPIO_PIN_PULLUP; // 默认上拉 |
||||
|
// inConfig.sense = NRF_GPIOTE_POLARITY_LOTOHI; // 上升沿触发 |
||||
|
// ZERROR_CHECK(nrfx_gpiote_in_init(ADS1293_READY_PIN, &inConfig, ads1293_ready_pin_irq)); |
||||
|
// nrfx_gpiote_in_event_enable(ADS1293_READY_PIN, true); |
||||
|
} |
||||
|
|
||||
|
{} |
||||
|
} |
||||
|
|
||||
|
void ads1293_sample_one_frame(); |
||||
|
void nrfx_timer_event_handler(nrf_timer_event_t event_type, void* p_context) { // |
||||
|
ads1293_sample_one_frame(); |
||||
|
} |
||||
|
// static void ads1293_ready_pin_irq(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { ads1293_sample_one_frame(); } |
||||
|
static void ads1293_sample_one_frame() { |
||||
|
if (!m_work_flag) { |
||||
|
return; |
||||
|
} |
||||
|
if (m_frame_filter_index < FRAME_FILTER_INDEX_NUM) { |
||||
|
m_frame_filter_index++; |
||||
|
return; |
||||
|
} |
||||
|
m_frame_index++; |
||||
|
// 检查缓冲区是否为空 |
||||
|
if (!m_frame_buffer) prvf_buffer_switch(); |
||||
|
|
||||
|
static uint32_t sample[6]; |
||||
|
ads1293_read_ecgs(&m_ads1293_0, &sample[0]); |
||||
|
ads1293_read_ecgs(&m_ads1293_1, &sample[3]); |
||||
|
|
||||
|
m_lodstate0 = ads1293_read_error_lod(&m_ads1293_0); |
||||
|
m_lodstate1 = ads1293_read_error_lod(&m_ads1293_1); |
||||
|
|
||||
|
if (!m_drop_state_triggered) { |
||||
|
if (m_lodstate0 || m_lodstate1) { |
||||
|
m_drop_state_triggered = true; |
||||
|
prvf_trigger_sensor_drop_event(m_lodstate0, m_lodstate1); |
||||
|
} |
||||
|
} else { |
||||
|
if (!(m_lodstate0 || m_lodstate1)) { |
||||
|
m_drop_state_triggered = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static uint8_t cache[9]; |
||||
|
cache[0] = (sample[SENSOR0_ID] >> 0) & 0xff; |
||||
|
cache[1] = (sample[SENSOR0_ID] >> 8) & 0xff; |
||||
|
cache[2] = (sample[SENSOR0_ID] >> 16) & 0xff; |
||||
|
|
||||
|
cache[3] = (sample[SENSOR1_ID] >> 0) & 0xff; |
||||
|
cache[4] = (sample[SENSOR1_ID] >> 8) & 0xff; |
||||
|
cache[5] = (sample[SENSOR1_ID] >> 16) & 0xff; |
||||
|
|
||||
|
cache[6] = (sample[SENSOR2_ID] >> 0) & 0xff; |
||||
|
cache[7] = (sample[SENSOR2_ID] >> 8) & 0xff; |
||||
|
cache[8] = (sample[SENSOR2_ID] >> 16) & 0xff; |
||||
|
|
||||
|
/** |
||||
|
* @brief 缓存数据,并触发数据块事件 |
||||
|
*/ |
||||
|
for (int i = 0; i < 9; i++) { |
||||
|
if (prvf_buffer_is_full()) { |
||||
|
prvf_trigger_capture_data_block_event(m_frame_buffer, HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE); |
||||
|
prvf_buffer_switch(); |
||||
|
} |
||||
|
prvf_buffer_push_one_byte(cache[i]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief 缓存数据,并触发小数据块事件 |
||||
|
*/ |
||||
|
prvf_little_block_cache_push_one_frame(sample[SENSOR0_ID], sample[SENSOR1_ID], sample[SENSOR2_ID]); |
||||
|
if (prvf_light_block_cache_is_full()) { |
||||
|
prvf_light_block_trigger_event(); |
||||
|
prvf_light_block_cache_clear(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static void ads1293_uninit() { |
||||
|
hwss_stop_capture(); |
||||
|
m_ads1293_driver_is_inited = false; |
||||
|
nrf_drv_spi_uninit(&spi); |
||||
|
} |
||||
|
|
||||
|
void hwss_init(void) { |
||||
|
/** |
||||
|
* @brief 初始化定时器 |
||||
|
*/ |
||||
|
nrfx_err_t err; |
||||
|
nrfx_timer_config_t timer_cfg = { |
||||
|
.frequency = NRF_TIMER_FREQ_250kHz, |
||||
|
.mode = NRF_TIMER_MODE_TIMER, |
||||
|
.bit_width = NRF_TIMER_BIT_WIDTH_24, |
||||
|
.p_context = NULL, |
||||
|
.interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, |
||||
|
}; |
||||
|
|
||||
|
err = nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler); |
||||
|
if (err != NRFX_SUCCESS) { |
||||
|
NRF_LOG_ERROR("nrfx_timer_init failed with: %d\n", err); |
||||
|
} |
||||
|
|
||||
|
ZASSERT(SAMPLE_RATE == 400); |
||||
|
uint32_t timer_ticks = nrfx_timer_ms_to_ticks(&m_timer, 5); // 200HZ |
||||
|
ZLOGI("timer_ticks:%d\n", timer_ticks); |
||||
|
ZASSERT(timer_ticks % 2 == 0); // |
||||
|
timer_ticks = timer_ticks / 2; // 400HZ |
||||
|
nrfx_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, timer_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true); |
||||
|
} |
||||
|
|
||||
|
void hwss_load(void) { ads1293_init(); } |
||||
|
void hwss_unload(void) { |
||||
|
nrfx_timer_disable(&m_timer); |
||||
|
ads1293_uninit(); |
||||
|
} |
||||
|
|
||||
|
void hwss_start_capture(void) { |
||||
|
m_drop_state_triggered = false; |
||||
|
m_work_flag = true; |
||||
|
m_frame_index = 0; |
||||
|
m_frame_filter_index = 0; |
||||
|
prvf_light_block_cache_clear(); |
||||
|
ads1293_start_conversion(&m_ads1293_0); |
||||
|
ads1293_start_conversion(&m_ads1293_1); |
||||
|
nrfx_timer_enable(&m_timer); |
||||
|
} |
||||
|
void hwss_stop_capture(void) { |
||||
|
nrfx_timer_disable(&m_timer); |
||||
|
m_work_flag = false; |
||||
|
m_frame_index = 0; |
||||
|
m_frame_filter_index = 0; |
||||
|
prvf_light_block_cache_clear(); |
||||
|
ads1293_stop_conversion(&m_ads1293_0); |
||||
|
ads1293_stop_conversion(&m_ads1293_1); |
||||
|
} |
||||
|
|
||||
|
bool hwss_is_capturing(void) { return m_work_flag; } |
||||
|
|
||||
|
uint8_t hwss_get_drop_state0() { return m_lodstate0; } |
||||
|
uint8_t hwss_get_drop_state1() { return m_lodstate1; } |
@ -0,0 +1,35 @@ |
|||||
|
/** |
||||
|
* @file heart_wave_sample_service.h |
||||
|
* @author zhaohe (h_zhaohe@163.com) |
||||
|
* @brief Ðĵ粨ÐβÉÑù·þÎñ |
||||
|
* @version 0.1 |
||||
|
* @date 2024-02-01 |
||||
|
* |
||||
|
* @copyright Copyright (c) 2024 |
||||
|
* |
||||
|
*/ |
||||
|
#pragma once |
||||
|
#include "app_event.h" |
||||
|
#include "board/board.h" |
||||
|
|
||||
|
/** |
||||
|
* @brief ³õʼ»¯ |
||||
|
*/ |
||||
|
void hwss_init(void); |
||||
|
|
||||
|
void hwss_load(void); |
||||
|
void hwss_unload(void); |
||||
|
|
||||
|
/** |
||||
|
* @brief ¿ªÊ¼²É¼¯ |
||||
|
*/ |
||||
|
void hwss_start_capture(void); |
||||
|
/** |
||||
|
* @brief Í£Ö¹²É¼¯ |
||||
|
*/ |
||||
|
void hwss_stop_capture(void); |
||||
|
|
||||
|
bool hwss_is_capturing(void); |
||||
|
|
||||
|
uint8_t hwss_get_drop_state0(); |
||||
|
uint8_t hwss_get_drop_state1(); |
@ -0,0 +1,43 @@ |
|||||
|
#if 1 |
||||
|
#include "znordic.h" |
||||
|
// |
||||
|
#include <stdarg.h> |
||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
// |
||||
|
#include "app_ble_service.h" |
||||
|
#include "app_event_distribute.h" |
||||
|
#include "basic/ads1293/ads1293.h" |
||||
|
#include "board/board.h" |
||||
|
#include "device_ctrl_service.h" |
||||
|
#include "zble_module.h" |
||||
|
#include "zdatachannel_service.h" |
||||
|
#include "znordic_device_info_mgr.h" |
||||
|
// |
||||
|
|
||||
|
int main() { |
||||
|
APP_SCHED_INIT(APP_MAX_EVEN_SIZE, APP_EVENT_QUEUE_SIZE); |
||||
|
znordic_init(); |
||||
|
NRF_LOG_INFO("compile time :%s", __TIME__); |
||||
|
ZLOGI("CUSTOMER :%d", NRF_UICR->CUSTOMER[0]); |
||||
|
/******************************************************************************* |
||||
|
* 蓝牙服务初始化 * |
||||
|
*******************************************************************************/ |
||||
|
static zble_module_cfg_t cfg; |
||||
|
cfg.deviceName = device_info_read_sn_str(); |
||||
|
cfg.on_service_init = AppBleService_onServiceInitCB; |
||||
|
zble_module_init(&cfg); |
||||
|
AppBleService_init(); |
||||
|
/******************************************************************************* |
||||
|
* 设备控制服务初始化 * |
||||
|
*******************************************************************************/ |
||||
|
DeviceCtrl_init(); |
||||
|
/******************************************************************************* |
||||
|
* LOOP * |
||||
|
*******************************************************************************/ |
||||
|
znordic_loop(); |
||||
|
} |
||||
|
#else |
||||
|
#include "ads1293_simple_tester.c" |
||||
|
#endif |
@ -0,0 +1,171 @@ |
|||||
|
#include "sample_data_manager_service.h" |
||||
|
|
||||
|
#include "board/board.h" |
||||
|
#include "board/board_sdcard_driver.h" |
||||
|
#include "znordic.h" |
||||
|
/******************************************************************************* |
||||
|
* 全局变量 * |
||||
|
*******************************************************************************/ |
||||
|
static FIL m_default_file_handler; |
||||
|
static sample_data_fileinfo_list_t m_sample_fileinfo_list; |
||||
|
static sample_data_fileinfo_t m_sample_fileinfo[FILE_MAX_COUNT]; |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 接口层 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
static void read_file_info() { |
||||
|
/** |
||||
|
* @brief |
||||
|
* |
||||
|
* fdate: |
||||
|
* bit15:9 |
||||
|
* Year origin from 1980 (0..127) |
||||
|
* bit8:5 |
||||
|
* Month (1..12) |
||||
|
* bit4:0 |
||||
|
* Day of the month(1..31) |
||||
|
* ftime: |
||||
|
* bit15:11 |
||||
|
* Hour (0..23) |
||||
|
* bit10:5 |
||||
|
* Minute (0..59) |
||||
|
* bit4:0 |
||||
|
* Second / 2 (0..29) |
||||
|
*/ |
||||
|
FILINFO fno; |
||||
|
FRESULT ff_result = f_stat("0.bin", &fno); |
||||
|
m_sample_fileinfo_list.fileinfo[0] = &m_sample_fileinfo[0]; |
||||
|
|
||||
|
if (ff_result == FR_OK) { |
||||
|
static sample_data_filename_t _filename; |
||||
|
_filename.year = (fno.fdate >> 9) + 1980 - 2000; |
||||
|
_filename.month = (fno.fdate >> 5) & 0x0F; |
||||
|
_filename.day = fno.fdate & 0x1F; |
||||
|
_filename.hour = (fno.ftime >> 11); |
||||
|
_filename.min = (fno.ftime >> 5) & 0x3F; |
||||
|
_filename.sec = (fno.ftime & 0x1F) * 2; |
||||
|
memcpy(m_sample_fileinfo_list.fileinfo[0]->filename, &_filename, sizeof(sample_data_filename_t)); |
||||
|
m_sample_fileinfo_list.fileinfo[0]->size = fno.fsize; |
||||
|
m_sample_fileinfo_list.count = 1; |
||||
|
|
||||
|
ZLOGI("filelist:"); |
||||
|
ZLOGI(" name:%s", "0.bin"); |
||||
|
ZLOGI(" size:%d", fno.fsize); |
||||
|
|
||||
|
} else { |
||||
|
m_sample_fileinfo_list.fileinfo[0]->size = 0; |
||||
|
m_sample_fileinfo_list.count = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief 文件驱动管理 |
||||
|
*/ |
||||
|
void SampleDataMgr_init() { |
||||
|
Board_sdcardInit(); |
||||
|
// 先连接到单片机,读取下文件状态信息 |
||||
|
SampleDataMgr_changeToLocalMode(); |
||||
|
SampleDataMgr_changeToExtMode(); |
||||
|
} |
||||
|
void SampleDataMgr_loadDriver() { |
||||
|
// donothing |
||||
|
} |
||||
|
void SampleDataMgr_unloadDriver() { |
||||
|
// donothin |
||||
|
} |
||||
|
typedef struct { |
||||
|
uint8_t filename[8]; |
||||
|
uint32_t filesize; |
||||
|
|
||||
|
} disk_state_t; |
||||
|
|
||||
|
/** |
||||
|
* @brief 存储器连接单片机 |
||||
|
*/ |
||||
|
void SampleDataMgr_changeToLocalMode() { |
||||
|
ZLOGI("change to local mode"); |
||||
|
Board_sdcardConnectToInternal(); |
||||
|
read_file_info(); |
||||
|
} |
||||
|
/** |
||||
|
* @brief 存储器连接外部typec |
||||
|
*/ |
||||
|
void SampleDataMgr_changeToExtMode() { |
||||
|
ZLOGI("change to ext mode"); |
||||
|
if (Board_sdcardGetConnectTo() == kConnectToInternal) { |
||||
|
read_file_info(); |
||||
|
} |
||||
|
Board_sdcardConnectToExt(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @brief 打开文件 |
||||
|
* |
||||
|
* @param filename |
||||
|
* @param flag |
||||
|
* @return int32_t |
||||
|
*/ |
||||
|
|
||||
|
static FIL m_default_file_handler; |
||||
|
static bool m_is_open; |
||||
|
|
||||
|
int32_t SampleDataMgr_open(sample_data_filename_t* filename, wrflag_t flag) { |
||||
|
if (flag == kwrflag_write_only) { |
||||
|
FRESULT ff_result = f_open(&m_default_file_handler, (const TCHAR*)"0.bin", FA_CREATE_ALWAYS | FA_READ | FA_WRITE); |
||||
|
ZASSERT(ff_result == FR_OK); |
||||
|
m_is_open = true; |
||||
|
return 1; |
||||
|
} else { |
||||
|
FRESULT ff_result = f_open(&m_default_file_handler, (const TCHAR*)"0.bin", FA_READ); |
||||
|
if (ff_result != FR_OK) { |
||||
|
return -1; |
||||
|
} |
||||
|
m_is_open = true; |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
int32_t SampleDataMgr_close(int32_t fd) { |
||||
|
ZASSERT(m_is_open); |
||||
|
FRESULT ff_result = f_close(&m_default_file_handler); |
||||
|
ZASSERT(ff_result == FR_OK); |
||||
|
m_is_open = false; |
||||
|
return 0; |
||||
|
} |
||||
|
int32_t SampleDataMgr_write(int32_t fd, const uint8_t* data, int32_t size) { |
||||
|
ZASSERT(m_is_open); |
||||
|
UINT write_size; |
||||
|
FRESULT ff_result = f_write(&m_default_file_handler, data, size, &write_size); |
||||
|
ZASSERT(ff_result == FR_OK); |
||||
|
return write_size; |
||||
|
} |
||||
|
int32_t SampleDataMgr_read(int32_t fd, uint8_t* data, int32_t size) { |
||||
|
ZASSERT(m_is_open); |
||||
|
UINT read_size; |
||||
|
FRESULT ff_result = f_read(&m_default_file_handler, data, size, &read_size); |
||||
|
ZASSERT(ff_result == FR_OK); |
||||
|
return read_size; |
||||
|
} |
||||
|
uint32_t SampleDataMgr_getFileSizeByFd(int32_t fd) { |
||||
|
ZASSERT(m_is_open); |
||||
|
return f_size(&m_default_file_handler); |
||||
|
} |
||||
|
|
||||
|
int32_t SampleDataMgr_deleteFile(sample_data_filename_t* filename) { |
||||
|
if (Board_sdcardGetConnectTo() == kConnectToExt) { |
||||
|
/** |
||||
|
* @brief |
||||
|
* 由于设备空闲阶段,SD卡连接的是外部读卡器,所以无法删除文件 |
||||
|
*/ |
||||
|
ZLOGW("unsupport now"); |
||||
|
return 0; |
||||
|
} |
||||
|
f_unlink((const TCHAR*)"0.bin"); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
sample_data_fileinfo_list_t* SampleDataMgr_getFileinfoList() { // |
||||
|
return &m_sample_fileinfo_list; |
||||
|
} |
||||
|
bool SampleDataMgr_storageIsFull() { return m_sample_fileinfo_list.count >= FILE_MAX_COUNT; } |
||||
|
int32_t SampleDataMgr_getFileNum() { return m_sample_fileinfo_list.count; } |
@ -0,0 +1,78 @@ |
|||||
|
/** |
||||
|
* @file sample_data_manager_service.h |
||||
|
* @author zhaohe (h_zhaohe@domain.com) |
||||
|
* @brief 采样数据存储服务 |
||||
|
* @version 0.1 |
||||
|
* @date 2024-02-01 |
||||
|
* |
||||
|
* @copyright Copyright (c) 2024 |
||||
|
* |
||||
|
*/ |
||||
|
#pragma once |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
|
||||
|
#include "board/board.h" |
||||
|
|
||||
|
typedef struct { |
||||
|
uint8_t year; // from 2000 |
||||
|
uint8_t month; // 1-12 |
||||
|
uint8_t day; // 1-31 |
||||
|
uint8_t hour; // 0-23 |
||||
|
uint8_t min; // 0-59 |
||||
|
uint8_t sec; // 0-59 |
||||
|
uint8_t placeholder[2]; |
||||
|
} sample_data_filename_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
uint8_t filename[8]; |
||||
|
int32_t fileuuid; |
||||
|
int32_t size; |
||||
|
} sample_data_fileinfo_t; |
||||
|
|
||||
|
typedef enum { |
||||
|
kwrflag_read_only, |
||||
|
kwrflag_write_only, |
||||
|
} wrflag_t; |
||||
|
|
||||
|
typedef struct { |
||||
|
sample_data_fileinfo_t* fileinfo[FILE_MAX_COUNT]; |
||||
|
int count; |
||||
|
} sample_data_fileinfo_list_t; |
||||
|
|
||||
|
/** |
||||
|
* @brief 文件驱动管理 |
||||
|
*/ |
||||
|
void SampleDataMgr_init(); |
||||
|
void SampleDataMgr_loadDriver(); |
||||
|
void SampleDataMgr_unloadDriver(); |
||||
|
/******************************************************************************* |
||||
|
* 模式切换操作 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
/** |
||||
|
* @brief 存储器连接单片机 |
||||
|
*/ |
||||
|
void SampleDataMgr_changeToLocalMode(); |
||||
|
/** |
||||
|
* @brief 存储器连接外部typec |
||||
|
*/ |
||||
|
void SampleDataMgr_changeToExtMode(); |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* FILE_OPERATION * |
||||
|
*******************************************************************************/ |
||||
|
int32_t SampleDataMgr_open(sample_data_filename_t* filename, wrflag_t flag); |
||||
|
int32_t SampleDataMgr_close(int32_t fd); |
||||
|
int32_t SampleDataMgr_write(int32_t fd, const uint8_t* data, int32_t size); |
||||
|
int32_t SampleDataMgr_read(int32_t fd, uint8_t* data, int32_t size); |
||||
|
uint32_t SampleDataMgr_getFileSizeByFd(int32_t fd); |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 文件管理操作 * |
||||
|
*******************************************************************************/ |
||||
|
int32_t SampleDataMgr_deleteFile(sample_data_filename_t* filename); |
||||
|
sample_data_fileinfo_list_t* SampleDataMgr_getFileinfoList(); |
||||
|
bool SampleDataMgr_storageIsFull(); |
||||
|
int32_t SampleDataMgr_getFileNum(); |
@ -0,0 +1 @@ |
|||||
|
Subproject commit ae9a76be52669663d773370339d6a0608df4a9d4 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue