I am trying to send a n array of bytes from the BLE chip to the smartphone, AFTER I receive an array of bytes in the BLE chip from the smartphone, that is, my intended order of operation is as follows:
Smartphone --BLE--> DA14580 chip --BLE--> smartphone
I have managed to do the first part (Smartphone --BLE--> DA14580 chip) but I am having trouble understanding how to do the second part
I am modifying the ble_app_peripheral sample program
I took the code inside void app_adcval1_timer_cb_handler() in user_custs1_impl.c, and tried to modify it, but it doesn't work (that is, my bustom BLE receive app on my smartphone does not detect anything)
(I am also sure it is not a problem with the smartphone app, as it can detect incoming BLE data from another custom BLE module that I have, and my goal to create my own version of this custom module)
Here is my code:
void user_server_rx_data_ind_handler(ke_msg_id_t const msgid,
struct custs1_val_write_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
arch_printf("in function %s\n\r", __func__ );
//DO OPERATION: just display data for now
for(int i=0; ilength; i++){
arch_printf("\tparam->value[%d] = %d (0x%x)\n\r", i, param->value[i], param->value[i] );
}
//2018-02-12: I2C send byte to external dev
//send the data part of the received byte array to I2C slave address
arch_printf("Writing to I2C: Add: %d value: %d\n\r", I2C_SLAVE_ADDRESS, param->value[(param->length) - 1] );
i2c_write_mine(I2C_SLAVE_ADDRESS, param->value[(param->length) - 1]);
//2018-02-20: from forum post (https://support.dialog-semiconductor.com/ble-transmission)
//*************************************Custom value 1*********************************//
struct custs1_val_ntf_req* req = KE_MSG_ALLOC_DYN(CUSTS1_VAL_NTF_REQ,
TASK_CUSTS1,
TASK_APP,
custs1_val_ntf_req,
DEF_USER_SERVER_TX_DATA_CHAR_LEN);
arch_printf("Inside %s\n\r\tCUSTS1_VAL_NTF_REQ = %d\n\r\tTASK_CUSTS1 = %d\n\r\tTASK_APP = %d\n\r\tDEF_CUST1_ADC_VAL_1_CHAR_LEN = %d\n\r",__func__, CUSTS1_VAL_NTF_REQ, TASK_CUSTS1, TASK_APP, DEF_USER_SERVER_TX_DATA_CHAR_LEN);
static uint16_t sample[20];
for(int i=0; i< 20; i++)
{
sample[i] = 65 + i;
}
req->conhdl = app_env->conhdl;
//req->handle = CUST1_IDX_ADC_VAL_1_VAL; // 2018-02-20 : ORIG
req->handle = USER_IDX_SERVER_TX_DATA_VAL;
//req->length = DEF_CUST1_ADC_VAL_1_CHAR_LEN; // 2018-02-20 : ORIG
req->length = DEF_USER_SERVER_TX_DATA_CHAR_LEN;
//memcpy(req->value, &sample, DEF_CUST1_ADC_VAL_1_CHAR_LEN); // 2018-02-20 : ORIG
memcpy(req->value, &sample, DEF_USER_SERVER_TX_DATA_CHAR_LEN);
ke_msg_send(req);
arch_printf("I2C data sending completed\n\r");
}
user_server_rx_data_ind_handler() is the custom function that gets called when DA14580 receives bytes from BLE (this function is called inside user_catch_rest_hndl() in user_peripheral.c, inside one of the switch()...case blocks
USER_IDX_SERVER_TX_DATA_VAL is defined in user_custs1_def.h, as an enum along side CUST1_IDX_ADC_VAL_1_VAL. This enum entry was created following the tutorial for the ble_peripheral_app. The other enums created alongside this are:
USER_IDX_SERVER_TX_DATA_CHAR,
USER_IDX_SERVER_TX_DATA_VAL,
USER_IDX_SERVER_TX_DATA_NTF_CFG,
USER_IDX_SERVER_TX_DATA_USER_DESC,
Basically I have tried to make this the same as CUST1_IDX_ADC_VAL_1_*
DEF_USER_SERVER_TX_DATA_CHAR_LEN is defined in user_custs1_def.h as
#define DEF_USER_SERVER_TX_DATA_CHAR_LEN 20
The ble_peripheral_app tutorial I followed is
Training_03_custom_profile_gatt_cmd_example_v1 0.pdf
I think I am missing something very basic here. How can I send a single byte of data from the BLE chip to the smartphone?
--- EDIT ---
This causes the following outputs on the UART terminal:
Inside user_server_rx_data_ind_handler
CUSTS1_VAL_NTF_REQ = 55300
TASK_CUSTS1 = 54
TASK_APP = 50
DEF_CUST1_ADC_VAL_1_CHAR_LEN = 20
I2C data sending completed
It also causes a call to the user_catch_rest_hndl () function in user_peripheral.c
Entered user_catch_rest_hndl :
msgid = 0xd805
CUSTS1_VAL_NTF_CFM detected : msg_param->handle = 27
--- EDIT 2 ---
The following entries were also added to the user_custs1_def.c file's struct attm_desc_128 custs1_att_db[CUST1_IDX_NB] = structure definition:
//user Server TX data Characteristic Declaration
[USER_IDX_SERVER_TX_DATA_CHAR] = {(uint8_t*)&att_decl_char, ATT_UUID_16_LEN, PERM(RD, ENABLE),
sizeof(user_server_tx_data_char), sizeof(user_server_tx_data_char), (uint8_t*)&user_server_tx_data_char},
//user Server TX data Characteristic Value
//might have to enable NTF permission here; come back to this point if needed later
[USER_IDX_SERVER_TX_DATA_VAL] = {USER_SERVER_TX_DATA_UUID_128, ATT_UUID_128_LEN, PERM(RD, ENABLE) | PERM(NTF, ENABLE),
DEF_USER_SERVER_TX_DATA_CHAR_LEN, 0, NULL},
//user Server TX data Characteristic Configuration Descriptor
[USER_IDX_SERVER_TX_DATA_NTF_CFG] = {(uint8_t*)&att_decl_cfg, ATT_UUID_16_LEN, PERM(RD, ENABLE) | PERM(WR, ENABLE),
sizeof(uint16_t), 0, NULL},
//user Server TX data Characteristic User Description
[USER_IDX_SERVER_TX_DATA_USER_DESC] = {(uint8_t*)&att_decl_user_desc, ATT_UUID_16_LEN, PERM(RD, ENABLE),
sizeof(USER_SERVER_TX_DATA_USER_DESC) - 1, sizeof(USER_SERVER_TX_DATA_USER_DESC) - 1, USER_SERVER_TX_DATA_USER_DESC},
Hi mahaju,
The ble_app_peripheral contains writable characteristics, like control point and readable – notifiable characteristics, like ADC VAL 1. The central can write a characteristic from a device, and the device can notify a characteristic from the central.
In your application, when you send a message from your smartphone to the DA14580 SoC over BLE, this is a writable characteristic. On the other side, when you send a message from DA14580 SoC to your smartphone, this is a notifiable characteristic and you must have the notifications activated.
Please, check if the notifications are activated.
Thanks PM_dialog
HI I enabled notifications in the Dialog chip code as shown below:
struct custs1_val_set_req* msg_en_notf = KE_MSG_ALLOC_DYN(CUSTS1_VAL_SET_REQ,
TASK_CUSTS1,
TASK_APP,
custs1_val_set_req,
0x2);
static uint16_t enable_notif;
enable_notif = 0x0001;
//enable_notif[0] = 0x01;
//enable_notif[2] = 0x00;
msg_en_notf->conhdl = app_env->conhdl;
msg_en_notf->handle = USER_IDX_SERVER_TX_DATA_NTF_CFG;
//msg_en_notf->handle = USER_IDX_SERVER_TX_DATA_VAL;
msg_en_notf->length = 0x2; // use the same value as the argument for KE_MSG_ALLOC_DYN() above
memcpy(msg_en_notf->value, &enable_notif, 0x2);
ke_msg_send(msg_en_notf);
I call this block of code every time I need to send something from the BLE chip to smartphone, and I am able to view the data I sent from the BLE chip in my smartphone app
Is this the correct approach? I tried calling this just once in user_app_init() in user_peripheral.c, but it didn't work.
Hi mahaju,
No, this isn’t a correct approach. The correct approach is that the master should enable the indication/notification characteristic. In your implementation you have done the opposite, you write the notification attribute from your code. According to BLE specifications, the master enable the notification attribute, so you must enable the notifications from your smartphone application.
Its’s expected that it didn’t work when you call your block of code in the user_app_init() function. First the user_app_init() is called and then the BLE stack is reset. After the reset, you will lose all your data and the BLE stack get discharged.
Thanks PM_dialog
Hi sorry for following up to this so late, but I have another question
If I understand this correctly, notifications should be enabled by just using the android functions in the smartphone
这是正确的吗?我需要添加一些额外的代码吗in the Dialog program to accept and process the "notification enable" command from the smartphone?
Hi mahaju,
Yes, that is correct. You should enable the notifications by using you mobile BLE application, but your characteristic should be notifiable, and no you should not add anything extra in your code, the profile will manage this. I suggest you to check the ble_app_peripheral example of the SDK. This example contains the implementation of a notifiable characteristic (ADC VAL 1 characteristic).
Thanks PM_dialog