diff --git a/include/zble_module.h b/include/zble_module.h new file mode 100644 index 0000000..3c42aa1 --- /dev/null +++ b/include/zble_module.h @@ -0,0 +1,20 @@ +#pragma once +#include + +/** + * @brief + */ + +typedef void (*on_service_init_t)(void); + +typedef struct { + const char* deviceName; + on_service_init_t on_service_init; +} zble_module_cfg_t; + +void zble_module_init(zble_module_cfg_t* cfg); + +void zble_module_start_adv(); +void zble_module_stop_adv(); + +int32_t zble_module_get_mtu_size(); \ No newline at end of file diff --git a/include/zdatachannel_service.h b/include/zdatachannel_service.h new file mode 100644 index 0000000..7015f3a --- /dev/null +++ b/include/zdatachannel_service.h @@ -0,0 +1,96 @@ +#ifndef ZDATACHANNEL_H__ +#define ZDATACHANNEL_H__ + +#include +#include + +#include "ble.h" +#include "ble_link_ctx_manager.h" +#include "ble_srv_common.h" +#include "nrf_sdh_ble.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a ble_nus instance. + * + * @param _name Name of the instance. + * @param[in] _nus_max_clients Maximum number of NUS clients connected at a time. + * @hideinitializer + */ +#define ZDATACHANNEL_DEF(_name, _ble_observer_prio, _nus_max_clients) \ + static zdatachannel_t _name; \ + NRF_SDH_BLE_OBSERVER(_name##_obs, _ble_observer_prio, zdatachannel_on_ble_evt, &_name) + +#define OPCODE_LENGTH 1 +#define HANDLE_LENGTH 2 + +/**@brief Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */ +#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0) +#define ZDATACHANNEL_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH) +#else +#define ZDATACHANNEL_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH) +#warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined. +#endif + +/**@brief Nordic UART Service event types. */ +typedef enum { + ZDATACHANNEL_EVT_RX_DATA, /**< Data received. */ +} zdatachannel_evt_type_t; + +typedef struct zdatachannel_s zdatachannel_t; + +typedef struct { + uint8_t const* p_data; /**< A pointer to the buffer with received data. */ + uint16_t length; /**< Length of received data. */ +} zdatachannel_evt_rx_data_t; + +typedef struct { + zdatachannel_evt_type_t type; /**< Event type. */ + union { + zdatachannel_evt_rx_data_t rx_data; /**< @ref ZDATACHANNEL_EVT_RX_DATA event data. */ + } params; +} zdatachannel_evt_t; + +typedef void (*zdatachannel_data_handler_t)(zdatachannel_evt_t* p_evt); + +typedef struct { + zdatachannel_data_handler_t data_handler; +} zdatachannel_init_t; + +struct zdatachannel_s { + uint8_t uuid_type; /**< UUID type for Nordic UART Service Base UUID. */ + uint16_t service_handle; /**< Handle of Nordic UART Service (as provided by the SoftDevice). */ + ble_gatts_char_handles_t cmd_tx_handles; /**< 指令发送句柄 */ + ble_gatts_char_handles_t cmd_rx_handles; /**< 指令接收句柄 */ + ble_gatts_char_handles_t datablock_tx_handles; /**< 数据块发送句柄 */ + zdatachannel_data_handler_t data_handler; /**< Event handler to be called for handling received data. */ + + // 状态 + int16_t conn_handle; + bool cmd_tx_channel_is_notification_enabled; + bool datablock_tx_channel_is_notification_enabled; +}; + +uint32_t zdatachannel_init(zdatachannel_t* p_nus, zdatachannel_init_t const* p_nus_init); +void zdatachannel_on_ble_evt(ble_evt_t const* p_ble_evt, void* p_context); +bool zdatachannel_is_connected(); + +uint32_t zdatachannel_data_send(uint8_t* p_data, uint16_t* p_length); +static inline uint32_t zdatachannel_data_send2(uint8_t* p_data, uint16_t p_length){ + return zdatachannel_data_send(p_data, &p_length); +} +uint32_t zdatachannel_block_data_send(uint8_t* p_data, uint16_t* p_length); +static inline uint32_t zdatachannel_block_data_send2(uint8_t* p_data, uint16_t p_length){ + return zdatachannel_block_data_send(p_data, &p_length); +} + +#ifdef __cplusplus +} +#endif + +#endif // ZDATACHANNEL_H__ + +/** @} */ diff --git a/include/znordic_device_info_mgr.h b/include/znordic_device_info_mgr.h new file mode 100644 index 0000000..89895ff --- /dev/null +++ b/include/znordic_device_info_mgr.h @@ -0,0 +1,13 @@ +#pragma once +#include "znordic.h" + +typedef struct { + uint8_t sn[14]; +} sn_t; + + +void device_info_read_sn(sn_t *sn); +uint16_t device_info_read_blestack_version(void); +uint16_t device_info_read_bootloader_version(void); +uint16_t device_info_read_firmware_version(void); +uint16_t device_info_read_hardware_version(void); \ No newline at end of file diff --git a/src/zble_module.c b/src/zble_module.c new file mode 100644 index 0000000..b89e6c8 --- /dev/null +++ b/src/zble_module.c @@ -0,0 +1,237 @@ + + +#include "zble_module.h" + +#include +#include + +#include "znordic.h" +/******************************************************************************* + * 广播包配?? * + *******************************************************************************/ +#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */ +#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */ +#define SLAVE_LATENCY 0 /**< Slave latency. */ +#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */ +#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */ +static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ + {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; +#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */ +#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ +BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ + +/******************************************************************************* + * GATT配置 * + *******************************************************************************/ +NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ + +/******************************************************************************* + * 连接参数配置 * + *******************************************************************************/ +#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ +#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ +#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ + +/******************************************************************************* + * CODE * + *******************************************************************************/ + +static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< 当前连接句柄 */ +static uint16_t m_mtu_size = BLE_GATT_ATT_MTU_DEFAULT - 3; + +static void ble_evt_handler(ble_evt_t const* p_ble_evt, void* p_context) { + uint32_t err_code; + switch (p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + break; + + case BLE_GAP_EVT_DISCONNECTED: + m_conn_handle = BLE_CONN_HANDLE_INVALID; + break; + + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { + NRF_LOG_DEBUG("PHY update request."); + ble_gap_phys_t const phys = { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); + ZERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + // Pairing not supported + err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + // No system attributes have been stored. + err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTC_EVT_TIMEOUT: + // Disconnect on GATT Client timeout event. + err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTS_EVT_TIMEOUT: + // Disconnect on GATT Server timeout event. + err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + ZERROR_CHECK(err_code); + break; + + default: + // No implementation needed. + break; + } +} +static void gatt_evt_handler(nrf_ble_gatt_t* p_gatt, nrf_ble_gatt_evt_t const* p_evt) { + /******************************************************************************* + * MTU SIZE 更新 * + *******************************************************************************/ + if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { + m_mtu_size = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; + NRF_LOG_DEBUG("ATT MTU exchange completed. central %d peripheral %d", p_gatt->att_mtu_desired_central, p_gatt->att_mtu_desired_periph); + } +} +static void on_conn_params_evt(ble_conn_params_evt_t* p_evt) { + uint32_t err_code; + if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { + err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); + ZERROR_CHECK(err_code); + } +} +static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } +static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { + switch (ble_adv_evt) { + case BLE_ADV_EVT_FAST: + // err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); + // ZERROR_CHECK(err_code); + break; + case BLE_ADV_EVT_IDLE: + // sleep_mode_enter(); + break; + default: + break; + } +} + +void zble_module_start_adv() { + uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); + ZERROR_CHECK(err_code); +} +void zble_module_stop_adv() { + uint32_t err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle); + ZERROR_CHECK(err_code); +} + +/******************************************************************************* + * INIT * + *******************************************************************************/ +void zble_module_init(zble_module_cfg_t* cfg) { + /** + * @brief + * 初始化蓝牙协议栈,并注册蓝牙事件处理函数,固定代码,勿修?? + */ + { NRF_SDH_BLE_OBSERVER(m_ble_observer, 3, ble_evt_handler, NULL); } + /******************************************************************************* + * GAP初始?? * + *******************************************************************************/ + { + uint32_t err_code; + ble_gap_conn_params_t gap_conn_params; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t*)cfg->deviceName, strlen(cfg->deviceName)); + ZERROR_CHECK(err_code); + + memset(&gap_conn_params, 0, sizeof(gap_conn_params)); + + gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; + gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; + gap_conn_params.slave_latency = SLAVE_LATENCY; + gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; + + err_code = sd_ble_gap_ppcp_set(&gap_conn_params); + ZERROR_CHECK(err_code); + } + + /******************************************************************************* + * GATT 初始?? * + *******************************************************************************/ + { + ret_code_t err_code; + + err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); + ZERROR_CHECK(err_code); + + err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); + ZERROR_CHECK(err_code); + } + + /******************************************************************************* + * 蓝牙服务初始?? * + *******************************************************************************/ + { + if (cfg->on_service_init) cfg->on_service_init(); + } + + /******************************************************************************* + * 广播初始?? * + *******************************************************************************/ + { + uint32_t err_code; + ble_advertising_init_t init; + + memset(&init, 0, sizeof(init)); + + init.advdata.name_type = BLE_ADVDATA_FULL_NAME; + init.advdata.include_appearance = false; + // init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; + init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + + init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); + init.srdata.uuids_complete.p_uuids = m_adv_uuids; + + init.config.ble_adv_fast_enabled = true; + init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; + init.config.ble_adv_fast_timeout = 0; + init.evt_handler = on_adv_evt; + + err_code = ble_advertising_init(&m_advertising, &init); + ZERROR_CHECK(err_code); + + ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); + } + /******************************************************************************* + * 连接参数初始?? * + *******************************************************************************/ + { + uint32_t err_code; + ble_conn_params_init_t cp_init; + + memset(&cp_init, 0, sizeof(cp_init)); + + cp_init.p_conn_params = NULL; + cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; + cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; + cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; + cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; + cp_init.disconnect_on_fail = false; + cp_init.evt_handler = on_conn_params_evt; + cp_init.error_handler = conn_params_error_handler; + + err_code = ble_conn_params_init(&cp_init); + ZERROR_CHECK(err_code); + } + + // zble_module_start_adv(); +} + +int32_t zble_module_get_mtu_size() { return m_mtu_size; } \ No newline at end of file diff --git a/src/zdatachannel_service.c b/src/zdatachannel_service.c new file mode 100644 index 0000000..a11367d --- /dev/null +++ b/src/zdatachannel_service.c @@ -0,0 +1,225 @@ +#include "zdatachannel_service.h" + +#include "ble.h" +#include "ble_srv_common.h" +#include "nrf_log.h" +#include "sdk_common.h" +#include "znordic.h" + +#define ZDATACHANNEL_UUID_NUS_SERVICE 0x0001 /**< The UUID of the Nordic UART Service. */ +#define ZDATACHANNEL_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */ +#define ZDATACHANNEL_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */ +#define ZDATACHANNEL_DATABLOCK_TX_CHARACTERISTIC 0x0004 /**< The UUID of the RX Characteristic. */ + +#define ZDATACHANNEL_MAX_RX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ +#define ZDATACHANNEL_MAX_TX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ +#define ZDATACHANNEL_DATABLOCK_TX_CHAR_LEN ZDATACHANNEL_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ + +#define NUS_BASE_UUID \ + { \ + { 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E } \ + } /**< Used vendor specific UUID. */ + +static zdatachannel_t *p_datachannel; +static uint32_t m_mtusize; + +static bool notification_enable(uint16_t conn_handle, uint16_t cccd_handle) { + ret_code_t err_code; + ble_gatts_value_t gatts_val; + uint8_t cccd_value[2]; + memset(&gatts_val, 0, sizeof(ble_gatts_value_t)); + gatts_val.p_value = cccd_value; + gatts_val.len = sizeof(cccd_value); + gatts_val.offset = 0; + err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &gatts_val); + if ((err_code == NRF_SUCCESS) && ble_srv_is_notification_enabled(gatts_val.p_value)) { + return true; + } + return false; +} + +/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_write(zdatachannel_t *p_nus, ble_evt_t const *p_ble_evt) { + zdatachannel_evt_t evt; + ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + memset(&evt, 0, sizeof(zdatachannel_evt_t)); + + if ((p_evt_write->handle == p_nus->cmd_tx_handles.cccd_handle) && (p_evt_write->len == 2)) { + if (ble_srv_is_notification_enabled(p_evt_write->data)) { + p_nus->cmd_tx_channel_is_notification_enabled = true; + } else { + p_nus->cmd_tx_channel_is_notification_enabled = false; + } + } else if ((p_evt_write->handle == p_nus->datablock_tx_handles.cccd_handle) && (p_evt_write->len == 2)) { + if (ble_srv_is_notification_enabled(p_evt_write->data)) { + p_nus->datablock_tx_channel_is_notification_enabled = true; + } else { + p_nus->datablock_tx_channel_is_notification_enabled = false; + } + } else if ((p_evt_write->handle == p_nus->cmd_rx_handles.value_handle) && (p_nus->data_handler != NULL)) { + evt.type = ZDATACHANNEL_EVT_RX_DATA; + evt.params.rx_data.p_data = p_evt_write->data; + evt.params.rx_data.length = p_evt_write->len; + + p_nus->data_handler(&evt); + } else { + // Do Nothing. This event is not relevant for this service. + } +} + +void zdatachannel_on_ble_evt(ble_evt_t const *p_ble_evt, void *p_context) { + if ((p_context == NULL) || (p_ble_evt == NULL)) { + return; + } + + zdatachannel_t *p_nus = (zdatachannel_t *)p_context; + + switch (p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + ZLOGI("BLE_GAP_EVT_CONNECTED"); + p_nus->conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + p_nus->cmd_tx_channel_is_notification_enabled = notification_enable(p_ble_evt->evt.gap_evt.conn_handle, p_nus->cmd_tx_handles.cccd_handle); + p_nus->datablock_tx_channel_is_notification_enabled = notification_enable(p_ble_evt->evt.gap_evt.conn_handle, p_nus->cmd_tx_handles.cccd_handle); + break; + case BLE_GAP_EVT_DISCONNECTED: + ZLOGI("BLE_GAP_EVT_DISCONNECTED"); + p_nus->conn_handle = BLE_CONN_HANDLE_INVALID; + // ZLOGI("-----%d %d", p_datachannel->conn_handle, BLE_CONN_HANDLE_INVALID); + break; + case BLE_GATTS_EVT_WRITE: + on_write(p_nus, p_ble_evt); + break; + default: + // No implementation needed. + break; + } +} + +bool zdatachannel_is_connected() { + // ZLOGI("%d %d", p_datachannel->conn_handle, BLE_CONN_HANDLE_INVALID); + return p_datachannel->conn_handle != (int16_t)BLE_CONN_HANDLE_INVALID; +} + +uint32_t zdatachannel_init(zdatachannel_t *p_nus, zdatachannel_init_t const *p_nus_init) { + p_datachannel = p_nus; + p_datachannel->conn_handle = BLE_CONN_HANDLE_INVALID; + ret_code_t err_code; + ble_uuid_t ble_uuid; + ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; + ble_add_char_params_t add_char_params; + + VERIFY_PARAM_NOT_NULL(p_nus); + VERIFY_PARAM_NOT_NULL(p_nus_init); + + // Initialize the service structure. + p_nus->data_handler = p_nus_init->data_handler; + + /**@snippet [Adding proprietary Service to the SoftDevice] */ + // Add a custom base UUID. + err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); + VERIFY_SUCCESS(err_code); + + ble_uuid.type = p_nus->uuid_type; + ble_uuid.uuid = ZDATACHANNEL_UUID_NUS_SERVICE; + + // Add the service. + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_nus->service_handle); + /**@snippet [Adding proprietary Service to the SoftDevice] */ + VERIFY_SUCCESS(err_code); + + // Add the RX Characteristic. + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = ZDATACHANNEL_RX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = ZDATACHANNEL_MAX_RX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.write = 1; + add_char_params.char_props.write_wo_resp = 1; + + add_char_params.read_access = SEC_NO_ACCESS; + add_char_params.write_access = SEC_OPEN; + + VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->cmd_rx_handles)); + + // Add the TX Characteristic. + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = ZDATACHANNEL_TX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = ZDATACHANNEL_MAX_TX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.cccd_write_access = SEC_OPEN; + + VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->cmd_tx_handles)); + + // Add the TX Characteristic. + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = ZDATACHANNEL_DATABLOCK_TX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = ZDATACHANNEL_DATABLOCK_TX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.cccd_write_access = SEC_OPEN; + + VERIFY_SUCCESS(characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->datablock_tx_handles)); + + return NRF_SUCCESS; + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ +} + +uint32_t zdatachannel_data_send(uint8_t *p_data, uint16_t *p_length) { + ble_gatts_hvx_params_t hvx_params; + + if (!p_datachannel->cmd_tx_channel_is_notification_enabled) { + return NRF_ERROR_INVALID_STATE; + } + + if (*p_length > ZDATACHANNEL_MAX_DATA_LEN) { + return NRF_ERROR_INVALID_PARAM; + } + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_datachannel->cmd_tx_handles.value_handle; + hvx_params.p_data = p_data; + hvx_params.p_len = p_length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + + return sd_ble_gatts_hvx(p_datachannel->conn_handle, &hvx_params); +} + +uint32_t zdatachannel_block_data_send(uint8_t *p_data, uint16_t *p_length) { + ble_gatts_hvx_params_t hvx_params; + + if (!p_datachannel->datablock_tx_channel_is_notification_enabled) { + return NRF_ERROR_INVALID_STATE; + } + + if (*p_length > ZDATACHANNEL_MAX_DATA_LEN) { + return NRF_ERROR_INVALID_PARAM; + } + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_datachannel->datablock_tx_handles.value_handle; + hvx_params.p_data = p_data; + hvx_params.p_len = p_length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + + return sd_ble_gatts_hvx(p_datachannel->conn_handle, &hvx_params); +} diff --git a/src/znordic.c b/src/znordic.c index 81a466c..8211d35 100644 --- a/src/znordic.c +++ b/src/znordic.c @@ -107,9 +107,9 @@ int16_t znrf_adc_channel_read_val(uint16_t channel) { /******************************************************************************* * RTC * *******************************************************************************/ -#define DEFAULT_TIME (1704038400 + 8 * 60 * 60) // 2024/01/01/00:00:00 +#define DEFAULT_TIME (1704038400 + 8 * 60 * 60) // 2024/01/01/00:00:00 volatile uint32_t g_timestamp = 0; -volatile uint32_t g_power_on_rtc = (DEFAULT_TIME); +volatile uint32_t g_power_on_rtc = (DEFAULT_TIME); // static uint8_t s_timeCount1second = 0; uint32_t znordic_getpower_on_ms() { @@ -195,4 +195,24 @@ const char* hex2str(const uint8_t* data, uint16_t len) { buf[i * 2 + 1] = (data[i] & 0x0f) + '0'; } return buf; +} + +/******************************************************************************* + * FATFS * + *******************************************************************************/ +static DWORD get_fattime_0(uint32_t year, uint32_t month, uint32_t day, uint32_t hour, uint32_t min, uint32_t sec) { + // return ((DWORD)(year - 1980) << 25 | (DWORD)month << 21 | (DWORD)day << 16); + DWORD fattime = 0; + fattime |= ((DWORD)(year - 1980) << 25); // 年份从1980年开始 + fattime |= ((DWORD)(month + 1) << 21); // 月份范围是1-12 + fattime |= ((DWORD)day << 16); // 日 + fattime |= ((DWORD)hour << 11); // 时 + fattime |= ((DWORD)min << 5); // 分 + fattime |= ((DWORD)sec / 2); // 秒,以2秒为单位 + + return fattime; +} + +DWORD get_fattime(void) { + return get_fattime_0(2024, 1, 23, 23, 29, 31); } \ No newline at end of file diff --git a/src/znordic_device_info_mgr.c b/src/znordic_device_info_mgr.c new file mode 100644 index 0000000..e5cb744 --- /dev/null +++ b/src/znordic_device_info_mgr.c @@ -0,0 +1,10 @@ +#include "device_info_mgr.h" + +void device_info_read_sn(sn_t* sn) { + const char* sn_str = "M1002000000001"; + memcpy(sn->sn, sn_str, sizeof(sn->sn)); +} +uint16_t device_info_read_blestack_version(void) { return 1; } +uint16_t device_info_read_bootloader_version(void) { return 1; } +uint16_t device_info_read_firmware_version(void) { return 1; } +uint16_t device_info_read_hardware_version(void) { return 1; } \ No newline at end of file