58:de6b64cd7f21
Release 0.1.0 ============= We've achieved significant gains in power consumption: the BLE_Beacon demo now runs at around 35uA of average current broadcasting once a second at 0dB; when not using the radio, this demo consumes around 7uA. Features ~~~~~~~~ - Replace initialization of high-frequency external crystal clock-source with the use of low-frequency clock. This brings in significant gains in power consumption. - Re-implement the micro-second timer on nRF51 using the app_timer module (which internally uses RTC). This limits the precision of the us_Timer to 30uS; but brings in significant gains in power consumption. - Reduce the number of available app_timers and the event depths for app-timer events; this will reduce memory consumption for zero-initialized data by around 1K. - Remove the call to conn_params_init() at startup. This is not mandatory; and was causing an unnecessary re-negotiation of connection parameters a few seconds into every connection. - Reduce default transmission power level to 0dbB (was 4dbB before). - Reduce min connection interval to 50ms and max to 500ms (previous values were much larger). - Replace a few instances of use of wait() with nrf_delay_us(). - onConnection() callback now receives connection-parameters applicable to the new connection. - onDataSent() callback now receives a count parameter containing the number of times notifications were sent out since the last callback. - A 'reason' parameter has been added to Gap::disconnect() to indicate the reason for disconnection; and also to the onDisconnection callback to receive a reason from the remote host. - disable the app_gpiote module by default. Bugfixes ~~~~~~~~ - onDataWritten() callback now passes an additional parameter (GattServer::WriteEventCallback_t) encapsulating the update. This avoids having to re-fetch the updated characteristic's value attribute. It also fixes a bug where multiple updates to the characteristic's value-attribute could get clobbered if they occurred in quick succession before the callbacks could be processed. Compatibility ~~~~~~~~~~~~~ Compatible with revision 0.1.0 of the BLE_API.master
commit
384c84522b
|
@ -39,13 +39,13 @@
|
|||
#include "nRF51Gap.h"
|
||||
#include "nRF51GattServer.h"
|
||||
|
||||
#include "ble_hci.h"
|
||||
|
||||
#if NEED_BOND_MANAGER /* disabled by default */
|
||||
static void service_error_callback(uint32_t nrf_error);
|
||||
#endif
|
||||
extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
|
||||
void app_error_handler(uint32_t error_code,
|
||||
uint32_t line_num,
|
||||
const uint8_t *p_file_name);
|
||||
extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
|
||||
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name);
|
||||
|
||||
#if NEED_BOND_MANAGER /* disabled by default */
|
||||
static error_t bond_manager_init(void);
|
||||
|
@ -62,8 +62,40 @@ static void sys_evt_dispatch(uint32_t sys_evt)
|
|||
|
||||
error_t btle_init(void)
|
||||
{
|
||||
APP_TIMER_INIT(0, 8, 5, false);
|
||||
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
|
||||
const bool useScheduler = false;
|
||||
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, useScheduler);
|
||||
|
||||
// Enable BLE stack
|
||||
/**
|
||||
* Using this call, the application can select whether to include the
|
||||
* Service Changed characteristic in the GATT Server. The default in all
|
||||
* previous releases has been to include the Service Changed characteristic,
|
||||
* but this affects how GATT clients behave. Specifically, it requires
|
||||
* clients to subscribe to this attribute and not to cache attribute handles
|
||||
* between connections unless the devices are bonded. If the application
|
||||
* does not need to change the structure of the GATT server attributes at
|
||||
* runtime this adds unnecessary complexity to the interaction with peer
|
||||
* clients. If the SoftDevice is enabled with the Service Changed
|
||||
* Characteristics turned off, then clients are allowed to cache attribute
|
||||
* handles making applications simpler on both sides.
|
||||
*/
|
||||
static const bool IS_SRVC_CHANGED_CHARACT_PRESENT = false;
|
||||
ble_enable_params_t enableParams = {
|
||||
.gatts_enable_params = {
|
||||
.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT
|
||||
}
|
||||
};
|
||||
if (sd_ble_enable(&enableParams) != NRF_SUCCESS) {
|
||||
return ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ble_gap_addr_t addr;
|
||||
if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) {
|
||||
return ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) {
|
||||
return ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler));
|
||||
ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch));
|
||||
|
@ -82,14 +114,17 @@ static void btle_handler(ble_evt_t *p_ble_evt)
|
|||
#if NEED_BOND_MANAGER /* disabled by default */
|
||||
ble_bondmngr_on_ble_evt(p_ble_evt);
|
||||
#endif
|
||||
#if SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
ble_conn_params_on_ble_evt(p_ble_evt);
|
||||
#endif
|
||||
|
||||
/* Custom event handler */
|
||||
switch (p_ble_evt->header.evt_id) {
|
||||
case BLE_GAP_EVT_CONNECTED: {
|
||||
Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
nRF51Gap::getInstance().setConnectionHandle(handle);
|
||||
nRF51Gap::getInstance().processHandleSpecificEvent(GapEvents::GAP_EVENT_CONNECTED, handle);
|
||||
const Gap::ConnectionParams_t *params = reinterpret_cast<Gap::ConnectionParams_t *>(&(p_ble_evt->evt.gap_evt.params.connected.conn_params));
|
||||
nRF51Gap::getInstance().processConnectionEvent(handle, params);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -101,7 +136,10 @@ static void btle_handler(ble_evt_t *p_ble_evt)
|
|||
#if NEED_BOND_MANAGER /* disabled by default */
|
||||
ASSERT_STATUS_RET_VOID ( ble_bondmngr_bonded_centrals_store());
|
||||
#endif
|
||||
nRF51Gap::getInstance().processHandleSpecificEvent(GapEvents::GAP_EVENT_DISCONNECTED, handle);
|
||||
|
||||
if (p_ble_evt->evt.gap_evt.params.disconnected.reason == BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION) {
|
||||
nRF51Gap::getInstance().processDisconnectionEvent(handle, Gap::LOCAL_HOST_TERMINATED_CONNECTION);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -117,11 +155,8 @@ static void btle_handler(ble_evt_t *p_ble_evt)
|
|||
sec_params.min_key_size = CFG_BLE_SEC_PARAM_MIN_KEY_SIZE;
|
||||
sec_params.max_key_size = CFG_BLE_SEC_PARAM_MAX_KEY_SIZE;
|
||||
|
||||
ASSERT_STATUS_RET_VOID(
|
||||
sd_ble_gap_sec_params_reply(nRF51Gap::getInstance().
|
||||
getConnectionHandle(),
|
||||
BLE_GAP_SEC_STATUS_SUCCESS,
|
||||
&sec_params));
|
||||
ASSERT_STATUS_RET_VOID(sd_ble_gap_sec_params_reply(nRF51Gap::getInstance().getConnectionHandle(),
|
||||
BLE_GAP_SEC_STATUS_SUCCESS, &sec_params));
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "ble_conn_params.h"
|
||||
|
||||
static inline uint32_t msec_to_1_25msec(uint32_t interval_ms) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
#if SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
static void error_callback(uint32_t nrf_error);
|
||||
#endif // SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
|
@ -46,6 +48,11 @@ error_t btle_gap_init(void)
|
|||
ASSERT_STATUS( sd_ble_gap_ppcp_set(&gap_conn_params));
|
||||
ASSERT_STATUS( sd_ble_gap_tx_power_set(CFG_BLE_TX_POWER_LEVEL));
|
||||
|
||||
/**
|
||||
* Call to conn_params_init() is not necessary; and so is disabled by default.
|
||||
* This API should be exposed to the user to be invoked when necessary.
|
||||
*/
|
||||
#if SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
/* Connection Parameters */
|
||||
enum {
|
||||
FIRST_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER),
|
||||
|
@ -65,6 +72,7 @@ error_t btle_gap_init(void)
|
|||
cp_init.error_handler = error_callback;
|
||||
|
||||
ASSERT_STATUS ( ble_conn_params_init(&cp_init));
|
||||
#endif // SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
@ -84,7 +92,9 @@ static inline uint32_t msec_to_1_25msec(uint32_t interval_ms)
|
|||
return (interval_ms * 4) / 5;
|
||||
}
|
||||
|
||||
#if SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
static void error_callback(uint32_t nrf_error)
|
||||
{
|
||||
ASSERT_STATUS_RET_VOID( nrf_error );
|
||||
}
|
||||
#endif // SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
* structures involved in maintaining a local cache of 128-bit UUIDs.
|
||||
*/
|
||||
typedef struct {
|
||||
LongUUID_t uuid;
|
||||
uint8_t type;
|
||||
LongUUIDBytes_t uuid;
|
||||
uint8_t type;
|
||||
} converted_uuid_table_entry_t;
|
||||
static const unsigned UUID_TABLE_MAX_ENTRIES = 8; /* This is the maximum number
|
||||
* of 128-bit UUIDs with distinct bases that
|
||||
|
@ -40,7 +40,7 @@ converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES];
|
|||
* @return true if a match is found.
|
||||
*/
|
||||
static bool
|
||||
lookupConvertedUUIDTable(const LongUUID_t uuid, uint8_t *recoveredType)
|
||||
lookupConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t *recoveredType)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < uuidTableEntries; i++) {
|
||||
|
@ -56,7 +56,7 @@ lookupConvertedUUIDTable(const LongUUID_t uuid, uint8_t *recoveredType)
|
|||
}
|
||||
|
||||
static void
|
||||
addToConvertedUUIDTable(const LongUUID_t uuid, uint8_t type)
|
||||
addToConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t type)
|
||||
{
|
||||
if (uuidTableEntries == UUID_TABLE_MAX_ENTRIES) {
|
||||
return; /* recovery needed; or at least the user should be
|
||||
|
@ -157,7 +157,7 @@ uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base)
|
|||
error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base,
|
||||
ble_uuid_t *p_uuid)
|
||||
{
|
||||
LongUUID_t uuid_base_le;
|
||||
LongUUIDBytes_t uuid_base_le;
|
||||
|
||||
/* Reverse the bytes since ble_uuid128_t is LSB */
|
||||
for (uint8_t i = 0; i<16; i++) {
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CSI_CODE(seq) "\33[" seq
|
||||
|
@ -95,7 +95,7 @@
|
|||
#define ANSI_BG_DEFAULT CSI_SGR(49)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_ANSI_ESC_CODE_H_ */
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nrf_soc.h"
|
||||
|
||||
#include "btle/btle.h"
|
||||
#include "nrf_delay.h"
|
||||
|
||||
/**
|
||||
* The singleton which represents the nRF51822 transport for the BLEDevice.
|
||||
|
@ -133,10 +134,10 @@ ble_error_t nRF51822n::init(void)
|
|||
/**************************************************************************/
|
||||
ble_error_t nRF51822n::reset(void)
|
||||
{
|
||||
wait(0.5);
|
||||
nrf_delay_us(500000);
|
||||
|
||||
/* Wait for the radio to come back up */
|
||||
wait(1);
|
||||
nrf_delay_us(1000000);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
|
60
nRF51Gap.cpp
60
nRF51Gap.cpp
|
@ -168,8 +168,7 @@ ble_error_t nRF51Gap::startAdvertising(const GapAdvertisingParams ¶ms)
|
|||
adv_para.interval = params.getInterval(); // advertising interval (in units of 0.625 ms)
|
||||
adv_para.timeout = params.getTimeout();
|
||||
|
||||
ASSERT(ERROR_NONE == sd_ble_gap_adv_start(&adv_para),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE);
|
||||
ASSERT(ERROR_NONE == sd_ble_gap_adv_start(&adv_para), BLE_ERROR_PARAM_OUT_OF_RANGE);
|
||||
|
||||
state.advertising = 1;
|
||||
|
||||
|
@ -218,14 +217,23 @@ ble_error_t nRF51Gap::stopAdvertising(void)
|
|||
@endcode
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ble_error_t nRF51Gap::disconnect(void)
|
||||
ble_error_t nRF51Gap::disconnect(DisconnectionReason_t reason)
|
||||
{
|
||||
state.advertising = 0;
|
||||
state.connected = 0;
|
||||
|
||||
uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION;
|
||||
switch (reason) {
|
||||
case REMOTE_USER_TERMINATED_CONNECTION:
|
||||
code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION;
|
||||
break;
|
||||
case CONN_INTERVAL_UNACCEPTABLE:
|
||||
code = BLE_HCI_CONN_INTERVAL_UNACCEPTABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disconnect if we are connected to a central device */
|
||||
ASSERT_INT(ERROR_NONE,
|
||||
sd_ble_gap_disconnect(m_connectionHandle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION), BLE_ERROR_PARAM_OUT_OF_RANGE);
|
||||
ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(m_connectionHandle, code), BLE_ERROR_PARAM_OUT_OF_RANGE);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -252,8 +260,7 @@ ble_error_t nRF51Gap::updateConnectionParams(Handle_t handle, const ConnectionPa
|
|||
{
|
||||
uint32_t rc;
|
||||
|
||||
rc = sd_ble_gap_conn_param_update(handle,
|
||||
reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams)));
|
||||
rc = sd_ble_gap_conn_param_update(handle, reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams)));
|
||||
if (rc == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
|
@ -314,3 +321,42 @@ ble_error_t nRF51Gap::setAddress(addr_type_t type, const uint8_t address[6])
|
|||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t nRF51Gap::setDeviceName(const uint8_t *deviceName)
|
||||
{
|
||||
ble_gap_conn_sec_mode_t sec_mode;
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed
|
||||
|
||||
if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t nRF51Gap::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
|
||||
{
|
||||
if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t nRF51Gap::setAppearance(uint16_t appearance)
|
||||
{
|
||||
if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t nRF51Gap::getAppearance(uint16_t *appearanceP)
|
||||
{
|
||||
if (sd_ble_gap_appearance_get(appearanceP)) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,12 @@ public:
|
|||
const GapAdvertisingData &);
|
||||
virtual ble_error_t startAdvertising(const GapAdvertisingParams &);
|
||||
virtual ble_error_t stopAdvertising(void);
|
||||
virtual ble_error_t disconnect(void);
|
||||
virtual ble_error_t disconnect(DisconnectionReason_t reason);
|
||||
|
||||
virtual ble_error_t setDeviceName(const uint8_t *deviceName);
|
||||
virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP);
|
||||
virtual ble_error_t setAppearance(uint16_t appearance);
|
||||
virtual ble_error_t getAppearance(uint16_t *appearanceP);
|
||||
|
||||
void setConnectionHandle(uint16_t con_handle);
|
||||
uint16_t getConnectionHandle(void);
|
||||
|
|
|
@ -77,7 +77,7 @@ ble_error_t nRF51GattServer::addService(GattService &service)
|
|||
p_characteristics[characteristicCount++] = p_char;
|
||||
|
||||
p_char->getValueAttribute().setHandle(charHandle);
|
||||
|
||||
|
||||
/* Add optional descriptors if any */
|
||||
/* ToDo: Make sure we don't overflow the array */
|
||||
for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
|
||||
|
@ -95,10 +95,9 @@ ble_error_t nRF51GattServer::addService(GattService &service)
|
|||
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
||||
|
||||
uint16_t descHandle = descriptorCount;
|
||||
p_descriptors[descriptorCount++] = p_desc;
|
||||
p_descriptors[descriptorCount++] = p_desc;
|
||||
p_desc->setHandle(descHandle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
serviceCount++;
|
||||
|
@ -213,45 +212,6 @@ ble_error_t nRF51GattServer::updateValue(uint16_t charHandle, uint8_t buffer[],
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t nRF51GattServer::setDeviceName(const uint8_t *deviceName)
|
||||
{
|
||||
ble_gap_conn_sec_mode_t sec_mode;
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed
|
||||
|
||||
if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t nRF51GattServer::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
|
||||
{
|
||||
if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t nRF51GattServer::setAppearance(uint16_t appearance)
|
||||
{
|
||||
if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t nRF51GattServer::getAppearance(uint16_t *appearanceP)
|
||||
{
|
||||
if (sd_ble_gap_appearance_get(appearanceP)) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Callback handler for events getting pushed up from the SD
|
||||
|
@ -259,52 +219,52 @@ ble_error_t nRF51GattServer::getAppearance(uint16_t *appearanceP)
|
|||
/**************************************************************************/
|
||||
void nRF51GattServer::hwCallback(ble_evt_t *p_ble_evt)
|
||||
{
|
||||
uint16_t handle_value;
|
||||
GattServerEvents::gattEvent_t event;
|
||||
uint16_t handle_value;
|
||||
GattServerEvents::gattEvent_t eventType;
|
||||
const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt;
|
||||
|
||||
switch (p_ble_evt->header.evt_id) {
|
||||
case BLE_GATTS_EVT_WRITE:
|
||||
/* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */
|
||||
|
||||
/* 1.) Handle CCCD changes */
|
||||
handle_value = p_ble_evt->evt.gatts_evt.params.write.handle;
|
||||
handle_value = gattsEventP->params.write.handle;
|
||||
for (uint8_t i = 0; i<characteristicCount; i++) {
|
||||
if ((p_characteristics[i]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
|
||||
(nrfCharacteristicHandles[i].cccd_handle == handle_value)) {
|
||||
uint16_t cccd_value =
|
||||
(p_ble_evt->evt.gatts_evt.params.write.data[1] << 8) |
|
||||
p_ble_evt->evt.gatts_evt.params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
|
||||
(gattsEventP->params.write.data[1] << 8) |
|
||||
gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
|
||||
|
||||
if (((p_characteristics[i]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) ||
|
||||
((p_characteristics[i]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) {
|
||||
event = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
|
||||
eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
|
||||
} else {
|
||||
event = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
|
||||
eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
|
||||
}
|
||||
|
||||
handleEvent(event, i);
|
||||
handleEvent(eventType, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2.) Changes to the characteristic value will be handled with other events below */
|
||||
event = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
|
||||
eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
|
||||
break;
|
||||
|
||||
case BLE_EVT_TX_COMPLETE:
|
||||
for (uint8_t i = 0; i<p_ble_evt->evt.common_evt.params.tx_complete.count; i++){
|
||||
handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT);
|
||||
}
|
||||
return;
|
||||
|
||||
case BLE_GATTS_EVT_HVC:
|
||||
/* Indication confirmation received */
|
||||
event = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
|
||||
handle_value = p_ble_evt->evt.gatts_evt.params.hvc.handle;
|
||||
eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
|
||||
handle_value = gattsEventP->params.hvc.handle;
|
||||
break;
|
||||
|
||||
case BLE_EVT_TX_COMPLETE: {
|
||||
handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count);
|
||||
return;
|
||||
}
|
||||
|
||||
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
|
||||
sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0);
|
||||
sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0);
|
||||
return;
|
||||
|
||||
default:
|
||||
|
@ -314,8 +274,21 @@ void nRF51GattServer::hwCallback(ble_evt_t *p_ble_evt)
|
|||
/* Find index (charHandle) in the pool */
|
||||
for (uint8_t i = 0; i<characteristicCount; i++) {
|
||||
if (nrfCharacteristicHandles[i].value_handle == handle_value) {
|
||||
handleEvent(event, i);
|
||||
break;
|
||||
switch (eventType) {
|
||||
case GattServerEvents::GATT_EVENT_DATA_WRITTEN: {
|
||||
GattCharacteristicWriteCBParams cbParams = {
|
||||
.op = static_cast<GattCharacteristicWriteCBParams::Type>(gattsEventP->params.write.op),
|
||||
.offset = gattsEventP->params.write.offset,
|
||||
.len = gattsEventP->params.write.len,
|
||||
.data = gattsEventP->params.write.data
|
||||
};
|
||||
handleDataWrittenEvent(i, &cbParams);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
handleEvent(eventType, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,11 +39,6 @@ public:
|
|||
virtual ble_error_t readValue(uint16_t handle, uint8_t buffer[], uint16_t *const lengthP);
|
||||
virtual ble_error_t updateValue(uint16_t, uint8_t[], uint16_t, bool localOnly = false);
|
||||
|
||||
virtual ble_error_t setDeviceName(const uint8_t *deviceName);
|
||||
virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP);
|
||||
virtual ble_error_t setAppearance(uint16_t appearance);
|
||||
virtual ble_error_t getAppearance(uint16_t *appearanceP);
|
||||
|
||||
/* nRF51 Functions */
|
||||
void eventCallback(void);
|
||||
void hwCallback(ble_evt_t *p_ble_evt);
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "app_button.h"
|
||||
#include <string.h>
|
||||
#include "nordic_common.h"
|
||||
#include "app_util.h"
|
||||
#include "app_gpiote.h"
|
||||
#include "app_timer.h"
|
||||
#include "app_error.h"
|
||||
|
||||
|
||||
static app_button_cfg_t * mp_buttons = NULL; /**< Button configuration. */
|
||||
static uint8_t m_button_count; /**< Number of configured buttons. */
|
||||
static uint32_t m_detection_delay; /**< Delay before a button is reported as pushed. */
|
||||
static app_button_evt_schedule_func_t m_evt_schedule_func; /**< Pointer to function for propagating button events to the scheduler. */
|
||||
static app_gpiote_user_id_t m_gpiote_user_id; /**< GPIOTE user id for buttons module. */
|
||||
static app_timer_id_t m_detection_delay_timer_id; /**< Polling timer id. */
|
||||
static pin_transition_t m_pin_transition; /**< pin transaction direction. */
|
||||
|
||||
|
||||
/**@brief Function for executing the application button handler for specified button.
|
||||
*
|
||||
* @param[in] p_btn Button that has been pushed.
|
||||
*/
|
||||
static void button_handler_execute(app_button_cfg_t * p_btn, uint32_t transition)
|
||||
{
|
||||
if (m_evt_schedule_func != NULL)
|
||||
{
|
||||
uint32_t err_code = m_evt_schedule_func(p_btn->button_handler, p_btn->pin_no,transition);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(transition == APP_BUTTON_PUSH)
|
||||
{
|
||||
p_btn->button_handler(p_btn->pin_no, APP_BUTTON_PUSH);
|
||||
}
|
||||
else if(transition == APP_BUTTON_RELEASE)
|
||||
{
|
||||
p_btn->button_handler(p_btn->pin_no, APP_BUTTON_RELEASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the timeout that delays reporting buttons as pushed.
|
||||
*
|
||||
* @details The detection_delay_timeout_handler(...) is a call-back issued from the app_timer
|
||||
* module. It is called with the p_context parameter. The p_context parameter is
|
||||
* provided to the app_timer module when a timer is started, using the call
|
||||
* @ref app_timer_start. On @ref app_timer_start the p_context will be holding the
|
||||
* currently pressed buttons.
|
||||
*
|
||||
* @param[in] p_context Pointer used for passing information app_start_timer() was called.
|
||||
* In the app_button module the p_context holds information on pressed
|
||||
* buttons.
|
||||
*/
|
||||
static void detection_delay_timeout_handler(void * p_context)
|
||||
{
|
||||
uint32_t err_code;
|
||||
uint32_t current_state_pins;
|
||||
|
||||
// Get current state of pins.
|
||||
err_code = app_gpiote_pins_state_get(m_gpiote_user_id, ¤t_state_pins);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
|
||||
// Pushed button(s) detected, execute button handler(s).
|
||||
for (i = 0; i < m_button_count; i++)
|
||||
{
|
||||
app_button_cfg_t * p_btn = &mp_buttons[i];
|
||||
|
||||
if (((m_pin_transition.high_to_low & (1 << p_btn->pin_no)) != 0) && (p_btn->button_handler != NULL))
|
||||
{
|
||||
//If it's active high then going from high to low was a release of the button.
|
||||
if(p_btn->active_state == APP_BUTTON_ACTIVE_HIGH)
|
||||
{
|
||||
button_handler_execute(p_btn, APP_BUTTON_RELEASE);
|
||||
}
|
||||
//If it's active low then going from high to low was a push of the button.
|
||||
else
|
||||
{
|
||||
button_handler_execute(p_btn, APP_BUTTON_PUSH);
|
||||
}
|
||||
}
|
||||
else if (((m_pin_transition.low_to_high & (1 << p_btn->pin_no)) != 0) && (p_btn->button_handler != NULL))
|
||||
{
|
||||
//If it's active high then going from low to high was a push of the button.
|
||||
if(p_btn->active_state == APP_BUTTON_ACTIVE_HIGH)
|
||||
{
|
||||
button_handler_execute(p_btn,APP_BUTTON_PUSH);
|
||||
}
|
||||
//If it's active low then going from low to high was a release of the button.
|
||||
else
|
||||
{
|
||||
button_handler_execute(p_btn,APP_BUTTON_RELEASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the GPIOTE event.
|
||||
*
|
||||
* @details Saves the current status of the button pins, and starts a timer. If the timer is already
|
||||
* running, it will be restarted.
|
||||
*
|
||||
* @param[in] event_pins_low_to_high Mask telling which pin(s) had a low to high transition.
|
||||
* @param[in] event_pins_high_to_low Mask telling which pin(s) had a high to low transition.
|
||||
*/
|
||||
static void gpiote_event_handler(uint32_t event_pins_low_to_high, uint32_t event_pins_high_to_low)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
// Start detection timer. If timer is already running, the detection period is restarted.
|
||||
// NOTE: Using the p_context parameter of app_timer_start() to transfer the pin states to the
|
||||
// timeout handler (by casting event_pins_mask into the equally sized void * p_context
|
||||
// parameter).
|
||||
STATIC_ASSERT(sizeof(void *) == sizeof(uint32_t));
|
||||
|
||||
err_code = app_timer_stop(m_detection_delay_timer_id);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
// The impact in app_button of the app_timer queue running full is losing a button press.
|
||||
// The current implementation ensures that the system will continue working as normal.
|
||||
return;
|
||||
}
|
||||
|
||||
m_pin_transition.low_to_high = event_pins_low_to_high;
|
||||
m_pin_transition.high_to_low = event_pins_high_to_low;
|
||||
|
||||
err_code = app_timer_start(m_detection_delay_timer_id,
|
||||
m_detection_delay,
|
||||
(void *)(event_pins_low_to_high | event_pins_high_to_low));
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
// The impact in app_button of the app_timer queue running full is losing a button press.
|
||||
// The current implementation ensures that the system will continue working as normal.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t app_button_init(app_button_cfg_t * p_buttons,
|
||||
uint8_t button_count,
|
||||
uint32_t detection_delay,
|
||||
app_button_evt_schedule_func_t evt_schedule_func)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
if (detection_delay < APP_TIMER_MIN_TIMEOUT_TICKS)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// Save configuration.
|
||||
mp_buttons = p_buttons;
|
||||
m_button_count = button_count;
|
||||
m_detection_delay = detection_delay;
|
||||
m_evt_schedule_func = evt_schedule_func;
|
||||
|
||||
// Configure pins.
|
||||
uint32_t pins_transition_mask = 0;
|
||||
|
||||
while (button_count--)
|
||||
{
|
||||
app_button_cfg_t * p_btn = &p_buttons[button_count];
|
||||
|
||||
// Configure pin.
|
||||
nrf_gpio_cfg_input(p_btn->pin_no, p_btn->pull_cfg);
|
||||
|
||||
// Build GPIOTE user registration masks.
|
||||
pins_transition_mask |= (1 << p_btn->pin_no);
|
||||
}
|
||||
|
||||
// Register button module as a GPIOTE user.
|
||||
err_code = app_gpiote_user_register(&m_gpiote_user_id,
|
||||
pins_transition_mask,
|
||||
pins_transition_mask,
|
||||
gpiote_event_handler);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
// Create polling timer.
|
||||
return app_timer_create(&m_detection_delay_timer_id,
|
||||
APP_TIMER_MODE_SINGLE_SHOT,
|
||||
detection_delay_timeout_handler);
|
||||
}
|
||||
|
||||
|
||||
uint32_t app_button_enable(void)
|
||||
{
|
||||
if (mp_buttons == NULL)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return app_gpiote_user_enable(m_gpiote_user_id);
|
||||
}
|
||||
|
||||
|
||||
uint32_t app_button_disable(void)
|
||||
{
|
||||
uint32_t err_code;
|
||||
|
||||
if (mp_buttons == NULL)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
err_code = app_gpiote_user_disable(m_gpiote_user_id);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
// Make sure polling timer is not running.
|
||||
return app_timer_stop(m_detection_delay_timer_id);
|
||||
}
|
||||
|
||||
|
||||
uint32_t app_button_is_pushed(uint8_t pin_no, bool * p_is_pushed)
|
||||
{
|
||||
uint32_t err_code;
|
||||
uint32_t active_pins;
|
||||
|
||||
app_button_cfg_t * p_btn = &mp_buttons[pin_no];
|
||||
|
||||
if (mp_buttons == NULL)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
err_code = app_gpiote_pins_state_get(m_gpiote_user_id, &active_pins);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
return err_code;
|
||||
}
|
||||
|
||||
if(p_btn->active_state == APP_BUTTON_ACTIVE_LOW)
|
||||
{
|
||||
// If the pin is active low, then the pin being high means it is not pushed.
|
||||
if(((active_pins >> pin_no) & 0x01))
|
||||
{
|
||||
*p_is_pushed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_is_pushed = true;
|
||||
}
|
||||
}
|
||||
else if(p_btn->active_state == APP_BUTTON_ACTIVE_HIGH)
|
||||
{
|
||||
// If the pin is active high, then the pin being high means it is pushed.
|
||||
if(((active_pins >> pin_no) & 0x01))
|
||||
{
|
||||
*p_is_pushed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_is_pushed = false;
|
||||
}
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
|
@ -10,6 +10,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#if NEED_APP_GPIOTE /* disabled by default */
|
||||
|
||||
#include "app_gpiote.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -358,3 +360,5 @@ uint32_t app_gpiote_disable_interrupts(void)
|
|||
return NRF_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
#endif // SVCALL_AS_NORMAL_FUNCTION || SER_CONNECTIVITY
|
||||
|
||||
#endif // #if NEED_APP_GPIOTE
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
#include "nrf51_bitfields.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "app_error.h"
|
||||
//#include "nrf_delay.h"
|
||||
#include "mbed.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "app_util.h"
|
||||
#include "app_util_platform.h"
|
||||
|
||||
|
@ -30,8 +29,6 @@
|
|||
// (e.g. by using guard/trigger flags).
|
||||
STATIC_ASSERT(RTC1_IRQ_PRI == SWI0_IRQ_PRI);
|
||||
|
||||
#define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */
|
||||
|
||||
#define APP_HIGH_USER_ID 0 /**< User Id for the Application High "user". */
|
||||
#define APP_LOW_USER_ID 1 /**< User Id for the Application Low "user". */
|
||||
#define THREAD_MODE_USER_ID 2 /**< User Id for the Thread Mode "user". */
|
||||
|
@ -125,7 +122,6 @@ STATIC_ASSERT(sizeof(timer_user_t) % 4 == 0);
|
|||
*/
|
||||
typedef uint32_t timer_user_id_t;
|
||||
|
||||
#define TIMER_NULL ((app_timer_id_t)(0 - 1)) /**< Invalid timer id. */
|
||||
#define CONTEXT_QUEUE_SIZE_MAX (2) /**< Timer internal elapsed ticks queue size. */
|
||||
|
||||
static uint8_t m_node_array_size; /**< Size of timer node array. */
|
||||
|
@ -138,6 +134,8 @@ static uint32_t m_ticks_elapsed[CONTEXT_QUEUE_SIZE_MAX];
|
|||
static uint8_t m_ticks_elapsed_q_read_ind; /**< Timer internal elapsed ticks queue read index. */
|
||||
static uint8_t m_ticks_elapsed_q_write_ind; /**< Timer internal elapsed ticks queue write index. */
|
||||
static app_timer_evt_schedule_func_t m_evt_schedule_func; /**< Pointer to function for propagating timeout events to the scheduler. */
|
||||
static bool m_rtc1_running; /**< Boolean indicating if RTC1 is running. */
|
||||
static volatile uint64_t overflowBits; /**< The upper 40 bits of the 64-bit value returned by cnt_get() */
|
||||
|
||||
|
||||
/**@brief Function for initializing the RTC1 counter.
|
||||
|
@ -155,14 +153,20 @@ static void rtc1_init(uint32_t prescaler)
|
|||
*/
|
||||
static void rtc1_start(void)
|
||||
{
|
||||
if (m_rtc1_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk;
|
||||
NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;
|
||||
NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk | RTC_INTENSET_OVRFLW_Msk;
|
||||
|
||||
NVIC_ClearPendingIRQ(RTC1_IRQn);
|
||||
NVIC_EnableIRQ(RTC1_IRQn);
|
||||
|
||||
NRF_RTC1->TASKS_START = 1;
|
||||
wait(0.0000001 * MAX_RTC_TASKS_DELAY);
|
||||
nrf_delay_us(MAX_RTC_TASKS_DELAY);
|
||||
|
||||
m_rtc1_running = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -170,13 +174,23 @@ static void rtc1_start(void)
|
|||
*/
|
||||
static void rtc1_stop(void)
|
||||
{
|
||||
if (!m_rtc1_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
NVIC_DisableIRQ(RTC1_IRQn);
|
||||
|
||||
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
|
||||
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
|
||||
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk | RTC_INTENSET_OVRFLW_Msk;
|
||||
|
||||
NRF_RTC1->TASKS_STOP = 1;
|
||||
wait(0.0000001 * MAX_RTC_TASKS_DELAY);
|
||||
nrf_delay_us(MAX_RTC_TASKS_DELAY);
|
||||
|
||||
NRF_RTC1->TASKS_CLEAR = 1;
|
||||
m_ticks_latest = 0;
|
||||
nrf_delay_us(MAX_RTC_TASKS_DELAY);
|
||||
|
||||
m_rtc1_running = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -296,6 +310,12 @@ static void timer_list_remove(app_timer_id_t timer_id)
|
|||
if (previous == current)
|
||||
{
|
||||
m_timer_id_head = mp_nodes[m_timer_id_head].next;
|
||||
|
||||
// No more timers in the list. Disable RTC1.
|
||||
if (m_timer_id_head == TIMER_NULL)
|
||||
{
|
||||
rtc1_stop();
|
||||
}
|
||||
}
|
||||
|
||||
// Remaining timeout between next timeout
|
||||
|
@ -673,7 +693,7 @@ static void compare_reg_update(app_timer_id_t timer_id_head_old)
|
|||
uint32_t cc = m_ticks_latest;
|
||||
uint32_t ticks_elapsed = ticks_diff_get(pre_counter_val, cc) + RTC_COMPARE_OFFSET_MIN;
|
||||
|
||||
if (timer_id_head_old == TIMER_NULL)
|
||||
if (!m_rtc1_running)
|
||||
{
|
||||
// No timers were already running, start RTC
|
||||
rtc1_start();
|
||||
|
@ -686,11 +706,7 @@ static void compare_reg_update(app_timer_id_t timer_id_head_old)
|
|||
|
||||
uint32_t post_counter_val = rtc1_counter_get();
|
||||
|
||||
if (
|
||||
(ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN)
|
||||
>
|
||||
ticks_diff_get(cc, pre_counter_val)
|
||||
)
|
||||
if ((ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN) > ticks_diff_get(cc, pre_counter_val))
|
||||
{
|
||||
// When this happens the COMPARE event may not be triggered by the RTC.
|
||||
// The nRF51 Series User Specification states that if the COUNTER value is N
|
||||
|
@ -897,6 +913,9 @@ extern "C" void RTC1_IRQHandler(void)
|
|||
NRF_RTC1->EVENTS_COMPARE[2] = 0;
|
||||
NRF_RTC1->EVENTS_COMPARE[3] = 0;
|
||||
NRF_RTC1->EVENTS_TICK = 0;
|
||||
if (NRF_RTC1->EVENTS_OVRFLW) {
|
||||
overflowBits += (1 << 24);
|
||||
}
|
||||
NRF_RTC1->EVENTS_OVRFLW = 0;
|
||||
|
||||
// Check for expired timers
|
||||
|
@ -979,6 +998,7 @@ uint32_t app_timer_init(uint32_t prescaler,
|
|||
NVIC_EnableIRQ(SWI0_IRQn);
|
||||
|
||||
rtc1_init(prescaler);
|
||||
rtc1_start();
|
||||
|
||||
m_ticks_latest = rtc1_counter_get();
|
||||
|
||||
|
@ -1115,9 +1135,9 @@ uint32_t app_timer_stop_all(void)
|
|||
}
|
||||
|
||||
|
||||
uint32_t app_timer_cnt_get(uint32_t * p_ticks)
|
||||
uint32_t app_timer_cnt_get(uint64_t * p_ticks)
|
||||
{
|
||||
*p_ticks = rtc1_counter_get();
|
||||
*p_ticks = overflowBits | rtc1_counter_get();
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -62,6 +62,8 @@ extern "C" {
|
|||
#define APP_TIMER_USER_SIZE 8 /**< Size of app_timer.timer_user_t (only for use inside APP_TIMER_BUF_SIZE()). */
|
||||
#define APP_TIMER_INT_LEVELS 3 /**< Number of interrupt levels from where timer operations may be initiated (only for use inside APP_TIMER_BUF_SIZE()). */
|
||||
|
||||
#define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */
|
||||
|
||||
/**@brief Compute number of bytes required to hold the application timer data structures.
|
||||
*
|
||||
* @param[in] MAX_TIMERS Maximum number of timers that can be created at any given time.
|
||||
|
@ -106,6 +108,8 @@ extern "C" {
|
|||
/**@brief Timer id type. */
|
||||
typedef uint32_t app_timer_id_t;
|
||||
|
||||
#define TIMER_NULL ((app_timer_id_t)(0 - 1)) /**< Invalid timer id. */
|
||||
|
||||
/**@brief Application timeout handler type. */
|
||||
typedef void (*app_timer_timeout_handler_t)(void * p_context);
|
||||
|
||||
|
@ -249,13 +253,14 @@ uint32_t app_timer_stop(app_timer_id_t timer_id);
|
|||
*/
|
||||
uint32_t app_timer_stop_all(void);
|
||||
|
||||
/**@brief Function for returning the current value of the RTC1 counter.
|
||||
/**@brief Function for returning the current value of the RTC1 counter. The
|
||||
* value includes overflow bits to extend the range to 64-bits.
|
||||
*
|
||||
* @param[out] p_ticks Current value of the RTC1 counter.
|
||||
*
|
||||
* @retval NRF_SUCCESS Counter was successfully read.
|
||||
*/
|
||||
uint32_t app_timer_cnt_get(uint32_t * p_ticks);
|
||||
uint32_t app_timer_cnt_get(uint64_t * p_ticks);
|
||||
|
||||
/**@brief Function for computing the difference between two RTC1 counter values.
|
||||
*
|
||||
|
|
|
@ -164,7 +164,7 @@ typedef union
|
|||
*/
|
||||
typedef struct
|
||||
{
|
||||
ble_gatts_enable_params_t gatts_enable_params; /**< GATTS init options @ref ble_gatts_enable_params_t. */
|
||||
ble_gatts_enable_params_t gatts_enable_params; /**< GATTS init options @ref ble_gatts_enable_params_t. */
|
||||
} ble_enable_params_t;
|
||||
|
||||
/** @} */
|
||||
|
@ -188,16 +188,16 @@ SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(ble_enable_params_t * p_ble_enable
|
|||
* @param[in] p_dest Pointer to buffer to be filled in with an event, or NULL to retrieve the event length. This buffer <b>must be 4-byte aligned in memory</b>.
|
||||
* @param[in, out] p_len Pointer the length of the buffer, on return it is filled with the event length.
|
||||
*
|
||||
* @details This call allows the application to pull a BLE event from the BLE stack. The application is signalled that an event is
|
||||
* @details This call allows the application to pull a BLE event from the BLE stack. The application is signalled that an event is
|
||||
* available from the BLE Stack by the triggering of the SD_EVT_IRQn interrupt (mapped to IRQ 22).
|
||||
* The application is free to choose whether to call this function from thread mode (main context) or directly from the Interrupt Service Routine
|
||||
* that maps to SD_EVT_IRQn. In any case however, and because the BLE stack runs at a higher priority than the application, this function should be called
|
||||
* in a loop (until @ref NRF_ERROR_NOT_FOUND is returned) every time SD_EVT_IRQn is raised to ensure that all available events are pulled from the stack.
|
||||
* in a loop (until @ref NRF_ERROR_NOT_FOUND is returned) every time SD_EVT_IRQn is raised to ensure that all available events are pulled from the stack.
|
||||
* Failure to do so could potentially leave events in the internal queue without the application being aware of this fact.
|
||||
* Sizing the p_dest buffer is equally important, since the application needs to provide all the memory necessary for the event to be copied into
|
||||
* application memory. If the buffer provided is not large enough to fit the entire contents of the event, @ref NRF_ERROR_DATA_SIZE will be returned
|
||||
* and the application can then call again with a larger buffer size.
|
||||
* Please note that because of the variable length nature of some events, sizeof(ble_evt_t) will not always be large enough to fit certain events,
|
||||
* Please note that because of the variable length nature of some events, sizeof(ble_evt_t) will not always be large enough to fit certain events,
|
||||
* and so it is the application's responsability to provide an amount of memory large enough so that the relevant event is copied in full.
|
||||
* The application may "peek" the event length by providing p_dest as a NULL pointer and inspecting the value of *p_len upon return.
|
||||
*
|
||||
|
@ -219,7 +219,7 @@ SVCALL(SD_BLE_EVT_GET, uint32_t, sd_ble_evt_get(uint8_t* p_dest, uint16_t *p_len
|
|||
* The application has two options to handle its own application transmission buffers:
|
||||
* - Use a simple arithmetic calculation: at boot time the application should use this function
|
||||
* to find out the total amount of buffers available to it and store it in a variable.
|
||||
* Every time a packet that consumes an application buffer is sent using any of the
|
||||
* Every time a packet that consumes an application buffer is sent using any of the
|
||||
* exposed functions in this BLE API, the application should decrement that variable.
|
||||
* Conversely, whenever a @ref BLE_EVT_TX_COMPLETE event is received by the application
|
||||
* it should retrieve the count field in such event and add that number to the same
|
||||
|
@ -228,11 +228,11 @@ SVCALL(SD_BLE_EVT_GET, uint32_t, sd_ble_evt_get(uint8_t* p_dest, uint16_t *p_len
|
|||
* application packets available in the BLE stack's internal buffers, and therefore
|
||||
* it can know with certainty whether it is possible to send more data or it has to
|
||||
* wait for a @ref BLE_EVT_TX_COMPLETE event before it proceeds.
|
||||
* - Choose to simply not keep track of available buffers at all, and instead handle the
|
||||
* @ref BLE_ERROR_NO_TX_BUFFERS error by queueing the packet to be transmitted and
|
||||
* - Choose to simply not keep track of available buffers at all, and instead handle the
|
||||
* @ref BLE_ERROR_NO_TX_BUFFERS error by queueing the packet to be transmitted and
|
||||
* try again as soon as a @ref BLE_EVT_TX_COMPLETE event arrives.
|
||||
*
|
||||
* The API functions that <b>may</b> consume an application buffer depending on
|
||||
* The API functions that <b>may</b> consume an application buffer depending on
|
||||
* the parameters supplied to them can be found below:
|
||||
*
|
||||
* - @ref sd_ble_gattc_write (write witout response only)
|
||||
|
@ -253,15 +253,15 @@ SVCALL(SD_BLE_TX_BUFFER_COUNT_GET, uint32_t, sd_ble_tx_buffer_count_get(uint8_t*
|
|||
* @details This call enables the application to add a vendor specific UUID to the BLE stack's table,
|
||||
* for later use all other modules and APIs. This then allows the application to use the shorter,
|
||||
* 24-bit @ref ble_uuid_t format when dealing with both 16-bit and 128-bit UUIDs without having to
|
||||
* check for lengths and having split code paths. The way that this is accomplished is by extending the
|
||||
* grouping mechanism that the Bluetooth SIG standard base UUID uses for all other 128-bit UUIDs. The
|
||||
* type field in the @ref ble_uuid_t structure is an index (relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN)
|
||||
* to the table populated by multiple calls to this function, and the uuid field in the same structure
|
||||
* contains the 2 bytes at indices 12 and 13. The number of possible 128-bit UUIDs available to the
|
||||
* application is therefore the number of Vendor Specific UUIDs added with the help of this function times 65536,
|
||||
* check for lengths and having split code paths. The way that this is accomplished is by extending the
|
||||
* grouping mechanism that the Bluetooth SIG standard base UUID uses for all other 128-bit UUIDs. The
|
||||
* type field in the @ref ble_uuid_t structure is an index (relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN)
|
||||
* to the table populated by multiple calls to this function, and the uuid field in the same structure
|
||||
* contains the 2 bytes at indices 12 and 13. The number of possible 128-bit UUIDs available to the
|
||||
* application is therefore the number of Vendor Specific UUIDs added with the help of this function times 65536,
|
||||
* although restricted to modifying bytes 12 and 13 for each of the entries in the supplied array.
|
||||
*
|
||||
* @note Bytes 12 and 13 of the provided UUID will not be used internally, since those are always replaced by
|
||||
* @note Bytes 12 and 13 of the provided UUID will not be used internally, since those are always replaced by
|
||||
* the 16-bit uuid field in @ref ble_uuid_t.
|
||||
*
|
||||
*
|
||||
|
@ -278,11 +278,11 @@ SVCALL(SD_BLE_UUID_VS_ADD, uint32_t, sd_ble_uuid_vs_add(ble_uuid128_t const * co
|
|||
|
||||
|
||||
/** @brief Decode little endian raw UUID bytes (16-bit or 128-bit) into a 24 bit @ref ble_uuid_t structure.
|
||||
*
|
||||
* @details The raw UUID bytes excluding bytes 12 and 13 (i.e. bytes 0-11 and 14-15) of p_uuid_le are compared
|
||||
* to the corresponding ones in each entry of the table of vendor specific UUIDs pouplated with @ref sd_ble_uuid_vs_add
|
||||
* to look for a match. If there is such a match, bytes 12 and 13 are returned as p_uuid->uuid and the index
|
||||
* relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN as p_uuid->type.
|
||||
*
|
||||
* @details The raw UUID bytes excluding bytes 12 and 13 (i.e. bytes 0-11 and 14-15) of p_uuid_le are compared
|
||||
* to the corresponding ones in each entry of the table of vendor specific UUIDs pouplated with @ref sd_ble_uuid_vs_add
|
||||
* to look for a match. If there is such a match, bytes 12 and 13 are returned as p_uuid->uuid and the index
|
||||
* relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN as p_uuid->type.
|
||||
*
|
||||
* @note If the UUID length supplied is 2, then the type set by this call will always be @ref BLE_UUID_TYPE_BLE.
|
||||
*
|
||||
|
@ -294,7 +294,7 @@ SVCALL(SD_BLE_UUID_VS_ADD, uint32_t, sd_ble_uuid_vs_add(ble_uuid128_t const * co
|
|||
* @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @return @ref NRF_ERROR_INVALID_LENGTH Invalid UUID length.
|
||||
* @return @ref NRF_ERROR_NOT_FOUND For a 128-bit UUID, no match in the populated table of UUIDs.
|
||||
*/
|
||||
*/
|
||||
SVCALL(SD_BLE_UUID_DECODE, uint32_t, sd_ble_uuid_decode(uint8_t uuid_le_len, uint8_t const * const p_uuid_le, ble_uuid_t * const p_uuid));
|
||||
|
||||
|
||||
|
|
|
@ -6,20 +6,20 @@
|
|||
agreement with Nordic Semiconductor.
|
||||
*/
|
||||
/**
|
||||
@addtogroup BLE_COMMON
|
||||
@addtogroup BLE_COMMON
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BLE_HCI_H__
|
||||
#define BLE_HCI_H__
|
||||
#define BLE_HCI_H__
|
||||
|
||||
/** @defgroup BLE_HCI_STATUS_CODES Bluetooth status codes
|
||||
* @{ */
|
||||
|
||||
#define BLE_HCI_STATUS_CODE_SUCCESS 0x00
|
||||
#define BLE_HCI_STATUS_CODE_UNKNOWN_BTLE_COMMAND 0x01
|
||||
#define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02
|
||||
#define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02
|
||||
/*0x03 Hardware Failure
|
||||
0x04 Page Timeout
|
||||
*/
|
||||
|
|
|
@ -71,21 +71,12 @@ typedef void (*sys_evt_handler_t) (uint32_t evt_id);
|
|||
* reinitialization).
|
||||
*/
|
||||
/*lint -emacro(506, SOFTDEVICE_HANDLER_INIT) */ /* Suppress "Constant value Boolean */
|
||||
#define SOFTDEVICE_HANDLER_INIT(CLOCK_SOURCE, \
|
||||
USE_SCHEDULER) \
|
||||
#define SOFTDEVICE_HANDLER_INIT(CLOCK_SOURCE, USE_SCHEDULER) \
|
||||
do \
|
||||
{ \
|
||||
static uint32_t EVT_BUFFER[CEIL_DIV(MAX( \
|
||||
MAX(BLE_STACK_EVT_MSG_BUF_SIZE, \
|
||||
ANT_STACK_EVT_STRUCT_SIZE), \
|
||||
SYS_EVT_MSG_BUF_SIZE \
|
||||
), \
|
||||
sizeof(uint32_t))]; \
|
||||
static uint32_t EVT_BUFFER[CEIL_DIV(MAX(MAX(BLE_STACK_EVT_MSG_BUF_SIZE, ANT_STACK_EVT_STRUCT_SIZE), SYS_EVT_MSG_BUF_SIZE), sizeof(uint32_t))]; \
|
||||
uint32_t ERR_CODE; \
|
||||
ERR_CODE = softdevice_handler_init((CLOCK_SOURCE), \
|
||||
EVT_BUFFER, \
|
||||
sizeof(EVT_BUFFER), \
|
||||
(USE_SCHEDULER) ? softdevice_evt_schedule : NULL); \
|
||||
ERR_CODE = softdevice_handler_init((CLOCK_SOURCE), EVT_BUFFER, sizeof(EVT_BUFFER), (USE_SCHEDULER) ? softdevice_evt_schedule : NULL); \
|
||||
APP_ERROR_CHECK(ERR_CODE); \
|
||||
} while (0)
|
||||
|
||||
|
|
|
@ -235,36 +235,6 @@ uint32_t softdevice_handler_init(nrf_clock_lfclksrc_t clock_source,
|
|||
return err_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using this call, the application can select whether to include the
|
||||
* Service Changed characteristic in the GATT Server. The default in all
|
||||
* previous releases has been to include the Service Changed characteristic,
|
||||
* but this affects how GATT clients behave. Specifically, it requires
|
||||
* clients to subscribe to this attribute and not to cache attribute handles
|
||||
* between connections unless the devices are bonded. If the application
|
||||
* does not need to change the structure of the GATT server attributes at
|
||||
* runtime this adds unnecessary complexity to the interaction with peer
|
||||
* clients. If the SoftDevice is enabled with the Service Changed
|
||||
* Characteristics turned off, then clients are allowed to cache attribute
|
||||
* handles making applications simpler on both sides.
|
||||
*/
|
||||
ble_enable_params_t enableParams = {
|
||||
.gatts_enable_params = {
|
||||
.service_changed = 0
|
||||
}
|
||||
};
|
||||
if ((err_code = sd_ble_enable(&enableParams)) != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
|
||||
ble_gap_addr_t addr;
|
||||
if ((err_code = sd_ble_gap_address_get(&addr)) != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
if ((err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr)) != NRF_SUCCESS) {
|
||||
return err_code;
|
||||
}
|
||||
|
||||
m_softdevice_enabled = true;
|
||||
// Enable BLE event interrupt (interrupt priority has already been set by the stack).
|
||||
return sd_nvic_EnableIRQ(SWI2_IRQn);
|
||||
|
|
|
@ -88,8 +88,8 @@
|
|||
|
||||
/*-------------------------------- TIMER ------------------------------*/
|
||||
#define CFG_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. freq = (32768/(PRESCALER+1)) */
|
||||
#define CFG_TIMER_MAX_INSTANCE 8 /**< Maximum number of simultaneously created timers. */
|
||||
#define CFG_TIMER_OPERATION_QUEUE_SIZE 5 /**< Size of timer operation queues. */
|
||||
#define CFG_TIMER_MAX_INSTANCE 1 /**< Maximum number of simultaneously created timers. */
|
||||
#define CFG_TIMER_OPERATION_QUEUE_SIZE 1 /**< Size of timer operation queues. */
|
||||
/*=========================================================================*/
|
||||
|
||||
|
||||
|
@ -97,7 +97,7 @@
|
|||
BTLE SETTINGS
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
#define CFG_BLE_TX_POWER_LEVEL 4 /**< in dBm (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */
|
||||
#define CFG_BLE_TX_POWER_LEVEL 0 /**< in dBm (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */
|
||||
|
||||
/*---------------------------- BOND MANAGER ---------------------------*/
|
||||
#define CFG_BLE_BOND_FLASH_PAGE_BOND (BLE_FLASH_PAGE_END-1) /**< Flash page used for bond manager bonding information.*/
|
||||
|
@ -115,8 +115,8 @@
|
|||
#define CFG_GAP_APPEARANCE BLE_APPEARANCE_GENERIC_TAG
|
||||
#define CFG_GAP_LOCAL_NAME "nRF5x"
|
||||
|
||||
#define CFG_GAP_CONNECTION_MIN_INTERVAL_MS 500 /**< Minimum acceptable connection interval */
|
||||
#define CFG_GAP_CONNECTION_MAX_INTERVAL_MS 1000 /**< Maximum acceptable connection interval */
|
||||
#define CFG_GAP_CONNECTION_MIN_INTERVAL_MS 50 /**< Minimum acceptable connection interval */
|
||||
#define CFG_GAP_CONNECTION_MAX_INTERVAL_MS 500 /**< Maximum acceptable connection interval */
|
||||
#define CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS 4000 /**< Connection supervisory timeout */
|
||||
#define CFG_GAP_CONNECTION_SLAVE_LATENCY 0 /**< Slave Latency in number of connection events. */
|
||||
|
||||
|
|
Loading…
Reference in New Issue