9 changed files with 663 additions and 214 deletions
-
3.vscode/settings.json
-
174app/app.uvoptx
-
10app/app.uvprojx
-
218app/src/basic/qrs_time_domain_zh.c
-
17app/src/basic/qrs_time_domain_zh.h
-
135app/src/heart_wave_sample_service.c
-
313app/src/heart_wave_sample_service.c.bak
-
1app/src/heart_wave_sample_service.h
-
6app/src/one_conduction_main.c
@ -0,0 +1,218 @@ |
|||||
|
#include "qrs_time_domain_zh.h" |
||||
|
|
||||
|
#include <stdbool.h> |
||||
|
#include <stdint.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
#define HEART_RATE_FILTER_SIZE 5 |
||||
|
|
||||
|
typedef struct { |
||||
|
uint16_t data[HEART_RATE_FILTER_SIZE]; |
||||
|
uint16_t data_process_buf[HEART_RATE_FILTER_SIZE]; |
||||
|
uint32_t cnt; |
||||
|
uint32_t index; |
||||
|
} HeartRateMedianFilter_t; // 中值滤波器 |
||||
|
|
||||
|
typedef struct { |
||||
|
uint16_t data[HEART_RATE_FILTER_SIZE]; |
||||
|
uint32_t cnt; |
||||
|
uint32_t index; |
||||
|
uint32_t sum; |
||||
|
} HeartRateMeanFilter_t; // 均值滤波器 |
||||
|
|
||||
|
HeartRateMedianFilter_t m_heart_rate_median_filter; |
||||
|
HeartRateMeanFilter_t m_heart_rate_mean_filter; |
||||
|
|
||||
|
static void HeartRateMedianFilter_reset() { |
||||
|
memset(m_heart_rate_median_filter.data, 0, sizeof(m_heart_rate_median_filter.data)); |
||||
|
m_heart_rate_median_filter.cnt = 0; |
||||
|
m_heart_rate_median_filter.index = 0; |
||||
|
} |
||||
|
static uint16_t HeartRateMedianFilter_process(uint16_t data) { |
||||
|
HeartRateMedianFilter_t* pfilter = &m_heart_rate_median_filter; |
||||
|
|
||||
|
pfilter->data[pfilter->index] = data; |
||||
|
pfilter->index++; |
||||
|
pfilter->cnt++; |
||||
|
if (pfilter->index >= 5) { |
||||
|
pfilter->index = 0; |
||||
|
} |
||||
|
|
||||
|
if (pfilter->cnt < 5) { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
memcpy(pfilter->data_process_buf, pfilter->data, HEART_RATE_FILTER_SIZE * sizeof(uint16_t)); |
||||
|
for (uint8_t i = 0; i < HEART_RATE_FILTER_SIZE; i++) { |
||||
|
for (uint8_t j = i + 1; j < HEART_RATE_FILTER_SIZE; j++) { |
||||
|
if (pfilter->data_process_buf[i] > pfilter->data_process_buf[j]) { |
||||
|
uint16_t temp = pfilter->data_process_buf[i]; |
||||
|
pfilter->data_process_buf[i] = pfilter->data_process_buf[j]; |
||||
|
pfilter->data_process_buf[j] = temp; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return pfilter->data_process_buf[2]; |
||||
|
} |
||||
|
static void HeartRateMeanFilter_reset() { |
||||
|
memset(m_heart_rate_mean_filter.data, 0, sizeof(m_heart_rate_mean_filter.data)); |
||||
|
m_heart_rate_mean_filter.cnt = 0; |
||||
|
m_heart_rate_mean_filter.index = 0; |
||||
|
m_heart_rate_mean_filter.sum = 0; |
||||
|
} |
||||
|
static uint16_t HeartRateMeanFilter_process(uint16_t data) { |
||||
|
HeartRateMeanFilter_t* pfilter = &m_heart_rate_mean_filter; |
||||
|
|
||||
|
pfilter->sum -= pfilter->data[pfilter->index]; |
||||
|
pfilter->data[pfilter->index] = data; |
||||
|
pfilter->sum += data; |
||||
|
|
||||
|
pfilter->index++; |
||||
|
pfilter->cnt++; |
||||
|
|
||||
|
if (pfilter->index >= 5) { |
||||
|
pfilter->index = 0; |
||||
|
} |
||||
|
|
||||
|
if (pfilter->cnt < 5) { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
return pfilter->sum / 5; |
||||
|
} |
||||
|
|
||||
|
static uint16_t m_data[TABLE_SIZE]; |
||||
|
static uint32_t m_ndata = 0; |
||||
|
static uint32_t m_dataindex = 0; |
||||
|
static uint32_t m_data_cnt = 0; |
||||
|
static uint16_t m_heartrate = 0; |
||||
|
|
||||
|
static uint32_t m_datasum = 0; |
||||
|
static float m_avg = 0; |
||||
|
static uint32_t m_max_val_in_m_data; |
||||
|
|
||||
|
static bool m_findpeak = false; |
||||
|
|
||||
|
static uint16_t pQRS_median_filter_cache[5]; |
||||
|
static uint16_t pQRS_median_filter_cache_index = 0; |
||||
|
static uint16_t pQRS_median_filter_cache_cnt = 0; |
||||
|
|
||||
|
static uint32_t m_last_peak_pos = 0; |
||||
|
static uint32_t m_peakcnt = 0; |
||||
|
|
||||
|
static uint16_t pQRS_median_filter(uint16_t indata) { |
||||
|
// memcpy(pQRS_median_filter_cache + 1, pQRS_median_filter_cache, 4 * sizeof(uint16_t)); |
||||
|
pQRS_median_filter_cache[pQRS_median_filter_cache_index] = indata; |
||||
|
pQRS_median_filter_cache_index++; |
||||
|
pQRS_median_filter_cache_cnt++; |
||||
|
if (pQRS_median_filter_cache_index >= 5) { |
||||
|
pQRS_median_filter_cache_index = 0; |
||||
|
} |
||||
|
|
||||
|
if (pQRS_median_filter_cache_cnt < 5) { |
||||
|
return indata; |
||||
|
} |
||||
|
|
||||
|
static uint16_t process_cache[5]; |
||||
|
memcpy(process_cache, pQRS_median_filter_cache, 5 * sizeof(uint16_t)); |
||||
|
for (uint8_t i = 0; i < 5; i++) { |
||||
|
for (uint8_t j = i + 1; j < 5; j++) { |
||||
|
if (process_cache[i] > process_cache[j]) { |
||||
|
uint16_t temp = process_cache[i]; |
||||
|
process_cache[i] = process_cache[j]; |
||||
|
process_cache[j] = temp; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return process_cache[2]; |
||||
|
} |
||||
|
|
||||
|
static uint32_t pQRS_findMaxValue() { |
||||
|
uint32_t max_val = 0; |
||||
|
for (uint32_t i = 0; i < TABLE_SIZE; i++) { |
||||
|
if (m_data[i] > max_val) { |
||||
|
max_val = m_data[i]; |
||||
|
} |
||||
|
} |
||||
|
return max_val; |
||||
|
} |
||||
|
|
||||
|
void QRS_resetBuf() { // |
||||
|
m_ndata = 0; |
||||
|
m_dataindex = 0; |
||||
|
m_heartrate = 0; |
||||
|
m_data_cnt = 0; |
||||
|
memset(m_data, 0, sizeof(m_data)); |
||||
|
m_datasum = 0; |
||||
|
m_findpeak = false; |
||||
|
pQRS_median_filter_cache_index = 0; |
||||
|
pQRS_median_filter_cache_cnt = 0; |
||||
|
m_peakcnt = 0; |
||||
|
|
||||
|
HeartRateMedianFilter_reset(); |
||||
|
HeartRateMeanFilter_reset(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void QRS_processData(uint16_t _data) { |
||||
|
uint16_t data = pQRS_median_filter(_data); |
||||
|
/******************************************************************************* |
||||
|
* 填充BUF * |
||||
|
*******************************************************************************/ |
||||
|
m_datasum -= m_data[m_dataindex]; |
||||
|
m_data[m_dataindex] = data; |
||||
|
m_datasum += data; |
||||
|
|
||||
|
m_data_cnt++; |
||||
|
|
||||
|
if (m_dataindex < TABLE_SIZE) { |
||||
|
m_dataindex++; |
||||
|
} else { |
||||
|
m_dataindex = 0; |
||||
|
} |
||||
|
|
||||
|
m_ndata++; |
||||
|
if (m_ndata > TABLE_SIZE) { |
||||
|
m_ndata = TABLE_SIZE; |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 求BUF的平均值和最大值 * |
||||
|
*******************************************************************************/ |
||||
|
if (m_ndata == TABLE_SIZE) { |
||||
|
m_avg = (float)m_datasum / m_ndata; |
||||
|
m_max_val_in_m_data = pQRS_findMaxValue(); |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 寻找QRS波峰和波谷 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
if (!m_findpeak) { |
||||
|
uint16_t thresholdValue = (m_max_val_in_m_data - m_avg) * 0.666 + m_avg; |
||||
|
if (data > thresholdValue) { |
||||
|
m_findpeak = true; |
||||
|
m_peakcnt++; |
||||
|
|
||||
|
if (m_last_peak_pos != 0) { |
||||
|
uint16_t diff_peak_pos = m_data_cnt - m_last_peak_pos; |
||||
|
if (diff_peak_pos > 0) { |
||||
|
// |
||||
|
// m_heartrate = 60 * 500 / diff_peak_pos; |
||||
|
|
||||
|
uint16_t diff_peak_ms = diff_peak_pos * 2; // 500Hz |
||||
|
uint16_t heart_rate = 60 * 1000 / diff_peak_ms; |
||||
|
|
||||
|
m_heartrate = HeartRateMeanFilter_process(HeartRateMedianFilter_process(heart_rate)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
m_last_peak_pos = m_data_cnt; |
||||
|
} |
||||
|
} else { |
||||
|
if (data < m_avg) { |
||||
|
m_findpeak = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
uint16_t QRS_getHeartRate() { return m_heartrate; } |
@ -0,0 +1,17 @@ |
|||||
|
/** |
||||
|
* @file qrs_time_domain_zh.h |
||||
|
* @author zhaohe (zhaohe@domain.com) |
||||
|
* @brief |
||||
|
* @version 0.1 |
||||
|
* @date 2024-02-10 |
||||
|
* |
||||
|
* @copyright Copyright (c) 2024 |
||||
|
* |
||||
|
*/ |
||||
|
#pragma once |
||||
|
#include <stdint.h> |
||||
|
#define TABLE_SIZE 500 |
||||
|
|
||||
|
void QRS_resetBuf(); |
||||
|
void QRS_processData(uint16_t data); |
||||
|
uint16_t QRS_getHeartRate(); |
@ -0,0 +1,313 @@ |
|||||
|
#include "heart_wave_sample_service.h" |
||||
|
|
||||
|
#include "app_event.h" |
||||
|
#include "app_event_distribute.h" |
||||
|
#include "basic/FIR.h" |
||||
|
#include "basic/HC_Chen_detect.h" |
||||
|
#include "basic/So_Chen_detect.h" |
||||
|
#include "basic/adaptive_algorithm.h" |
||||
|
#include "basic/Pan_Tompkins_detect.h" |
||||
|
#include "board/board_ecg_sensor.h" |
||||
|
#include "nrfx_timer.h" |
||||
|
#include "one_conduction_board.h" |
||||
|
|
||||
|
static uint16_t m_capture_buffer_a[128]; |
||||
|
static uint16_t m_capture_buffer_b[128]; |
||||
|
|
||||
|
static uint16_t* m_capture_buffer; |
||||
|
static uint16_t m_capture_buffer_index = 0; |
||||
|
|
||||
|
volatile static float m_sensor_display_data = 0; // 0->100 |
||||
|
static uint32_t m_start_capture_tp; |
||||
|
static uint32_t m_frame_index = 0; |
||||
|
|
||||
|
static one_frame_data_t m_sensor_little_frame_cache[LITTLE_DATA_BLOCK_FRAME_NUM]; |
||||
|
static uint32_t m_little_frame_index; |
||||
|
static bool m_prestart_flag; |
||||
|
|
||||
|
static nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(HEART_WAVE_SAMPLE_TMR_INSTANCE); |
||||
|
|
||||
|
typedef struct { |
||||
|
int heartSignalCnt; |
||||
|
int heart_rate; |
||||
|
uint32_t last_qrs_point; |
||||
|
uint32_t time_cnt; |
||||
|
uint32_t origin_time_cnt; |
||||
|
|
||||
|
uint32_t index; |
||||
|
float index_f; |
||||
|
} QRS_t; |
||||
|
|
||||
|
QRS_t m_qrs; |
||||
|
|
||||
|
void QRS_reset() { |
||||
|
m_qrs.heartSignalCnt = 0; |
||||
|
m_qrs.heart_rate = 0; |
||||
|
m_qrs.time_cnt = 0; |
||||
|
m_qrs.index = 0; |
||||
|
m_qrs.index_f = 0; |
||||
|
FIR_reset_buffer(); |
||||
|
} |
||||
|
|
||||
|
void QRS_process(float value) { |
||||
|
bool isPeak = false; |
||||
|
#if 1 |
||||
|
float result = value; |
||||
|
SignalPoint sp; |
||||
|
sp.value = result; |
||||
|
sp.index = m_qrs.time_cnt; |
||||
|
SignalPoint peak = So_Chen_detect(sp, SAMPLING_RATE * 0.25f, 4, 16); |
||||
|
if (peak.index != -1) { |
||||
|
isPeak = true; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if 0 |
||||
|
isPeak = HC_Chen_detect(value); |
||||
|
#endif |
||||
|
|
||||
|
#if 0 |
||||
|
static const float CV_LIMIT = 50.0f; |
||||
|
static const float THRESHOLD_FACTOR = 3.0f; |
||||
|
double mean = CalculateMean(value); |
||||
|
double rms = CalculateRootMeanSquare(value); |
||||
|
double cv = CalculateCoefficientOfVariation(value); |
||||
|
double threshold; |
||||
|
if (cv > CV_LIMIT) { |
||||
|
threshold = rms; |
||||
|
} else { |
||||
|
threshold = rms * (cv / 100.0f) * THRESHOLD_FACTOR; |
||||
|
} |
||||
|
bool is_peak; |
||||
|
SignalPoint result; |
||||
|
result = PeakDetect(value, m_qrs.time_cnt, threshold, &is_peak); |
||||
|
if (result.index != -1) { |
||||
|
if (is_peak) { |
||||
|
isPeak = true; |
||||
|
} |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#if 0 |
||||
|
|
||||
|
|
||||
|
double result = value; |
||||
|
double bandpass; |
||||
|
double integral; |
||||
|
double square; |
||||
|
|
||||
|
bandpass = result; |
||||
|
result = Derivative(result); |
||||
|
result = Squar(result); |
||||
|
square = result; |
||||
|
result = MovingWindowIntegral(result); |
||||
|
integral = result; |
||||
|
|
||||
|
SignalPoint peak = ThresholdCalculate(m_qrs.time_cnt,value,bandpass,square,integral); |
||||
|
|
||||
|
if(peak.index != -1){ |
||||
|
isPeak = true; |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
// if (isPeak) { |
||||
|
// uint32_t time_diff = m_qrs.time_cnt - m_qrs.last_qrs_point; |
||||
|
// m_qrs.last_qrs_point = m_qrs.time_cnt; |
||||
|
// m_qrs.heartSignalCnt++; |
||||
|
// // m_qrs.heart_rate = m_qrs.heartSignalCnt; |
||||
|
// if (m_qrs.last_qrs_point != 0) { |
||||
|
// m_qrs.heart_rate = 60 * (1 / (time_diff * 1.0 / SAMPLING_RATE)); |
||||
|
// } |
||||
|
// } |
||||
|
|
||||
|
m_qrs.time_cnt++; |
||||
|
} |
||||
|
|
||||
|
static const void compute_heart_rate(float sample_data) { |
||||
|
ZASSERT(SAMPLE_RATE == 500); |
||||
|
m_qrs.index_f = m_frame_index / 500.0 * 360; |
||||
|
if ((m_qrs.index_f - m_qrs.index) > 1) { |
||||
|
m_qrs.index = m_qrs.index_f; |
||||
|
float val = sample_data; |
||||
|
QRS_process(FIR_filter(val)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static void swap_buffer() { |
||||
|
if (m_capture_buffer == NULL) { |
||||
|
m_capture_buffer = m_capture_buffer_a; |
||||
|
m_capture_buffer_index = 0; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (m_capture_buffer == m_capture_buffer_a) { |
||||
|
m_capture_buffer = m_capture_buffer_b; |
||||
|
} else { |
||||
|
m_capture_buffer = m_capture_buffer_a; |
||||
|
} |
||||
|
m_capture_buffer_index = 0; |
||||
|
return; |
||||
|
} |
||||
|
static float amp_val(uint16_t val, uint16_t valcener, float amp) { |
||||
|
float valf = (float)val - valcener; |
||||
|
valf = valf * amp; |
||||
|
valf += valcener; |
||||
|
|
||||
|
if (valf >= 100) { |
||||
|
valf = 100; |
||||
|
} |
||||
|
|
||||
|
if (valf <= 0) { |
||||
|
valf = 0; |
||||
|
} |
||||
|
return valf; |
||||
|
} |
||||
|
|
||||
|
typedef struct { |
||||
|
float value; |
||||
|
float efectiveFactor; |
||||
|
} filter_t; |
||||
|
|
||||
|
filter_t m_filter = {0, 0.8}; |
||||
|
|
||||
|
static float Filter(filter_t* filter, float newInput) { |
||||
|
float newv = ((float)filter->value * (1.0f - filter->efectiveFactor)) + ((float)newInput * filter->efectiveFactor); |
||||
|
filter->value = newv; |
||||
|
return newv; |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 小包数据上报 * |
||||
|
*******************************************************************************/ |
||||
|
static inline void prvf_little_block_cache_push_one_frame(uint16_t data) { |
||||
|
if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) { |
||||
|
return; |
||||
|
} |
||||
|
m_sensor_little_frame_cache[m_little_frame_index].data = data; |
||||
|
m_little_frame_index++; |
||||
|
} |
||||
|
|
||||
|
static inline bool prvf_light_block_cache_is_full(void) { |
||||
|
if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) { |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
static inline void prvf_light_block_cache_clear(void) { m_little_frame_index = 0; } |
||||
|
static inline void prvf_light_block_trigger_event() { |
||||
|
static app_event_t event; |
||||
|
event.eventType = kevent_capture_little_data_block_event; |
||||
|
for (uint32_t i = 0; i < LITTLE_DATA_BLOCK_FRAME_NUM; i++) { |
||||
|
event.val.little_data_block.data[i].data = m_sensor_little_frame_cache[i].data; |
||||
|
} |
||||
|
event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM; |
||||
|
// ZLOGI("%d", event.val.little_data_block.frameIndex); |
||||
|
AppEvent_pushEvent(&event); |
||||
|
} |
||||
|
|
||||
|
void nrfx_timer_event_handler(nrf_timer_event_t event_type, void* p_context) { // |
||||
|
uint16_t val = BoardEcgSensor_plod_get_ecg_val(); // 12bit |
||||
|
float val_af100 = (float)val / 4096.0f * 100; |
||||
|
if (m_prestart_flag) { |
||||
|
compute_heart_rate(val_af100); |
||||
|
return; |
||||
|
} else { |
||||
|
compute_heart_rate(val_af100); |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 显示数据计算并赋值 * |
||||
|
*******************************************************************************/ |
||||
|
|
||||
|
m_frame_index++; |
||||
|
val_af100 = amp_val(val_af100, 45, 3.5f); |
||||
|
val_af100 = Filter(&m_filter, val_af100); |
||||
|
m_sensor_display_data = val_af100; |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 采样数据缓存 * |
||||
|
*******************************************************************************/ |
||||
|
if (m_capture_buffer == NULL) { |
||||
|
swap_buffer(); |
||||
|
} |
||||
|
|
||||
|
if (m_capture_buffer_index < 128) { |
||||
|
m_capture_buffer[m_capture_buffer_index++] = val; |
||||
|
} |
||||
|
|
||||
|
if (m_capture_buffer_index == 128) { |
||||
|
app_event_t evt; |
||||
|
evt.eventType = kevent_capture_256data_event; |
||||
|
evt.val.capture_data_cache = (uint8_t*)m_capture_buffer; |
||||
|
swap_buffer(); |
||||
|
AppEvent_pushEvent(&evt); |
||||
|
} |
||||
|
|
||||
|
/******************************************************************************* |
||||
|
* 实时采样数据事件上报 * |
||||
|
*******************************************************************************/ |
||||
|
/** |
||||
|
* @brief 缓存数据,并触发小数据块事件 |
||||
|
*/ |
||||
|
prvf_little_block_cache_push_one_frame(val); |
||||
|
if (prvf_light_block_cache_is_full()) { |
||||
|
prvf_light_block_trigger_event(); |
||||
|
prvf_light_block_cache_clear(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void hwss_init(void) { |
||||
|
static bool m_timer_inited = false; |
||||
|
if (!m_timer_inited) { |
||||
|
/** |
||||
|
* @brief 初始化定时器 |
||||
|
*/ |
||||
|
static nrfx_timer_config_t timer_cfg = { |
||||
|
.frequency = NRF_TIMER_FREQ_500kHz, |
||||
|
.mode = NRF_TIMER_MODE_TIMER, |
||||
|
.bit_width = NRF_TIMER_BIT_WIDTH_24, |
||||
|
.p_context = NULL, |
||||
|
.interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, |
||||
|
}; |
||||
|
|
||||
|
// nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler); |
||||
|
ZERROR_CHECK(nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler)); |
||||
|
uint32_t timer_ticks = nrfx_timer_ms_to_ticks(&m_timer, 2); // |
||||
|
ZASSERT(SAMPLE_RATE == 500); |
||||
|
nrfx_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, timer_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true); |
||||
|
m_timer_inited = true; |
||||
|
} |
||||
|
} |
||||
|
void hwss_uninit(void) { nrfx_timer_disable(&m_timer); } |
||||
|
|
||||
|
void hwss_pre_start_capture(void) { |
||||
|
m_start_capture_tp = znordic_getpower_on_s(); |
||||
|
swap_buffer(); |
||||
|
m_frame_index = 0; |
||||
|
|
||||
|
QRS_reset(); |
||||
|
|
||||
|
prvf_light_block_cache_clear(); |
||||
|
nrfx_timer_enable(&m_timer); |
||||
|
m_prestart_flag = true; |
||||
|
} |
||||
|
|
||||
|
void hwss_start_capture(void) { m_prestart_flag = false; } |
||||
|
void hwss_stop_capture(void) { |
||||
|
nrfx_timer_disable(&m_timer); |
||||
|
m_frame_index = 0; |
||||
|
prvf_light_block_cache_clear(); |
||||
|
} |
||||
|
|
||||
|
float hwss_read_val(void) { |
||||
|
__disable_irq(); |
||||
|
float val = m_sensor_display_data; |
||||
|
__enable_irq(); |
||||
|
return val; |
||||
|
} |
||||
|
float hwss_read_heart_rate(void) { // |
||||
|
return m_qrs.heart_rate; |
||||
|
} |
||||
|
|
||||
|
int hwss_has_captured_time_ms() { return (znordic_getpower_on_s() - m_start_capture_tp) * 1000; } |
Write
Preview
Loading…
Cancel
Save
Reference in new issue