Thank you for your reply
we use the device:MKW31Z512XXX4
base sdk is:SDK_2.X_MKW31Z512XXX4
we modifications:
#define mHeartRateReportInterval_c (10)
static void BleApp_ConnectionCallback (deviceId_t peerDeviceId, gapConnectionEvent_t* pConnectionEvent)
{
---->
switch (pConnectionEvent->eventType)
{
case gConnEvtConnected_c:
{
Hrs_Subscribe(peerDeviceId);
BleApp_StartHeartRate(mHeartRateReportInterval_c);
break;
}
....
}
--->void BleApp_StartHeartRate(uint16_t mtime)
{
TMR_StartLowPowerTimer(mHeartRateMeasurementTimerId, gTmrLowPowerIntervalMillisTimer_c,
TmrMilliseconds(mtime), HeartRateMeasurementTimerCallback, NULL);
}
----->
static hrsUserData_t hrsUserData;
static hrsConfig_t hrsServiceConfig = {service_heart_rate, TRUE, FALSE, TRUE, gHrs_BodySensorLocOther_c, &hrsUserData};
void HeartRateMeasurementTimerCallback(void * pParam)
{
uint16_t hr=0,hs=0,energy = 0;
rtc_datetime_t date;
uint16_t hr_l = 0,hr_c=0,hr_r=0;
hr_l = ADC16_Mic0();
hs = hr_c = ADC16_Mic1();
hr_r = ADC16_Mic2();
hr=(hr_r + hr_l)/2 - hr_c;
if(hr < 0)
hr = 0;
if(hrsUserData.cRrIntervals == gHrs_NumOfRRIntervalsRecorded_c){
if(hs < hs_tmp)
hs = hs_tmp;
hs_tmp = 0;
Hrs_AddExpendedEnergy(&hrsUserData, energy,hs);
Hrs_RecordHeartRateMeasurement(service_heart_rate, hr, &hrsUserData);
}else
{
//PRINTF("stephen not 7 hr=0x%x,hs=0x%x,hs_tmp=0x%x\r\n",hr,hs,hs_tmp);
if(hs > hs_tmp)
hs_tmp = hs;//add stephen
Hrs_RecordRRInterval(&hrsUserData,hr);
}
}
==============
for Hrs_RecordHeartRateMeasurement
typedef struct hrsUserData_tag
{
#if gHrs_EnableRRIntervalMeasurements_d
/*! Heart Rate Service - RR Interval Measurements Buffer*/
uint16_t *pStoredRrIntervals;
/*! Heart Rate Service - RR Interval Count*/
uint8_t cRrIntervals;
/*! Heart Rate Service - Current Position in RR Interval Measurements Vector*/
uint8_t rrCursor;
#endif
/*! Heart Rate Service - Expended Energy Values */
uint16_t expendedEnergy;
uint16_t adc_Hs;
}hrsUserData_t;
void Hrs_AddExpendedEnergy(hrsUserData_t *pHrsUserData, uint16_t energy,uint16_t hs)
{
pHrsUserData->expendedEnergy = energy;// no use
pHrsUserData->adc_Hs = hs;
}
bleResult_t Hrs_RecordHeartRateMeasurement (uint16_t serviceHandle, uint16_t heartRate, hrsUserData_t *pHrsUserData)
{
uint16_t hValueHrMeasurement;
bleResult_t result;
bleUuid_t uuid = Uuid16(gBleSig_HrMeasurement_d);
//PRINTF("Hrs_RecordHeartRateMeasurement\r\n");
/* Get handle of Heart Rate Measurement characteristic */
result = GattDb_FindCharValueHandleInService(serviceHandle,
gBleUuidType16_c, &uuid, &hValueHrMeasurement);
if (result != gBleSuccess_c)
return result;
/* Update characteristic value and send notification */
if (!Hrs_UpdateHrmCharacteristic(hValueHrMeasurement, heartRate, pHrsUserData))
{
Hrs_SendNotifications(hValueHrMeasurement);
}
return gBleSuccess_c;
}
====
for Hrs_UpdateHrmCharacteristic
#define Hrs_MaxNotificationSize 20
static uint8_t characteristic[Hrs_MaxNotificationSize];
static bleResult_t Hrs_UpdateHrmCharacteristic
(
uint16_t handle,
uint16_t heartRate,
hrsUserData_t *pHrsUserData
){
{
uint8_t index = 0;
uint8_t flag = 0;
uint32_t date_s;
#if gHrs_EnableRRIntervalMeasurements_d
uint8_t iRRIntervalsCount;
#endif
/* Add flags */
Hrs_GetHrmFlags(handle, &flag);//add stephen
/* Add HR Value*/
if (Hrs_GetHeartRateFormat(heartRate) & gHrs_16BitHeartRateFormat_c)
{
//PRINTF("stephen HR Value 16 bit\r\n");
//characteristic[0] |= gHrs_16BitHeartRateFormat_c;//modify stephen
flag |= gHrs_16BitHeartRateFormat_c;
FLib_MemCpy(&characteristic[index], &heartRate, sizeof(uint16_t));
index++;
}
else
{
//characteristic[0] &= ~gHrs_16BitHeartRateFormat_c; //modify stephen
flag |= gHrs_16BitHeartRateFormat_c;//add stephen
characteristic[index] = (uint8_t) heartRate;
}
index++;
if (characteristic[0] & gHrs_SensorContactSupported_c)
{
//uint16_t nr = ADC16_Mic1();
uint16_t nr = pHrsUserData->adc_Hs;
FLib_MemCpy(&characteristic[index], &nr, sizeof(uint16_t));
index += sizeof(uint16_t);
}
if (flag & gHrs_EnergyExpendedEnabled_c)//add stephen
{
FLib_MemCpy(&characteristic[index], &pHrsUserData->expendedEnergy, sizeof(uint16_t));
index += sizeof(uint16_t);
}
#if gHrs_EnableRRIntervalMeasurements_d
/* Add RR Intervals */
if (pHrsUserData->cRrIntervals > 0)
{
iRRIntervalsCount = MIN(
(Hrs_MaxNotificationSize - index) / sizeof(uint16_t),
pHrsUserData->cRrIntervals);
//characteristic[0] |= gHrs_RrIntervalsEnabled_c; //modify stephen
flag |= gHrs_RrIntervalsEnabled_c; //add stephen
//PRINTF("stephen indexa=%d,iRRIntervalsCount=%d,cRrIntervals=%d,Hrs_MaxNotificationSize=%d\r\n",index,iRRIntervalsCount,pHrsUserData->cRrIntervals,Hrs_MaxNotificationSize);
if (pHrsUserData->rrCursor + iRRIntervalsCount > gHrs_NumOfRRIntervalsRecorded_c)
{
FLib_MemCpy(&characteristic[index],
&pHrsUserData->pStoredRrIntervals[pHrsUserData->rrCursor],
(gHrs_NumOfRRIntervalsRecorded_c - pHrsUserData->rrCursor)
* sizeof(uint16_t));
index += (gHrs_NumOfRRIntervalsRecorded_c - pHrsUserData->rrCursor) * sizeof(uint16_t);
FLib_MemCpy(&characteristic[index], &pHrsUserData->pStoredRrIntervals[0],
(iRRIntervalsCount + pHrsUserData->rrCursor
- gHrs_NumOfRRIntervalsRecorded_c) * sizeof(uint16_t));
index += (iRRIntervalsCount + pHrsUserData->rrCursor
- gHrs_NumOfRRIntervalsRecorded_c) * sizeof(uint16_t);
//PRINTF("stephen indexb=%d\r\n",index);
}
else
{
FLib_MemCpy(&characteristic[index],
&pHrsUserData->pStoredRrIntervals[0],
iRRIntervalsCount * sizeof(uint16_t));
index += iRRIntervalsCount * sizeof(uint16_t);
//PRINTF("stephen indexc=%d\r\n",index);
}
/* Update circular buffer */
pHrsUserData->rrCursor = (pHrsUserData->rrCursor + iRRIntervalsCount)
% gHrs_NumOfRRIntervalsRecorded_c;
pHrsUserData->cRrIntervals -= iRRIntervalsCount;
}
#endif /* gHrs_EnableRRIntervalMeasurements_d */
return GattDb_WriteAttribute(handle, index, &characteristic[0]);
}
}
===
bluetooth\profiles\heart_rate
PRIMARY_SERVICE(service_heart_rate, gBleSig_HeartRateService_d)
CHARACTERISTIC(char_hr_measurement, gBleSig_HrMeasurement_d, (gGattCharPropNotify_c))
VALUE_VARLEN(value_hr_measurement, gBleSig_HrMeasurement_d, (gPermissionNone_c), 20, 2, 0x00, 0xB4)
CCCD(cccd_hr_measurement)
CHARACTERISTIC(char_body_sensor_location, gBleSig_BodySensorLocation_d, (gGattCharPropRead_c) )
VALUE(value_body_sensor_location, gBleSig_BodySensorLocation_d, (gPermissionFlagReadable_c), 1, 0x01)
CHARACTERISTIC(char_hr_ctrl_point, gBleSig_HrControlPoint_d, (gGattCharPropWrite_c | gGattCharPropRead_c) )
VALUE(value_hr_ctrl_point, gBleSig_HrControlPoint_d, (gPermissionFlagReadable_c | gPermissionFlagWritable_c), 7, 20,19,9,2,14,19,30)