diff options
Diffstat (limited to 'src/sample/io_sample/ADC')
52 files changed, 12608 insertions, 0 deletions
diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/ancs.c b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/ancs.c new file mode 100644 index 0000000..ac3254e --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/ancs.c @@ -0,0 +1,662 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ancs.c + * @brief This file handles ANCS Client routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#if F_BT_ANCS_CLIENT_SUPPORT +#include <trace.h> +#include <string.h> +#include <os_msg.h> +#include <os_mem.h> +#include <ancs.h> +#include <ancs_client.h> + +/** @defgroup PERIPH_ANCS Peripheral ANCS + * @brief Apple ANCS service modulization + * @{ + */ +/*============================================================================* + * Types + *============================================================================*/ +typedef struct +{ + uint8_t m_parse_state; + uint8_t app_type; + uint16_t current_len; + void *ancs_queue_handle; + uint8_t *ptr; + T_DS_NOTIFICATION_ATTR notification_attr; +#if F_BT_ANCS_GET_APP_ATTR + T_DS_APP_ATTR app_attr; +#endif +} T_APP_ANCS_LINK; + +/*============================================================================* + * Variables + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Variables ANCS Exported Variables + * @brief app register ancs client to upperstack, and return ancs client id + * @{ + */ +T_CLIENT_ID ancs_client; /**< ancs client id*/ + +T_APP_ANCS_LINK *ancs_link_table; +uint8_t ancs_link_number; + +/** End of PERIPH_ANCS_Exported_Variables + * @} + */ +extern void *evt_queue_handle; //!< Event queue handle +extern void *io_queue_handle; //!< IO queue handle +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +void ancs_send_msg_to_app(uint8_t conn_id) +{ + T_IO_MSG io_msg; + uint8_t event = EVENT_IO_TO_APP; + io_msg.type = IO_MSG_TYPE_ANCS; + io_msg.subtype = 0; + io_msg.u.param = conn_id; + + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail1"); + } + else if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail2"); + } +} + +void app_handle_notification_attribute_data(T_APP_ANCS_LINK *p_ancs_link) +{ + if (p_ancs_link->notification_attr.attribute_id != DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + uint8_t *p_value = p_ancs_link->notification_attr.data; + +#if F_BT_ANCS_APP_FILTER + //filter QQ , wechat , short message and incoming call + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: app identifiter %s", TRACE_STRING(p_value)); +#endif + //wechat + if (0 == memcmp(p_value, "com.tencent.xin", 16)) + { + p_ancs_link->app_type = 1; + } + else if (0 == memcmp(p_value, "com.apple.MobileSMS", 20)) + { + p_ancs_link->app_type = 2; + } + else if (0 == memcmp(p_value, "com.apple.mobilephone", 22)) + { + p_ancs_link->app_type = 3; + } + else if (0 == memcmp(p_value, "com.tencent.mqq", 16)) + { + p_ancs_link->app_type = 4; + } + else if (0 == memcmp(p_value, "com.tencent.qq", 15)) + { + p_ancs_link->app_type = 5; + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_MESSAGE) + { + if (p_ancs_link->app_type == 2) + { + APP_PRINT_INFO1("MobileSMS: message %s", TRACE_STRING(p_value)); + } + else if (p_ancs_link->app_type == 5) + { + APP_PRINT_INFO1("QQ: message %s", TRACE_STRING(p_value)); + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_DATE) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: date %s", TRACE_STRING(p_value)); +#endif + } +#endif + } + else/* All attributes has been parased*/ + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO0("parse notify attr: parse done"); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } +} + +void app_parse_notification_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_NOTIFICATION_COMMAND_ID: + p_ancs_link->notification_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID1; + break; + + case DS_PARSE_UID1: + p_ancs_link->notification_attr.notification_uid[0] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID2; + break; + + case DS_PARSE_UID2: + p_ancs_link->notification_attr.notification_uid[1] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID3; + break; + + case DS_PARSE_UID3: + p_ancs_link->notification_attr.notification_uid[2] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID4; + break; + + case DS_PARSE_UID4: + p_ancs_link->notification_attr.notification_uid[3] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + break; + + case DS_PARSE_ATTRIBUTE_ID: + p_ancs_link->notification_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_ATTRIBUTE_LEN1: + p_ancs_link->notification_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_ATTRIBUTE_LEN2: + p_ancs_link->notification_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->notification_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse notify attr: attribute_id %d, attribute_len %d", + p_ancs_link->notification_attr.attribute_id, + p_ancs_link->notification_attr.attribute_len + ); +#endif + if (p_ancs_link->notification_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + } + if (p_ancs_link->notification_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse notify attr: error, attribute_len %d > max length %d", + p_ancs_link->notification_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } + break; + + case DS_PARSE_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->notification_attr.attribute_len) + { + /*An attribute is always a string whose length in bytes is provided in the tuple but that is not NULL-terminated.*/ + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: data %b", + TRACE_BINARY(p_ancs_link->notification_attr.attribute_len, + p_ancs_link->notification_attr.data)); +#endif + app_handle_notification_attribute_data(p_ancs_link); + } + break; + } + } +} + +#if F_BT_ANCS_GET_APP_ATTR +void app_parse_app_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_APP_COMMAND_ID: + p_ancs_link->app_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_START; + break; + + case DS_PARSE_APP_IDENTIFIER_START: + if (p_data[i] == 0x00) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_END; + + if (i + 1 == len) + { + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + else + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + } + + } + break; + + case DS_PARSE_APP_ATTRIBUTE_ID: + p_ancs_link->app_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN1: + p_ancs_link->app_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN2: + p_ancs_link->app_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->app_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse app attr: attribute_id %d, attribute_len %d", + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len + ); +#endif + if (p_ancs_link->app_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + + } + if (p_ancs_link->app_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse app attr: error, attribute_len %d > max length %d", + p_ancs_link->app_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + break; + + case DS_PARSE_APP_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->app_attr.attribute_len) + { + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO4("parse app attr: command_id 0x%x, attribute_id 0x%x, attribute_len %d, data %s", + p_ancs_link->app_attr.command_id, + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len, + TRACE_STRING(p_ancs_link->app_attr.data)); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + + } + break; + } + } +} +#endif + +/** + * @brief Parse ancs data source notification + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @param[in] len data length + * @return void + */ +void app_parse_data_soucre_notifications(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + APP_PRINT_INFO2("ANCS_FROM_DATA_SOURCE: conn_id %d, len =%d", conn_id, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("data = %b", TRACE_BINARY(len, p_data)); +#endif + T_APP_ANCS_LINK *p_ancs_link = &ancs_link_table[conn_id]; + +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("m_parse_state %d", p_ancs_link->m_parse_state); +#endif + if (p_ancs_link->m_parse_state == DS_PARSE_NOT_START) + { + if (len >= 1 && p_data[0] == CP_CMD_ID_GET_NOTIFICATION_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_NOTIFICATION_COMMAND_ID; + } +#if F_BT_ANCS_GET_APP_ATTR + else if (len >= 1 && p_data[0] == CP_CMD_ID_GET_APP_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_APP_COMMAND_ID; + } +#endif + } + + if (p_ancs_link->m_parse_state < DS_PARSE_GET_APP_COMMAND_ID) + { + app_parse_notification_attribute(p_ancs_link, p_data, len); + } +#if F_BT_ANCS_GET_APP_ATTR + else + { + app_parse_app_attribute(p_ancs_link, p_data, len); + } +#endif +} + +void app_parse_notification_source_data(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + if (8 == len) + { + T_NS_DATA ns_data; + + memcpy(&ns_data, p_data, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO5("app_parse_notification_source_data: event_id %d, event_flags 0x%02x, category_id %d, category_count %d, notification_uid 0x%08x", + ns_data.event_id, + ns_data.event_flags, + ns_data.category_id, + ns_data.category_count, + ns_data.notification_uid + ); + APP_PRINT_INFO5("event_flags: slient %d, important %d, pre existing %d, positive action %d, negative action %d ", + ns_data.event_flags & NS_EVENT_FLAG_SILENT, + ns_data.event_flags & NS_EVENT_FLAG_IMPORTANT, + ns_data.event_flags & NS_EVENT_FLAG_PRE_EXISTING, + ns_data.event_flags & NS_EVENT_FLAG_POSITIVE_ACTION, + ns_data.event_flags & NS_EVENT_FLAG_NEGATIVE_ACTION + ); +#endif + //you can filter by category_id here, for demo purpose, we didn't filter any CategoryID here. +#if F_BT_ANCS_APP_FILTER + //filter social and other category & phone category & email category + if (ns_data.category_id == NS_CATEGORY_ID_SOCIAL || + ns_data.category_id == NS_CATEGORY_ID_OTHER || + ns_data.category_id == NS_CATEGORY_ID_INCOMING_CALL || + ns_data.category_id == NS_CATEGORY_ID_EMAIL) + { +#endif + if (ns_data.event_id != NS_EVENT_ID_NOTIFICATION_REMOVED) + { + uint32_t msg_num; + T_ANCS_MSG ancs_msg; + uint8_t attr_id_list[14]; + uint8_t cur_index = 0; + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_SUB_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_DATE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL; + + os_msg_queue_peek(ancs_link_table[conn_id].ancs_queue_handle, &msg_num); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("app_parse_notification_source_data: msg_num %d", msg_num); +#endif + if (msg_num == 0) + { + if (ancs_get_notification_attr(conn_id, ns_data.notification_uid, attr_id_list, + cur_index) == true) + { + return; + } + } + + ancs_msg.type = ANCS_MSG_TYPE_GET_NOTIFI_ATTR; + ancs_msg.data.notifi_attr.conn_id = conn_id; + ancs_msg.data.notifi_attr.notification_uid = ns_data.notification_uid; + ancs_msg.data.notifi_attr.attribute_ids_len = cur_index; + memcpy(ancs_msg.data.notifi_attr.attribute_ids, attr_id_list, cur_index); + if (os_msg_send(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_ERROR0("app_parse_notification_source_data: discard, msg queue is full"); + } + } +#if F_BT_ANCS_APP_FILTER + } +#endif + } +} + +/** + * @brief Ancs client callback handle message from upperstack + * @param[in] client_id client identifier + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @return @ref T_APP_RESULT + */ +T_APP_RESULT ancs_client_cb(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_ANCS_CB_DATA *p_cb_data = (T_ANCS_CB_DATA *)p_data; + + switch (p_cb_data->cb_type) + { + case ANCS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_cb_data->cb_content.disc_state) + { + case DISC_ANCS_DONE: + APP_PRINT_INFO0("ANCS BLE Client CB: discover procedure done."); + ancs_set_data_source_notify(conn_id, true); + break; + case DISC_ANCS_FAILED: + APP_PRINT_ERROR0("ANCS BLE Client CB: discover request failed."); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (p_cb_data->cb_content.notify_data.type) + { + case ANCS_FROM_DATA_SOURCE:; + app_parse_data_soucre_notifications(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + case ANCS_FROM_NOTIFICATION_SOURCE: + APP_PRINT_INFO2("ANCS_FROM_NOTIFICATION_SOURCE: conn_id %d, length %d", + conn_id, p_cb_data->cb_content.notify_data.value_size); + app_parse_notification_source_data(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_WRITE_RESULT: + { + if (p_cb_data->cb_content.write_result.cause != ATT_SUCCESS) + { + APP_PRINT_ERROR1("ANCS_CLIENT_CB_TYPE_WRITE_RESULT: Failed, cause 0x%x", + p_cb_data->cb_content.write_result.cause); + } + switch (p_cb_data->cb_content.write_result.type) + { + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE"); + break; + + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE"); + ancs_set_notification_source_notify(conn_id, true); + break; + case ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_CONTROL_POINT: + APP_PRINT_INFO0("ANCS_WRITE_CONTROL_POINT"); +#if F_BT_ANCS_CLIENT_DEBUG + if (p_cb_data->cb_content.write_result.cause == 0x4A0) + { + APP_PRINT_ERROR0("The commandID was not recognized by the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A1) + { + APP_PRINT_ERROR0("The command was improperly formatted."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A2) + { + APP_PRINT_ERROR0("One of the parameters (for example, the NotificationUID) does not refer to an existing object on the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A3) + { + APP_PRINT_ERROR0("The action was not performed."); + } +#endif + ancs_send_msg_to_app(conn_id); + break; + + default: + break; + } + } + break; + + case ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: + { + T_ANCS_MSG ancs_msg; + void *ancs_queue_handle = ancs_link_table[conn_id].ancs_queue_handle; + APP_PRINT_INFO1("ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: conn_id = 0x%x", conn_id); + memset(&ancs_link_table[conn_id], 0, sizeof(T_APP_ANCS_LINK)); + ancs_link_table[conn_id].ancs_queue_handle = ancs_queue_handle; + /*release msg queue*/ + while (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0)); + } + break; + + default: + break; + } + return result; +} + +void ancs_handle_msg(T_IO_MSG *p_io_msg) +{ + uint8_t conn_id = p_io_msg->u.param; + T_ANCS_MSG ancs_msg; + if (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_INFO1("ancs_handle_msg: conn_id 0x%x os_msg_recv failed", conn_id); + return; + } + if (ancs_msg.type == ANCS_MSG_TYPE_GET_NOTIFI_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: notification_uid 0x%x", + ancs_msg.data.notifi_attr.notification_uid); + if (ancs_get_notification_attr(ancs_msg.data.notifi_attr.conn_id, + ancs_msg.data.notifi_attr.notification_uid, + ancs_msg.data.notifi_attr.attribute_ids, ancs_msg.data.notifi_attr.attribute_ids_len + ) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: Failed"); + } + + } + else if (ancs_msg.type == ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: notification_uid 0x%x", + ancs_msg.data.perform_action.notification_uid); + if (ancs_perform_notification_action(ancs_msg.data.perform_action.conn_id, + ancs_msg.data.perform_action.notification_uid, + ancs_msg.data.perform_action.action_id) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: Failed"); + } + + } +#if F_BT_ANCS_GET_APP_ATTR + else if (ancs_msg.type == ANCS_MSG_TYPE_GET_APP_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_APP_ATTR: app_identifier %s", + TRACE_STRING(ancs_msg.data.app_attr.app_identifier)); + if (ancs_get_app_attr(ancs_msg.data.app_attr.conn_id, + ancs_msg.data.app_attr.app_identifier, + ancs_msg.data.app_attr.attribute_ids, + ancs_msg.data.app_attr.attribute_ids_len) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_APP_ATTR: Failed"); + } + + } +#endif +} + +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num) +{ + uint8_t i; + ancs_link_number = link_num; + ancs_link_table = os_mem_zalloc(RAM_TYPE_DATA_ON, ancs_link_number * sizeof(T_APP_ANCS_LINK)); + if (ancs_link_table == NULL) + { + APP_PRINT_ERROR0("ancs_init: allocate buffer failed"); + } + for (i = 0; i < ancs_link_number; i++) + { + if (os_msg_queue_create(&(ancs_link_table[i].ancs_queue_handle), ANCS_MSG_QUEUE_NUM, + sizeof(T_ANCS_MSG)) == false) + { + APP_PRINT_ERROR2("ancs_init: link_num %d, i 0x%x create queue failed", link_num, i); + } + } + ancs_client = ancs_add_client(ancs_client_cb, link_num); +} +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#endif diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/ancs.h b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/ancs.h new file mode 100644 index 0000000..68ec35b --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/ancs.h @@ -0,0 +1,259 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file ancs.h +* @brief ancs +* @details ancs +* @author ranhui +* @date 2015-03-27 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _ANCS_H__ +#define _ANCS_H__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +/** @addtogroup PERIPH_ANCS + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Macros ANCS Exported Macros + * @{ + */ +#define ANCS_MAX_ATTR_LEN 256 //!< Max ancs attribute length + +#if F_BT_ANCS_GET_APP_ATTR +#define ANCS_APP_IDENTIFIER_MAX_LEN 30 //!< Max app IDENTIFIER length +#endif + +#define ANCS_MSG_QUEUE_NUM 5 //!< ANCS message queue size + + +/** @brief ANCS event flag */ +#define NS_EVENT_FLAG_SILENT (1 << 0) +#define NS_EVENT_FLAG_IMPORTANT (1 << 1) +#define NS_EVENT_FLAG_PRE_EXISTING (1 << 2) +#define NS_EVENT_FLAG_POSITIVE_ACTION (1 << 3) //!<A positive action exists and is associated with this iOS notification +#define NS_EVENT_FLAG_NEGATIVE_ACTION (1 << 4) //!<A negative action exists and is associated with this iOS notification. + +/** End of PERIPH_ANCS_Exported_Macros + * @} + */ + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Types ANCS Exported Types + * @{ + */ +/** @brief ANCS event id for the peer device notification */ +typedef enum +{ + NS_EVENT_ID_NOTIFICATION_ADD = 0, /**< The arrival of a new iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_MODIFIED = 1, /**< The modification of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_REMOVED = 2, /**< The removal of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_RESERVED = 0xff +} T_NS_EVENT_ID; + +/** @brief ANCS category id */ +typedef enum +{ + NS_CATEGORY_ID_OTHER = 0, + NS_CATEGORY_ID_INCOMING_CALL = 1, + NS_CATEGORY_ID_MISSED_CALL = 2, + NS_CATEGORY_ID_VOICE_MAIL = 3, + NS_CATEGORY_ID_SOCIAL = 4, + NS_CATEGORY_ID_SCHEDULE = 5, + NS_CATEGORY_ID_EMAIL = 6, + NS_CATEGORY_ID_NEWS = 7, + NS_CATEGORY_ID_HEALTH_AND_FITNESS = 8, + NS_CATEGORY_ID_BUSINESS_ADN_FINANCE = 9, + NS_CATEGORY_ID_LOCATION = 10, + NS_CATEGORY_ID_ENTERTAINMENT = 11, + NS_CATEGORY_ID_RESERVED = 255 +} T_NS_CATEGORY_ID; + +/** @brief ANCS notification attribute id */ +typedef enum +{ + DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER = 0, /**< Format: UTF-8 strings */ + DS_NOTIFICATION_ATTR_ID_TITLE = 1, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_SUB_TITLE = 2, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE = 3, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE = 4, /**<The format of the DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE constant is a string + that represents the integral value of the message size. */ + DS_NOTIFICATION_ATTR_ID_DATE = 5, /**<The format of the DS_NOTIFICATION_ATTR_ID_DATE constant is a string + that uses the Unicode Technical Standard (UTS) #35 date format pattern yyyyMMdd'T'HHmmSS. */ + DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL = 6, /**<Format: UTF-8 strings. The label used to describe + the positive action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL = 7, /**<Format: UTF-8 strings. The label used to describe + the negative action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_RESERVED = 255 +} T_DS_NOTIFICATION_ATTR_ID; + +/** @brief App parse ANCS notification attribute state */ +typedef enum +{ + DS_PARSE_NOT_START = 0x00, + DS_PARSE_GET_NOTIFICATION_COMMAND_ID = 0x01, + DS_PARSE_UID1, + DS_PARSE_UID2, + DS_PARSE_UID3, + DS_PARSE_UID4, + DS_PARSE_ATTRIBUTE_ID, + DS_PARSE_ATTRIBUTE_LEN1, + DS_PARSE_ATTRIBUTE_LEN2, + DS_PARSE_ATTRIBUTE_READY +} T_DS_NOTIFICATION_ATTR_PARSE_STATE; + +/** @brief Smart Phone App attribute id. */ +typedef enum +{ + DS_APP_ATTR_ID_DISPLAY_NAME = 0, + DS_APP_ATTR_ID_RESERVED = 255 +} T_DS_APP_ATTR_ID; + +/** @brief App parse ANCS attribute state */ +typedef enum +{ + DS_PARSE_GET_APP_COMMAND_ID = 0x10, + DS_PARSE_APP_IDENTIFIER_START, + DS_PARSE_APP_IDENTIFIER_END, + DS_PARSE_APP_ATTRIBUTE_ID, + DS_PARSE_APP_ATTRIBUTE_LEN1, + DS_PARSE_APP_ATTRIBUTE_LEN2, + DS_PARSE_APP_ATTRIBUTE_READY +} T_DS_APP_ATTR_PARSE_STATE; + +/** @brief ANCS action id state */ +typedef enum +{ + CP_ACTION_ID_POSITIVE = 0, + CP_ACTION_ID_NEGATIVE = 1, + CP_ACTION_ID_RESERVED = 255 +} T_CP_ACTION_ID_VALUES; + +/** @brief Define notification source data for record ANCS notification parameters */ +typedef struct +{ + uint8_t event_id; /**< This field informs the accessory whether the given iOS notification + was added, modified, or removed. The enumerated values for this field are defined in @ref T_NS_EVENT_ID*/ + uint8_t event_flags; /**< A bitmask whose set bits inform an NC of specificities with the iOS notification. */ + uint8_t category_id; /**< A numerical value providing a category in which the iOS notification + can be classified. The enumerated values for this field are defined in @ref T_NS_CATEGORY_ID*/ + uint8_t category_count; /**< The current number of active iOS notifications in the given category. */ + uint32_t notification_uid; /**< A 32-bit numerical value that is the unique identifier (UID) for the iOS notification.*/ +} T_NS_DATA, *P_NS_DATA; + +/** @brief Define notification attribute details data */ +/** App can acquire details information by attribute id */ +typedef struct +{ + uint8_t command_id; + uint8_t notification_uid[4]; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_NOTIFICATION_ATTR; + +/** @brief Local app record notification attribute information */ +typedef struct +{ + uint8_t command_id; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_APP_ATTR; + +/** @brief ANCS Message Type */ +typedef enum +{ + ANCS_MSG_TYPE_GET_NOTIFI_ATTR, + ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION, + ANCS_MSG_TYPE_GET_APP_ATTR, +} T_ANCS_MSG_TYPE; + +/** @brief Message data of ANCS_MSG_TYPE_GET_NOTIFI_ATTR */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t attribute_ids[14]; + uint8_t attribute_ids_len; +} T_ANCS_GET_NOTIFI_ATTR; + +/** @brief Message data of ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t action_id; +} T_ANCS_PERFORM_NOTIFI_ACTION; + +#if F_BT_ANCS_GET_APP_ATTR +/** @brief Message data of ANCS_MSG_TYPE_GET_APP_ATTR */ +typedef struct +{ + uint8_t conn_id; + char app_identifier[ANCS_APP_IDENTIFIER_MAX_LEN]; + uint8_t attribute_ids[1]; + uint8_t attribute_ids_len; +} T_ANCS_GET_APP_ATTR; +#endif + +/** @brief ANCS Message Data */ +typedef struct +{ + T_ANCS_MSG_TYPE type; + union + { + T_ANCS_GET_NOTIFI_ATTR notifi_attr; + T_ANCS_PERFORM_NOTIFI_ACTION perform_action; +#if F_BT_ANCS_GET_APP_ATTR + T_ANCS_GET_APP_ATTR app_attr; +#endif + } data; +} T_ANCS_MSG; +/** End of PERIPH_ANCS_Exported_Types + * @} + */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num); + +/** + * @brief All the ancs messages are pre-handled in this function + * @param[in] io_msg IO message data + * @return void + */ +void ancs_handle_msg(T_IO_MSG *p_io_msg); +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app.c b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app.c new file mode 100644 index 0000000..bb0beb9 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app.c @@ -0,0 +1,613 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file peripheral_app.c +* @brief This file handles BLE peripheral application routines. +* @author jane +* @date 2017-06-06 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <string.h> +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_conn_le.h> +#include <gap_msg.h> +#include <bas.h> +#include <simple_ble_service.h> +#if F_BT_ANCS_CLIENT_SUPPORT +#include <ancs_client.h> +#include "ancs.h" +#endif + +#include "app.h" +#include "io_adc.h" + +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE peripheral application routines. + * @{ + */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bas_srv_id; /**< Battery service id */ +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ + +/*============================================================================* + * Functions + *============================================================================*/ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; +#if F_BT_ANCS_CLIENT_SUPPORT + case IO_MSG_TYPE_ANCS: + { + ancs_handle_msg(&io_msg); + } + break; +#endif + case IO_MSG_TYPE_ADC: + { + APP_PRINT_INFO0("[app] app_handle_io_msg: adc msg."); + io_handle_adc_msg(&io_msg); + //Add user code here! + } + break; + case IO_MSG_TYPE_GDMA: + { + APP_PRINT_INFO0("[app]app_handle_io_msg: gdma msg."); + io_handle_gdma_msg(&io_msg); + //Add user code here! + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ +// le_adv_start(); + io_adc_sample_start(); + } + } + + if (gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + } + } + + gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, gap_conn_state, new_state, disc_cause); + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, remote_bd, &remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + } + break; + + default: + break; + } + gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { +#if F_BT_ANCS_CLIENT_SUPPORT + ancs_start_discovery(conn_id); +#endif + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("app_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("app_handle_conn_param_update_evt update pending."); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ + +/** @defgroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value[2] = {0x01, 0x02}; + APP_PRINT_INFO0("SIMP_READ_V1"); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + else if (service_id == bas_srv_id) + { + T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; + switch (p_bas_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_bas_cb_data->msg_data.notification_indification_index) + { + case BAS_NOTIFY_BATTERY_LEVEL_ENABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE"); + } + break; + + case BAS_NOTIFY_BATTERY_LEVEL_DISABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL) + { + uint8_t battery_level = 90; + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level); + bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level); + } + } + break; + + default: + break; + } + } + + return app_result; +} + +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @} */ /* End of group PERIPH_APP */ diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app.h b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app.h new file mode 100644 index 0000000..8aed00b --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app.h @@ -0,0 +1,72 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app.h +* @brief This file handles BLE peripheral application routines. +* @author jane +* @date 2017-06-06 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +#ifndef _APP_H +#define _APP_H + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <profile_server.h> + +#include "app_msg.h" + + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bas_srv_id; /**< Battery service id */ + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg:IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * @param[in] service_id: Profile service ID + * @param[in] p_data: Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_flags.h b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_flags.h new file mode 100644 index 0000000..3371839 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_flags.h @@ -0,0 +1,40 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#include "upperstack_config.h" + +/** @defgroup PERIPH_Config Peripheral App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +/** @brief Config DLPS: 0-Disable DLPS, 1-Enable DLPS */ +#define F_BT_DLPS_EN 0 +/** @brief Config ANCS Client: 0-Not built in, 1-Open ANCS client function */ +#define F_BT_ANCS_CLIENT_SUPPORT 0 +#define F_BT_ANCS_APP_FILTER (F_BT_ANCS_CLIENT_SUPPORT & 1) +#define F_BT_ANCS_GET_APP_ATTR (F_BT_ANCS_CLIENT_SUPPORT & 0) +/** @brief Config ANCS Client debug log: 0-close, 1-open */ +#define F_BT_ANCS_CLIENT_DEBUG (F_BT_ANCS_CLIENT_SUPPORT & 0) + +/** @} */ /* End of group PERIPH_Config */ +#endif diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_task.c b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_task.c new file mode 100644 index 0000000..39fe610 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_task.c @@ -0,0 +1,124 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +#include "app.h" +#include "app_task.h" +#include "io_adc.h" + + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +extern void driver_init(void); + +void app_main_task(void *p_param); + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg) +{ + uint8_t event = EVENT_IO_TO_APP; + + if (os_msg_send(io_queue_handle, p_msg, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_io_msg_to_app fail"); + return false; + } + if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_evt_msg_to_app fail"); + return false; + } + return true; +} + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param: Parameters sending to the task + * @return void + */ +void app_main_task(void *p_param) +{ + uint8_t event; + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + driver_init(); + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** @} */ /* End of group PERIPH_APP_TASK */ + + diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_task.h b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_task.h new file mode 100644 index 0000000..5d5918a --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/app_task.h @@ -0,0 +1,47 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app_task.h +* @brief Routines to create App task and handle events & messages +* @author jane +* @date 2017-06-02 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#include <string.h> + +#include "os_msg.h" +#include "os_queue.h" +#include "os_sched.h" +#include "os_task.h" +#include "os_timer.h" + +#include "app_msg.h" + +#include "trace.h" + + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg); + +/** + * @brief Initialize app task + * @return void + */ +void app_task_init(void); + +#endif + diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/main.c b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/main.c new file mode 100644 index 0000000..3b04eac --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/ble_peripheral/main.c @@ -0,0 +1,242 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file main.c +* @brief Source file for BLE peripheral project, mainly used for initialize modules +* @author jane +* @date 2017-06-12 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <stdlib.h> +#include <string.h> +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_msg.h> +#include <bas.h> +#include <simple_ble_service.h> + +#if F_BT_ANCS_CLIENT_SUPPORT +#include <profile_client.h> +#include "ancs.h" +#endif + +#include "app.h" +#include "app_task.h" +#include "app_flags.h" +#include "io_adc.h" + + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + + +/*============================================================================* + * Variables + *============================================================================*/ + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x0F, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'L', 'E', '_', 'P', 'E', 'R', 'I', 'P', 'H', 'E', 'R', 'A', 'L', +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_PERIPHERAL"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; +#if F_BT_ANCS_CLIENT_SUPPORT + uint8_t auth_sec_req_enable = true; +#else + uint8_t auth_sec_req_enable = false; +#endif + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(app_gap_callback); +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void app_le_profile_init(void) +{ + server_init(2); + bas_srv_id = bas_add_service(app_profile_callback); + simp_srv_id = simp_ble_service_add_service(app_profile_callback); + server_register_app_cb(app_profile_callback); +#if F_BT_ANCS_CLIENT_SUPPORT + client_init(1); + ancs_init(APP_MAX_LINKS); +#endif +} + +/** + * @brief Initialize global data. + * @param No parameter. + * @return void + */ +void global_data_init(void) +{ + global_data_adc_init(); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be performed with the IO initializing. + * @return void + */ +void board_init(void) +{ + board_adc_init(); +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void driver_init(void) +{ + driver_adc_init(); + driver_gdma_adc_init(); +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void task_init(void) +{ + app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int main(void) +{ + extern uint32_t random_seed_value; + srand(random_seed_value); +// global_data_init(); + board_init(); + le_gap_init(APP_MAX_LINKS); + gap_lib_init(); + app_le_gap_init(); + app_le_profile_init(); + pwr_mgr_init(); + task_init(); + os_sched_start(); + return 0; +} +/** @} */ /* End of group PERIPH_DEMO_MAIN */ + + diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/io_adc.c b/src/sample/io_sample/ADC/ContinuousMode+GDMA/io_adc.c new file mode 100644 index 0000000..284aa13 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/io_adc.c @@ -0,0 +1,358 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.c +* @brief This file provides demo code of adc continuous sample and read by gdma. +* @details +* @author yuan +* @date 2018-12-07 +* @version v1.0 +********************************************************************************************************* +*/ + +/* Includes ------------------------------------------------------------------*/ +#include "io_adc.h" +#include "app_task.h" + +/* Globals ------------------------------------------------------------------*/ +uint16_t ADC_Recv_Buffer[GDMA_TRANSFER_SIZE]; + +/** + * @brief Initialization adc global data. + * @param No parameter. + * @return void + */ +void global_data_adc_init(void) +{ + /* Initialize adc k value! */ + APP_PRINT_INFO0("[io_adc]global_data_adc_init"); + bool adc_k_status = false; + adc_k_status = ADC_CalibrationInit(); + if (false == adc_k_status) + { + APP_PRINT_ERROR0("[io_adc]global_data_adc_init: ADC_CalibrationInit fail!"); + } + memset(&ADC_Recv_Buffer, 0, sizeof(ADC_Recv_Buffer)); +} + +/** + * @brief Initialization of pinmux settings and pad settings. + * @param No parameter. + * @return void + */ +void board_adc_init(void) +{ + Pad_Config(ADC_SAMPLE_PIN_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); + Pad_Config(ADC_SAMPLE_PIN_1, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); + Pad_Config(ADC_SAMPLE_PIN_2, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); + Pad_Config(ADC_SAMPLE_PIN_3, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); +} + +/** + * @brief Initialize ADC peripheral. + * @param No parameter. + * @return void + */ +void driver_adc_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE); + + ADC_InitTypeDef ADC_InitStruct; + ADC_StructInit(&ADC_InitStruct); + + ADC_InitStruct.ADC_WaterLevel = 4; + /* Configure the ADC sampling schedule, a schedule represents an ADC channel data, + up to 16, i.e. schIndex[0] ~ schIndex[15] */ + ADC_InitStruct.ADC_SchIndex[0] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_0); + ADC_InitStruct.ADC_SchIndex[1] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_1); + ADC_InitStruct.ADC_SchIndex[2] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_2); + ADC_InitStruct.ADC_SchIndex[3] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_3); + /* Set the bitmap corresponding to schedule, 16 bits, LSB, + schIndex[0-15] corresponding to 16 bits of bitmap bit0-bit15. + For example, if config schIndex[0] and schIndex [1], then bitmap is 0000 0000 0011 (that is, 0x0003); + if config schIndex [0] and schIndex [2], then bitmap is 0000 0000 0101 (that is, 0x0005). + */ + ADC_InitStruct.ADC_Bitmap = 0x0F; + /* Configuration of ADC continuous sampling cycle. */ + ADC_InitStruct.ADC_SampleTime = ADC_CONTINUOUS_SAMPLE_PERIOD; + + ADC_InitStruct.ADC_PowerAlwaysOnEn = ADC_POWER_ALWAYS_ON_ENABLE; + + ADC_Init(ADC, &ADC_InitStruct); + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + /* High bypass resistance mode config, please notice that the input voltage of + adc channel using high bypass mode should not be over 0.9V */ + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, ENABLE); + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_1, ENABLE); + APP_PRINT_INFO0("[io_adc]driver_adc_init: ADC sample mode is bypass mode !"); +#else + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, DISABLE); + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_1, DISABLE); +#endif + + ADC_INTConfig(ADC, ADC_INT_FIFO_RD_ERR, ENABLE); + ADC_INTConfig(ADC, ADC_INT_FIFO_OVERFLOW, ENABLE); + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = ADC_IRQn; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + /* When ADC is enabled, sampling will be done quickly and interruption will occur. + After initialization, ADC can be enabled when sampling is needed.*/ +// ADC_Cmd(ADC, ADC_Continuous_Mode, ENABLE); +} + +/** + * @brief Initialize gdma peripheral. + * @param No parameter. + * @return void + */ +void driver_gdma_adc_init(void) +{ + uint32_t i = 0; + + /* Initialize data buffer which for storing data from adc */ + for (i = 0; i < GDMA_TRANSFER_SIZE; i++) + { + ADC_Recv_Buffer[i] = 0; + } + + /* GDMA init */ + GDMA_InitTypeDef GDMA_InitStruct; + GDMA_StructInit(&GDMA_InitStruct); + + GDMA_InitStruct.GDMA_ChannelNum = ADC_GDMA_CHANNEL_NUM; + GDMA_InitStruct.GDMA_DIR = GDMA_DIR_PeripheralToMemory; + GDMA_InitStruct.GDMA_BufferSize = GDMA_TRANSFER_SIZE;//Determine total transfer size + GDMA_InitStruct.GDMA_SourceInc = DMA_SourceInc_Fix; + GDMA_InitStruct.GDMA_DestinationInc = DMA_DestinationInc_Inc; + GDMA_InitStruct.GDMA_SourceDataSize = GDMA_DataSize_HalfWord; + GDMA_InitStruct.GDMA_DestinationDataSize = GDMA_DataSize_HalfWord; + GDMA_InitStruct.GDMA_SourceMsize = GDMA_Msize_4; + GDMA_InitStruct.GDMA_DestinationMsize = GDMA_Msize_4; + GDMA_InitStruct.GDMA_SourceAddr = (uint32_t)(&(ADC->FIFO)); + GDMA_InitStruct.GDMA_DestinationAddr = (uint32_t)ADC_Recv_Buffer; + GDMA_InitStruct.GDMA_SourceHandshake = GDMA_Handshake_ADC; + + GDMA_Init(ADC_GDMA_Channel, &GDMA_InitStruct); + + GDMA_INTConfig(ADC_GDMA_CHANNEL_NUM, GDMA_INT_Transfer, ENABLE); + + /* GDMA irq init */ + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = ADC_GDMA_Channel_IRQn; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + +// /* Start to receive data */ +// GDMA_Cmd(ADC_GDMA_CHANNEL_NUM, ENABLE); +// /* Enable adc */ +// ADC_Cmd(ADC, ADC_Continuous_Mode, ENABLE); + +} + +/** + * @brief Calculate adc sample voltage. + * @param No parameter. + * @return void + */ +static void io_adc_voltage_calculate(T_IO_MSG *io_adc_msg) +{ + uint16_t *p_buf = io_adc_msg->u.buf; + + for (uint32_t i = 0; i < GDMA_TRANSFER_SIZE; i++) + { + uint16_t sample_data = p_buf[i]; + float sample_voltage = 0; + ADC_ErrorStatus error_status = NO_ERROR; + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + sample_voltage = ADC_GetVoltage(BYPASS_SINGLE_MODE, (int32_t)sample_data, &error_status); +#else + sample_voltage = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data, &error_status); +#endif + if (error_status < 0) + { + APP_PRINT_INFO2("[io_adc]io_adc_voltage_calculate: ADC parameter or efuse data error! i = %d, error_status = %d", + i, error_status); + } + else + { + APP_PRINT_INFO4("[io_adc]io_adc_voltage_calculate: ADC rawdata_%-4d = %d, voltage_%-4d = %dmV ", i, + sample_data, i, (uint32_t)sample_voltage); + } + } + + platform_delay_ms(1000); + /* Restart dma and adc */ + GDMA_SetSourceAddress(ADC_GDMA_Channel, (uint32_t)(&(ADC->FIFO))); + GDMA_SetDestinationAddress(ADC_GDMA_Channel, (uint32_t)(ADC_Recv_Buffer)); + GDMA_SetBufferSize(ADC_GDMA_Channel, GDMA_TRANSFER_SIZE); + GDMA_ClearINTPendingBit(ADC_GDMA_CHANNEL_NUM, GDMA_INT_Transfer); + GDMA_Cmd(ADC_GDMA_CHANNEL_NUM, ENABLE); + ADC_ClearFIFO(ADC); + ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, ENABLE); +} + +/** + * @brief Handle adc error function. + * @param No parameter. + * @return void + */ +static void io_handle_adc_error(T_IO_MSG *io_adc_msg) +{ + uint16_t adc_msg_subtype = io_adc_msg->subtype; + + switch (adc_msg_subtype) + { + case IO_MSG_ADC_FIFO_READ_ERR: + { + APP_PRINT_ERROR0("[io_adc]io_handle_adc_error: IO_MSG_ADC_FIFO_READ_ERR!"); + //Add user code here! + } + break; + case IO_MSG_ADC_FIFO_OVERFLOW: + { + APP_PRINT_ERROR0("[io_adc]io_handle_adc_error: IO_MSG_ADC_FIFO_OVERFLOW!"); + //Add user code here! + } + break; + default: + break; + } +} + +/** + * @brief Handle adc msg function. + * @param No parameter. + * @return void + */ +void io_handle_adc_msg(T_IO_MSG *io_adc_msg) +{ + io_handle_adc_error(io_adc_msg); +} + +/** + * @brief Handle gdma msg function. + * @param No parameter. + * @return void + */ +void io_handle_gdma_msg(T_IO_MSG *io_gdma_msg) +{ + io_adc_voltage_calculate(io_gdma_msg); +} + +/** + * @brief ADC sample start. + * @param No parameter. + * @return void + */ +void io_adc_sample_start(void) +{ + /* Start to receive data */ + GDMA_Cmd(ADC_GDMA_CHANNEL_NUM, ENABLE); + + /* Clear adc fifo */ + ADC_ClearFIFO(ADC); + /* Enable adc */ + ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, ENABLE); +} + +/** + * @brief ADC sample stop. + * @param No parameter. + * @return void + */ +void io_adc_sample_stop(void) +{ + /* Stop dma */ + GDMA_SuspendCmd(ADC_GDMA_Channel, ENABLE); + while (!(GDMA_GetSuspendChannelStatus(ADC_GDMA_Channel))); + GDMA_Cmd(ADC_GDMA_CHANNEL_NUM, DISABLE); + + /* Clear adc fifo */ + ADC_ClearFIFO(ADC); + /* Disable adc */ + ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, DISABLE); +} + +/** + * @brief ADC interrupt handler function. + * @param No parameter. + * @return void + */ +void ADC_Handler(void) +{ + if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_RD_ERR) == SET) + { + T_IO_MSG int_adc_msg; + + int_adc_msg.type = IO_MSG_TYPE_ADC; + int_adc_msg.subtype = IO_MSG_ADC_FIFO_READ_ERR; + if (false == app_send_msg_to_apptask(&int_adc_msg)) + { + APP_PRINT_ERROR0("[io_adc]ADC_Handler: 1111Send int_adc_msg failed!"); + //Add user code here! + io_adc_sample_stop(); +// ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, DISABLE); +// ADC_ClearFifo(ADC); + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_RD_ERR); + return; + } + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_RD_ERR); + } + if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_OVERFLOW) == SET) + { + ADC_WriteFIFOCmd(ADC, DISABLE); + DBG_DIRECT("ADC_INT_FIFO_OVERFLOW"); + + T_IO_MSG int_adc_msg; + + int_adc_msg.type = IO_MSG_TYPE_ADC; + int_adc_msg.subtype = IO_MSG_ADC_FIFO_OVERFLOW; + if (false == app_send_msg_to_apptask(&int_adc_msg)) + { + APP_PRINT_ERROR0("[io_adc]ADC_Handler: Send int_adc_msg failed!"); + io_adc_sample_stop(); +// ADC_ClearFifo(ADC); + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_OVERFLOW); + return; + } + ADC_ClearFIFO(ADC); + ADC_WriteFIFOCmd(ADC, ENABLE); + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_OVERFLOW); + } +} + +/** + * @brief GDMA channel interrupt handler function. + * @param No parameter. + * @return void + */ +void ADC_GDMA_Channel_Handler(void) +{ + ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, DISABLE); + + T_IO_MSG int_gdma_msg; + + int_gdma_msg.type = IO_MSG_TYPE_GDMA; + int_gdma_msg.subtype = 0; + int_gdma_msg.u.buf = (void *)(ADC_Recv_Buffer); + if (false == app_send_msg_to_apptask(&int_gdma_msg)) + { + APP_PRINT_ERROR0("[io_adc]ADC_GDMA_Channel_Handler: Send int_gdma_msg failed!"); + io_adc_sample_stop(); +// ADC_ClearFifo(ADC); + GDMA_ClearINTPendingBit(ADC_GDMA_CHANNEL_NUM, GDMA_INT_Transfer); + return; + } + GDMA_ClearINTPendingBit(ADC_GDMA_CHANNEL_NUM, GDMA_INT_Transfer); +} diff --git a/src/sample/io_sample/ADC/ContinuousMode+GDMA/io_adc.h b/src/sample/io_sample/ADC/ContinuousMode+GDMA/io_adc.h new file mode 100644 index 0000000..90dd436 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode+GDMA/io_adc.h @@ -0,0 +1,78 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.h +* @brief +* @details +* @author yuan +* @date 2018-12-07 +* @version v1.0 +********************************************************************************************************* +*/ + +#ifndef __IO_ADC_H +#define __IO_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "rtl876x_adc.h" +#include "rtl876x_gdma.h" +#include "rtl876x_nvic.h" +#include "rtl876x_pinmux.h" +#include "rtl876x_rcc.h" + +#include "app_msg.h" +#include "board.h" + +/* Defines ------------------------------------------------------------------*/ +/** ADC sample channel config. + * ADC sample channel config:P2_2,P2_3,P2_6,P2_7 and VBAT + * ADC sample channel index select: #define ADC_Channel_Index_0 0 + * #define ADC_Channel_Index_1 1 + * #define ADC_Channel_Index_2 2 + * #define ADC_Channel_Index_3 3 + + * If ADC_SAMPLE_PIN = P2_2, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_0; + * If ADC_SAMPLE_PIN = P2_3, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_1; + * If ADC_SAMPLE_PIN = P2_6, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_2; + * If ADC_SAMPLE_PIN = P2_7, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_3; + */ +#define ADC_SAMPLE_CHANNEL_0 ADC_Channel_Index_0 +#define ADC_SAMPLE_CHANNEL_1 ADC_Channel_Index_1 +#define ADC_SAMPLE_CHANNEL_2 ADC_Channel_Index_2 +#define ADC_SAMPLE_CHANNEL_3 ADC_Channel_Index_3 + +/** ADC mode config. + * ADC pin hardware mode: bypass mode + * divide mode + */ +#define ADC_DIVIDE_MODE 0 +#define ADC_BYPASS_MODE 1 +#define ADC_MODE_DIVIDE_OR_BYPASS ADC_DIVIDE_MODE + +#define ADC_CONTINUOUS_SAMPLE_PERIOD (20-1)//2us + +#define GDMA_TRANSFER_SIZE 4000 + + +extern uint16_t ADC_Recv_Buffer[GDMA_TRANSFER_SIZE]; + +void global_data_adc_init(void); +void board_adc_init(void); +void driver_adc_init(void); +void driver_gdma_adc_init(void); +void io_handle_adc_msg(T_IO_MSG *io_adc_msg); +void io_handle_gdma_msg(T_IO_MSG *io_gdma_msg); +void io_adc_sample_start(void); +void io_adc_sample_stop(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/ancs.c b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/ancs.c new file mode 100644 index 0000000..ac3254e --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/ancs.c @@ -0,0 +1,662 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ancs.c + * @brief This file handles ANCS Client routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#if F_BT_ANCS_CLIENT_SUPPORT +#include <trace.h> +#include <string.h> +#include <os_msg.h> +#include <os_mem.h> +#include <ancs.h> +#include <ancs_client.h> + +/** @defgroup PERIPH_ANCS Peripheral ANCS + * @brief Apple ANCS service modulization + * @{ + */ +/*============================================================================* + * Types + *============================================================================*/ +typedef struct +{ + uint8_t m_parse_state; + uint8_t app_type; + uint16_t current_len; + void *ancs_queue_handle; + uint8_t *ptr; + T_DS_NOTIFICATION_ATTR notification_attr; +#if F_BT_ANCS_GET_APP_ATTR + T_DS_APP_ATTR app_attr; +#endif +} T_APP_ANCS_LINK; + +/*============================================================================* + * Variables + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Variables ANCS Exported Variables + * @brief app register ancs client to upperstack, and return ancs client id + * @{ + */ +T_CLIENT_ID ancs_client; /**< ancs client id*/ + +T_APP_ANCS_LINK *ancs_link_table; +uint8_t ancs_link_number; + +/** End of PERIPH_ANCS_Exported_Variables + * @} + */ +extern void *evt_queue_handle; //!< Event queue handle +extern void *io_queue_handle; //!< IO queue handle +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +void ancs_send_msg_to_app(uint8_t conn_id) +{ + T_IO_MSG io_msg; + uint8_t event = EVENT_IO_TO_APP; + io_msg.type = IO_MSG_TYPE_ANCS; + io_msg.subtype = 0; + io_msg.u.param = conn_id; + + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail1"); + } + else if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail2"); + } +} + +void app_handle_notification_attribute_data(T_APP_ANCS_LINK *p_ancs_link) +{ + if (p_ancs_link->notification_attr.attribute_id != DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + uint8_t *p_value = p_ancs_link->notification_attr.data; + +#if F_BT_ANCS_APP_FILTER + //filter QQ , wechat , short message and incoming call + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: app identifiter %s", TRACE_STRING(p_value)); +#endif + //wechat + if (0 == memcmp(p_value, "com.tencent.xin", 16)) + { + p_ancs_link->app_type = 1; + } + else if (0 == memcmp(p_value, "com.apple.MobileSMS", 20)) + { + p_ancs_link->app_type = 2; + } + else if (0 == memcmp(p_value, "com.apple.mobilephone", 22)) + { + p_ancs_link->app_type = 3; + } + else if (0 == memcmp(p_value, "com.tencent.mqq", 16)) + { + p_ancs_link->app_type = 4; + } + else if (0 == memcmp(p_value, "com.tencent.qq", 15)) + { + p_ancs_link->app_type = 5; + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_MESSAGE) + { + if (p_ancs_link->app_type == 2) + { + APP_PRINT_INFO1("MobileSMS: message %s", TRACE_STRING(p_value)); + } + else if (p_ancs_link->app_type == 5) + { + APP_PRINT_INFO1("QQ: message %s", TRACE_STRING(p_value)); + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_DATE) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: date %s", TRACE_STRING(p_value)); +#endif + } +#endif + } + else/* All attributes has been parased*/ + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO0("parse notify attr: parse done"); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } +} + +void app_parse_notification_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_NOTIFICATION_COMMAND_ID: + p_ancs_link->notification_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID1; + break; + + case DS_PARSE_UID1: + p_ancs_link->notification_attr.notification_uid[0] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID2; + break; + + case DS_PARSE_UID2: + p_ancs_link->notification_attr.notification_uid[1] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID3; + break; + + case DS_PARSE_UID3: + p_ancs_link->notification_attr.notification_uid[2] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID4; + break; + + case DS_PARSE_UID4: + p_ancs_link->notification_attr.notification_uid[3] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + break; + + case DS_PARSE_ATTRIBUTE_ID: + p_ancs_link->notification_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_ATTRIBUTE_LEN1: + p_ancs_link->notification_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_ATTRIBUTE_LEN2: + p_ancs_link->notification_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->notification_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse notify attr: attribute_id %d, attribute_len %d", + p_ancs_link->notification_attr.attribute_id, + p_ancs_link->notification_attr.attribute_len + ); +#endif + if (p_ancs_link->notification_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + } + if (p_ancs_link->notification_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse notify attr: error, attribute_len %d > max length %d", + p_ancs_link->notification_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } + break; + + case DS_PARSE_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->notification_attr.attribute_len) + { + /*An attribute is always a string whose length in bytes is provided in the tuple but that is not NULL-terminated.*/ + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: data %b", + TRACE_BINARY(p_ancs_link->notification_attr.attribute_len, + p_ancs_link->notification_attr.data)); +#endif + app_handle_notification_attribute_data(p_ancs_link); + } + break; + } + } +} + +#if F_BT_ANCS_GET_APP_ATTR +void app_parse_app_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_APP_COMMAND_ID: + p_ancs_link->app_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_START; + break; + + case DS_PARSE_APP_IDENTIFIER_START: + if (p_data[i] == 0x00) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_END; + + if (i + 1 == len) + { + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + else + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + } + + } + break; + + case DS_PARSE_APP_ATTRIBUTE_ID: + p_ancs_link->app_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN1: + p_ancs_link->app_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN2: + p_ancs_link->app_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->app_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse app attr: attribute_id %d, attribute_len %d", + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len + ); +#endif + if (p_ancs_link->app_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + + } + if (p_ancs_link->app_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse app attr: error, attribute_len %d > max length %d", + p_ancs_link->app_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + break; + + case DS_PARSE_APP_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->app_attr.attribute_len) + { + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO4("parse app attr: command_id 0x%x, attribute_id 0x%x, attribute_len %d, data %s", + p_ancs_link->app_attr.command_id, + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len, + TRACE_STRING(p_ancs_link->app_attr.data)); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + + } + break; + } + } +} +#endif + +/** + * @brief Parse ancs data source notification + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @param[in] len data length + * @return void + */ +void app_parse_data_soucre_notifications(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + APP_PRINT_INFO2("ANCS_FROM_DATA_SOURCE: conn_id %d, len =%d", conn_id, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("data = %b", TRACE_BINARY(len, p_data)); +#endif + T_APP_ANCS_LINK *p_ancs_link = &ancs_link_table[conn_id]; + +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("m_parse_state %d", p_ancs_link->m_parse_state); +#endif + if (p_ancs_link->m_parse_state == DS_PARSE_NOT_START) + { + if (len >= 1 && p_data[0] == CP_CMD_ID_GET_NOTIFICATION_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_NOTIFICATION_COMMAND_ID; + } +#if F_BT_ANCS_GET_APP_ATTR + else if (len >= 1 && p_data[0] == CP_CMD_ID_GET_APP_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_APP_COMMAND_ID; + } +#endif + } + + if (p_ancs_link->m_parse_state < DS_PARSE_GET_APP_COMMAND_ID) + { + app_parse_notification_attribute(p_ancs_link, p_data, len); + } +#if F_BT_ANCS_GET_APP_ATTR + else + { + app_parse_app_attribute(p_ancs_link, p_data, len); + } +#endif +} + +void app_parse_notification_source_data(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + if (8 == len) + { + T_NS_DATA ns_data; + + memcpy(&ns_data, p_data, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO5("app_parse_notification_source_data: event_id %d, event_flags 0x%02x, category_id %d, category_count %d, notification_uid 0x%08x", + ns_data.event_id, + ns_data.event_flags, + ns_data.category_id, + ns_data.category_count, + ns_data.notification_uid + ); + APP_PRINT_INFO5("event_flags: slient %d, important %d, pre existing %d, positive action %d, negative action %d ", + ns_data.event_flags & NS_EVENT_FLAG_SILENT, + ns_data.event_flags & NS_EVENT_FLAG_IMPORTANT, + ns_data.event_flags & NS_EVENT_FLAG_PRE_EXISTING, + ns_data.event_flags & NS_EVENT_FLAG_POSITIVE_ACTION, + ns_data.event_flags & NS_EVENT_FLAG_NEGATIVE_ACTION + ); +#endif + //you can filter by category_id here, for demo purpose, we didn't filter any CategoryID here. +#if F_BT_ANCS_APP_FILTER + //filter social and other category & phone category & email category + if (ns_data.category_id == NS_CATEGORY_ID_SOCIAL || + ns_data.category_id == NS_CATEGORY_ID_OTHER || + ns_data.category_id == NS_CATEGORY_ID_INCOMING_CALL || + ns_data.category_id == NS_CATEGORY_ID_EMAIL) + { +#endif + if (ns_data.event_id != NS_EVENT_ID_NOTIFICATION_REMOVED) + { + uint32_t msg_num; + T_ANCS_MSG ancs_msg; + uint8_t attr_id_list[14]; + uint8_t cur_index = 0; + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_SUB_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_DATE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL; + + os_msg_queue_peek(ancs_link_table[conn_id].ancs_queue_handle, &msg_num); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("app_parse_notification_source_data: msg_num %d", msg_num); +#endif + if (msg_num == 0) + { + if (ancs_get_notification_attr(conn_id, ns_data.notification_uid, attr_id_list, + cur_index) == true) + { + return; + } + } + + ancs_msg.type = ANCS_MSG_TYPE_GET_NOTIFI_ATTR; + ancs_msg.data.notifi_attr.conn_id = conn_id; + ancs_msg.data.notifi_attr.notification_uid = ns_data.notification_uid; + ancs_msg.data.notifi_attr.attribute_ids_len = cur_index; + memcpy(ancs_msg.data.notifi_attr.attribute_ids, attr_id_list, cur_index); + if (os_msg_send(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_ERROR0("app_parse_notification_source_data: discard, msg queue is full"); + } + } +#if F_BT_ANCS_APP_FILTER + } +#endif + } +} + +/** + * @brief Ancs client callback handle message from upperstack + * @param[in] client_id client identifier + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @return @ref T_APP_RESULT + */ +T_APP_RESULT ancs_client_cb(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_ANCS_CB_DATA *p_cb_data = (T_ANCS_CB_DATA *)p_data; + + switch (p_cb_data->cb_type) + { + case ANCS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_cb_data->cb_content.disc_state) + { + case DISC_ANCS_DONE: + APP_PRINT_INFO0("ANCS BLE Client CB: discover procedure done."); + ancs_set_data_source_notify(conn_id, true); + break; + case DISC_ANCS_FAILED: + APP_PRINT_ERROR0("ANCS BLE Client CB: discover request failed."); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (p_cb_data->cb_content.notify_data.type) + { + case ANCS_FROM_DATA_SOURCE:; + app_parse_data_soucre_notifications(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + case ANCS_FROM_NOTIFICATION_SOURCE: + APP_PRINT_INFO2("ANCS_FROM_NOTIFICATION_SOURCE: conn_id %d, length %d", + conn_id, p_cb_data->cb_content.notify_data.value_size); + app_parse_notification_source_data(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_WRITE_RESULT: + { + if (p_cb_data->cb_content.write_result.cause != ATT_SUCCESS) + { + APP_PRINT_ERROR1("ANCS_CLIENT_CB_TYPE_WRITE_RESULT: Failed, cause 0x%x", + p_cb_data->cb_content.write_result.cause); + } + switch (p_cb_data->cb_content.write_result.type) + { + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE"); + break; + + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE"); + ancs_set_notification_source_notify(conn_id, true); + break; + case ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_CONTROL_POINT: + APP_PRINT_INFO0("ANCS_WRITE_CONTROL_POINT"); +#if F_BT_ANCS_CLIENT_DEBUG + if (p_cb_data->cb_content.write_result.cause == 0x4A0) + { + APP_PRINT_ERROR0("The commandID was not recognized by the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A1) + { + APP_PRINT_ERROR0("The command was improperly formatted."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A2) + { + APP_PRINT_ERROR0("One of the parameters (for example, the NotificationUID) does not refer to an existing object on the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A3) + { + APP_PRINT_ERROR0("The action was not performed."); + } +#endif + ancs_send_msg_to_app(conn_id); + break; + + default: + break; + } + } + break; + + case ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: + { + T_ANCS_MSG ancs_msg; + void *ancs_queue_handle = ancs_link_table[conn_id].ancs_queue_handle; + APP_PRINT_INFO1("ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: conn_id = 0x%x", conn_id); + memset(&ancs_link_table[conn_id], 0, sizeof(T_APP_ANCS_LINK)); + ancs_link_table[conn_id].ancs_queue_handle = ancs_queue_handle; + /*release msg queue*/ + while (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0)); + } + break; + + default: + break; + } + return result; +} + +void ancs_handle_msg(T_IO_MSG *p_io_msg) +{ + uint8_t conn_id = p_io_msg->u.param; + T_ANCS_MSG ancs_msg; + if (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_INFO1("ancs_handle_msg: conn_id 0x%x os_msg_recv failed", conn_id); + return; + } + if (ancs_msg.type == ANCS_MSG_TYPE_GET_NOTIFI_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: notification_uid 0x%x", + ancs_msg.data.notifi_attr.notification_uid); + if (ancs_get_notification_attr(ancs_msg.data.notifi_attr.conn_id, + ancs_msg.data.notifi_attr.notification_uid, + ancs_msg.data.notifi_attr.attribute_ids, ancs_msg.data.notifi_attr.attribute_ids_len + ) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: Failed"); + } + + } + else if (ancs_msg.type == ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: notification_uid 0x%x", + ancs_msg.data.perform_action.notification_uid); + if (ancs_perform_notification_action(ancs_msg.data.perform_action.conn_id, + ancs_msg.data.perform_action.notification_uid, + ancs_msg.data.perform_action.action_id) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: Failed"); + } + + } +#if F_BT_ANCS_GET_APP_ATTR + else if (ancs_msg.type == ANCS_MSG_TYPE_GET_APP_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_APP_ATTR: app_identifier %s", + TRACE_STRING(ancs_msg.data.app_attr.app_identifier)); + if (ancs_get_app_attr(ancs_msg.data.app_attr.conn_id, + ancs_msg.data.app_attr.app_identifier, + ancs_msg.data.app_attr.attribute_ids, + ancs_msg.data.app_attr.attribute_ids_len) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_APP_ATTR: Failed"); + } + + } +#endif +} + +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num) +{ + uint8_t i; + ancs_link_number = link_num; + ancs_link_table = os_mem_zalloc(RAM_TYPE_DATA_ON, ancs_link_number * sizeof(T_APP_ANCS_LINK)); + if (ancs_link_table == NULL) + { + APP_PRINT_ERROR0("ancs_init: allocate buffer failed"); + } + for (i = 0; i < ancs_link_number; i++) + { + if (os_msg_queue_create(&(ancs_link_table[i].ancs_queue_handle), ANCS_MSG_QUEUE_NUM, + sizeof(T_ANCS_MSG)) == false) + { + APP_PRINT_ERROR2("ancs_init: link_num %d, i 0x%x create queue failed", link_num, i); + } + } + ancs_client = ancs_add_client(ancs_client_cb, link_num); +} +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#endif diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/ancs.h b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/ancs.h new file mode 100644 index 0000000..68ec35b --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/ancs.h @@ -0,0 +1,259 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file ancs.h +* @brief ancs +* @details ancs +* @author ranhui +* @date 2015-03-27 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _ANCS_H__ +#define _ANCS_H__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +/** @addtogroup PERIPH_ANCS + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Macros ANCS Exported Macros + * @{ + */ +#define ANCS_MAX_ATTR_LEN 256 //!< Max ancs attribute length + +#if F_BT_ANCS_GET_APP_ATTR +#define ANCS_APP_IDENTIFIER_MAX_LEN 30 //!< Max app IDENTIFIER length +#endif + +#define ANCS_MSG_QUEUE_NUM 5 //!< ANCS message queue size + + +/** @brief ANCS event flag */ +#define NS_EVENT_FLAG_SILENT (1 << 0) +#define NS_EVENT_FLAG_IMPORTANT (1 << 1) +#define NS_EVENT_FLAG_PRE_EXISTING (1 << 2) +#define NS_EVENT_FLAG_POSITIVE_ACTION (1 << 3) //!<A positive action exists and is associated with this iOS notification +#define NS_EVENT_FLAG_NEGATIVE_ACTION (1 << 4) //!<A negative action exists and is associated with this iOS notification. + +/** End of PERIPH_ANCS_Exported_Macros + * @} + */ + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Types ANCS Exported Types + * @{ + */ +/** @brief ANCS event id for the peer device notification */ +typedef enum +{ + NS_EVENT_ID_NOTIFICATION_ADD = 0, /**< The arrival of a new iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_MODIFIED = 1, /**< The modification of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_REMOVED = 2, /**< The removal of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_RESERVED = 0xff +} T_NS_EVENT_ID; + +/** @brief ANCS category id */ +typedef enum +{ + NS_CATEGORY_ID_OTHER = 0, + NS_CATEGORY_ID_INCOMING_CALL = 1, + NS_CATEGORY_ID_MISSED_CALL = 2, + NS_CATEGORY_ID_VOICE_MAIL = 3, + NS_CATEGORY_ID_SOCIAL = 4, + NS_CATEGORY_ID_SCHEDULE = 5, + NS_CATEGORY_ID_EMAIL = 6, + NS_CATEGORY_ID_NEWS = 7, + NS_CATEGORY_ID_HEALTH_AND_FITNESS = 8, + NS_CATEGORY_ID_BUSINESS_ADN_FINANCE = 9, + NS_CATEGORY_ID_LOCATION = 10, + NS_CATEGORY_ID_ENTERTAINMENT = 11, + NS_CATEGORY_ID_RESERVED = 255 +} T_NS_CATEGORY_ID; + +/** @brief ANCS notification attribute id */ +typedef enum +{ + DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER = 0, /**< Format: UTF-8 strings */ + DS_NOTIFICATION_ATTR_ID_TITLE = 1, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_SUB_TITLE = 2, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE = 3, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE = 4, /**<The format of the DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE constant is a string + that represents the integral value of the message size. */ + DS_NOTIFICATION_ATTR_ID_DATE = 5, /**<The format of the DS_NOTIFICATION_ATTR_ID_DATE constant is a string + that uses the Unicode Technical Standard (UTS) #35 date format pattern yyyyMMdd'T'HHmmSS. */ + DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL = 6, /**<Format: UTF-8 strings. The label used to describe + the positive action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL = 7, /**<Format: UTF-8 strings. The label used to describe + the negative action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_RESERVED = 255 +} T_DS_NOTIFICATION_ATTR_ID; + +/** @brief App parse ANCS notification attribute state */ +typedef enum +{ + DS_PARSE_NOT_START = 0x00, + DS_PARSE_GET_NOTIFICATION_COMMAND_ID = 0x01, + DS_PARSE_UID1, + DS_PARSE_UID2, + DS_PARSE_UID3, + DS_PARSE_UID4, + DS_PARSE_ATTRIBUTE_ID, + DS_PARSE_ATTRIBUTE_LEN1, + DS_PARSE_ATTRIBUTE_LEN2, + DS_PARSE_ATTRIBUTE_READY +} T_DS_NOTIFICATION_ATTR_PARSE_STATE; + +/** @brief Smart Phone App attribute id. */ +typedef enum +{ + DS_APP_ATTR_ID_DISPLAY_NAME = 0, + DS_APP_ATTR_ID_RESERVED = 255 +} T_DS_APP_ATTR_ID; + +/** @brief App parse ANCS attribute state */ +typedef enum +{ + DS_PARSE_GET_APP_COMMAND_ID = 0x10, + DS_PARSE_APP_IDENTIFIER_START, + DS_PARSE_APP_IDENTIFIER_END, + DS_PARSE_APP_ATTRIBUTE_ID, + DS_PARSE_APP_ATTRIBUTE_LEN1, + DS_PARSE_APP_ATTRIBUTE_LEN2, + DS_PARSE_APP_ATTRIBUTE_READY +} T_DS_APP_ATTR_PARSE_STATE; + +/** @brief ANCS action id state */ +typedef enum +{ + CP_ACTION_ID_POSITIVE = 0, + CP_ACTION_ID_NEGATIVE = 1, + CP_ACTION_ID_RESERVED = 255 +} T_CP_ACTION_ID_VALUES; + +/** @brief Define notification source data for record ANCS notification parameters */ +typedef struct +{ + uint8_t event_id; /**< This field informs the accessory whether the given iOS notification + was added, modified, or removed. The enumerated values for this field are defined in @ref T_NS_EVENT_ID*/ + uint8_t event_flags; /**< A bitmask whose set bits inform an NC of specificities with the iOS notification. */ + uint8_t category_id; /**< A numerical value providing a category in which the iOS notification + can be classified. The enumerated values for this field are defined in @ref T_NS_CATEGORY_ID*/ + uint8_t category_count; /**< The current number of active iOS notifications in the given category. */ + uint32_t notification_uid; /**< A 32-bit numerical value that is the unique identifier (UID) for the iOS notification.*/ +} T_NS_DATA, *P_NS_DATA; + +/** @brief Define notification attribute details data */ +/** App can acquire details information by attribute id */ +typedef struct +{ + uint8_t command_id; + uint8_t notification_uid[4]; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_NOTIFICATION_ATTR; + +/** @brief Local app record notification attribute information */ +typedef struct +{ + uint8_t command_id; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_APP_ATTR; + +/** @brief ANCS Message Type */ +typedef enum +{ + ANCS_MSG_TYPE_GET_NOTIFI_ATTR, + ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION, + ANCS_MSG_TYPE_GET_APP_ATTR, +} T_ANCS_MSG_TYPE; + +/** @brief Message data of ANCS_MSG_TYPE_GET_NOTIFI_ATTR */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t attribute_ids[14]; + uint8_t attribute_ids_len; +} T_ANCS_GET_NOTIFI_ATTR; + +/** @brief Message data of ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t action_id; +} T_ANCS_PERFORM_NOTIFI_ACTION; + +#if F_BT_ANCS_GET_APP_ATTR +/** @brief Message data of ANCS_MSG_TYPE_GET_APP_ATTR */ +typedef struct +{ + uint8_t conn_id; + char app_identifier[ANCS_APP_IDENTIFIER_MAX_LEN]; + uint8_t attribute_ids[1]; + uint8_t attribute_ids_len; +} T_ANCS_GET_APP_ATTR; +#endif + +/** @brief ANCS Message Data */ +typedef struct +{ + T_ANCS_MSG_TYPE type; + union + { + T_ANCS_GET_NOTIFI_ATTR notifi_attr; + T_ANCS_PERFORM_NOTIFI_ACTION perform_action; +#if F_BT_ANCS_GET_APP_ATTR + T_ANCS_GET_APP_ATTR app_attr; +#endif + } data; +} T_ANCS_MSG; +/** End of PERIPH_ANCS_Exported_Types + * @} + */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num); + +/** + * @brief All the ancs messages are pre-handled in this function + * @param[in] io_msg IO message data + * @return void + */ +void ancs_handle_msg(T_IO_MSG *p_io_msg); +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.c b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.c new file mode 100644 index 0000000..cbc9143 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.c @@ -0,0 +1,608 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <string.h> + +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_conn_le.h> +#include <gap_msg.h> +#if F_BT_ANCS_CLIENT_SUPPORT +#include <ancs_client.h> +#include "ancs.h" +#endif +#include <bas.h> +#include <simple_ble_service.h> + +#include "trace.h" + +#include "app.h" +#include "io_adc.h" + +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE peripheral application routines. + * @{ + */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bas_srv_id; /**< Battery service id */ +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ + +/*============================================================================* + * Functions + *============================================================================*/ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; +#if F_BT_ANCS_CLIENT_SUPPORT + case IO_MSG_TYPE_ANCS: + { + ancs_handle_msg(&io_msg); + } + break; +#endif + case IO_MSG_TYPE_ADC: + { +// APP_PRINT_INFO0("[app] app_handle_io_msg: adc msg."); + io_handle_adc_msg(&io_msg); + //Add user code here! + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ +// le_adv_start(); + } + } + + if (gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + } + } + + gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, gap_conn_state, new_state, disc_cause); + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, remote_bd, &remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + } + break; + + default: + break; + } + gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { +#if F_BT_ANCS_CLIENT_SUPPORT + ancs_start_discovery(conn_id); +#endif + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("app_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("app_handle_conn_param_update_evt update pending."); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ + +/** @defgroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value[2] = {0x01, 0x02}; + APP_PRINT_INFO0("SIMP_READ_V1"); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + else if (service_id == bas_srv_id) + { + T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; + switch (p_bas_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_bas_cb_data->msg_data.notification_indification_index) + { + case BAS_NOTIFY_BATTERY_LEVEL_ENABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE"); + } + break; + + case BAS_NOTIFY_BATTERY_LEVEL_DISABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL) + { + uint8_t battery_level = 90; + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level); + bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level); + } + } + break; + + default: + break; + } + } + + return app_result; +} + +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @} */ /* End of group PERIPH_APP */ diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.h b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.h new file mode 100644 index 0000000..8aed00b --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app.h @@ -0,0 +1,72 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app.h +* @brief This file handles BLE peripheral application routines. +* @author jane +* @date 2017-06-06 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +#ifndef _APP_H +#define _APP_H + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <profile_server.h> + +#include "app_msg.h" + + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bas_srv_id; /**< Battery service id */ + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg:IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * @param[in] service_id: Profile service ID + * @param[in] p_data: Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_flags.h b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_flags.h new file mode 100644 index 0000000..d3e92fe --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_flags.h @@ -0,0 +1,40 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app_flags.h +* @brief This file is used to config app functions. +* @author jane +* @date 2017-06-06 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#include "upperstack_config.h" + +/** @defgroup PERIPH_Config Peripheral App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +/** @brief Config DLPS: 0-Disable DLPS, 1-Enable DLPS */ +#define F_BT_DLPS_EN 0 +/** @brief Config ANCS Client: 0-Not built in, 1-Open ANCS client function */ +#define F_BT_ANCS_CLIENT_SUPPORT 0 +#define F_BT_ANCS_APP_FILTER (F_BT_ANCS_CLIENT_SUPPORT & 1) +#define F_BT_ANCS_GET_APP_ATTR (F_BT_ANCS_CLIENT_SUPPORT & 0) +/** @brief Config ANCS Client debug log: 0-close, 1-open */ +#define F_BT_ANCS_CLIENT_DEBUG (F_BT_ANCS_CLIENT_SUPPORT & 0) + +/** @} */ /* End of group PERIPH_Config */ +#endif diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_task.c b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_task.c new file mode 100644 index 0000000..635c4c3 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_task.c @@ -0,0 +1,123 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +#include "app.h" +#include "app_task.h" + + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +extern void driver_init(void); + +void app_main_task(void *p_param); + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg) +{ + uint8_t event = EVENT_IO_TO_APP; + + if (os_msg_send(io_queue_handle, p_msg, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_io_msg_to_app fail"); + return false; + } + if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_evt_msg_to_app fail"); + return false; + } + return true; +} + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param: Parameters sending to the task + * @return void + */ +void app_main_task(void *p_param) +{ + uint8_t event; + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + driver_init(); + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** @} */ /* End of group PERIPH_APP_TASK */ + + diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_task.h b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_task.h new file mode 100644 index 0000000..5d5918a --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/app_task.h @@ -0,0 +1,47 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app_task.h +* @brief Routines to create App task and handle events & messages +* @author jane +* @date 2017-06-02 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#include <string.h> + +#include "os_msg.h" +#include "os_queue.h" +#include "os_sched.h" +#include "os_task.h" +#include "os_timer.h" + +#include "app_msg.h" + +#include "trace.h" + + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg); + +/** + * @brief Initialize app task + * @return void + */ +void app_task_init(void); + +#endif + diff --git a/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/main.c b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/main.c new file mode 100644 index 0000000..831ba68 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/ble_peripheral/main.c @@ -0,0 +1,241 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file main.c +* @brief Source file for BLE peripheral project, mainly used for initialize modules +* @author jane +* @date 2017-06-12 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <stdlib.h> +#include <string.h> +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_msg.h> +#include <bas.h> +#include <simple_ble_service.h> +#if F_BT_ANCS_CLIENT_SUPPORT +#include <profile_client.h> +#include "ancs.h" +#endif + +#include "app.h" +#include "app_task.h" +#include "app_flags.h" +#include "io_adc.h" + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + + +/*============================================================================* + * Variables + *============================================================================*/ + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x0F, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'L', 'E', '_', 'P', 'E', 'R', 'I', 'P', 'H', 'E', 'R', 'A', 'L', +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_PERIPHERAL"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; +#if F_BT_ANCS_CLIENT_SUPPORT + uint8_t auth_sec_req_enable = true; +#else + uint8_t auth_sec_req_enable = false; +#endif + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(app_gap_callback); +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void app_le_profile_init(void) +{ + server_init(2); + bas_srv_id = bas_add_service(app_profile_callback); + simp_srv_id = simp_ble_service_add_service(app_profile_callback); + server_register_app_cb(app_profile_callback); +#if F_BT_ANCS_CLIENT_SUPPORT + client_init(1); + ancs_init(APP_MAX_LINKS); +#endif +} + +/** + * @brief Initialize global data. + * @param No parameter. + * @return void + */ +void global_data_init(void) +{ + global_data_adc_init(); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be performed with the IO initializing. + * @return void + */ +void board_init(void) +{ + board_adc_init(); +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void driver_init(void) +{ + driver_adc_init(); +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void task_init(void) +{ + app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int main(void) +{ + extern uint32_t random_seed_value; + srand(random_seed_value); + global_data_init(); + board_init(); + le_gap_init(APP_MAX_LINKS); + gap_lib_init(); + app_le_gap_init(); + app_le_profile_init(); + pwr_mgr_init(); + task_init(); + os_sched_start(); + + return 0; +} +/** @} */ /* End of group PERIPH_DEMO_MAIN */ + + diff --git a/src/sample/io_sample/ADC/ContinuousMode/io_adc.c b/src/sample/io_sample/ADC/ContinuousMode/io_adc.c new file mode 100644 index 0000000..49e1c61 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/io_adc.c @@ -0,0 +1,200 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.c +* @brief This file provides demo code of adc continuous mode. +* @details +* @author yuan +* @date 2018-12-07 +* @version v1.0 +********************************************************************************************************* +*/ + +/* Includes ------------------------------------------------------------------*/ +#include "io_adc.h" + +#include "app_task.h" + +/* Globals ------------------------------------------------------------------*/ +ADC_Data_TypeDef ADC_Global_Data; + +/** + * @brief Initialization adc global data. + * @param No parameter. + * @return void + */ +void global_data_adc_init(void) +{ + /* Initialize adc k value! */ + APP_PRINT_INFO0("[io_adc] global_data_adc_init"); + bool adc_k_status = false; + adc_k_status = ADC_CalibrationInit(); + if (false == adc_k_status) + { + APP_PRINT_ERROR0("[io_adc] global_data_adc_init: ADC_CalibrationInit fail!"); + } + memset(&ADC_Global_Data, 0, sizeof(ADC_Global_Data)); +} + +/** + * @brief Initialization of pinmux settings and pad settings. + * @param No parameter. + * @return void +*/ +void board_adc_init(void) +{ + Pad_Config(ADC_SAMPLE_PIN_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); + Pad_Config(ADC_SAMPLE_PIN_1, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); +} + +/** + * @brief Initialize ADC peripheral. + * @param No parameter. + * @return void + */ +void driver_adc_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE); + + ADC_InitTypeDef ADC_InitStruct; + ADC_StructInit(&ADC_InitStruct); + /* Configure the ADC sampling schedule, a schedule represents an ADC channel data, + up to 16, i.e. schIndex[0] ~ schIndex[15] */ + ADC_InitStruct.ADC_SchIndex[0] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_0); + ADC_InitStruct.ADC_SchIndex[1] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_1); + /* Set the bitmap corresponding to schedule, 15 bits, LSB, + schIndex[0-15] corresponding to 16 bits of bitmap bit0-bit15. + For example, if config schIndex[0] and schIndex [1], then bitmap is 0000 0000 0011 (that is, 0x0003); + if config schIndex [0] and schIndex [2], then bitmap is 0000 0000 0101 (that is, 0x0005). + */ + ADC_InitStruct.ADC_Bitmap = 0x03; + ADC_InitStruct.ADC_SampleTime = ADC_CONTINUOUS_SAMPLE_PERIOD; + /* Configure the interrupt of ADC_INT_FIFO_TH threshold value. */ + ADC_InitStruct.ADC_FifoThdLevel = 16; + ADC_Init(ADC, &ADC_InitStruct); + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + /* High bypass resistance mode config, please notice that the input voltage of + adc channel using high bypass mode should not be over 0.9V */ + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, ENABLE); + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_1, ENABLE); + APP_PRINT_INFO0("[ADC] ADC sample mode is bypass mode !"); +#else + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, DISABLE); + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_1, DISABLE); + APP_PRINT_INFO0("[ADC] ADC sample mode is divide mode !"); +#endif + + ADC_INTConfig(ADC, ADC_INT_FIFO_THD, ENABLE); + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = ADC_IRQn; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + /* When ADC is enabled, sampling will be done quickly and interruption will occur. + After initialization, ADC can be enabled when sampling is needed.*/ + ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, ENABLE); +} + +/** + * @brief Calculate adc sample voltage. + * @param No parameter. + * @return void + */ +static void io_adc_voltage_calculate(T_IO_MSG *io_adc_msg) +{ + uint8_t sample_data_len = 0; + uint16_t sample_data[ADC_FIFO_MAX] = {0}; + float sample_voltage[ADC_FIFO_MAX] = {0}; + ADC_ErrorStatus error_status = NO_ERROR; + + uint16_t *p_buf = io_adc_msg->u.buf; + + sample_data_len = p_buf[0]; + for (uint8_t i = 0; i < sample_data_len; i++) + { + sample_data[i] = p_buf[i + 1]; + } + for (uint8_t i = 0; i < sample_data_len; i++) + { +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + sample_voltage[i] = ADC_GetVoltage(BYPASS_SINGLE_MODE, (int32_t)sample_data[i], &error_status); +#else + sample_voltage[i] = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data[i], &error_status); +#endif + if (error_status < 0) + { + APP_PRINT_INFO2("[io_adc] io_adc_voltage_calculate: ADC parameter or efuse data error! i = %d, error_status = %d", + i, error_status); + } + else + { + APP_PRINT_INFO4("[io_adc] io_adc_voltage_calculate: ADC rawdata_%-4d = %d, voltage_%-4d = %dmV ", i, + sample_data[i], i, (uint32_t)sample_voltage[i]); + + } + } + memset(&ADC_Global_Data, 0, sizeof(ADC_Global_Data)); + for (uint32_t i = 0; i < 1000000; i++); + ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, ENABLE); +} + +/** + * @brief Handle adc data function. + * @param No parameter. + * @return void + */ +void io_handle_adc_msg(T_IO_MSG *io_adc_msg) +{ + io_adc_voltage_calculate(io_adc_msg); +} + +/** + * @brief ADC interrupt handler function. + * @param No parameter. + * @return void + */ +void ADC_Handler(void) +{ + uint8_t data_len = 0; + uint16_t sample_data[ADC_FIFO_MAX] = {0}; + + if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_THD) == SET) + { + ADC_Cmd(ADC, ADC_CONTINUOUS_MODE, DISABLE); + + data_len = ADC_GetFIFODataLen(ADC); + /* ADC continuous sampling mode, read data from FIFO. + In multi-channel sampling, + the data order in FIFO corresponds to the channel order set by schedule index. + */ + ADC_ReadFIFOData(ADC, sample_data, data_len); + + ADC_ClearFIFO(ADC); + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_THD); + + T_IO_MSG int_adc_msg; + + int_adc_msg.type = IO_MSG_TYPE_ADC; + int_adc_msg.subtype = 0; + ADC_Global_Data.RawData[0] = data_len; + for (uint8_t i = 0; i < data_len; i++) + { + ADC_Global_Data.RawData[i + 1] = sample_data[i]; + } + int_adc_msg.u.buf = (void *)(ADC_Global_Data.RawData); + if (false == app_send_msg_to_apptask(&int_adc_msg)) + { + APP_PRINT_ERROR0("[io_adc] ADC_Handler: Send int_adc_msg failed!"); + //Add user code here! + ADC_ClearFIFO(ADC); + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_THD); + return; + } + } +} + diff --git a/src/sample/io_sample/ADC/ContinuousMode/io_adc.h b/src/sample/io_sample/ADC/ContinuousMode/io_adc.h new file mode 100644 index 0000000..bf908d0 --- /dev/null +++ b/src/sample/io_sample/ADC/ContinuousMode/io_adc.h @@ -0,0 +1,77 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.h +* @brief +* @details +* @author yuan +* @date 2018-12-07 +* @version v1.0 +********************************************************************************************************* +*/ + +#ifndef __IO_ADC_H +#define __IO_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "rtl876x_adc.h" +#include "rtl876x_nvic.h" +#include "rtl876x_pinmux.h" +#include "rtl876x_rcc.h" +#include "app_msg.h" +#include "board.h" + +/* Defines ------------------------------------------------------------------*/ +/** ADC sample channel config. + * ADC sample channel config:P2_2,P2_3,P2_6,P2_7 and VBAT + * ADC sample channel index select: #define ADC_Channel_Index_0 0 + * #define ADC_Channel_Index_1 1 + * #define ADC_Channel_Index_2 2 + * #define ADC_Channel_Index_3 3 + + * If ADC_SAMPLE_PIN = P2_2, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_0; + * If ADC_SAMPLE_PIN = P2_3, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_1; + * If ADC_SAMPLE_PIN = P2_6, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_2; + * If ADC_SAMPLE_PIN = P2_7, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_3; + */ +#define ADC_SAMPLE_CHANNEL_0 ADC_Channel_Index_0 +#define ADC_SAMPLE_CHANNEL_1 ADC_Channel_Index_1 + +/** ADC mode config. + * ADC pin hardware mode: bypass mode + * divide mode + */ +#define ADC_DIVIDE_MODE 0 +#define ADC_BYPASS_MODE 1 +#define ADC_MODE_DIVIDE_OR_BYPASS ADC_DIVIDE_MODE + +#define ADC_CONTINUOUS_SAMPLE_PERIOD (200-1)//20us + +#define ADC_FIFO_MAX (32) + +/* ADC global data struct*/ +typedef struct +{ + uint16_t RawData[ADC_FIFO_MAX + 1]; +// float voltage[ADC_FIFO_THD]; +} ADC_Data_TypeDef; + +extern ADC_Data_TypeDef ADC_Global_Data; + +void global_data_adc_init(void); +void board_adc_init(void); +void driver_adc_init(void); +void io_handle_adc_msg(T_IO_MSG *io_adc_msg); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/DLPS/ble_peripheral/ancs.c b/src/sample/io_sample/ADC/DLPS/ble_peripheral/ancs.c new file mode 100644 index 0000000..ac3254e --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/ble_peripheral/ancs.c @@ -0,0 +1,662 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ancs.c + * @brief This file handles ANCS Client routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#if F_BT_ANCS_CLIENT_SUPPORT +#include <trace.h> +#include <string.h> +#include <os_msg.h> +#include <os_mem.h> +#include <ancs.h> +#include <ancs_client.h> + +/** @defgroup PERIPH_ANCS Peripheral ANCS + * @brief Apple ANCS service modulization + * @{ + */ +/*============================================================================* + * Types + *============================================================================*/ +typedef struct +{ + uint8_t m_parse_state; + uint8_t app_type; + uint16_t current_len; + void *ancs_queue_handle; + uint8_t *ptr; + T_DS_NOTIFICATION_ATTR notification_attr; +#if F_BT_ANCS_GET_APP_ATTR + T_DS_APP_ATTR app_attr; +#endif +} T_APP_ANCS_LINK; + +/*============================================================================* + * Variables + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Variables ANCS Exported Variables + * @brief app register ancs client to upperstack, and return ancs client id + * @{ + */ +T_CLIENT_ID ancs_client; /**< ancs client id*/ + +T_APP_ANCS_LINK *ancs_link_table; +uint8_t ancs_link_number; + +/** End of PERIPH_ANCS_Exported_Variables + * @} + */ +extern void *evt_queue_handle; //!< Event queue handle +extern void *io_queue_handle; //!< IO queue handle +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +void ancs_send_msg_to_app(uint8_t conn_id) +{ + T_IO_MSG io_msg; + uint8_t event = EVENT_IO_TO_APP; + io_msg.type = IO_MSG_TYPE_ANCS; + io_msg.subtype = 0; + io_msg.u.param = conn_id; + + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail1"); + } + else if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail2"); + } +} + +void app_handle_notification_attribute_data(T_APP_ANCS_LINK *p_ancs_link) +{ + if (p_ancs_link->notification_attr.attribute_id != DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + uint8_t *p_value = p_ancs_link->notification_attr.data; + +#if F_BT_ANCS_APP_FILTER + //filter QQ , wechat , short message and incoming call + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: app identifiter %s", TRACE_STRING(p_value)); +#endif + //wechat + if (0 == memcmp(p_value, "com.tencent.xin", 16)) + { + p_ancs_link->app_type = 1; + } + else if (0 == memcmp(p_value, "com.apple.MobileSMS", 20)) + { + p_ancs_link->app_type = 2; + } + else if (0 == memcmp(p_value, "com.apple.mobilephone", 22)) + { + p_ancs_link->app_type = 3; + } + else if (0 == memcmp(p_value, "com.tencent.mqq", 16)) + { + p_ancs_link->app_type = 4; + } + else if (0 == memcmp(p_value, "com.tencent.qq", 15)) + { + p_ancs_link->app_type = 5; + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_MESSAGE) + { + if (p_ancs_link->app_type == 2) + { + APP_PRINT_INFO1("MobileSMS: message %s", TRACE_STRING(p_value)); + } + else if (p_ancs_link->app_type == 5) + { + APP_PRINT_INFO1("QQ: message %s", TRACE_STRING(p_value)); + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_DATE) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: date %s", TRACE_STRING(p_value)); +#endif + } +#endif + } + else/* All attributes has been parased*/ + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO0("parse notify attr: parse done"); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } +} + +void app_parse_notification_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_NOTIFICATION_COMMAND_ID: + p_ancs_link->notification_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID1; + break; + + case DS_PARSE_UID1: + p_ancs_link->notification_attr.notification_uid[0] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID2; + break; + + case DS_PARSE_UID2: + p_ancs_link->notification_attr.notification_uid[1] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID3; + break; + + case DS_PARSE_UID3: + p_ancs_link->notification_attr.notification_uid[2] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID4; + break; + + case DS_PARSE_UID4: + p_ancs_link->notification_attr.notification_uid[3] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + break; + + case DS_PARSE_ATTRIBUTE_ID: + p_ancs_link->notification_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_ATTRIBUTE_LEN1: + p_ancs_link->notification_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_ATTRIBUTE_LEN2: + p_ancs_link->notification_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->notification_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse notify attr: attribute_id %d, attribute_len %d", + p_ancs_link->notification_attr.attribute_id, + p_ancs_link->notification_attr.attribute_len + ); +#endif + if (p_ancs_link->notification_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + } + if (p_ancs_link->notification_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse notify attr: error, attribute_len %d > max length %d", + p_ancs_link->notification_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } + break; + + case DS_PARSE_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->notification_attr.attribute_len) + { + /*An attribute is always a string whose length in bytes is provided in the tuple but that is not NULL-terminated.*/ + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: data %b", + TRACE_BINARY(p_ancs_link->notification_attr.attribute_len, + p_ancs_link->notification_attr.data)); +#endif + app_handle_notification_attribute_data(p_ancs_link); + } + break; + } + } +} + +#if F_BT_ANCS_GET_APP_ATTR +void app_parse_app_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_APP_COMMAND_ID: + p_ancs_link->app_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_START; + break; + + case DS_PARSE_APP_IDENTIFIER_START: + if (p_data[i] == 0x00) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_END; + + if (i + 1 == len) + { + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + else + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + } + + } + break; + + case DS_PARSE_APP_ATTRIBUTE_ID: + p_ancs_link->app_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN1: + p_ancs_link->app_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN2: + p_ancs_link->app_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->app_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse app attr: attribute_id %d, attribute_len %d", + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len + ); +#endif + if (p_ancs_link->app_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + + } + if (p_ancs_link->app_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse app attr: error, attribute_len %d > max length %d", + p_ancs_link->app_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + break; + + case DS_PARSE_APP_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->app_attr.attribute_len) + { + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO4("parse app attr: command_id 0x%x, attribute_id 0x%x, attribute_len %d, data %s", + p_ancs_link->app_attr.command_id, + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len, + TRACE_STRING(p_ancs_link->app_attr.data)); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + + } + break; + } + } +} +#endif + +/** + * @brief Parse ancs data source notification + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @param[in] len data length + * @return void + */ +void app_parse_data_soucre_notifications(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + APP_PRINT_INFO2("ANCS_FROM_DATA_SOURCE: conn_id %d, len =%d", conn_id, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("data = %b", TRACE_BINARY(len, p_data)); +#endif + T_APP_ANCS_LINK *p_ancs_link = &ancs_link_table[conn_id]; + +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("m_parse_state %d", p_ancs_link->m_parse_state); +#endif + if (p_ancs_link->m_parse_state == DS_PARSE_NOT_START) + { + if (len >= 1 && p_data[0] == CP_CMD_ID_GET_NOTIFICATION_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_NOTIFICATION_COMMAND_ID; + } +#if F_BT_ANCS_GET_APP_ATTR + else if (len >= 1 && p_data[0] == CP_CMD_ID_GET_APP_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_APP_COMMAND_ID; + } +#endif + } + + if (p_ancs_link->m_parse_state < DS_PARSE_GET_APP_COMMAND_ID) + { + app_parse_notification_attribute(p_ancs_link, p_data, len); + } +#if F_BT_ANCS_GET_APP_ATTR + else + { + app_parse_app_attribute(p_ancs_link, p_data, len); + } +#endif +} + +void app_parse_notification_source_data(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + if (8 == len) + { + T_NS_DATA ns_data; + + memcpy(&ns_data, p_data, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO5("app_parse_notification_source_data: event_id %d, event_flags 0x%02x, category_id %d, category_count %d, notification_uid 0x%08x", + ns_data.event_id, + ns_data.event_flags, + ns_data.category_id, + ns_data.category_count, + ns_data.notification_uid + ); + APP_PRINT_INFO5("event_flags: slient %d, important %d, pre existing %d, positive action %d, negative action %d ", + ns_data.event_flags & NS_EVENT_FLAG_SILENT, + ns_data.event_flags & NS_EVENT_FLAG_IMPORTANT, + ns_data.event_flags & NS_EVENT_FLAG_PRE_EXISTING, + ns_data.event_flags & NS_EVENT_FLAG_POSITIVE_ACTION, + ns_data.event_flags & NS_EVENT_FLAG_NEGATIVE_ACTION + ); +#endif + //you can filter by category_id here, for demo purpose, we didn't filter any CategoryID here. +#if F_BT_ANCS_APP_FILTER + //filter social and other category & phone category & email category + if (ns_data.category_id == NS_CATEGORY_ID_SOCIAL || + ns_data.category_id == NS_CATEGORY_ID_OTHER || + ns_data.category_id == NS_CATEGORY_ID_INCOMING_CALL || + ns_data.category_id == NS_CATEGORY_ID_EMAIL) + { +#endif + if (ns_data.event_id != NS_EVENT_ID_NOTIFICATION_REMOVED) + { + uint32_t msg_num; + T_ANCS_MSG ancs_msg; + uint8_t attr_id_list[14]; + uint8_t cur_index = 0; + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_SUB_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_DATE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL; + + os_msg_queue_peek(ancs_link_table[conn_id].ancs_queue_handle, &msg_num); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("app_parse_notification_source_data: msg_num %d", msg_num); +#endif + if (msg_num == 0) + { + if (ancs_get_notification_attr(conn_id, ns_data.notification_uid, attr_id_list, + cur_index) == true) + { + return; + } + } + + ancs_msg.type = ANCS_MSG_TYPE_GET_NOTIFI_ATTR; + ancs_msg.data.notifi_attr.conn_id = conn_id; + ancs_msg.data.notifi_attr.notification_uid = ns_data.notification_uid; + ancs_msg.data.notifi_attr.attribute_ids_len = cur_index; + memcpy(ancs_msg.data.notifi_attr.attribute_ids, attr_id_list, cur_index); + if (os_msg_send(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_ERROR0("app_parse_notification_source_data: discard, msg queue is full"); + } + } +#if F_BT_ANCS_APP_FILTER + } +#endif + } +} + +/** + * @brief Ancs client callback handle message from upperstack + * @param[in] client_id client identifier + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @return @ref T_APP_RESULT + */ +T_APP_RESULT ancs_client_cb(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_ANCS_CB_DATA *p_cb_data = (T_ANCS_CB_DATA *)p_data; + + switch (p_cb_data->cb_type) + { + case ANCS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_cb_data->cb_content.disc_state) + { + case DISC_ANCS_DONE: + APP_PRINT_INFO0("ANCS BLE Client CB: discover procedure done."); + ancs_set_data_source_notify(conn_id, true); + break; + case DISC_ANCS_FAILED: + APP_PRINT_ERROR0("ANCS BLE Client CB: discover request failed."); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (p_cb_data->cb_content.notify_data.type) + { + case ANCS_FROM_DATA_SOURCE:; + app_parse_data_soucre_notifications(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + case ANCS_FROM_NOTIFICATION_SOURCE: + APP_PRINT_INFO2("ANCS_FROM_NOTIFICATION_SOURCE: conn_id %d, length %d", + conn_id, p_cb_data->cb_content.notify_data.value_size); + app_parse_notification_source_data(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_WRITE_RESULT: + { + if (p_cb_data->cb_content.write_result.cause != ATT_SUCCESS) + { + APP_PRINT_ERROR1("ANCS_CLIENT_CB_TYPE_WRITE_RESULT: Failed, cause 0x%x", + p_cb_data->cb_content.write_result.cause); + } + switch (p_cb_data->cb_content.write_result.type) + { + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE"); + break; + + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE"); + ancs_set_notification_source_notify(conn_id, true); + break; + case ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_CONTROL_POINT: + APP_PRINT_INFO0("ANCS_WRITE_CONTROL_POINT"); +#if F_BT_ANCS_CLIENT_DEBUG + if (p_cb_data->cb_content.write_result.cause == 0x4A0) + { + APP_PRINT_ERROR0("The commandID was not recognized by the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A1) + { + APP_PRINT_ERROR0("The command was improperly formatted."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A2) + { + APP_PRINT_ERROR0("One of the parameters (for example, the NotificationUID) does not refer to an existing object on the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A3) + { + APP_PRINT_ERROR0("The action was not performed."); + } +#endif + ancs_send_msg_to_app(conn_id); + break; + + default: + break; + } + } + break; + + case ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: + { + T_ANCS_MSG ancs_msg; + void *ancs_queue_handle = ancs_link_table[conn_id].ancs_queue_handle; + APP_PRINT_INFO1("ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: conn_id = 0x%x", conn_id); + memset(&ancs_link_table[conn_id], 0, sizeof(T_APP_ANCS_LINK)); + ancs_link_table[conn_id].ancs_queue_handle = ancs_queue_handle; + /*release msg queue*/ + while (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0)); + } + break; + + default: + break; + } + return result; +} + +void ancs_handle_msg(T_IO_MSG *p_io_msg) +{ + uint8_t conn_id = p_io_msg->u.param; + T_ANCS_MSG ancs_msg; + if (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_INFO1("ancs_handle_msg: conn_id 0x%x os_msg_recv failed", conn_id); + return; + } + if (ancs_msg.type == ANCS_MSG_TYPE_GET_NOTIFI_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: notification_uid 0x%x", + ancs_msg.data.notifi_attr.notification_uid); + if (ancs_get_notification_attr(ancs_msg.data.notifi_attr.conn_id, + ancs_msg.data.notifi_attr.notification_uid, + ancs_msg.data.notifi_attr.attribute_ids, ancs_msg.data.notifi_attr.attribute_ids_len + ) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: Failed"); + } + + } + else if (ancs_msg.type == ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: notification_uid 0x%x", + ancs_msg.data.perform_action.notification_uid); + if (ancs_perform_notification_action(ancs_msg.data.perform_action.conn_id, + ancs_msg.data.perform_action.notification_uid, + ancs_msg.data.perform_action.action_id) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: Failed"); + } + + } +#if F_BT_ANCS_GET_APP_ATTR + else if (ancs_msg.type == ANCS_MSG_TYPE_GET_APP_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_APP_ATTR: app_identifier %s", + TRACE_STRING(ancs_msg.data.app_attr.app_identifier)); + if (ancs_get_app_attr(ancs_msg.data.app_attr.conn_id, + ancs_msg.data.app_attr.app_identifier, + ancs_msg.data.app_attr.attribute_ids, + ancs_msg.data.app_attr.attribute_ids_len) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_APP_ATTR: Failed"); + } + + } +#endif +} + +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num) +{ + uint8_t i; + ancs_link_number = link_num; + ancs_link_table = os_mem_zalloc(RAM_TYPE_DATA_ON, ancs_link_number * sizeof(T_APP_ANCS_LINK)); + if (ancs_link_table == NULL) + { + APP_PRINT_ERROR0("ancs_init: allocate buffer failed"); + } + for (i = 0; i < ancs_link_number; i++) + { + if (os_msg_queue_create(&(ancs_link_table[i].ancs_queue_handle), ANCS_MSG_QUEUE_NUM, + sizeof(T_ANCS_MSG)) == false) + { + APP_PRINT_ERROR2("ancs_init: link_num %d, i 0x%x create queue failed", link_num, i); + } + } + ancs_client = ancs_add_client(ancs_client_cb, link_num); +} +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#endif diff --git a/src/sample/io_sample/ADC/DLPS/ble_peripheral/ancs.h b/src/sample/io_sample/ADC/DLPS/ble_peripheral/ancs.h new file mode 100644 index 0000000..68ec35b --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/ble_peripheral/ancs.h @@ -0,0 +1,259 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file ancs.h +* @brief ancs +* @details ancs +* @author ranhui +* @date 2015-03-27 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _ANCS_H__ +#define _ANCS_H__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +/** @addtogroup PERIPH_ANCS + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Macros ANCS Exported Macros + * @{ + */ +#define ANCS_MAX_ATTR_LEN 256 //!< Max ancs attribute length + +#if F_BT_ANCS_GET_APP_ATTR +#define ANCS_APP_IDENTIFIER_MAX_LEN 30 //!< Max app IDENTIFIER length +#endif + +#define ANCS_MSG_QUEUE_NUM 5 //!< ANCS message queue size + + +/** @brief ANCS event flag */ +#define NS_EVENT_FLAG_SILENT (1 << 0) +#define NS_EVENT_FLAG_IMPORTANT (1 << 1) +#define NS_EVENT_FLAG_PRE_EXISTING (1 << 2) +#define NS_EVENT_FLAG_POSITIVE_ACTION (1 << 3) //!<A positive action exists and is associated with this iOS notification +#define NS_EVENT_FLAG_NEGATIVE_ACTION (1 << 4) //!<A negative action exists and is associated with this iOS notification. + +/** End of PERIPH_ANCS_Exported_Macros + * @} + */ + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Types ANCS Exported Types + * @{ + */ +/** @brief ANCS event id for the peer device notification */ +typedef enum +{ + NS_EVENT_ID_NOTIFICATION_ADD = 0, /**< The arrival of a new iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_MODIFIED = 1, /**< The modification of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_REMOVED = 2, /**< The removal of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_RESERVED = 0xff +} T_NS_EVENT_ID; + +/** @brief ANCS category id */ +typedef enum +{ + NS_CATEGORY_ID_OTHER = 0, + NS_CATEGORY_ID_INCOMING_CALL = 1, + NS_CATEGORY_ID_MISSED_CALL = 2, + NS_CATEGORY_ID_VOICE_MAIL = 3, + NS_CATEGORY_ID_SOCIAL = 4, + NS_CATEGORY_ID_SCHEDULE = 5, + NS_CATEGORY_ID_EMAIL = 6, + NS_CATEGORY_ID_NEWS = 7, + NS_CATEGORY_ID_HEALTH_AND_FITNESS = 8, + NS_CATEGORY_ID_BUSINESS_ADN_FINANCE = 9, + NS_CATEGORY_ID_LOCATION = 10, + NS_CATEGORY_ID_ENTERTAINMENT = 11, + NS_CATEGORY_ID_RESERVED = 255 +} T_NS_CATEGORY_ID; + +/** @brief ANCS notification attribute id */ +typedef enum +{ + DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER = 0, /**< Format: UTF-8 strings */ + DS_NOTIFICATION_ATTR_ID_TITLE = 1, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_SUB_TITLE = 2, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE = 3, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE = 4, /**<The format of the DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE constant is a string + that represents the integral value of the message size. */ + DS_NOTIFICATION_ATTR_ID_DATE = 5, /**<The format of the DS_NOTIFICATION_ATTR_ID_DATE constant is a string + that uses the Unicode Technical Standard (UTS) #35 date format pattern yyyyMMdd'T'HHmmSS. */ + DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL = 6, /**<Format: UTF-8 strings. The label used to describe + the positive action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL = 7, /**<Format: UTF-8 strings. The label used to describe + the negative action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_RESERVED = 255 +} T_DS_NOTIFICATION_ATTR_ID; + +/** @brief App parse ANCS notification attribute state */ +typedef enum +{ + DS_PARSE_NOT_START = 0x00, + DS_PARSE_GET_NOTIFICATION_COMMAND_ID = 0x01, + DS_PARSE_UID1, + DS_PARSE_UID2, + DS_PARSE_UID3, + DS_PARSE_UID4, + DS_PARSE_ATTRIBUTE_ID, + DS_PARSE_ATTRIBUTE_LEN1, + DS_PARSE_ATTRIBUTE_LEN2, + DS_PARSE_ATTRIBUTE_READY +} T_DS_NOTIFICATION_ATTR_PARSE_STATE; + +/** @brief Smart Phone App attribute id. */ +typedef enum +{ + DS_APP_ATTR_ID_DISPLAY_NAME = 0, + DS_APP_ATTR_ID_RESERVED = 255 +} T_DS_APP_ATTR_ID; + +/** @brief App parse ANCS attribute state */ +typedef enum +{ + DS_PARSE_GET_APP_COMMAND_ID = 0x10, + DS_PARSE_APP_IDENTIFIER_START, + DS_PARSE_APP_IDENTIFIER_END, + DS_PARSE_APP_ATTRIBUTE_ID, + DS_PARSE_APP_ATTRIBUTE_LEN1, + DS_PARSE_APP_ATTRIBUTE_LEN2, + DS_PARSE_APP_ATTRIBUTE_READY +} T_DS_APP_ATTR_PARSE_STATE; + +/** @brief ANCS action id state */ +typedef enum +{ + CP_ACTION_ID_POSITIVE = 0, + CP_ACTION_ID_NEGATIVE = 1, + CP_ACTION_ID_RESERVED = 255 +} T_CP_ACTION_ID_VALUES; + +/** @brief Define notification source data for record ANCS notification parameters */ +typedef struct +{ + uint8_t event_id; /**< This field informs the accessory whether the given iOS notification + was added, modified, or removed. The enumerated values for this field are defined in @ref T_NS_EVENT_ID*/ + uint8_t event_flags; /**< A bitmask whose set bits inform an NC of specificities with the iOS notification. */ + uint8_t category_id; /**< A numerical value providing a category in which the iOS notification + can be classified. The enumerated values for this field are defined in @ref T_NS_CATEGORY_ID*/ + uint8_t category_count; /**< The current number of active iOS notifications in the given category. */ + uint32_t notification_uid; /**< A 32-bit numerical value that is the unique identifier (UID) for the iOS notification.*/ +} T_NS_DATA, *P_NS_DATA; + +/** @brief Define notification attribute details data */ +/** App can acquire details information by attribute id */ +typedef struct +{ + uint8_t command_id; + uint8_t notification_uid[4]; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_NOTIFICATION_ATTR; + +/** @brief Local app record notification attribute information */ +typedef struct +{ + uint8_t command_id; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_APP_ATTR; + +/** @brief ANCS Message Type */ +typedef enum +{ + ANCS_MSG_TYPE_GET_NOTIFI_ATTR, + ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION, + ANCS_MSG_TYPE_GET_APP_ATTR, +} T_ANCS_MSG_TYPE; + +/** @brief Message data of ANCS_MSG_TYPE_GET_NOTIFI_ATTR */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t attribute_ids[14]; + uint8_t attribute_ids_len; +} T_ANCS_GET_NOTIFI_ATTR; + +/** @brief Message data of ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t action_id; +} T_ANCS_PERFORM_NOTIFI_ACTION; + +#if F_BT_ANCS_GET_APP_ATTR +/** @brief Message data of ANCS_MSG_TYPE_GET_APP_ATTR */ +typedef struct +{ + uint8_t conn_id; + char app_identifier[ANCS_APP_IDENTIFIER_MAX_LEN]; + uint8_t attribute_ids[1]; + uint8_t attribute_ids_len; +} T_ANCS_GET_APP_ATTR; +#endif + +/** @brief ANCS Message Data */ +typedef struct +{ + T_ANCS_MSG_TYPE type; + union + { + T_ANCS_GET_NOTIFI_ATTR notifi_attr; + T_ANCS_PERFORM_NOTIFI_ACTION perform_action; +#if F_BT_ANCS_GET_APP_ATTR + T_ANCS_GET_APP_ATTR app_attr; +#endif + } data; +} T_ANCS_MSG; +/** End of PERIPH_ANCS_Exported_Types + * @} + */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num); + +/** + * @brief All the ancs messages are pre-handled in this function + * @param[in] io_msg IO message data + * @return void + */ +void ancs_handle_msg(T_IO_MSG *p_io_msg); +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/DLPS/ble_peripheral/app.c b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app.c new file mode 100644 index 0000000..242570a --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app.c @@ -0,0 +1,613 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <string.h> +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_conn_le.h> +#include <gap_msg.h> +#if F_BT_ANCS_CLIENT_SUPPORT +#include <ancs_client.h> +#include "ancs.h" +#endif +#include <bas.h> +#include <simple_ble_service.h> + +#include "app.h" +#include "io_adc.h" + +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE peripheral application routines. + * @{ + */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bas_srv_id; /**< Battery service id */ +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ + +/*============================================================================* + * Functions + *============================================================================*/ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; +#if F_BT_ANCS_CLIENT_SUPPORT + case IO_MSG_TYPE_ANCS: + { + ancs_handle_msg(&io_msg); + } + break; +#endif + case IO_MSG_TYPE_ADC: + { + APP_PRINT_INFO0("[app] app_handle_io_msg: ADC data msg."); + io_handle_adc_msg(&io_msg); + //Add user code here! + } + break; + case IO_MSG_TYPE_GPIO: + { + APP_PRINT_INFO0("[app] app_handle_io_msg: gpio msg."); + io_adc_sample_start(); + //Add user code here! + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ +// le_adv_start(); + io_adc_sample_start(); + } + } + + if (gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + } + } + + gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, gap_conn_state, new_state, disc_cause); + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, remote_bd, &remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + } + break; + + default: + break; + } + gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { +#if F_BT_ANCS_CLIENT_SUPPORT + ancs_start_discovery(conn_id); +#endif + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("app_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("app_handle_conn_param_update_evt update pending."); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ + +/** @defgroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value[2] = {0x01, 0x02}; + APP_PRINT_INFO0("SIMP_READ_V1"); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + else if (service_id == bas_srv_id) + { + T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; + switch (p_bas_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_bas_cb_data->msg_data.notification_indification_index) + { + case BAS_NOTIFY_BATTERY_LEVEL_ENABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE"); + } + break; + + case BAS_NOTIFY_BATTERY_LEVEL_DISABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL) + { + uint8_t battery_level = 90; + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level); + bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level); + } + } + break; + + default: + break; + } + } + + return app_result; +} + +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @} */ /* End of group PERIPH_APP */ diff --git a/src/sample/io_sample/ADC/DLPS/ble_peripheral/app.h b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app.h new file mode 100644 index 0000000..8aed00b --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app.h @@ -0,0 +1,72 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app.h +* @brief This file handles BLE peripheral application routines. +* @author jane +* @date 2017-06-06 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +#ifndef _APP_H +#define _APP_H + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <profile_server.h> + +#include "app_msg.h" + + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bas_srv_id; /**< Battery service id */ + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg:IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * @param[in] service_id: Profile service ID + * @param[in] p_data: Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_flags.h b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_flags.h new file mode 100644 index 0000000..0b1c430 --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_flags.h @@ -0,0 +1,39 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + + +/** @defgroup PERIPH_Config Peripheral App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +/** @brief Config DLPS: 0-Disable DLPS, 1-Enable DLPS */ +#define F_BT_DLPS_EN 0 +/** @brief Config ANCS Client: 0-Not built in, 1-Open ANCS client function */ +#define F_BT_ANCS_CLIENT_SUPPORT 0 +#define F_BT_ANCS_APP_FILTER (F_BT_ANCS_CLIENT_SUPPORT & 1) +#define F_BT_ANCS_GET_APP_ATTR (F_BT_ANCS_CLIENT_SUPPORT & 0) +/** @brief Config ANCS Client debug log: 0-close, 1-open */ +#define F_BT_ANCS_CLIENT_DEBUG (F_BT_ANCS_CLIENT_SUPPORT & 0) + +/** @} */ /* End of group PERIPH_Config */ +#endif diff --git a/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_task.c b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_task.c new file mode 100644 index 0000000..0580a66 --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_task.c @@ -0,0 +1,124 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> +#include "app.h" +#include "app_task.h" +#include "io_adc.h" + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 4 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +extern void driver_init(void); + +void app_main_task(void *p_param); + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg) +{ + uint8_t event = EVENT_IO_TO_APP; + + if (os_msg_send(io_queue_handle, p_msg, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_io_msg_to_app fail"); + return false; + } + if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_evt_msg_to_app fail"); + return false; + } + return true; +} + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param: Parameters sending to the task + * @return void + */ +//uint8_t String_Buf[100]; +void app_main_task(void *p_param) +{ + uint8_t event; + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + driver_init(); + + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** @} */ /* End of group PERIPH_APP_TASK */ + + diff --git a/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_task.h b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_task.h new file mode 100644 index 0000000..bd16830 --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/ble_peripheral/app_task.h @@ -0,0 +1,46 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app_task.h +* @brief Routines to create App task and handle events & messages +* @author jane +* @date 2017-06-02 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#include <string.h> + +#include "os_msg.h" +#include "os_queue.h" +#include "os_sched.h" +#include "os_task.h" +#include "os_timer.h" + +#include "app_msg.h" + +#include "trace.h" + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg); + +/** + * @brief Initialize app task + * @return void + */ +void app_task_init(void); + +#endif + diff --git a/src/sample/io_sample/ADC/DLPS/ble_peripheral/main.c b/src/sample/io_sample/ADC/DLPS/ble_peripheral/main.c new file mode 100644 index 0000000..968e5d5 --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/ble_peripheral/main.c @@ -0,0 +1,308 @@ +/** +***************************************************************************************** +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file main.c +* @brief Source file for BLE peripheral project, mainly used for initialize modules +* @author yuan +* @date 2017-06-12 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2018 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <string.h> +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_msg.h> +#include <bas.h> +#include <simple_ble_service.h> + +#if F_BT_ANCS_CLIENT_SUPPORT +#include <profile_client.h> +#include "ancs.h" +#endif + +#include "app.h" +#include "app_task.h" +#include "app_flags.h" +#include "dlps.h" +#include "io_adc.h" + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + + +/*============================================================================* + * Variables + *============================================================================*/ + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x0F, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'L', 'E', '_', 'P', 'E', 'R', 'I', 'P', 'H', 'E', 'R', 'A', 'L', +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_PERIPHERAL"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; +#if F_BT_ANCS_CLIENT_SUPPORT + uint8_t auth_sec_req_enable = true; +#else + uint8_t auth_sec_req_enable = false; +#endif + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(app_gap_callback); +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void app_le_profile_init(void) +{ + server_init(2); + simp_srv_id = simp_ble_service_add_service(app_profile_callback); + bas_srv_id = bas_add_service(app_profile_callback); + server_register_app_cb(app_profile_callback); +#if F_BT_ANCS_CLIENT_SUPPORT + client_init(1); + ancs_init(APP_MAX_LINKS); +#endif +} + +void global_data_init(void) +{ + global_data_adc_init(); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be performed with the IO initializing. + * @return void + */ +void board_init(void) +{ + board_adc_init(); + board_gpio_init(); +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void driver_init(void) +{ + driver_adc_init(); + driver_gpio_init(); +} + +#if DLPS_EN +/** + * @brief this function will be called before enter DLPS + * + * set PAD and wakeup pin config for enterring DLPS + * + * @param none + * @return none + * @retval void + */ +void app_enter_dlps_config(void) +{ + io_adc_dlps_enter(); +} + +/** + * @brief this function will be called after exit DLPS + * + * set PAD and wakeup pin config for enterring DLPS + * + * @param none + * @return none + * @retval void + */ +void app_exit_dlps_config(void) +{ + io_adc_dlps_exit(); +} + +/** + * @brief Contains the setting about app dlps callback. + */ +bool app_dlps_check_cb(void) +{ + return (io_adc_dlps_check()); +} +#endif /* DLPS_EN */ + +/** + * @brief The setting about power mode. + * @param No parameter. + * @return void + */ +void pwr_mgr_init(void) +{ +#if DLPS_EN + if (false == dlps_check_cb_reg(app_dlps_check_cb)) + { + APP_PRINT_ERROR0("Error: dlps_check_cb_reg(app_dlps_check_cb) failed!"); + } + DLPS_IORegUserDlpsEnterCb(app_enter_dlps_config); + DLPS_IORegUserDlpsExitCb(app_exit_dlps_config); + DLPS_IORegister(); + lps_mode_set(PLATFORM_DLPS_PFM); + + /* Config WakeUp pin */ + System_WakeUpPinEnable(ADC_DLPS_WAKEUP_PIN, PAD_WAKEUP_POL_LOW, 0); +#else + lps_mode_set(LPM_ACTIVE_MODE); +#endif +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void task_init(void) +{ + app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int main(void) +{ + global_data_init(); + board_init(); + le_gap_init(APP_MAX_LINKS); + gap_lib_init(); + app_le_gap_init(); + app_le_profile_init(); + pwr_mgr_init(); + task_init(); + os_sched_start(); + + return 0; +} +/** @} */ /* End of group PERIPH_DEMO_MAIN */ + +/** + * @brief System interrupt handler function, for wakeup pin. + * @param No parameter. + * @return void +*/ +void System_Handler(void) +{ + if (System_WakeUpInterruptValue(ADC_DLPS_WAKEUP_PIN) == SET) + { + APP_PRINT_INFO0("System_Handler"); + Pad_ClearWakeupINTPendingBit(ADC_DLPS_WAKEUP_PIN); + System_WakeUpPinDisable(ADC_DLPS_WAKEUP_PIN); + IO_ADC_DLPS_Enter_Allowed = false; + } +} + +/******************* (C) COPYRIGHT 2018 Realtek Semiconductor Corporation *****END OF FILE****/ + diff --git a/src/sample/io_sample/ADC/DLPS/io_adc.c b/src/sample/io_sample/ADC/DLPS/io_adc.c new file mode 100644 index 0000000..be49b1f --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/io_adc.c @@ -0,0 +1,269 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file io_uart.c +* @brief uart interrupt demo +* @details +* @author yuan +* @date 2018-06-28 +* @version v0.1 +********************************************************************************************************* +*/ + +/* Includes ------------------------------------------------------------------*/ +#include "io_adc.h" +#include <string.h> +#include "app_task.h" + +/* Globals ------------------------------------------------------------------*/ +uint16_t ADC_DATA_Buffer[32]; +uint8_t ADC_DATA_Length = 0; + +bool IO_ADC_DLPS_Enter_Allowed = false; + +/** + * @brief Initialize uart global data. + * @param No parameter. + * @return void + */ +void global_data_adc_init(void) +{ + IO_ADC_DLPS_Enter_Allowed = true; + ADC_DATA_Length = 0; + memset(ADC_DATA_Buffer, 0, sizeof(ADC_DATA_Buffer)); +} + +void board_adc_init(void) +{ + Pad_Config(ADC_SAMPLE_PIN_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); + + Pad_Config(ADC_SAMPLE_PIN_1, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); +} + +/** + * @brief Initialize adc peripheral. + * @param No parameter. + * @return void +*/ +void driver_adc_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE); + + ADC_InitTypeDef ADC_InitStruct; + ADC_StructInit(&ADC_InitStruct); + + ADC_InitStruct.ADC_SampleTime = 255; /* (n + 1) cycle of 10MHz,n = 0~255 or n = 2048~14591 */ + + ADC_InitStruct.ADC_SchIndex[0] = INTERNAL_VBAT_MODE; + ADC_InitStruct.ADC_Bitmap = 0x01; + + ADC_InitStruct.ADC_PowerAlwaysOnEn = ADC_POWER_ALWAYS_ON_ENABLE; + ADC_Init(ADC, &ADC_InitStruct); + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + /* High bypass resistance mode config, please notice that the input voltage of + adc channel using high bypass mode should not be over 0.9V */ + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, ENABLE); + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_1, ENABLE); +#endif + + ADC_INTConfig(ADC, ADC_INT_ONE_SHOT_DONE, ENABLE); + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = ADC_IRQn; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); +} + + +/** + * @brief Initialization of pinmux settings and pad settings. + * @param No parameter. + * @return void + */ +void board_gpio_init(void) +{ + Pad_Config(ADC_DLPS_WAKEUP_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, + PAD_OUT_HIGH); + + Pinmux_Config(ADC_DLPS_WAKEUP_PIN, DWGPIO); +} + +/** + * @brief Initialize GPIO peripheral. + * @param No parameter. + * @return void + */ +void driver_gpio_init(void) +{ + /* Initialize GPIO peripheral */ + RCC_PeriphClockCmd(APBPeriph_GPIO, APBPeriph_GPIO_CLOCK, ENABLE); + + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = GPIO_PIN_INPUT; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStruct.GPIO_ITCmd = ENABLE; + GPIO_InitStruct.GPIO_ITTrigger = GPIO_INT_Trigger_EDGE; + GPIO_InitStruct.GPIO_ITPolarity = GPIO_INT_POLARITY_ACTIVE_LOW; + GPIO_InitStruct.GPIO_ITDebounce = GPIO_INT_DEBOUNCE_ENABLE; + GPIO_InitStruct.GPIO_DebounceTime = 64;/* unit:ms , can be 1~64 ms */ + GPIO_Init(&GPIO_InitStruct); + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = GPIO_PIN_INPUT_IRQN; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + + GPIO_MaskINTConfig(GPIO_PIN_INPUT, DISABLE); + GPIO_INTConfig(GPIO_PIN_INPUT, ENABLE); +} + +/** + * @brief IO enter dlps call back function. + * @param No parameter. + * @return void + */ +void io_adc_dlps_enter(void) +{ + uint8_t reg_value = 0; + reg_value = btaon_fast_read_safe(0x113); + btaon_fast_write(0x113, reg_value | 0x04); + /* Switch pad to Software mode */ + Pad_ControlSelectValue(ADC_DLPS_WAKEUP_PIN, PAD_SW_MODE); + System_WakeUpPinEnable(ADC_DLPS_WAKEUP_PIN, PAD_WAKEUP_POL_LOW, 0); + DBG_DIRECT("io_adc_dlps_enter"); +} + +/** + * @brief IO exit dlps call back function. + * @param No parameter. + * @return void + */ +void io_adc_dlps_exit(void) +{ + uint8_t reg_value = 0; + reg_value = btaon_fast_read_safe(0x113); + btaon_fast_write(0x113, reg_value & (~0x04)); + /* Switch pad to Pinmux mode */ + Pad_ControlSelectValue(ADC_DLPS_WAKEUP_PIN, PAD_PINMUX_MODE); + DBG_DIRECT("io_adc_dlps_exit"); +} + +/** + * @brief IO enter dlps check function. + * @param No parameter. + * @return void + */ +bool io_adc_dlps_check(void) +{ + return IO_ADC_DLPS_Enter_Allowed; +} + +/** + * @brief Handle uart data function. + * @param No parameter. + * @return void + */ +void io_adc_handle_msg(T_IO_MSG *io_adc_msg) +{ + uint16_t *p_buf = io_adc_msg->u.buf; + uint16_t type = io_adc_msg->type; + + if (IO_MSG_TYPE_ADC == type) + { + DBG_DIRECT("io_adc_handle_msg: len = %d", ADC_DATA_Length); + for (uint8_t i = 0; i < ADC_DATA_Length; i++) + { + DBG_DIRECT("adc raw data = 0x%X", p_buf[i]); + } + platform_delay_ms(1000); + IO_ADC_DLPS_Enter_Allowed = true; + } +} + +/** + * @brief Handle uart msg function. + * @param No parameter. + * @return void + */ +void io_handle_adc_msg(T_IO_MSG *io_adc_msg) +{ + io_adc_handle_msg(io_adc_msg); +} + +/** + * @brief IO enter dlps check function. + * @param No parameter. + * @return void + */ +void io_adc_sample_start(void) +{ + ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE); +} + +/** + * @brief ADC interrupt handler function. + * @param No parameter. + * @return void +*/ +void ADC_Handler(void) +{ + uint16_t sample_data[32]; + + if (ADC_GetINTStatus(ADC, ADC_INT_ONE_SHOT_DONE) == SET) + { + ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE); + + /* Send msg to app task */ + ADC_DATA_Length = 1; + sample_data[0] = ADC_ReadRawData(ADC, ADC_Schedule_Index_0); + + ADC_DATA_Buffer[0] = sample_data[0]; + T_IO_MSG int_adc_msg; + + int_adc_msg.type = IO_MSG_TYPE_ADC; + int_adc_msg.u.buf = (void *)(&ADC_DATA_Buffer); + if (false == app_send_msg_to_apptask(&int_adc_msg)) + { + APP_PRINT_ERROR0("[io_adc] ADC_Handler: Send int_adc_msg failed!"); + //Add user code here! + return; + } + } +} + +/** + * @brief GPIO interrupt handler function. + * @param No parameter. + * @return void + */ +void GPIO_Input_Handler(void) +{ + DBG_DIRECT("GPIO_Input_Handler"); + GPIO_INTConfig(GPIO_PIN_INPUT, DISABLE); + GPIO_MaskINTConfig(GPIO_PIN_INPUT, ENABLE); + + T_IO_MSG int_gpio_msg; + + int_gpio_msg.type = IO_MSG_TYPE_GPIO; + int_gpio_msg.subtype = 0; + if (false == app_send_msg_to_apptask(&int_gpio_msg)) + { + APP_PRINT_ERROR0("[io_gpio] GPIO_Input_Handler: Send int_gpio_msg failed!"); + //Add user code here! + GPIO_ClearINTPendingBit(GPIO_PIN_INPUT); + return; + } + + GPIO_ClearINTPendingBit(GPIO_PIN_INPUT); + GPIO_MaskINTConfig(GPIO_PIN_INPUT, DISABLE); + GPIO_INTConfig(GPIO_PIN_INPUT, ENABLE); +} + +/******************* (C) COPYRIGHT 2018 Realtek Semiconductor Corporation *****END OF FILE****/ diff --git a/src/sample/io_sample/ADC/DLPS/io_adc.h b/src/sample/io_sample/ADC/DLPS/io_adc.h new file mode 100644 index 0000000..71582fb --- /dev/null +++ b/src/sample/io_sample/ADC/DLPS/io_adc.h @@ -0,0 +1,78 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.h +* @brief +* @details +* @author yuan +* @date 2018-12-07 +* @version v1.0 +********************************************************************************************************* +*/ + +#ifndef __IO_ADC_H +#define __IO_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "rtl876x_adc.h" +#include "rtl876x_gpio.h" +#include "rtl876x_io_dlps.h" +#include "rtl876x_nvic.h" +#include "rtl876x_pinmux.h" +#include "rtl876x_rcc.h" +#include "rtl876x_tim.h" + +#include "app_msg.h" +#include "board.h" + +/* Defines --------------------------------------------------------------*/ +/** ADC sample channel config. + * ADC sample channel config:P2_2,P2_3,P2_6,P2_7 and VBAT + * ADC sample channel index select: #define ADC_Channel_Index_0 0 + * #define ADC_Channel_Index_1 1 + * #define ADC_Channel_Index_2 2 + * #define ADC_Channel_Index_3 3 + + * If ADC_SAMPLE_PIN = P2_2, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_0; + * If ADC_SAMPLE_PIN = P2_3, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_1; + * If ADC_SAMPLE_PIN = P2_6, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_2; + * If ADC_SAMPLE_PIN = P2_7, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_3; + */ +#define ADC_SAMPLE_CHANNEL_0 ADC_Channel_Index_0 +#define ADC_SAMPLE_CHANNEL_1 ADC_Channel_Index_1 + +/* Config ADC channel and mode --------------------------------------------------------------*/ +/* ADC bypass mode or divide mode */ +#define ADC_DIVIDE_MODE 0 +#define ADC_BYPASS_MODE 1 +#define ADC_MODE_DIVIDE_OR_BYPASS ADC_DIVIDE_MODE + +#define TIMER_ADC_ONE_SHOT_SAMPLE_PERIOD (100-1)//10us + +/* Globals ------------------------------------------------------------------*/ +extern bool IO_ADC_DLPS_Enter_Allowed; + +void global_data_adc_init(void); +void board_adc_init(void); +void driver_adc_init(void); +void board_gpio_init(void); +void driver_gpio_init(void); +void io_adc_dlps_enter(void); +void io_adc_dlps_exit(void); +bool io_adc_dlps_check(void); +void io_handle_adc_msg(T_IO_MSG *io_adc_msg); +void io_adc_sample_start(void); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode+GDMA/main.c b/src/sample/io_sample/ADC/OneShotMode+GDMA/main.c new file mode 100644 index 0000000..0550279 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode+GDMA/main.c @@ -0,0 +1,300 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file main.c +* @brief +* @details +* @author yuan +* @date 2021-06-09 +* @version v0.1 +********************************************************************************************************* +*/ + +/* Includes ------------------------------------------------------------------*/ +#include "rtl876x_adc.h" +#include "rtl876x_gdma.h" +#include "rtl876x_nvic.h" +#include "rtl876x_pinmux.h" +#include "rtl876x_rcc.h" +#include "rtl876x_tim.h" +#include "trace.h" + +/* Defines --------------------------------------------------------------*/ +#define ADC_Channel_Index_0 0 +#define ADC_Channel_Index_1 1 +#define ADC_Channel_Index_2 2 +#define ADC_Channel_Index_3 3 + + +#define ADC_Schedule_Index_0 0 +#define ADC_Schedule_Index_1 1 +#define ADC_Schedule_Index_2 2 +#define ADC_Schedule_Index_3 3 +#define ADC_Schedule_Index_4 4 +#define ADC_Schedule_Index_5 5 +#define ADC_Schedule_Index_6 6 +#define ADC_Schedule_Index_7 7 +#define ADC_Schedule_Index_8 8 +#define ADC_Schedule_Index_9 9 +#define ADC_Schedule_Index_10 10 +#define ADC_Schedule_Index_11 11 +#define ADC_Schedule_Index_12 12 +#define ADC_Schedule_Index_13 13 +#define ADC_Schedule_Index_14 14 +#define ADC_Schedule_Index_15 15 + + +/* Config ADC channel and mode --------------------------------------------------------------*/ +//ADC bypass mode or divide mode +#define ADC_DIVIDE_MODE 0 +#define ADC_BYPASS_MODE 1 +#define ADC_MODE_DIVIDE_OR_BYPASS ADC_DIVIDE_MODE + +/** ADC sample channel config. + * ADC sample channel config:P2_2,P2_3,P2_6,P2_7 and VBAT + * ADC sample channel index select: #define ADC_Channel_Index_0 0 + * #define ADC_Channel_Index_1 1 + * #define ADC_Channel_Index_2 2 + * #define ADC_Channel_Index_3 3 + + * If ADC_SAMPLE_PIN = P2_2, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_0; + * If ADC_SAMPLE_PIN = P2_3, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_1; + * If ADC_SAMPLE_PIN = P2_6, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_2; + * If ADC_SAMPLE_PIN = P2_7, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_3; + */ +#define ADC_SAMPLE_PIN_0 P2_2 +#define ADC_SAMPLE_PIN_1 P2_3 +#define ADC_SAMPLE_CHANNEL_0 ADC_Channel_Index_0 +#define ADC_SAMPLE_CHANNEL_1 ADC_Channel_Index_1 + +#define ADC_GDMA_CHANNEL_NUM 2 +#define ADC_GDMA_Channel GDMA_Channel2 +#define ADC_GDMA_Channel_IRQn GDMA0_Channel2_IRQn +#define ADC_GDMA_Channel_Handler GDMA0_Channel2_Handler +#define GDMA_TRANSFER_SIZE 2 + +#define TIMER_ADC_ONE_SHOT_SAMPLE_PERIOD (100)//100us + + +/* Globals --------------------------------------------------------------*/ +uint16_t ADC_Recv_Data_Buffer[GDMA_TRANSFER_SIZE]; + +/* Functions --------------------------------------------------------------*/ +/** + * @brief Initialization of pinmux settings and pad settings. + * @param No parameter. + * @return void +*/ +void board_adc_init(void) +{ + Pad_Config(ADC_SAMPLE_PIN_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); + + Pad_Config(ADC_SAMPLE_PIN_1, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); +} + +/** + * @brief Initialize adc peripheral. + * @param No parameter. + * @return void +*/ +void driver_adc_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE); + + ADC_InitTypeDef ADC_InitStruct; + ADC_StructInit(&ADC_InitStruct); + + ADC_InitStruct.ADC_DataWriteToFifo = ADC_DATA_WRITE_TO_FIFO_ENABLE; + ADC_InitStruct.ADC_WaterLevel = 0x4; + ADC_InitStruct.ADC_SchIndex[0] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_0); + ADC_InitStruct.ADC_SchIndex[1] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_1); + ADC_InitStruct.ADC_Bitmap = 0x03; + ADC_InitStruct.ADC_TimerTriggerEn = ADC_TIMER_TRIGGER_ENABLE; + ADC_InitStruct.ADC_PowerAlwaysOnEn = ADC_POWER_ALWAYS_ON_ENABLE; + ADC_InitStruct.ADC_SampleTime = 20 - + 1; /* (n + 1) cycle of 10MHz,n = 0~255 or n = 2048~14591 */ + + ADC_Init(ADC, &ADC_InitStruct); + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + /* High bypass resistance mode config, please notice that the input voltage of + adc channel using high bypass mode should not be over 0.9V */ + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, ENABLE); + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_1, ENABLE); +#endif + + ADC_INTConfig(ADC, ADC_INT_FIFO_RD_ERR, ENABLE); + ADC_INTConfig(ADC, ADC_INT_FIFO_OVERFLOW, ENABLE); + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = ADC_IRQn; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); +} + +/** + * @brief Initialize timer peripheral for adc one shot mode. + * @param No parameter. + * @return void +*/ +void driver_adc_timer_init(void) +{ + /* TIM7 for timing voltage acqusition(fix) */ + RCC_PeriphClockCmd(APBPeriph_TIMER, APBPeriph_TIMER_CLOCK, ENABLE); + + TIM_TimeBaseInitTypeDef TIM_InitStruct; + + TIM_StructInit(&TIM_InitStruct); + + TIM_InitStruct.TIM_PWM_En = PWM_DISABLE; + TIM_InitStruct.TIM_Period = TIMER_ADC_ONE_SHOT_SAMPLE_PERIOD - 1 ; //sampling once 1 second + TIM_InitStruct.TIM_Mode = TIM_Mode_UserDefine; + TIM_InitStruct.TIM_SOURCE_DIV = TIM_CLOCK_DIVIDER_40; + TIM_TimeBaseInit(TIM2, &TIM_InitStruct); + + TIM_ClearINT(TIM2); + TIM_Cmd(TIM2, ENABLE); +} + +/** + * @brief Initialize gdma peripheral. + * @param No parameter. + * @return void +*/ +void driver_adc_gdma_init(void) +{ + /* Initialize data buffer which for storing data from adc */ + for (uint32_t i = 0; i < GDMA_TRANSFER_SIZE; i++) + { + ADC_Recv_Data_Buffer[i] = 0; + } + + /* GDMA init */ + GDMA_InitTypeDef GDMA_InitStruct; + GDMA_StructInit(&GDMA_InitStruct); + + GDMA_InitStruct.GDMA_ChannelNum = ADC_GDMA_CHANNEL_NUM; + GDMA_InitStruct.GDMA_DIR = GDMA_DIR_PeripheralToMemory; + GDMA_InitStruct.GDMA_BufferSize = GDMA_TRANSFER_SIZE;//Determine total transfer size + GDMA_InitStruct.GDMA_SourceInc = DMA_SourceInc_Fix; + GDMA_InitStruct.GDMA_DestinationInc = DMA_DestinationInc_Inc; + GDMA_InitStruct.GDMA_SourceDataSize = GDMA_DataSize_HalfWord; + GDMA_InitStruct.GDMA_DestinationDataSize = GDMA_DataSize_HalfWord; + GDMA_InitStruct.GDMA_SourceMsize = GDMA_Msize_4; + GDMA_InitStruct.GDMA_DestinationMsize = GDMA_Msize_4; + GDMA_InitStruct.GDMA_SourceAddr = (uint32_t)(&(ADC->FIFO)); + GDMA_InitStruct.GDMA_DestinationAddr = (uint32_t)ADC_Recv_Data_Buffer; + GDMA_InitStruct.GDMA_SourceHandshake = GDMA_Handshake_ADC; + + GDMA_Init(ADC_GDMA_Channel, &GDMA_InitStruct); + + GDMA_INTConfig(ADC_GDMA_CHANNEL_NUM, GDMA_INT_Transfer, ENABLE); + + /* GDMA irq init */ + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = ADC_GDMA_Channel_IRQn; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + + /* Start to receive data */ + GDMA_Cmd(ADC_GDMA_CHANNEL_NUM, ENABLE); +} + +/** + * @brief Demo code of operation about adc. + * @param No parameter. + * @return void +*/ +void adc_demo(void) +{ +// ADC_CalibrationInit(); + /* Configure pad and pinmux firstly! */ + board_adc_init(); + /* Initialize adc peripheral */ + driver_adc_init(); + /* Initialize timer peripheral */ + driver_adc_timer_init(); + /* Initialize dma peripheral */ + driver_adc_gdma_init(); + + ADC_ClearFIFO(ADC); + ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE); +} + +/** + * @brief Entry of app code + * @return int (To avoid compile warning) + */ +int main(void) +{ + __enable_irq(); + adc_demo(); + + while (1) + { + __nop(); + __nop(); + __nop(); + __nop(); + __nop(); + __nop(); + } +} + + +/** + * @brief ADC interrupt handler function. + * @param No parameter. + * @return void +*/ +void ADC_Handler(void) +{ + DBG_DIRECT("ADC_Handler!"); + if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_RD_ERR) == SET) + { + DBG_DIRECT("ADC_INT_FIFO_RD_ERR"); + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_RD_ERR); + // Add user code here! + } + if (ADC_GetINTStatus(ADC, ADC_INT_FIFO_OVERFLOW) == SET) + { + DBG_DIRECT("ADC_INT_FIFO_OVERFLOW"); + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_OVERFLOW); + // Add user code here! + } +} + +/** + * @brief GDMA channel interrupt handler function. + * @param No parameter. + * @return void +*/ +void ADC_GDMA_Channel_Handler(void) +{ + TIM_Cmd(TIM2, DISABLE); + DBG_DIRECT("ADC_GDMA_Channel_Handler!"); + for (uint32_t i = 0; i < GDMA_TRANSFER_SIZE; i++) + { + DBG_DIRECT("ADC_GDMA_Channel_Handler: data[%d] = %d", i, ADC_Recv_Data_Buffer[i]); + } +// ADC_ErrorStatus error_status = NO_ERROR; +// for (uint32_t i = 0; i < GDMA_TRANSFER_SIZE; i++) +// { +// DBG_DIRECT("ADC sample data[%d] = %10d %10.2f", i, ADC_Recv_Data_Buffer[i], +// ADC_GetVoltage(DIVIDE_SINGLE_MODE, ADC_Recv_Data_Buffer[i], +// &error_status)); +// } + GDMA_SetSourceAddress(ADC_GDMA_Channel, (uint32_t)(&(ADC->FIFO))); + GDMA_SetDestinationAddress(ADC_GDMA_Channel, (uint32_t)(ADC_Recv_Data_Buffer)); + GDMA_SetBufferSize(ADC_GDMA_Channel, GDMA_TRANSFER_SIZE); + GDMA_ClearINTPendingBit(ADC_GDMA_CHANNEL_NUM, GDMA_INT_Transfer); + GDMA_Cmd(ADC_GDMA_CHANNEL_NUM, ENABLE); + ADC_ClearFIFO(ADC); + TIM_Cmd(TIM2, ENABLE); +} + diff --git a/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/ancs.c b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/ancs.c new file mode 100644 index 0000000..ac3254e --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/ancs.c @@ -0,0 +1,662 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ancs.c + * @brief This file handles ANCS Client routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#if F_BT_ANCS_CLIENT_SUPPORT +#include <trace.h> +#include <string.h> +#include <os_msg.h> +#include <os_mem.h> +#include <ancs.h> +#include <ancs_client.h> + +/** @defgroup PERIPH_ANCS Peripheral ANCS + * @brief Apple ANCS service modulization + * @{ + */ +/*============================================================================* + * Types + *============================================================================*/ +typedef struct +{ + uint8_t m_parse_state; + uint8_t app_type; + uint16_t current_len; + void *ancs_queue_handle; + uint8_t *ptr; + T_DS_NOTIFICATION_ATTR notification_attr; +#if F_BT_ANCS_GET_APP_ATTR + T_DS_APP_ATTR app_attr; +#endif +} T_APP_ANCS_LINK; + +/*============================================================================* + * Variables + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Variables ANCS Exported Variables + * @brief app register ancs client to upperstack, and return ancs client id + * @{ + */ +T_CLIENT_ID ancs_client; /**< ancs client id*/ + +T_APP_ANCS_LINK *ancs_link_table; +uint8_t ancs_link_number; + +/** End of PERIPH_ANCS_Exported_Variables + * @} + */ +extern void *evt_queue_handle; //!< Event queue handle +extern void *io_queue_handle; //!< IO queue handle +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +void ancs_send_msg_to_app(uint8_t conn_id) +{ + T_IO_MSG io_msg; + uint8_t event = EVENT_IO_TO_APP; + io_msg.type = IO_MSG_TYPE_ANCS; + io_msg.subtype = 0; + io_msg.u.param = conn_id; + + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail1"); + } + else if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail2"); + } +} + +void app_handle_notification_attribute_data(T_APP_ANCS_LINK *p_ancs_link) +{ + if (p_ancs_link->notification_attr.attribute_id != DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + uint8_t *p_value = p_ancs_link->notification_attr.data; + +#if F_BT_ANCS_APP_FILTER + //filter QQ , wechat , short message and incoming call + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: app identifiter %s", TRACE_STRING(p_value)); +#endif + //wechat + if (0 == memcmp(p_value, "com.tencent.xin", 16)) + { + p_ancs_link->app_type = 1; + } + else if (0 == memcmp(p_value, "com.apple.MobileSMS", 20)) + { + p_ancs_link->app_type = 2; + } + else if (0 == memcmp(p_value, "com.apple.mobilephone", 22)) + { + p_ancs_link->app_type = 3; + } + else if (0 == memcmp(p_value, "com.tencent.mqq", 16)) + { + p_ancs_link->app_type = 4; + } + else if (0 == memcmp(p_value, "com.tencent.qq", 15)) + { + p_ancs_link->app_type = 5; + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_MESSAGE) + { + if (p_ancs_link->app_type == 2) + { + APP_PRINT_INFO1("MobileSMS: message %s", TRACE_STRING(p_value)); + } + else if (p_ancs_link->app_type == 5) + { + APP_PRINT_INFO1("QQ: message %s", TRACE_STRING(p_value)); + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_DATE) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: date %s", TRACE_STRING(p_value)); +#endif + } +#endif + } + else/* All attributes has been parased*/ + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO0("parse notify attr: parse done"); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } +} + +void app_parse_notification_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_NOTIFICATION_COMMAND_ID: + p_ancs_link->notification_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID1; + break; + + case DS_PARSE_UID1: + p_ancs_link->notification_attr.notification_uid[0] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID2; + break; + + case DS_PARSE_UID2: + p_ancs_link->notification_attr.notification_uid[1] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID3; + break; + + case DS_PARSE_UID3: + p_ancs_link->notification_attr.notification_uid[2] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID4; + break; + + case DS_PARSE_UID4: + p_ancs_link->notification_attr.notification_uid[3] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + break; + + case DS_PARSE_ATTRIBUTE_ID: + p_ancs_link->notification_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_ATTRIBUTE_LEN1: + p_ancs_link->notification_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_ATTRIBUTE_LEN2: + p_ancs_link->notification_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->notification_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse notify attr: attribute_id %d, attribute_len %d", + p_ancs_link->notification_attr.attribute_id, + p_ancs_link->notification_attr.attribute_len + ); +#endif + if (p_ancs_link->notification_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + } + if (p_ancs_link->notification_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse notify attr: error, attribute_len %d > max length %d", + p_ancs_link->notification_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } + break; + + case DS_PARSE_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->notification_attr.attribute_len) + { + /*An attribute is always a string whose length in bytes is provided in the tuple but that is not NULL-terminated.*/ + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: data %b", + TRACE_BINARY(p_ancs_link->notification_attr.attribute_len, + p_ancs_link->notification_attr.data)); +#endif + app_handle_notification_attribute_data(p_ancs_link); + } + break; + } + } +} + +#if F_BT_ANCS_GET_APP_ATTR +void app_parse_app_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_APP_COMMAND_ID: + p_ancs_link->app_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_START; + break; + + case DS_PARSE_APP_IDENTIFIER_START: + if (p_data[i] == 0x00) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_END; + + if (i + 1 == len) + { + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + else + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + } + + } + break; + + case DS_PARSE_APP_ATTRIBUTE_ID: + p_ancs_link->app_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN1: + p_ancs_link->app_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN2: + p_ancs_link->app_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->app_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse app attr: attribute_id %d, attribute_len %d", + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len + ); +#endif + if (p_ancs_link->app_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + + } + if (p_ancs_link->app_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse app attr: error, attribute_len %d > max length %d", + p_ancs_link->app_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + break; + + case DS_PARSE_APP_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->app_attr.attribute_len) + { + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO4("parse app attr: command_id 0x%x, attribute_id 0x%x, attribute_len %d, data %s", + p_ancs_link->app_attr.command_id, + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len, + TRACE_STRING(p_ancs_link->app_attr.data)); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + + } + break; + } + } +} +#endif + +/** + * @brief Parse ancs data source notification + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @param[in] len data length + * @return void + */ +void app_parse_data_soucre_notifications(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + APP_PRINT_INFO2("ANCS_FROM_DATA_SOURCE: conn_id %d, len =%d", conn_id, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("data = %b", TRACE_BINARY(len, p_data)); +#endif + T_APP_ANCS_LINK *p_ancs_link = &ancs_link_table[conn_id]; + +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("m_parse_state %d", p_ancs_link->m_parse_state); +#endif + if (p_ancs_link->m_parse_state == DS_PARSE_NOT_START) + { + if (len >= 1 && p_data[0] == CP_CMD_ID_GET_NOTIFICATION_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_NOTIFICATION_COMMAND_ID; + } +#if F_BT_ANCS_GET_APP_ATTR + else if (len >= 1 && p_data[0] == CP_CMD_ID_GET_APP_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_APP_COMMAND_ID; + } +#endif + } + + if (p_ancs_link->m_parse_state < DS_PARSE_GET_APP_COMMAND_ID) + { + app_parse_notification_attribute(p_ancs_link, p_data, len); + } +#if F_BT_ANCS_GET_APP_ATTR + else + { + app_parse_app_attribute(p_ancs_link, p_data, len); + } +#endif +} + +void app_parse_notification_source_data(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + if (8 == len) + { + T_NS_DATA ns_data; + + memcpy(&ns_data, p_data, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO5("app_parse_notification_source_data: event_id %d, event_flags 0x%02x, category_id %d, category_count %d, notification_uid 0x%08x", + ns_data.event_id, + ns_data.event_flags, + ns_data.category_id, + ns_data.category_count, + ns_data.notification_uid + ); + APP_PRINT_INFO5("event_flags: slient %d, important %d, pre existing %d, positive action %d, negative action %d ", + ns_data.event_flags & NS_EVENT_FLAG_SILENT, + ns_data.event_flags & NS_EVENT_FLAG_IMPORTANT, + ns_data.event_flags & NS_EVENT_FLAG_PRE_EXISTING, + ns_data.event_flags & NS_EVENT_FLAG_POSITIVE_ACTION, + ns_data.event_flags & NS_EVENT_FLAG_NEGATIVE_ACTION + ); +#endif + //you can filter by category_id here, for demo purpose, we didn't filter any CategoryID here. +#if F_BT_ANCS_APP_FILTER + //filter social and other category & phone category & email category + if (ns_data.category_id == NS_CATEGORY_ID_SOCIAL || + ns_data.category_id == NS_CATEGORY_ID_OTHER || + ns_data.category_id == NS_CATEGORY_ID_INCOMING_CALL || + ns_data.category_id == NS_CATEGORY_ID_EMAIL) + { +#endif + if (ns_data.event_id != NS_EVENT_ID_NOTIFICATION_REMOVED) + { + uint32_t msg_num; + T_ANCS_MSG ancs_msg; + uint8_t attr_id_list[14]; + uint8_t cur_index = 0; + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_SUB_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_DATE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL; + + os_msg_queue_peek(ancs_link_table[conn_id].ancs_queue_handle, &msg_num); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("app_parse_notification_source_data: msg_num %d", msg_num); +#endif + if (msg_num == 0) + { + if (ancs_get_notification_attr(conn_id, ns_data.notification_uid, attr_id_list, + cur_index) == true) + { + return; + } + } + + ancs_msg.type = ANCS_MSG_TYPE_GET_NOTIFI_ATTR; + ancs_msg.data.notifi_attr.conn_id = conn_id; + ancs_msg.data.notifi_attr.notification_uid = ns_data.notification_uid; + ancs_msg.data.notifi_attr.attribute_ids_len = cur_index; + memcpy(ancs_msg.data.notifi_attr.attribute_ids, attr_id_list, cur_index); + if (os_msg_send(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_ERROR0("app_parse_notification_source_data: discard, msg queue is full"); + } + } +#if F_BT_ANCS_APP_FILTER + } +#endif + } +} + +/** + * @brief Ancs client callback handle message from upperstack + * @param[in] client_id client identifier + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @return @ref T_APP_RESULT + */ +T_APP_RESULT ancs_client_cb(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_ANCS_CB_DATA *p_cb_data = (T_ANCS_CB_DATA *)p_data; + + switch (p_cb_data->cb_type) + { + case ANCS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_cb_data->cb_content.disc_state) + { + case DISC_ANCS_DONE: + APP_PRINT_INFO0("ANCS BLE Client CB: discover procedure done."); + ancs_set_data_source_notify(conn_id, true); + break; + case DISC_ANCS_FAILED: + APP_PRINT_ERROR0("ANCS BLE Client CB: discover request failed."); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (p_cb_data->cb_content.notify_data.type) + { + case ANCS_FROM_DATA_SOURCE:; + app_parse_data_soucre_notifications(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + case ANCS_FROM_NOTIFICATION_SOURCE: + APP_PRINT_INFO2("ANCS_FROM_NOTIFICATION_SOURCE: conn_id %d, length %d", + conn_id, p_cb_data->cb_content.notify_data.value_size); + app_parse_notification_source_data(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_WRITE_RESULT: + { + if (p_cb_data->cb_content.write_result.cause != ATT_SUCCESS) + { + APP_PRINT_ERROR1("ANCS_CLIENT_CB_TYPE_WRITE_RESULT: Failed, cause 0x%x", + p_cb_data->cb_content.write_result.cause); + } + switch (p_cb_data->cb_content.write_result.type) + { + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE"); + break; + + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE"); + ancs_set_notification_source_notify(conn_id, true); + break; + case ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_CONTROL_POINT: + APP_PRINT_INFO0("ANCS_WRITE_CONTROL_POINT"); +#if F_BT_ANCS_CLIENT_DEBUG + if (p_cb_data->cb_content.write_result.cause == 0x4A0) + { + APP_PRINT_ERROR0("The commandID was not recognized by the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A1) + { + APP_PRINT_ERROR0("The command was improperly formatted."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A2) + { + APP_PRINT_ERROR0("One of the parameters (for example, the NotificationUID) does not refer to an existing object on the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A3) + { + APP_PRINT_ERROR0("The action was not performed."); + } +#endif + ancs_send_msg_to_app(conn_id); + break; + + default: + break; + } + } + break; + + case ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: + { + T_ANCS_MSG ancs_msg; + void *ancs_queue_handle = ancs_link_table[conn_id].ancs_queue_handle; + APP_PRINT_INFO1("ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: conn_id = 0x%x", conn_id); + memset(&ancs_link_table[conn_id], 0, sizeof(T_APP_ANCS_LINK)); + ancs_link_table[conn_id].ancs_queue_handle = ancs_queue_handle; + /*release msg queue*/ + while (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0)); + } + break; + + default: + break; + } + return result; +} + +void ancs_handle_msg(T_IO_MSG *p_io_msg) +{ + uint8_t conn_id = p_io_msg->u.param; + T_ANCS_MSG ancs_msg; + if (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_INFO1("ancs_handle_msg: conn_id 0x%x os_msg_recv failed", conn_id); + return; + } + if (ancs_msg.type == ANCS_MSG_TYPE_GET_NOTIFI_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: notification_uid 0x%x", + ancs_msg.data.notifi_attr.notification_uid); + if (ancs_get_notification_attr(ancs_msg.data.notifi_attr.conn_id, + ancs_msg.data.notifi_attr.notification_uid, + ancs_msg.data.notifi_attr.attribute_ids, ancs_msg.data.notifi_attr.attribute_ids_len + ) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: Failed"); + } + + } + else if (ancs_msg.type == ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: notification_uid 0x%x", + ancs_msg.data.perform_action.notification_uid); + if (ancs_perform_notification_action(ancs_msg.data.perform_action.conn_id, + ancs_msg.data.perform_action.notification_uid, + ancs_msg.data.perform_action.action_id) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: Failed"); + } + + } +#if F_BT_ANCS_GET_APP_ATTR + else if (ancs_msg.type == ANCS_MSG_TYPE_GET_APP_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_APP_ATTR: app_identifier %s", + TRACE_STRING(ancs_msg.data.app_attr.app_identifier)); + if (ancs_get_app_attr(ancs_msg.data.app_attr.conn_id, + ancs_msg.data.app_attr.app_identifier, + ancs_msg.data.app_attr.attribute_ids, + ancs_msg.data.app_attr.attribute_ids_len) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_APP_ATTR: Failed"); + } + + } +#endif +} + +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num) +{ + uint8_t i; + ancs_link_number = link_num; + ancs_link_table = os_mem_zalloc(RAM_TYPE_DATA_ON, ancs_link_number * sizeof(T_APP_ANCS_LINK)); + if (ancs_link_table == NULL) + { + APP_PRINT_ERROR0("ancs_init: allocate buffer failed"); + } + for (i = 0; i < ancs_link_number; i++) + { + if (os_msg_queue_create(&(ancs_link_table[i].ancs_queue_handle), ANCS_MSG_QUEUE_NUM, + sizeof(T_ANCS_MSG)) == false) + { + APP_PRINT_ERROR2("ancs_init: link_num %d, i 0x%x create queue failed", link_num, i); + } + } + ancs_client = ancs_add_client(ancs_client_cb, link_num); +} +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#endif diff --git a/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/ancs.h b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/ancs.h new file mode 100644 index 0000000..68ec35b --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/ancs.h @@ -0,0 +1,259 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file ancs.h +* @brief ancs +* @details ancs +* @author ranhui +* @date 2015-03-27 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _ANCS_H__ +#define _ANCS_H__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +/** @addtogroup PERIPH_ANCS + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Macros ANCS Exported Macros + * @{ + */ +#define ANCS_MAX_ATTR_LEN 256 //!< Max ancs attribute length + +#if F_BT_ANCS_GET_APP_ATTR +#define ANCS_APP_IDENTIFIER_MAX_LEN 30 //!< Max app IDENTIFIER length +#endif + +#define ANCS_MSG_QUEUE_NUM 5 //!< ANCS message queue size + + +/** @brief ANCS event flag */ +#define NS_EVENT_FLAG_SILENT (1 << 0) +#define NS_EVENT_FLAG_IMPORTANT (1 << 1) +#define NS_EVENT_FLAG_PRE_EXISTING (1 << 2) +#define NS_EVENT_FLAG_POSITIVE_ACTION (1 << 3) //!<A positive action exists and is associated with this iOS notification +#define NS_EVENT_FLAG_NEGATIVE_ACTION (1 << 4) //!<A negative action exists and is associated with this iOS notification. + +/** End of PERIPH_ANCS_Exported_Macros + * @} + */ + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Types ANCS Exported Types + * @{ + */ +/** @brief ANCS event id for the peer device notification */ +typedef enum +{ + NS_EVENT_ID_NOTIFICATION_ADD = 0, /**< The arrival of a new iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_MODIFIED = 1, /**< The modification of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_REMOVED = 2, /**< The removal of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_RESERVED = 0xff +} T_NS_EVENT_ID; + +/** @brief ANCS category id */ +typedef enum +{ + NS_CATEGORY_ID_OTHER = 0, + NS_CATEGORY_ID_INCOMING_CALL = 1, + NS_CATEGORY_ID_MISSED_CALL = 2, + NS_CATEGORY_ID_VOICE_MAIL = 3, + NS_CATEGORY_ID_SOCIAL = 4, + NS_CATEGORY_ID_SCHEDULE = 5, + NS_CATEGORY_ID_EMAIL = 6, + NS_CATEGORY_ID_NEWS = 7, + NS_CATEGORY_ID_HEALTH_AND_FITNESS = 8, + NS_CATEGORY_ID_BUSINESS_ADN_FINANCE = 9, + NS_CATEGORY_ID_LOCATION = 10, + NS_CATEGORY_ID_ENTERTAINMENT = 11, + NS_CATEGORY_ID_RESERVED = 255 +} T_NS_CATEGORY_ID; + +/** @brief ANCS notification attribute id */ +typedef enum +{ + DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER = 0, /**< Format: UTF-8 strings */ + DS_NOTIFICATION_ATTR_ID_TITLE = 1, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_SUB_TITLE = 2, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE = 3, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE = 4, /**<The format of the DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE constant is a string + that represents the integral value of the message size. */ + DS_NOTIFICATION_ATTR_ID_DATE = 5, /**<The format of the DS_NOTIFICATION_ATTR_ID_DATE constant is a string + that uses the Unicode Technical Standard (UTS) #35 date format pattern yyyyMMdd'T'HHmmSS. */ + DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL = 6, /**<Format: UTF-8 strings. The label used to describe + the positive action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL = 7, /**<Format: UTF-8 strings. The label used to describe + the negative action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_RESERVED = 255 +} T_DS_NOTIFICATION_ATTR_ID; + +/** @brief App parse ANCS notification attribute state */ +typedef enum +{ + DS_PARSE_NOT_START = 0x00, + DS_PARSE_GET_NOTIFICATION_COMMAND_ID = 0x01, + DS_PARSE_UID1, + DS_PARSE_UID2, + DS_PARSE_UID3, + DS_PARSE_UID4, + DS_PARSE_ATTRIBUTE_ID, + DS_PARSE_ATTRIBUTE_LEN1, + DS_PARSE_ATTRIBUTE_LEN2, + DS_PARSE_ATTRIBUTE_READY +} T_DS_NOTIFICATION_ATTR_PARSE_STATE; + +/** @brief Smart Phone App attribute id. */ +typedef enum +{ + DS_APP_ATTR_ID_DISPLAY_NAME = 0, + DS_APP_ATTR_ID_RESERVED = 255 +} T_DS_APP_ATTR_ID; + +/** @brief App parse ANCS attribute state */ +typedef enum +{ + DS_PARSE_GET_APP_COMMAND_ID = 0x10, + DS_PARSE_APP_IDENTIFIER_START, + DS_PARSE_APP_IDENTIFIER_END, + DS_PARSE_APP_ATTRIBUTE_ID, + DS_PARSE_APP_ATTRIBUTE_LEN1, + DS_PARSE_APP_ATTRIBUTE_LEN2, + DS_PARSE_APP_ATTRIBUTE_READY +} T_DS_APP_ATTR_PARSE_STATE; + +/** @brief ANCS action id state */ +typedef enum +{ + CP_ACTION_ID_POSITIVE = 0, + CP_ACTION_ID_NEGATIVE = 1, + CP_ACTION_ID_RESERVED = 255 +} T_CP_ACTION_ID_VALUES; + +/** @brief Define notification source data for record ANCS notification parameters */ +typedef struct +{ + uint8_t event_id; /**< This field informs the accessory whether the given iOS notification + was added, modified, or removed. The enumerated values for this field are defined in @ref T_NS_EVENT_ID*/ + uint8_t event_flags; /**< A bitmask whose set bits inform an NC of specificities with the iOS notification. */ + uint8_t category_id; /**< A numerical value providing a category in which the iOS notification + can be classified. The enumerated values for this field are defined in @ref T_NS_CATEGORY_ID*/ + uint8_t category_count; /**< The current number of active iOS notifications in the given category. */ + uint32_t notification_uid; /**< A 32-bit numerical value that is the unique identifier (UID) for the iOS notification.*/ +} T_NS_DATA, *P_NS_DATA; + +/** @brief Define notification attribute details data */ +/** App can acquire details information by attribute id */ +typedef struct +{ + uint8_t command_id; + uint8_t notification_uid[4]; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_NOTIFICATION_ATTR; + +/** @brief Local app record notification attribute information */ +typedef struct +{ + uint8_t command_id; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_APP_ATTR; + +/** @brief ANCS Message Type */ +typedef enum +{ + ANCS_MSG_TYPE_GET_NOTIFI_ATTR, + ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION, + ANCS_MSG_TYPE_GET_APP_ATTR, +} T_ANCS_MSG_TYPE; + +/** @brief Message data of ANCS_MSG_TYPE_GET_NOTIFI_ATTR */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t attribute_ids[14]; + uint8_t attribute_ids_len; +} T_ANCS_GET_NOTIFI_ATTR; + +/** @brief Message data of ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t action_id; +} T_ANCS_PERFORM_NOTIFI_ACTION; + +#if F_BT_ANCS_GET_APP_ATTR +/** @brief Message data of ANCS_MSG_TYPE_GET_APP_ATTR */ +typedef struct +{ + uint8_t conn_id; + char app_identifier[ANCS_APP_IDENTIFIER_MAX_LEN]; + uint8_t attribute_ids[1]; + uint8_t attribute_ids_len; +} T_ANCS_GET_APP_ATTR; +#endif + +/** @brief ANCS Message Data */ +typedef struct +{ + T_ANCS_MSG_TYPE type; + union + { + T_ANCS_GET_NOTIFI_ATTR notifi_attr; + T_ANCS_PERFORM_NOTIFI_ACTION perform_action; +#if F_BT_ANCS_GET_APP_ATTR + T_ANCS_GET_APP_ATTR app_attr; +#endif + } data; +} T_ANCS_MSG; +/** End of PERIPH_ANCS_Exported_Types + * @} + */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num); + +/** + * @brief All the ancs messages are pre-handled in this function + * @param[in] io_msg IO message data + * @return void + */ +void ancs_handle_msg(T_IO_MSG *p_io_msg); +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app.c b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app.c new file mode 100644 index 0000000..92e753c --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app.c @@ -0,0 +1,609 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <string.h> + +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_conn_le.h> +#include <gap_msg.h> +#if F_BT_ANCS_CLIENT_SUPPORT +#include <ancs_client.h> +#include "ancs.h" +#endif +#include <bas.h> +#include <simple_ble_service.h> + +#include "trace.h" + +#include "app.h" +#include "io_adc.h" + +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE peripheral application routines. + * @{ + */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bas_srv_id; /**< Battery service id */ +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ + +/*============================================================================* + * Functions + *============================================================================*/ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; +#if F_BT_ANCS_CLIENT_SUPPORT + case IO_MSG_TYPE_ANCS: + { + ancs_handle_msg(&io_msg); + } + break; +#endif + case IO_MSG_TYPE_ADC: + { +// APP_PRINT_INFO0("[app] app_handle_io_msg: adc msg."); + io_handle_adc_msg(&io_msg); + //Add user code here! + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ +// le_adv_start(); + adc_sample_start(); + } + } + + if (gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + } + } + + gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, gap_conn_state, new_state, disc_cause); + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, remote_bd, &remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + } + break; + + default: + break; + } + gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { +#if F_BT_ANCS_CLIENT_SUPPORT + ancs_start_discovery(conn_id); +#endif + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("app_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("app_handle_conn_param_update_evt update pending."); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ + +/** @defgroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value[2] = {0x01, 0x02}; + APP_PRINT_INFO0("SIMP_READ_V1"); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + else if (service_id == bas_srv_id) + { + T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; + switch (p_bas_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_bas_cb_data->msg_data.notification_indification_index) + { + case BAS_NOTIFY_BATTERY_LEVEL_ENABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE"); + } + break; + + case BAS_NOTIFY_BATTERY_LEVEL_DISABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL) + { + uint8_t battery_level = 90; + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level); + bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level); + } + } + break; + + default: + break; + } + } + + return app_result; +} + +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @} */ /* End of group PERIPH_APP */ diff --git a/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app.h b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app.h new file mode 100644 index 0000000..8aed00b --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app.h @@ -0,0 +1,72 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app.h +* @brief This file handles BLE peripheral application routines. +* @author jane +* @date 2017-06-06 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +#ifndef _APP_H +#define _APP_H + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <profile_server.h> + +#include "app_msg.h" + + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bas_srv_id; /**< Battery service id */ + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg:IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * @param[in] service_id: Profile service ID + * @param[in] p_data: Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_flags.h b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_flags.h new file mode 100644 index 0000000..3371839 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_flags.h @@ -0,0 +1,40 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#include "upperstack_config.h" + +/** @defgroup PERIPH_Config Peripheral App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +/** @brief Config DLPS: 0-Disable DLPS, 1-Enable DLPS */ +#define F_BT_DLPS_EN 0 +/** @brief Config ANCS Client: 0-Not built in, 1-Open ANCS client function */ +#define F_BT_ANCS_CLIENT_SUPPORT 0 +#define F_BT_ANCS_APP_FILTER (F_BT_ANCS_CLIENT_SUPPORT & 1) +#define F_BT_ANCS_GET_APP_ATTR (F_BT_ANCS_CLIENT_SUPPORT & 0) +/** @brief Config ANCS Client debug log: 0-close, 1-open */ +#define F_BT_ANCS_CLIENT_DEBUG (F_BT_ANCS_CLIENT_SUPPORT & 0) + +/** @} */ /* End of group PERIPH_Config */ +#endif diff --git a/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_task.c b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_task.c new file mode 100644 index 0000000..635c4c3 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_task.c @@ -0,0 +1,123 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +#include "app.h" +#include "app_task.h" + + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +extern void driver_init(void); + +void app_main_task(void *p_param); + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg) +{ + uint8_t event = EVENT_IO_TO_APP; + + if (os_msg_send(io_queue_handle, p_msg, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_io_msg_to_app fail"); + return false; + } + if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_evt_msg_to_app fail"); + return false; + } + return true; +} + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param: Parameters sending to the task + * @return void + */ +void app_main_task(void *p_param) +{ + uint8_t event; + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + driver_init(); + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** @} */ /* End of group PERIPH_APP_TASK */ + + diff --git a/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_task.h b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_task.h new file mode 100644 index 0000000..5d5918a --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/app_task.h @@ -0,0 +1,47 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app_task.h +* @brief Routines to create App task and handle events & messages +* @author jane +* @date 2017-06-02 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#include <string.h> + +#include "os_msg.h" +#include "os_queue.h" +#include "os_sched.h" +#include "os_task.h" +#include "os_timer.h" + +#include "app_msg.h" + +#include "trace.h" + + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg); + +/** + * @brief Initialize app task + * @return void + */ +void app_task_init(void); + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/main.c b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/main.c new file mode 100644 index 0000000..0d3fa3b --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/ble_peripheral/main.c @@ -0,0 +1,248 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file main.c +* @brief Source file for BLE peripheral project, mainly used for initialize modules +* @author jane +* @date 2017-06-12 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <string.h> +#include <stdlib.h> +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_msg.h> +#include <bas.h> +#include <simple_ble_service.h> + +#if F_BT_ANCS_CLIENT_SUPPORT +#include <profile_client.h> +#include "ancs.h" +#endif + +#include "trace.h" + +#include "app.h" +#include "app_task.h" +#include "app_flags.h" +//#include "app_timer.h" + +#include "io_adc.h" + + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + + +/*============================================================================* + * Variables + *============================================================================*/ + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x0F, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'L', 'E', '_', 'P', 'E', 'R', 'I', 'P', 'H', 'E', 'R', 'A', 'L', +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_PERIPHERAL"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; +#if F_BT_ANCS_CLIENT_SUPPORT + uint8_t auth_sec_req_enable = true; +#else + uint8_t auth_sec_req_enable = false; +#endif + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(app_gap_callback); +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void app_le_profile_init(void) +{ + server_init(2); + simp_srv_id = simp_ble_service_add_service(app_profile_callback); + bas_srv_id = bas_add_service(app_profile_callback); + server_register_app_cb(app_profile_callback); +#if F_BT_ANCS_CLIENT_SUPPORT + client_init(1); + ancs_init(APP_MAX_LINKS); +#endif +} + +/** + * @brief Initialize global data. + * @param No parameter. + * @return void + */ +void global_data_init(void) +{ + global_data_adc_init(); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be performed with the IO initializing. + * @return void + */ +void board_init(void) +{ + board_adc_init(); +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void driver_init(void) +{ + adc_demo_driver_init(); +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void task_init(void) +{ + app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int main(void) +{ + extern uint32_t random_seed_value; + srand(random_seed_value); + global_data_init(); + board_init(); + le_gap_init(APP_MAX_LINKS); + gap_lib_init(); + app_le_gap_init(); + app_le_profile_init(); + pwr_mgr_init(); +// sw_timer_init(); + task_init(); + os_sched_start(); + + return 0; +} +/** @} */ /* End of group PERIPH_DEMO_MAIN */ + + diff --git a/src/sample/io_sample/ADC/OneShotMode/io_adc.c b/src/sample/io_sample/ADC/OneShotMode/io_adc.c new file mode 100644 index 0000000..092d4c0 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/io_adc.c @@ -0,0 +1,248 @@ + +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.c +* @brief This file provides demo code of adc continuous mode. +* @details +* @author yuan +* @date 2018-12-07 +* @version v1.0 +********************************************************************************************************* +*/ + +/* Includes ------------------------------------------------------------------*/ +#include "io_adc.h" + +#include "app_task.h" + +/* Globals ------------------------------------------------------------------*/ +ADC_Data_TypeDef ADC_Global_Data; + +/** + * @brief Initialization adc global data. + * @param No parameter. + * @return void + */ +void global_data_adc_init(void) +{ + /* Initialize adc k value! */ + APP_PRINT_INFO0("[io_adc] global_data_adc_init"); + bool adc_k_status = false; + adc_k_status = ADC_CalibrationInit(); + if (false == adc_k_status) + { + APP_PRINT_ERROR0("[io_adc] global_data_adc_init: ADC_CalibrationInit fail!"); + } + memset(&ADC_Global_Data, 0, sizeof(ADC_Global_Data)); +} + +/** + * @brief Initialization of pinmux settings and pad settings. + * @param No parameter. + * @return void +*/ +void board_adc_init(void) +{ + Pad_Config(ADC_SAMPLE_PIN_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); +} + +/** + * @brief Initialize ADC peripheral. + * @param No parameter. + * @return void + */ +void driver_adc_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE); + + ADC_InitTypeDef ADC_InitStruct; + ADC_StructInit(&ADC_InitStruct); + + /* Configure the ADC sampling schedule0 */ + ADC_InitStruct.ADC_SchIndex[0] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_0); + /* Set the bitmap corresponding to schedule0*/ + ADC_InitStruct.ADC_Bitmap = 0x01; + +#if (ADC_DATA_HW_AVERAGE && ADC_DATA_OUTPUT_TO_FIFO) + APP_PRINT_ERROR0("[io_adc] driver_adc_init: ADC config error !"); +#elif (ADC_DATA_HW_AVERAGE ) + ADC_InitStruct.ADC_DataAvgEn = ADC_DATA_AVERAGE_ENABLE; + ADC_InitStruct.ADC_DataAvgSel = ADC_DATA_AVERAGE_OF_4; +#elif (ADC_DATA_OUTPUT_TO_FIFO) + ADC_InitStruct.ADC_DataWriteToFifo = ADC_DATA_WRITE_TO_FIFO_ENABLE; + ADC_InitStruct.ADC_FifoThdLevel = 0x0A; +#endif + + ADC_InitStruct.ADC_PowerAlwaysOnEn = ADC_POWER_ALWAYS_ON_ENABLE; + /* Fixed 255 in OneShot mode. */ + ADC_InitStruct.ADC_SampleTime = 255; + + ADC_Init(ADC, &ADC_InitStruct); + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + /* High bypass resistance mode config, please notice that the input voltage of + adc channel using high bypass mode should not be over 0.9V */ + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, ENABLE); + APP_PRINT_INFO0("[io_adc] driver_adc_init: ADC sample mode is bypass mode !"); +#else + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, DISABLE); + APP_PRINT_INFO0("[io_adc] driver_adc_init: ADC sample mode is divide mode !"); +#endif + +#if (!ADC_DATA_OUTPUT_TO_FIFO) + ADC_INTConfig(ADC, ADC_INT_ONE_SHOT_DONE, ENABLE); +#else + ADC_INTConfig(ADC, ADC_INT_FIFO_THD, ENABLE); +#endif + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = ADC_IRQn; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + /* When ADC is enabled, sampling will be done quickly and interruption will occur. + After initialization, ADC can be enabled when sampling is needed.*/ +// ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE); +} + +/** + * @brief Calculate adc sample voltage. + * @param No parameter. + * @return void + */ +static void io_adc_voltage_calculate(T_IO_MSG *io_adc_msg) +{ + ADC_Data_TypeDef *p_buf = io_adc_msg->u.buf; + uint8_t sample_data_len = 0; + uint16_t sample_data = 0; + + sample_data_len = p_buf->RawDataLen; + for (uint8_t i = 0; i < sample_data_len; i++) + { + sample_data = p_buf->RawData[i]; + DBG_DIRECT("io_adc_voltage_calculate: raw_data = 0x%X", sample_data); +#if (ADC_DATA_HW_AVERAGE ) + sample_data = (p_buf->RawData[i] & 0x3FFC) >> 2; + uint16_t sample_data_decimal = (p_buf->RawData[i] & 0x3); + + float cacl_result = sample_data; + float cacl_result_dec = 0; + cacl_result_dec = (float)(sample_data_decimal & 0x1) / 2 + (float)((sample_data_decimal >> 1) & 0x1) + / 2; + cacl_result += cacl_result_dec; + DBG_DIRECT("io_adc_voltage_calculate: sample_data = %d, cacl_result = %d\r\n", + sample_data, (uint32_t)cacl_result); + +#endif + float sample_voltage = 0; + ADC_ErrorStatus error_status = NO_ERROR; +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + sample_voltage = ADC_GetVoltage(BYPASS_SINGLE_MODE, (int32_t)sample_data, &error_status); +#else + sample_voltage = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data, &error_status); +#endif + if (error_status < 0) + { + APP_PRINT_INFO1("[io_adc] io_adc_voltage_calculate: ADC parameter or efuse data error! error_status = %d", + error_status); + } + else + { + APP_PRINT_INFO2("[io_adc] io_adc_voltage_calculate: ADC rawdata = %d, voltage = %dmV ", + sample_data, (uint32_t)sample_voltage); + } + } + memset(&ADC_Global_Data, 0, sizeof(ADC_Global_Data)); +} + +void adc_demo_driver_init(void) +{ + driver_adc_init(); +} + +void adc_sample_start(void) +{ +#if (ADC_DATA_OUTPUT_TO_FIFO) + ADC_ClearFifo(ADC); +#endif + /* Enable adc sample */ + ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE); + +} + +/** + * @brief Handle adc data function. + * @param No parameter. + * @return void + */ +void io_handle_adc_msg(T_IO_MSG *io_adc_msg) +{ + io_adc_voltage_calculate(io_adc_msg); +} + +/** + * @brief ADC interrupt handler function. + * @param No parameter. + * @return void + */ +void ADC_Handler(void) +{ +#if (!ADC_DATA_OUTPUT_TO_FIFO) + if (ADC_GetINTStatus(ADC, ADC_INT_ONE_SHOT_DONE) == SET) + { + ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE); + + uint16_t sample_data = 0; + sample_data = ADC_ReadRawData(ADC, ADC_Schedule_Index_0); + + T_IO_MSG int_adc_msg; + int_adc_msg.type = IO_MSG_TYPE_ADC; + int_adc_msg.subtype = 0; + ADC_Global_Data.RawDataLen = 1; + ADC_Global_Data.RawData[0] = sample_data; + int_adc_msg.u.buf = (void *)(&ADC_Global_Data); + if (false == app_send_msg_to_apptask(&int_adc_msg)) + { + APP_PRINT_ERROR0("[io_adc] ADC_Handler: Send int_adc_msg failed!"); + //Add user code here! + ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE); + return; + } + } +#else + if (ADC_GetIntFlagStatus(ADC, ADC_INT_FIFO_THD) == SET) + { +// uint16_t sample_data[32] = {0}; +// /* stop write fifo */ +// ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_THD); + ADC_Global_Data.RawDataLen = ADC_GetFifoLen(ADC); + ADC_GetFifoData(ADC, ADC_Global_Data.RawData, ADC_Global_Data.RawDataLen); + + DBG_DIRECT("ADC_INT_FIFO_THD: len = %d", ADC_Global_Data.RawDataLen); + for (uint8_t i = 0; i < ADC_Global_Data.RawDataLen; i++) + { + DBG_DIRECT("ADC_INT_FIFO_THD: data[%d] = %d", i, ADC_Global_Data.RawData[i]); + } + /* Send msg to app task */ + T_IO_MSG int_adc_msg; + int_adc_msg.type = IO_MSG_TYPE_ADC; + int_adc_msg.u.buf = (void *)(&ADC_Global_Data); + if (false == app_send_msg_to_apptask(&int_adc_msg)) + { + APP_PRINT_ERROR0("[io_adc] ADC_Handler: Send int_adc_msg failed!"); + //Add user code here! + TIM_Cmd(TIM7, DISABLE); + ADC_ClearFifo(ADC); + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_THD); + return; + } + ADC_ClearINTPendingBit(ADC, ADC_INT_FIFO_THD); + ADC_ClearFifo(ADC); + TIM_Cmd(TIM7, ENABLE); + } +#endif +} + diff --git a/src/sample/io_sample/ADC/OneShotMode/io_adc.h b/src/sample/io_sample/ADC/OneShotMode/io_adc.h new file mode 100644 index 0000000..c628a5f --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode/io_adc.h @@ -0,0 +1,121 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.h +* @brief +* @details +* @author yuan +* @date 2018-12-07 +* @version v1.0 +********************************************************************************************************* +*/ + +#ifndef __IO_ADC_H +#define __IO_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "rtl876x_adc.h" +#include "rtl876x_nvic.h" +#include "rtl876x_pinmux.h" +#include "rtl876x_rcc.h" + +#include "app_msg.h" +#include "board.h" + +/* Defines ------------------------------------------------------------------*/ +/** ADC sample channel config. + * ADC sample channel config:P2_2,P2_3,P2_6,P2_7 and VBAT + * ADC sample channel index select: #define ADC_Channel_Index_0 0 + * #define ADC_Channel_Index_1 1 + * #define ADC_Channel_Index_2 2 + * #define ADC_Channel_Index_3 3 + + * If ADC_SAMPLE_PIN = P2_2, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_0; + * If ADC_SAMPLE_PIN = P2_3, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_1; + * If ADC_SAMPLE_PIN = P2_6, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_4; + * If ADC_SAMPLE_PIN = P2_7, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_5; + */ +#define ADC_SAMPLE_CHANNEL_0 ADC_Channel_Index_0 +#define ADC_SAMPLE_CHANNEL_1 ADC_Channel_Index_1 +#define ADC_SAMPLE_CHANNEL_2 ADC_Channel_Index_2 +#define ADC_SAMPLE_CHANNEL_3 ADC_Channel_Index_3 + +/* Define schedule index. */ +#define ADC_Schedule_Index_0 0 +#define ADC_Schedule_Index_1 1 +#define ADC_Schedule_Index_2 2 +#define ADC_Schedule_Index_3 3 +#define ADC_Schedule_Index_4 4 +#define ADC_Schedule_Index_5 5 +#define ADC_Schedule_Index_6 6 +#define ADC_Schedule_Index_7 7 +#define ADC_Schedule_Index_8 8 +#define ADC_Schedule_Index_9 9 +#define ADC_Schedule_Index_10 10 +#define ADC_Schedule_Index_11 11 +#define ADC_Schedule_Index_12 12 +#define ADC_Schedule_Index_13 13 +#define ADC_Schedule_Index_14 14 +#define ADC_Schedule_Index_15 15 + +/** Define that how many schedules to use, max 16. + */ +#define ADC_SCHEDULE_NUM (2) + +/** ADC mode config. + * ADC pin hardware mode: bypass mode + * divide mode + */ +#define ADC_DIVIDE_MODE 0 +#define ADC_BYPASS_MODE 1 +#define ADC_MODE_DIVIDE_OR_BYPASS ADC_DIVIDE_MODE + +/** ADC data hardware average config, + * only sample one channel data and onle read data from ADC_Schedule_Index_0. + * Mode: 0: ADC data hardware average disable + * 1: ADC data hardware average enable + */ +#define ADC_DATA_HW_AVERAGE 1 + +/** ADC data output mode config. + * Mode: 0: ADC data output to schedule table + * 1: ADC data output to fifo + */ +#define ADC_DATA_OUTPUT_TO_FIFO 0 + +/** ADC ADC multiple fixed interval sampling config. + * Mode: 0: ADC sample once and stop + * 1: ADC timing sampling + */ +#define ADC_MULTI_SAMPLE 1 + +#define ADC_ONE_SHOT_SAMPLE_PERIOD (1000000-1)//100ms + +/* ADC global data struct*/ +typedef struct +{ + uint16_t RawData[32]; + uint8_t RawDataLen; +} ADC_Data_TypeDef; + +extern ADC_Data_TypeDef ADC_Global_Data; + +void global_data_adc_init(void); +void board_adc_init(void); +void adc_demo_driver_init(void); +void adc_sample_start(void); + +void io_handle_adc_msg(T_IO_MSG *io_adc_msg); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/ancs.c b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/ancs.c new file mode 100644 index 0000000..ac3254e --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/ancs.c @@ -0,0 +1,662 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ancs.c + * @brief This file handles ANCS Client routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#if F_BT_ANCS_CLIENT_SUPPORT +#include <trace.h> +#include <string.h> +#include <os_msg.h> +#include <os_mem.h> +#include <ancs.h> +#include <ancs_client.h> + +/** @defgroup PERIPH_ANCS Peripheral ANCS + * @brief Apple ANCS service modulization + * @{ + */ +/*============================================================================* + * Types + *============================================================================*/ +typedef struct +{ + uint8_t m_parse_state; + uint8_t app_type; + uint16_t current_len; + void *ancs_queue_handle; + uint8_t *ptr; + T_DS_NOTIFICATION_ATTR notification_attr; +#if F_BT_ANCS_GET_APP_ATTR + T_DS_APP_ATTR app_attr; +#endif +} T_APP_ANCS_LINK; + +/*============================================================================* + * Variables + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Variables ANCS Exported Variables + * @brief app register ancs client to upperstack, and return ancs client id + * @{ + */ +T_CLIENT_ID ancs_client; /**< ancs client id*/ + +T_APP_ANCS_LINK *ancs_link_table; +uint8_t ancs_link_number; + +/** End of PERIPH_ANCS_Exported_Variables + * @} + */ +extern void *evt_queue_handle; //!< Event queue handle +extern void *io_queue_handle; //!< IO queue handle +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +void ancs_send_msg_to_app(uint8_t conn_id) +{ + T_IO_MSG io_msg; + uint8_t event = EVENT_IO_TO_APP; + io_msg.type = IO_MSG_TYPE_ANCS; + io_msg.subtype = 0; + io_msg.u.param = conn_id; + + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail1"); + } + else if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail2"); + } +} + +void app_handle_notification_attribute_data(T_APP_ANCS_LINK *p_ancs_link) +{ + if (p_ancs_link->notification_attr.attribute_id != DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + uint8_t *p_value = p_ancs_link->notification_attr.data; + +#if F_BT_ANCS_APP_FILTER + //filter QQ , wechat , short message and incoming call + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: app identifiter %s", TRACE_STRING(p_value)); +#endif + //wechat + if (0 == memcmp(p_value, "com.tencent.xin", 16)) + { + p_ancs_link->app_type = 1; + } + else if (0 == memcmp(p_value, "com.apple.MobileSMS", 20)) + { + p_ancs_link->app_type = 2; + } + else if (0 == memcmp(p_value, "com.apple.mobilephone", 22)) + { + p_ancs_link->app_type = 3; + } + else if (0 == memcmp(p_value, "com.tencent.mqq", 16)) + { + p_ancs_link->app_type = 4; + } + else if (0 == memcmp(p_value, "com.tencent.qq", 15)) + { + p_ancs_link->app_type = 5; + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_MESSAGE) + { + if (p_ancs_link->app_type == 2) + { + APP_PRINT_INFO1("MobileSMS: message %s", TRACE_STRING(p_value)); + } + else if (p_ancs_link->app_type == 5) + { + APP_PRINT_INFO1("QQ: message %s", TRACE_STRING(p_value)); + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_DATE) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: date %s", TRACE_STRING(p_value)); +#endif + } +#endif + } + else/* All attributes has been parased*/ + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO0("parse notify attr: parse done"); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } +} + +void app_parse_notification_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_NOTIFICATION_COMMAND_ID: + p_ancs_link->notification_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID1; + break; + + case DS_PARSE_UID1: + p_ancs_link->notification_attr.notification_uid[0] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID2; + break; + + case DS_PARSE_UID2: + p_ancs_link->notification_attr.notification_uid[1] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID3; + break; + + case DS_PARSE_UID3: + p_ancs_link->notification_attr.notification_uid[2] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID4; + break; + + case DS_PARSE_UID4: + p_ancs_link->notification_attr.notification_uid[3] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + break; + + case DS_PARSE_ATTRIBUTE_ID: + p_ancs_link->notification_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_ATTRIBUTE_LEN1: + p_ancs_link->notification_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_ATTRIBUTE_LEN2: + p_ancs_link->notification_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->notification_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse notify attr: attribute_id %d, attribute_len %d", + p_ancs_link->notification_attr.attribute_id, + p_ancs_link->notification_attr.attribute_len + ); +#endif + if (p_ancs_link->notification_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + } + if (p_ancs_link->notification_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse notify attr: error, attribute_len %d > max length %d", + p_ancs_link->notification_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } + break; + + case DS_PARSE_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->notification_attr.attribute_len) + { + /*An attribute is always a string whose length in bytes is provided in the tuple but that is not NULL-terminated.*/ + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: data %b", + TRACE_BINARY(p_ancs_link->notification_attr.attribute_len, + p_ancs_link->notification_attr.data)); +#endif + app_handle_notification_attribute_data(p_ancs_link); + } + break; + } + } +} + +#if F_BT_ANCS_GET_APP_ATTR +void app_parse_app_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_APP_COMMAND_ID: + p_ancs_link->app_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_START; + break; + + case DS_PARSE_APP_IDENTIFIER_START: + if (p_data[i] == 0x00) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_END; + + if (i + 1 == len) + { + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + else + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + } + + } + break; + + case DS_PARSE_APP_ATTRIBUTE_ID: + p_ancs_link->app_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN1: + p_ancs_link->app_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN2: + p_ancs_link->app_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->app_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse app attr: attribute_id %d, attribute_len %d", + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len + ); +#endif + if (p_ancs_link->app_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + + } + if (p_ancs_link->app_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse app attr: error, attribute_len %d > max length %d", + p_ancs_link->app_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + break; + + case DS_PARSE_APP_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->app_attr.attribute_len) + { + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO4("parse app attr: command_id 0x%x, attribute_id 0x%x, attribute_len %d, data %s", + p_ancs_link->app_attr.command_id, + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len, + TRACE_STRING(p_ancs_link->app_attr.data)); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + + } + break; + } + } +} +#endif + +/** + * @brief Parse ancs data source notification + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @param[in] len data length + * @return void + */ +void app_parse_data_soucre_notifications(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + APP_PRINT_INFO2("ANCS_FROM_DATA_SOURCE: conn_id %d, len =%d", conn_id, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("data = %b", TRACE_BINARY(len, p_data)); +#endif + T_APP_ANCS_LINK *p_ancs_link = &ancs_link_table[conn_id]; + +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("m_parse_state %d", p_ancs_link->m_parse_state); +#endif + if (p_ancs_link->m_parse_state == DS_PARSE_NOT_START) + { + if (len >= 1 && p_data[0] == CP_CMD_ID_GET_NOTIFICATION_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_NOTIFICATION_COMMAND_ID; + } +#if F_BT_ANCS_GET_APP_ATTR + else if (len >= 1 && p_data[0] == CP_CMD_ID_GET_APP_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_APP_COMMAND_ID; + } +#endif + } + + if (p_ancs_link->m_parse_state < DS_PARSE_GET_APP_COMMAND_ID) + { + app_parse_notification_attribute(p_ancs_link, p_data, len); + } +#if F_BT_ANCS_GET_APP_ATTR + else + { + app_parse_app_attribute(p_ancs_link, p_data, len); + } +#endif +} + +void app_parse_notification_source_data(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + if (8 == len) + { + T_NS_DATA ns_data; + + memcpy(&ns_data, p_data, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO5("app_parse_notification_source_data: event_id %d, event_flags 0x%02x, category_id %d, category_count %d, notification_uid 0x%08x", + ns_data.event_id, + ns_data.event_flags, + ns_data.category_id, + ns_data.category_count, + ns_data.notification_uid + ); + APP_PRINT_INFO5("event_flags: slient %d, important %d, pre existing %d, positive action %d, negative action %d ", + ns_data.event_flags & NS_EVENT_FLAG_SILENT, + ns_data.event_flags & NS_EVENT_FLAG_IMPORTANT, + ns_data.event_flags & NS_EVENT_FLAG_PRE_EXISTING, + ns_data.event_flags & NS_EVENT_FLAG_POSITIVE_ACTION, + ns_data.event_flags & NS_EVENT_FLAG_NEGATIVE_ACTION + ); +#endif + //you can filter by category_id here, for demo purpose, we didn't filter any CategoryID here. +#if F_BT_ANCS_APP_FILTER + //filter social and other category & phone category & email category + if (ns_data.category_id == NS_CATEGORY_ID_SOCIAL || + ns_data.category_id == NS_CATEGORY_ID_OTHER || + ns_data.category_id == NS_CATEGORY_ID_INCOMING_CALL || + ns_data.category_id == NS_CATEGORY_ID_EMAIL) + { +#endif + if (ns_data.event_id != NS_EVENT_ID_NOTIFICATION_REMOVED) + { + uint32_t msg_num; + T_ANCS_MSG ancs_msg; + uint8_t attr_id_list[14]; + uint8_t cur_index = 0; + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_SUB_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_DATE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL; + + os_msg_queue_peek(ancs_link_table[conn_id].ancs_queue_handle, &msg_num); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("app_parse_notification_source_data: msg_num %d", msg_num); +#endif + if (msg_num == 0) + { + if (ancs_get_notification_attr(conn_id, ns_data.notification_uid, attr_id_list, + cur_index) == true) + { + return; + } + } + + ancs_msg.type = ANCS_MSG_TYPE_GET_NOTIFI_ATTR; + ancs_msg.data.notifi_attr.conn_id = conn_id; + ancs_msg.data.notifi_attr.notification_uid = ns_data.notification_uid; + ancs_msg.data.notifi_attr.attribute_ids_len = cur_index; + memcpy(ancs_msg.data.notifi_attr.attribute_ids, attr_id_list, cur_index); + if (os_msg_send(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_ERROR0("app_parse_notification_source_data: discard, msg queue is full"); + } + } +#if F_BT_ANCS_APP_FILTER + } +#endif + } +} + +/** + * @brief Ancs client callback handle message from upperstack + * @param[in] client_id client identifier + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @return @ref T_APP_RESULT + */ +T_APP_RESULT ancs_client_cb(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_ANCS_CB_DATA *p_cb_data = (T_ANCS_CB_DATA *)p_data; + + switch (p_cb_data->cb_type) + { + case ANCS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_cb_data->cb_content.disc_state) + { + case DISC_ANCS_DONE: + APP_PRINT_INFO0("ANCS BLE Client CB: discover procedure done."); + ancs_set_data_source_notify(conn_id, true); + break; + case DISC_ANCS_FAILED: + APP_PRINT_ERROR0("ANCS BLE Client CB: discover request failed."); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (p_cb_data->cb_content.notify_data.type) + { + case ANCS_FROM_DATA_SOURCE:; + app_parse_data_soucre_notifications(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + case ANCS_FROM_NOTIFICATION_SOURCE: + APP_PRINT_INFO2("ANCS_FROM_NOTIFICATION_SOURCE: conn_id %d, length %d", + conn_id, p_cb_data->cb_content.notify_data.value_size); + app_parse_notification_source_data(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_WRITE_RESULT: + { + if (p_cb_data->cb_content.write_result.cause != ATT_SUCCESS) + { + APP_PRINT_ERROR1("ANCS_CLIENT_CB_TYPE_WRITE_RESULT: Failed, cause 0x%x", + p_cb_data->cb_content.write_result.cause); + } + switch (p_cb_data->cb_content.write_result.type) + { + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE"); + break; + + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE"); + ancs_set_notification_source_notify(conn_id, true); + break; + case ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_CONTROL_POINT: + APP_PRINT_INFO0("ANCS_WRITE_CONTROL_POINT"); +#if F_BT_ANCS_CLIENT_DEBUG + if (p_cb_data->cb_content.write_result.cause == 0x4A0) + { + APP_PRINT_ERROR0("The commandID was not recognized by the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A1) + { + APP_PRINT_ERROR0("The command was improperly formatted."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A2) + { + APP_PRINT_ERROR0("One of the parameters (for example, the NotificationUID) does not refer to an existing object on the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A3) + { + APP_PRINT_ERROR0("The action was not performed."); + } +#endif + ancs_send_msg_to_app(conn_id); + break; + + default: + break; + } + } + break; + + case ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: + { + T_ANCS_MSG ancs_msg; + void *ancs_queue_handle = ancs_link_table[conn_id].ancs_queue_handle; + APP_PRINT_INFO1("ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: conn_id = 0x%x", conn_id); + memset(&ancs_link_table[conn_id], 0, sizeof(T_APP_ANCS_LINK)); + ancs_link_table[conn_id].ancs_queue_handle = ancs_queue_handle; + /*release msg queue*/ + while (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0)); + } + break; + + default: + break; + } + return result; +} + +void ancs_handle_msg(T_IO_MSG *p_io_msg) +{ + uint8_t conn_id = p_io_msg->u.param; + T_ANCS_MSG ancs_msg; + if (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_INFO1("ancs_handle_msg: conn_id 0x%x os_msg_recv failed", conn_id); + return; + } + if (ancs_msg.type == ANCS_MSG_TYPE_GET_NOTIFI_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: notification_uid 0x%x", + ancs_msg.data.notifi_attr.notification_uid); + if (ancs_get_notification_attr(ancs_msg.data.notifi_attr.conn_id, + ancs_msg.data.notifi_attr.notification_uid, + ancs_msg.data.notifi_attr.attribute_ids, ancs_msg.data.notifi_attr.attribute_ids_len + ) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: Failed"); + } + + } + else if (ancs_msg.type == ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: notification_uid 0x%x", + ancs_msg.data.perform_action.notification_uid); + if (ancs_perform_notification_action(ancs_msg.data.perform_action.conn_id, + ancs_msg.data.perform_action.notification_uid, + ancs_msg.data.perform_action.action_id) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: Failed"); + } + + } +#if F_BT_ANCS_GET_APP_ATTR + else if (ancs_msg.type == ANCS_MSG_TYPE_GET_APP_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_APP_ATTR: app_identifier %s", + TRACE_STRING(ancs_msg.data.app_attr.app_identifier)); + if (ancs_get_app_attr(ancs_msg.data.app_attr.conn_id, + ancs_msg.data.app_attr.app_identifier, + ancs_msg.data.app_attr.attribute_ids, + ancs_msg.data.app_attr.attribute_ids_len) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_APP_ATTR: Failed"); + } + + } +#endif +} + +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num) +{ + uint8_t i; + ancs_link_number = link_num; + ancs_link_table = os_mem_zalloc(RAM_TYPE_DATA_ON, ancs_link_number * sizeof(T_APP_ANCS_LINK)); + if (ancs_link_table == NULL) + { + APP_PRINT_ERROR0("ancs_init: allocate buffer failed"); + } + for (i = 0; i < ancs_link_number; i++) + { + if (os_msg_queue_create(&(ancs_link_table[i].ancs_queue_handle), ANCS_MSG_QUEUE_NUM, + sizeof(T_ANCS_MSG)) == false) + { + APP_PRINT_ERROR2("ancs_init: link_num %d, i 0x%x create queue failed", link_num, i); + } + } + ancs_client = ancs_add_client(ancs_client_cb, link_num); +} +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#endif diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/ancs.h b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/ancs.h new file mode 100644 index 0000000..68ec35b --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/ancs.h @@ -0,0 +1,259 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file ancs.h +* @brief ancs +* @details ancs +* @author ranhui +* @date 2015-03-27 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _ANCS_H__ +#define _ANCS_H__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +/** @addtogroup PERIPH_ANCS + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Macros ANCS Exported Macros + * @{ + */ +#define ANCS_MAX_ATTR_LEN 256 //!< Max ancs attribute length + +#if F_BT_ANCS_GET_APP_ATTR +#define ANCS_APP_IDENTIFIER_MAX_LEN 30 //!< Max app IDENTIFIER length +#endif + +#define ANCS_MSG_QUEUE_NUM 5 //!< ANCS message queue size + + +/** @brief ANCS event flag */ +#define NS_EVENT_FLAG_SILENT (1 << 0) +#define NS_EVENT_FLAG_IMPORTANT (1 << 1) +#define NS_EVENT_FLAG_PRE_EXISTING (1 << 2) +#define NS_EVENT_FLAG_POSITIVE_ACTION (1 << 3) //!<A positive action exists and is associated with this iOS notification +#define NS_EVENT_FLAG_NEGATIVE_ACTION (1 << 4) //!<A negative action exists and is associated with this iOS notification. + +/** End of PERIPH_ANCS_Exported_Macros + * @} + */ + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Types ANCS Exported Types + * @{ + */ +/** @brief ANCS event id for the peer device notification */ +typedef enum +{ + NS_EVENT_ID_NOTIFICATION_ADD = 0, /**< The arrival of a new iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_MODIFIED = 1, /**< The modification of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_REMOVED = 2, /**< The removal of an iOS notification on the NP */ + NS_EVENT_ID_NOTIFICATION_RESERVED = 0xff +} T_NS_EVENT_ID; + +/** @brief ANCS category id */ +typedef enum +{ + NS_CATEGORY_ID_OTHER = 0, + NS_CATEGORY_ID_INCOMING_CALL = 1, + NS_CATEGORY_ID_MISSED_CALL = 2, + NS_CATEGORY_ID_VOICE_MAIL = 3, + NS_CATEGORY_ID_SOCIAL = 4, + NS_CATEGORY_ID_SCHEDULE = 5, + NS_CATEGORY_ID_EMAIL = 6, + NS_CATEGORY_ID_NEWS = 7, + NS_CATEGORY_ID_HEALTH_AND_FITNESS = 8, + NS_CATEGORY_ID_BUSINESS_ADN_FINANCE = 9, + NS_CATEGORY_ID_LOCATION = 10, + NS_CATEGORY_ID_ENTERTAINMENT = 11, + NS_CATEGORY_ID_RESERVED = 255 +} T_NS_CATEGORY_ID; + +/** @brief ANCS notification attribute id */ +typedef enum +{ + DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER = 0, /**< Format: UTF-8 strings */ + DS_NOTIFICATION_ATTR_ID_TITLE = 1, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_SUB_TITLE = 2, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE = 3, /**<Format: UTF-8 strings. Needs to be followed by a 2-bytes max length parameter */ + DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE = 4, /**<The format of the DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE constant is a string + that represents the integral value of the message size. */ + DS_NOTIFICATION_ATTR_ID_DATE = 5, /**<The format of the DS_NOTIFICATION_ATTR_ID_DATE constant is a string + that uses the Unicode Technical Standard (UTS) #35 date format pattern yyyyMMdd'T'HHmmSS. */ + DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL = 6, /**<Format: UTF-8 strings. The label used to describe + the positive action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL = 7, /**<Format: UTF-8 strings. The label used to describe + the negative action that can be performed on the iOS notification. */ + DS_NOTIFICATION_ATTR_ID_RESERVED = 255 +} T_DS_NOTIFICATION_ATTR_ID; + +/** @brief App parse ANCS notification attribute state */ +typedef enum +{ + DS_PARSE_NOT_START = 0x00, + DS_PARSE_GET_NOTIFICATION_COMMAND_ID = 0x01, + DS_PARSE_UID1, + DS_PARSE_UID2, + DS_PARSE_UID3, + DS_PARSE_UID4, + DS_PARSE_ATTRIBUTE_ID, + DS_PARSE_ATTRIBUTE_LEN1, + DS_PARSE_ATTRIBUTE_LEN2, + DS_PARSE_ATTRIBUTE_READY +} T_DS_NOTIFICATION_ATTR_PARSE_STATE; + +/** @brief Smart Phone App attribute id. */ +typedef enum +{ + DS_APP_ATTR_ID_DISPLAY_NAME = 0, + DS_APP_ATTR_ID_RESERVED = 255 +} T_DS_APP_ATTR_ID; + +/** @brief App parse ANCS attribute state */ +typedef enum +{ + DS_PARSE_GET_APP_COMMAND_ID = 0x10, + DS_PARSE_APP_IDENTIFIER_START, + DS_PARSE_APP_IDENTIFIER_END, + DS_PARSE_APP_ATTRIBUTE_ID, + DS_PARSE_APP_ATTRIBUTE_LEN1, + DS_PARSE_APP_ATTRIBUTE_LEN2, + DS_PARSE_APP_ATTRIBUTE_READY +} T_DS_APP_ATTR_PARSE_STATE; + +/** @brief ANCS action id state */ +typedef enum +{ + CP_ACTION_ID_POSITIVE = 0, + CP_ACTION_ID_NEGATIVE = 1, + CP_ACTION_ID_RESERVED = 255 +} T_CP_ACTION_ID_VALUES; + +/** @brief Define notification source data for record ANCS notification parameters */ +typedef struct +{ + uint8_t event_id; /**< This field informs the accessory whether the given iOS notification + was added, modified, or removed. The enumerated values for this field are defined in @ref T_NS_EVENT_ID*/ + uint8_t event_flags; /**< A bitmask whose set bits inform an NC of specificities with the iOS notification. */ + uint8_t category_id; /**< A numerical value providing a category in which the iOS notification + can be classified. The enumerated values for this field are defined in @ref T_NS_CATEGORY_ID*/ + uint8_t category_count; /**< The current number of active iOS notifications in the given category. */ + uint32_t notification_uid; /**< A 32-bit numerical value that is the unique identifier (UID) for the iOS notification.*/ +} T_NS_DATA, *P_NS_DATA; + +/** @brief Define notification attribute details data */ +/** App can acquire details information by attribute id */ +typedef struct +{ + uint8_t command_id; + uint8_t notification_uid[4]; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_NOTIFICATION_ATTR; + +/** @brief Local app record notification attribute information */ +typedef struct +{ + uint8_t command_id; + uint8_t attribute_id; + uint16_t attribute_len; + uint8_t data[ANCS_MAX_ATTR_LEN]; +} T_DS_APP_ATTR; + +/** @brief ANCS Message Type */ +typedef enum +{ + ANCS_MSG_TYPE_GET_NOTIFI_ATTR, + ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION, + ANCS_MSG_TYPE_GET_APP_ATTR, +} T_ANCS_MSG_TYPE; + +/** @brief Message data of ANCS_MSG_TYPE_GET_NOTIFI_ATTR */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t attribute_ids[14]; + uint8_t attribute_ids_len; +} T_ANCS_GET_NOTIFI_ATTR; + +/** @brief Message data of ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION */ +typedef struct +{ + uint8_t conn_id; + uint32_t notification_uid; + uint8_t action_id; +} T_ANCS_PERFORM_NOTIFI_ACTION; + +#if F_BT_ANCS_GET_APP_ATTR +/** @brief Message data of ANCS_MSG_TYPE_GET_APP_ATTR */ +typedef struct +{ + uint8_t conn_id; + char app_identifier[ANCS_APP_IDENTIFIER_MAX_LEN]; + uint8_t attribute_ids[1]; + uint8_t attribute_ids_len; +} T_ANCS_GET_APP_ATTR; +#endif + +/** @brief ANCS Message Data */ +typedef struct +{ + T_ANCS_MSG_TYPE type; + union + { + T_ANCS_GET_NOTIFI_ATTR notifi_attr; + T_ANCS_PERFORM_NOTIFI_ACTION perform_action; +#if F_BT_ANCS_GET_APP_ATTR + T_ANCS_GET_APP_ATTR app_attr; +#endif + } data; +} T_ANCS_MSG; +/** End of PERIPH_ANCS_Exported_Types + * @} + */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num); + +/** + * @brief All the ancs messages are pre-handled in this function + * @param[in] io_msg IO message data + * @return void + */ +void ancs_handle_msg(T_IO_MSG *p_io_msg); +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app.c b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app.c new file mode 100644 index 0000000..cbc9143 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app.c @@ -0,0 +1,608 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <string.h> + +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_conn_le.h> +#include <gap_msg.h> +#if F_BT_ANCS_CLIENT_SUPPORT +#include <ancs_client.h> +#include "ancs.h" +#endif +#include <bas.h> +#include <simple_ble_service.h> + +#include "trace.h" + +#include "app.h" +#include "io_adc.h" + +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE peripheral application routines. + * @{ + */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bas_srv_id; /**< Battery service id */ +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ + +/*============================================================================* + * Functions + *============================================================================*/ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; +#if F_BT_ANCS_CLIENT_SUPPORT + case IO_MSG_TYPE_ANCS: + { + ancs_handle_msg(&io_msg); + } + break; +#endif + case IO_MSG_TYPE_ADC: + { +// APP_PRINT_INFO0("[app] app_handle_io_msg: adc msg."); + io_handle_adc_msg(&io_msg); + //Add user code here! + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ +// le_adv_start(); + } + } + + if (gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + } + } + + gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, gap_conn_state, new_state, disc_cause); + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, remote_bd, &remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + } + break; + + default: + break; + } + gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { +#if F_BT_ANCS_CLIENT_SUPPORT + ancs_start_discovery(conn_id); +#endif + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("app_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("app_handle_conn_param_update_evt update pending."); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ + +/** @defgroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value[2] = {0x01, 0x02}; + APP_PRINT_INFO0("SIMP_READ_V1"); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + else if (service_id == bas_srv_id) + { + T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; + switch (p_bas_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_bas_cb_data->msg_data.notification_indification_index) + { + case BAS_NOTIFY_BATTERY_LEVEL_ENABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE"); + } + break; + + case BAS_NOTIFY_BATTERY_LEVEL_DISABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL) + { + uint8_t battery_level = 90; + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level); + bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level); + } + } + break; + + default: + break; + } + } + + return app_result; +} + +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ + +/** @} */ /* End of group PERIPH_APP */ diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app.h b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app.h new file mode 100644 index 0000000..8aed00b --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app.h @@ -0,0 +1,72 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app.h +* @brief This file handles BLE peripheral application routines. +* @author jane +* @date 2017-06-06 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +#ifndef _APP_H +#define _APP_H + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include <profile_server.h> + +#include "app_msg.h" + + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bas_srv_id; /**< Battery service id */ + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg:IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * @param[in] service_id: Profile service ID + * @param[in] p_data: Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_flags.h b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_flags.h new file mode 100644 index 0000000..3371839 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_flags.h @@ -0,0 +1,40 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#include "upperstack_config.h" + +/** @defgroup PERIPH_Config Peripheral App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +/** @brief Config DLPS: 0-Disable DLPS, 1-Enable DLPS */ +#define F_BT_DLPS_EN 0 +/** @brief Config ANCS Client: 0-Not built in, 1-Open ANCS client function */ +#define F_BT_ANCS_CLIENT_SUPPORT 0 +#define F_BT_ANCS_APP_FILTER (F_BT_ANCS_CLIENT_SUPPORT & 1) +#define F_BT_ANCS_GET_APP_ATTR (F_BT_ANCS_CLIENT_SUPPORT & 0) +/** @brief Config ANCS Client debug log: 0-close, 1-open */ +#define F_BT_ANCS_CLIENT_DEBUG (F_BT_ANCS_CLIENT_SUPPORT & 0) + +/** @} */ /* End of group PERIPH_Config */ +#endif diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_task.c b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_task.c new file mode 100644 index 0000000..635c4c3 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_task.c @@ -0,0 +1,123 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + * <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> + ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <gap_le.h> + +#include "app.h" +#include "app_task.h" + + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +extern void driver_init(void); + +void app_main_task(void *p_param); + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg) +{ + uint8_t event = EVENT_IO_TO_APP; + + if (os_msg_send(io_queue_handle, p_msg, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_io_msg_to_app fail"); + return false; + } + if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + APP_PRINT_ERROR0("[app_task] app_send_msg_to_apptask: send_evt_msg_to_app fail"); + return false; + } + return true; +} + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param: Parameters sending to the task + * @return void + */ +void app_main_task(void *p_param) +{ + uint8_t event; + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + driver_init(); + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** @} */ /* End of group PERIPH_APP_TASK */ + + diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_task.h b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_task.h new file mode 100644 index 0000000..5d5918a --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/app_task.h @@ -0,0 +1,47 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file app_task.h +* @brief Routines to create App task and handle events & messages +* @author jane +* @date 2017-06-02 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#include <string.h> + +#include "os_msg.h" +#include "os_queue.h" +#include "os_sched.h" +#include "os_task.h" +#include "os_timer.h" + +#include "app_msg.h" + +#include "trace.h" + + +/** + * @brief Send msg to app task. + * @param[in] p_handle: The handle to the message queue being peeked. + * @return The status of the message queue peek. + * @retval true:Message queue was peeked successfully. + * @retval false:Message queue was failed to peek. + */ +bool app_send_msg_to_apptask(T_IO_MSG *p_msg); + +/** + * @brief Initialize app task + * @return void + */ +void app_task_init(void); + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/main.c b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/main.c new file mode 100644 index 0000000..5b0e091 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/ble_peripheral/main.c @@ -0,0 +1,249 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file main.c +* @brief Source file for BLE peripheral project, mainly used for initialize modules +* @author jane +* @date 2017-06-12 +* @version v1.0 +************************************************************************************** +* @attention +* <h2><center>© COPYRIGHT 2017 Realtek Semiconductor Corporation</center></h2> +************************************************************************************** +*/ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include <stdlib.h> +#include <string.h> + +#include <gap.h> +#include <gap_adv.h> +#include <gap_bond_le.h> +#include <gap_msg.h> +#include <bas.h> +#include <simple_ble_service.h> + +#if F_BT_ANCS_CLIENT_SUPPORT +#include <profile_client.h> +#include "ancs.h" +#endif + +#include "trace.h" + +#include "app.h" +#include "app_task.h" +#include "app_flags.h" +//#include "app_timer.h" + +#include "io_adc.h" + + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + + +/*============================================================================* + * Variables + *============================================================================*/ + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x0F, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'L', 'E', '_', 'P', 'E', 'R', 'I', 'P', 'H', 'E', 'R', 'A', 'L', +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_PERIPHERAL"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; +#if F_BT_ANCS_CLIENT_SUPPORT + uint8_t auth_sec_req_enable = true; +#else + uint8_t auth_sec_req_enable = false; +#endif + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(app_gap_callback); +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void app_le_profile_init(void) +{ + server_init(2); + simp_srv_id = simp_ble_service_add_service(app_profile_callback); + bas_srv_id = bas_add_service(app_profile_callback); + server_register_app_cb(app_profile_callback); +#if F_BT_ANCS_CLIENT_SUPPORT + client_init(1); + ancs_init(APP_MAX_LINKS); +#endif +} + +/** + * @brief Initialize global data. + * @param No parameter. + * @return void + */ +void global_data_init(void) +{ + global_data_adc_init(); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be performed with the IO initializing. + * @return void + */ +void board_init(void) +{ + board_adc_init(); +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void driver_init(void) +{ + driver_adc_init(); +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void task_init(void) +{ + app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int main(void) +{ + extern uint32_t random_seed_value; + srand(random_seed_value); + global_data_init(); + board_init(); + le_gap_init(APP_MAX_LINKS); + gap_lib_init(); + app_le_gap_init(); + app_le_profile_init(); + pwr_mgr_init(); +// sw_timer_init(); + task_init(); + os_sched_start(); + + return 0; +} +/** @} */ /* End of group PERIPH_DEMO_MAIN */ + + diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/io_adc.c b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/io_adc.c new file mode 100644 index 0000000..44e5d27 --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/io_adc.c @@ -0,0 +1,216 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.c +* @brief This file provides demo code of adc continuous mode. +* @details +* @author echo +* @date 2021-06-29 +* @version v1.0 +********************************************************************************************************* +*/ + +/* Includes ------------------------------------------------------------------*/ +#include "io_adc.h" + +#include "app_task.h" + +/* Globals ------------------------------------------------------------------*/ +ADC_Data_TypeDef ADC_Global_Data; + +/** + * @brief Initialization adc global data. + * @param No parameter. + * @return void + */ +void global_data_adc_init(void) +{ + /* Initialize adc k value! */ + APP_PRINT_INFO0("[io_adc] global_data_adc_init"); + bool adc_k_status = false; + adc_k_status = ADC_CalibrationInit(); + if (false == adc_k_status) + { + APP_PRINT_ERROR0("[io_adc] global_data_adc_init: ADC_CalibrationInit fail!"); + } + memset(&ADC_Global_Data, 0, sizeof(ADC_Global_Data)); +} + +/** + * @brief Initialization of pinmux settings and pad settings. + * @param No parameter. + * @return void +*/ +void board_adc_init(void) +{ + Pad_Config(ADC_SAMPLE_PIN_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); + Pad_Config(ADC_SAMPLE_PIN_1, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); +} + +/** + * @brief Initialize ADC peripheral. + * @param No parameter. + * @return void + */ +void driver_adc_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE); + + ADC_InitTypeDef ADC_InitStruct; + ADC_StructInit(&ADC_InitStruct); + /** Configure the ADC sampling schedule, a schedule represents an ADC channel data, + * up to 16, i.e. schIndex[0] ~ schIndex[15]. + * If one of the differential channel pairs uses P2_x, x = 2/6, then the other differential channel must be 1/2; + * If one of the differential channel pairs uses P2_x, x = 3/7, then the other differential channel must be 1/2. + * In differential mode, read the sample value of any channel of the differential channel pairs, + * and the absolute value of the two channels is approximately equal. + */ + ADC_InitStruct.ADC_SchIndex[0] = EXT_DIFFERENTIAL(ADC_SAMPLE_CHANNEL_0); + ADC_InitStruct.ADC_SchIndex[1] = EXT_DIFFERENTIAL(ADC_SAMPLE_CHANNEL_1); + /** Set the bitmap corresponding to schedule, 16 bits, LSB, + * schIndex[0-15] corresponding to 16 bits of bitmap bit0-bit15. + * For example, if config schIndex[0] and schIndex [1], then bitmap is 0000 0000 0011 (that is, 0x0003); + * if config schIndex [0] and schIndex [2], then bitmap is 0000 0000 0101 (that is, 0x0005). + */ + ADC_InitStruct.ADC_Bitmap = 0x03; + /* Fixed 255 in OneShot mode. */ + ADC_InitStruct.ADC_SampleTime = 255; + ADC_Init(ADC, &ADC_InitStruct); + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + /** High bypass resistance mode config, please notice that the input voltage of + * adc channel using high bypass mode should not be over 0.9V. + */ + APP_PRINT_INFO0("[io_adc]driver_adc_init: ADC sample mode is bypass mode !"); + uint8_t temp = ADC_SAMPLE_CHANNEL_0 & 0x02; + switch (temp) + { + case 0x0: + ADC_BypassCmd(0, ENABLE); + ADC_BypassCmd(1, ENABLE); + break; + case 0x02: + ADC_BypassCmd(2, ENABLE); + ADC_BypassCmd(3, ENABLE); + break; + default: + break; + } + temp += 0x01; +#else + ADC_BypassCmd(0, DISABLE); + ADC_BypassCmd(1, DISABLE); + ADC_BypassCmd(2, DISABLE); + ADC_BypassCmd(3, DISABLE); + APP_PRINT_INFO0("[io_adc]driver_adc_init: ADC sample mode is divide mode !"); +#endif + + ADC_INTConfig(ADC, ADC_INT_ONE_SHOT_DONE, ENABLE); + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = ADC_IRQn; + NVIC_InitStruct.NVIC_IRQChannelPriority = 3; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + /** When ADC is enabled, sampling will be done quickly and interruption will occur. + * After initialization, ADC can be enabled when sampling is needed. + */ + ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE); +} + +/** + * @brief Calculate adc sample voltage. + * @param No parameter. + * @return void + */ +static void io_adc_voltage_calculate(T_IO_MSG *io_adc_msg) +{ + uint8_t sample_data_len = 0; + uint16_t sample_data[ADC_SCHEDULE_NUM] = {0}; + float sample_voltage[ADC_SCHEDULE_NUM] = {0}; + ADC_ErrorStatus error_status = NO_ERROR; + + uint16_t *p_buf = io_adc_msg->u.buf; + + sample_data_len = p_buf[0]; + for (uint8_t i = 0; i < sample_data_len; i++) + { + sample_data[i] = p_buf[i + 1]; + } + for (uint8_t i = 0; i < sample_data_len; i++) + { + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + sample_voltage[i] = ADC_GetVoltage(BYPASS_DIFFERENTIAL_MODE, (int32_t)sample_data[i], + &error_status); +#else + sample_voltage[i] = ADC_GetVoltage(DIVIDE_DIFFERENTIAL_MODE, (int32_t)sample_data[i], + &error_status); +#endif + if (error_status < 0) + { + APP_PRINT_INFO2("[io_adc]io_adc_voltage_calculate: ADC parameter or efuse data error! i = %d, error_status = %d", + i, error_status); + } + else + { + APP_PRINT_INFO4("[io_adc]io_adc_voltage_calculate: ADC rawdata_%-4d = %d, voltage_%-4d = %dmV ", i, + sample_data[i], i, (int32_t)sample_voltage[i]); + } + } + memset(&ADC_Global_Data, 0, sizeof(ADC_Global_Data)); +} + +/** + * @brief Handle adc data function. + * @param No parameter. + * @return void + */ +void io_handle_adc_msg(T_IO_MSG *io_adc_msg) +{ + io_adc_voltage_calculate(io_adc_msg); +} + +/** + * @brief ADC interrupt handler function. + * @param No parameter. + * @return void + */ +void ADC_Handler(void) +{ + uint16_t sample_data[ADC_SCHEDULE_NUM] = {0}; + + if (ADC_GetINTStatus(ADC, ADC_INT_ONE_SHOT_DONE) == SET) + { + ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE); + /* ADC one shot sampling mode, read data from schedule table. + The schedule index is which config in adc init function. + The value is ADC_Schedule_Index_0 ~ ADC_Schedule_Index_15 + */ + + sample_data[0] = ADC_ReadRawData(ADC, ADC_Schedule_Index_0); + sample_data[1] = ADC_ReadRawData(ADC, ADC_Schedule_Index_1); + + T_IO_MSG int_adc_msg; + + int_adc_msg.type = IO_MSG_TYPE_ADC; + int_adc_msg.subtype = 0; + ADC_Global_Data.RawData[0] = 2; + for (uint8_t i = 0; i < ADC_SCHEDULE_NUM; i++) + { + ADC_Global_Data.RawData[i + 1] = sample_data[i]; + } + int_adc_msg.u.buf = (void *)(ADC_Global_Data.RawData); + if (false == app_send_msg_to_apptask(&int_adc_msg)) + { + APP_PRINT_ERROR0("[io_adc] ADC_Handler: Send int_adc_msg failed!"); + //Add user code here! + ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE); + return; + } + } +} + diff --git a/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/io_adc.h b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/io_adc.h new file mode 100644 index 0000000..9bf25da --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_DifferentialMode/io_adc.h @@ -0,0 +1,100 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file io_adc.h +* @brief +* @details +* @author yuan +* @date 2018-12-07 +* @version v1.0 +********************************************************************************************************* +*/ + +#ifndef __IO_ADC_H +#define __IO_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "rtl876x_adc.h" +#include "rtl876x_nvic.h" +#include "rtl876x_pinmux.h" +#include "rtl876x_rcc.h" + +#include "app_msg.h" +#include "board.h" + +/* Defines ------------------------------------------------------------------*/ +/** ADC sample channel config. + * ADC sample channel config:P2_2,P2_3,P2_6,P2_7 and VBAT + * ADC sample channel index select: #define ADC_Channel_Index_0 0 + * #define ADC_Channel_Index_1 1 + * #define ADC_Channel_Index_2 2 + * #define ADC_Channel_Index_3 3 + + * If ADC_SAMPLE_PIN = P2_2, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_0; + * If ADC_SAMPLE_PIN = P2_3, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_1; + * If ADC_SAMPLE_PIN = P2_6, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_2; + * If ADC_SAMPLE_PIN = P2_7, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_3; + */ +#define ADC_SAMPLE_CHANNEL_0 ADC_Channel_Index_0 +#define ADC_SAMPLE_CHANNEL_1 ADC_Channel_Index_1 + +/* Define schedule index. */ +#define ADC_Schedule_Index_0 0 +#define ADC_Schedule_Index_1 1 +#define ADC_Schedule_Index_2 2 +#define ADC_Schedule_Index_3 3 +#define ADC_Schedule_Index_4 4 +#define ADC_Schedule_Index_5 5 +#define ADC_Schedule_Index_6 6 +#define ADC_Schedule_Index_7 7 +#define ADC_Schedule_Index_8 8 +#define ADC_Schedule_Index_9 9 +#define ADC_Schedule_Index_10 10 +#define ADC_Schedule_Index_11 11 +#define ADC_Schedule_Index_12 12 +#define ADC_Schedule_Index_13 13 +#define ADC_Schedule_Index_14 14 +#define ADC_Schedule_Index_15 15 + +/** Define that how many schedules to use, max 16. + */ +#define ADC_SCHEDULE_NUM (2) + + +/** ADC mode config. + * ADC pin hardware mode: bypass mode + * divide mode + */ +#define ADC_DIVIDE_MODE 0 +#define ADC_BYPASS_MODE 1 +#define ADC_MODE_DIVIDE_OR_BYPASS ADC_DIVIDE_MODE + +#define ADC_ONE_SHOT_SAMPLE_PERIOD (1000000-1)//100ms + + +/* ADC global data struct*/ +typedef struct +{ + uint16_t RawData[ADC_SCHEDULE_NUM + 1]; +} ADC_Data_TypeDef; + +extern ADC_Data_TypeDef ADC_Global_Data; + +void global_data_adc_init(void); +void board_adc_init(void); +void driver_adc_init(void); +void driver_adc_timer_init(void); +void io_handle_adc_msg(T_IO_MSG *io_adc_msg); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sample/io_sample/ADC/OneShotMode_Polling/main.c b/src/sample/io_sample/ADC/OneShotMode_Polling/main.c new file mode 100644 index 0000000..3b4129a --- /dev/null +++ b/src/sample/io_sample/ADC/OneShotMode_Polling/main.c @@ -0,0 +1,209 @@ +/** +********************************************************************************************************* +* Copyright(c) 2018, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file main.c +* @brief Uses adc one shot sampling mode. Polling reads adc sampling data. +* @details +* @author yuan_feng +* @date 2018-12-03 +* @version v0.1 +********************************************************************************************************* +*/ + +/* Includes --------------------------------------------------------------*/ +#include <stdlib.h> +#include "rtl876x_adc.h" +#include "rtl876x_pinmux.h" +#include "rtl876x_rcc.h" + +#include "trace.h" + +/* Defines --------------------------------------------------------------*/ +#define ADC_Channel_Index_0 0 +#define ADC_Channel_Index_1 1 +#define ADC_Channel_Index_2 2 +#define ADC_Channel_Index_3 3 + + +#define ADC_Schedule_Index_0 0 +#define ADC_Schedule_Index_1 1 +#define ADC_Schedule_Index_2 2 +#define ADC_Schedule_Index_3 3 +#define ADC_Schedule_Index_4 4 +#define ADC_Schedule_Index_5 5 +#define ADC_Schedule_Index_6 6 +#define ADC_Schedule_Index_7 7 +#define ADC_Schedule_Index_8 8 +#define ADC_Schedule_Index_9 9 +#define ADC_Schedule_Index_10 10 +#define ADC_Schedule_Index_11 11 +#define ADC_Schedule_Index_12 12 +#define ADC_Schedule_Index_13 13 +#define ADC_Schedule_Index_14 14 +#define ADC_Schedule_Index_15 15 + +/* Config ADC channel and mode --------------------------------------------------------------*/ +/* ADC bypass mode or divide mode */ +#define ADC_DIVIDE_MODE 0 +#define ADC_BYPASS_MODE 1 +/* Change the ADC sampling mode here! */ +#define ADC_MODE_DIVIDE_OR_BYPASS ADC_DIVIDE_MODE + + +/* Change the ADC sampling pin here! */ +/** ADC sample channel config. + * ADC sample channel config:P2_2,P2_3,P2_6,P2_7 and VBAT + * ADC sample channel index select: #define ADC_Channel_Index_0 0 + * #define ADC_Channel_Index_1 1 + * #define ADC_Channel_Index_2 2 + * #define ADC_Channel_Index_3 3 + + * If ADC_SAMPLE_PIN = P2_2, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_0; + * If ADC_SAMPLE_PIN = P2_3, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_1; + * If ADC_SAMPLE_PIN = P2_6, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_2; + * If ADC_SAMPLE_PIN = P2_7, then ADC_SAMPLE_CHANNEL = ADC_Channel_Index_3; + */ +#define ADC_SAMPLE_PIN_0 P2_2 +#define ADC_SAMPLE_CHANNEL_0 ADC_Channel_Index_0 + + +/** + * @brief Initialization of pinmux settings and pad settings. + * @param No parameter. + * @return void + */ +void board_adc_init(void) +{ + Pad_Config(ADC_SAMPLE_PIN_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_LOW); +} + +/** + * @brief Initialize adc peripheral. + * @param No parameter. + * @return void +*/ +void driver_adc_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ADC, APBPeriph_ADC_CLOCK, ENABLE); + + ADC_InitTypeDef ADC_InitStruct; + ADC_StructInit(&ADC_InitStruct); + ADC_InitStruct.ADC_SampleTime = 255; + for (uint8_t i = 0; i < 16; i++) + { +#ifdef INTERNAL_VBAT_TEST + ADC_InitStruct.schIndex[i] = INTERNAL_VBAT_MODE; +#else + ADC_InitStruct.ADC_SchIndex[i] = EXT_SINGLE_ENDED(ADC_SAMPLE_CHANNEL_0); +#endif + } + ADC_InitStruct.ADC_Bitmap = 0xFFFF; + ADC_InitStruct.ADC_PowerAlwaysOnEn = ADC_POWER_ALWAYS_ON_ENABLE; + ADC_Init(ADC, &ADC_InitStruct); + +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + /* High bypass resistance mode config, please notice that the input voltage of + adc channel using high bypass mode should not be over 0.9V */ + ADC_BypassCmd(ADC_SAMPLE_CHANNEL_0, ENABLE); + DBG_DIRECT("[ADC]ADC sample mode is bypass mode !"); +#else + DBG_DIRECT("[ADC]ADC sample mode is divide mode !"); +#endif + ADC_INTConfig(ADC, ADC_INT_ONE_SHOT_DONE, ENABLE); +} + +/** + * @brief Demo code of operation about adc. + * @param No parameter. + * @return void + */ +void adc_demo(void) +{ + /* Initialize adc k value! */ + bool adc_k_status; + adc_k_status = ADC_CalibrationInit(); + if (false == adc_k_status) + { + APP_PRINT_ERROR0("[ADC]ADC_CalibrationInit fail!"); + } + /* Configure pad and pinmux firstly! */ + board_adc_init(); + + /* Initialize adc peripheral */ + driver_adc_init(); + + /* Enable adc */ + ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE); +} + +/** + * @brief ADC polling sample demo code. + * @param No parameter. + * @return void + */ +void adc_sample_demo(void) +{ + uint16_t sample_data[16] = {0}; + float sample_voltage[16] = {0}; + ADC_ErrorStatus error_status = NO_ERROR; + + while (ADC_GetINTStatus(ADC, ADC_INT_ONE_SHOT_DONE) == RESET); + ADC_ClearINTPendingBit(ADC, ADC_INT_ONE_SHOT_DONE); + for (uint8_t i = 0; i < 16; i++) + { + sample_data[i] = ADC_ReadRawData(ADC, ADC_Schedule_Index_0 + i); + } + + for (uint8_t i = 0; i < 16; i++) + { +#if (ADC_MODE_DIVIDE_OR_BYPASS == ADC_BYPASS_MODE) + sample_voltage[i] = ADC_GetVoltage(BYPASS_SINGLE_MODE, (int32_t)sample_data[i], &error_status); +#else + sample_voltage[i] = ADC_GetVoltage(DIVIDE_SINGLE_MODE, (int32_t)sample_data[i], &error_status); +#endif + if (error_status < 0) + { + /* Notes: DBG_DIRECT is only used for debug demo, do not use in app! + In app project, the APP_PRINT_INFO can be used. + */ + DBG_DIRECT("[ADC]adc_sample_demo: ADC parameter or efuse data error! i = %d, error_status = %d", i, + error_status); +// APP_PRINT_INFO2("[ADC] adc_sample_demo: ADC parameter or efuse data error! i = %d, error_status = %d", i, error_status); + } + else + { + /* Notes: DBG_DIRECT is only used for debug demo, do not use in app! + In app project, the APP_PRINT_INFO can be used. + */ + DBG_DIRECT("[ADC] adc_sample_demo: ADC one shot mode sample data_%d = %d, voltage_%d = %dmV ", i, + sample_data[i], i, (uint32_t)sample_voltage[i]); +// APP_PRINT_INFO4("[ADC] adc_sample_demo: ADC one shot mode sample data_%-4d = %d, voltage_%-4d = %dmV ", i, sample_data[i], i, (uint32_t)sample_voltage[i]); + } + } +} + +/** + * @brief Entry of app code + * @return int (To avoid compile warning) + */ +int main(void) +{ + extern uint32_t random_seed_value; + srand(random_seed_value); + adc_demo(); + + while (1) + { + /* Notes: DBG_DIRECT is only used for debug demo, do not use in app! + In app project, the APP_PRINT_INFO can be used. + */ + DBG_DIRECT("[ADC]Polling reads adc sample data !"); + adc_sample_demo(); + for (uint32_t i = 500000; i > 0; i--); + ADC_Cmd(ADC, ADC_ONE_SHOT_MODE, ENABLE); + } +} + + |