initial commit

This commit is contained in:
jhChun
2026-04-08 16:58:54 +09:00
commit 82e33d8bf9
2578 changed files with 1590432 additions and 0 deletions

View File

@@ -0,0 +1,853 @@
/*******************************************************************************
* @file measurements.c
* @brief LED/PD measurement control module for NIRS system
* @author Charles KWON <charleskwon@medithings.co.kr>
* @version V2.0.0
* @date 2025-12-31
*
* Copyright (c) 2025 Medithings Inc.
* All rights reserved.
*
* This module provides LED and photodetector (PD) control functions for the
* NIRS (Near-Infrared Spectroscopy) bladder monitoring system.
*
* ============================================================================
* MODULE OVERVIEW
* ============================================================================
*
* Hardware Components Controlled:
* - 48 NIR LEDs (LED0-LED47) via CAT9532 I2C LED driver
* - 4 Photodetectors (PD0, PD1, MOD, MOD2) via FSA5157P6X analog switch
* - MCP4725 DAC for PD gain control (I2C, 12-bit)
* - DS3930 EEPROM for LED power calibration storage
*
* LED-PD Mapping:
* - LED 0-23 -> PD0 (photodetector 0)
* - LED 24-47 -> PD1 (photodetector 1)
* - MOD/MOD2 -> Lock-in amplifier modulation channels
*
* DAC Gain Range:
* - MCP4725 output: 0.1V ~ 1.1V
* - DAC value range: 125 ~ 1366 (12-bit)
* - Default value: 1000 (mid-range)
*
* ============================================================================
* MAIN FUNCTIONS
* ============================================================================
*
* LED Control:
* - led_on(index) : Turn on specific LED (0-47)
* - led_off(index) : Turn off LED (99=all off, 98=clear)
* - led_select(index) : Select LED via GPIO multiplexer
*
* PD Control:
* - pd_on(index) : Turn on specific PD (0-3)
* - pd_off(index) : Turn off PD (99=all off)
* - pd_select(index) : Select PD channel
*
* Gain Control:
* - pd_gain_set(led) : Set PD gain from led_pd_dac_v[] lookup table
* - imm_gain_set(dac) : Set immediate DAC value
* - led_pd_mod_set() : Set modulation gain for lock-in
*
* EEPROM Operations:
* - led_power_read(index) : Read LED power from ROM
* - led_power_save_mem(index) : Save LED power to ROM
* - led_power_save_mem_48() : Save all 48 LED powers
*
******************************************************************************/
/*============================================================================*/
/* Includes - Charles KWON */
/*============================================================================*/
#include "sdk_common.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nrf.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_spi.h"
#include "nrf_drv_saadc.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "boards.h"
#include "bsp.h"
#include "app_error.h"
#include "nrf_delay.h"
#include "app_util_platform.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_log.h"
#include "ble_nus.h"
#include "LED_Parse.h"
#include "app_timer.h"
#include "measurements.h"
#include "main.h"
//#include "ad5272_i2c.h"
#include "mcp4725_i2c.h"
#include <cmd_parse.h>
#include "debug_print.h"
#include "i2c_manager.h"
/*============================================================================*/
/* Configuration Constants - Charles KWON */
/*============================================================================*/
/**
* @brief Total number of LEDs in the system
* - Charles KWON
*
* Currently using 24 LEDs (LED0-LED23) for single PD configuration.
* Can be extended to 48 for dual PD configuration.
*/
#define LED_NUM 24
/** @brief Timer interval for BLE data transmission (ms) */
#define MEA_SEND_LOOP_INTERVAL 100
/*============================================================================*/
/* State Variables - Charles KWON */
/*============================================================================*/
/**
* @brief Currently activated LED index
* - Charles KWON
*
* Tracks which LED is currently turned on.
* Value 99 indicates no LED is active (all off).
*/
uint8_t activated_led = 99;
/**
* @brief Currently activated photodetector index
* - Charles KWON
*
* Tracks which PD channel is currently selected.
* Value 99 indicates no PD is active (all off).
*/
uint8_t activated_pd = 99;
/*============================================================================*/
/* Timer Definitions - Charles KWON */
/*============================================================================*/
/** @brief Timer for sequenced BLE data transmission */
APP_TIMER_DEF(m_mea_send_loop_timer_id);
/** @brief Counter for BLE transmission sequence */
static uint8_t cnt = 0;
/*============================================================================*/
/* Communication Buffers - Charles KWON */
/*============================================================================*/
/** @brief TX buffer for BLE data transmission */
char mea_tx_buffer[BLE_NUS_MAX_DATA_LEN];
/** @brief External flag indicating command processing state */
extern volatile bool processing;
/*============================================================================*/
/* LED-PD Gain Calibration Table - Charles KWON */
/*============================================================================*/
/**
* @brief DAC values for LED-PD gain matching
* - Charles KWON
*
* Each LED has a corresponding DAC value that sets the optimal
* PD amplifier gain for that LED-PD pair. Values are calibrated
* during AGC (Automatic Gain Control) and stored in EEPROM.
*
* DAC Range:
* - Minimum: 125 (0.1V output)
* - Maximum: 1366 (1.1V output)
* - Default: 1000 (mid-range)
*
* This array is populated from EEPROM at startup or after AGC.
* Defined in device_config.c
*/
extern uint16_t led_pd_dac_v[];
/**
* @brief DAC value when all LEDs are off
* - Charles KWON
*
* Used as baseline/reference gain when no LED is active.
*/
uint16_t led_off_dac_v = 1360;
/**
* @brief Default PD channel when LED is off
* - Charles KWON
*/
uint8_t led_off_pd = 0;
/*============================================================================*/
/* BLE Data Transmission Functions - Charles KWON */
/*============================================================================*/
/**
* @brief Start LED-PD gain array printout via BLE
* - Charles KWON
*
* Initiates sequenced transmission of the led_pd_dac_v[] array
* over BLE. Data is sent in chunks to comply with BLE MTU limits.
*/
void led_pd_gain_array_printout(void)
{
cnt = 0;
mea_send_timer_start();
}
/**
* @brief Timer callback for sending LED-PD gain data via BLE
* - Charles KWON
*
* Called periodically to transmit gain calibration data.
* Sends data in 3 chunks (cnt 0-2), then outputs debug info
* and clears the processing flag.
*
* Output Format: "Tag-Currrnt [cnt], [dac0], [dac1], ..., [dac23]\r\n"
*
* @param[in] p_context Unused timer context
*/
void mea_send_loop(void *p_context)
{
UNUSED_PARAMETER(p_context);
DBG_PRINTF("\r\n1CNT =%d\r\n", cnt);
mea_send_timer_stop();
if (cnt < 6) {
uint8_t i = (int)(cnt);
if (cnt < 3) {
/* Build string dynamically for easy LED_NUM changes */
int offset = sprintf(mea_tx_buffer, "Tag-Currrnt %d", i);
for (uint8_t j = 0; j < LED_NUM; j++) {
offset += sprintf(mea_tx_buffer + offset, ",\t%d", led_pd_dac_v[j]);
}
sprintf(mea_tx_buffer + offset, "\r\n");
data_tx_handler(mea_tx_buffer);
}
DBG_PRINTF("\r\n2CNT =%d\r\n", cnt);
mea_send_timer_start();
} else {
/* Final iteration: print debug summary */
DBG_PRINTF("\r\nLED-PD Gain Array =\r\n");
for (uint16_t j = 0; j < LED_NUM; j++) {
DBG_PRINTF("%d,\t", led_pd_dac_v[j]);
}
DBG_PRINTF("\r\n");
processing = false;
}
cnt++;
}
/*============================================================================*/
/* LED Control Functions - Charles KWON */
/*============================================================================*/
/**
* @brief Turn on specified LED
* - Charles KWON
*
* Activates the specified LED through the CAT9532 LED driver.
* Also enables the analog switch trigger for signal routing.
*
* @param[in] led_index LED index (0-47 for specific LED, <=100 for valid range)
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on failure
*
* @note Sets activated_led to track current LED state
* @note Calls trig_SW(true) to enable signal path
*/
ret_code_t led_on(uint8_t led_index)
{
uint32_t err_code = NRF_SUCCESS;
#if FEATURE_PRINTF
DBG_PRINTF("\tled_on, %d =====================\r\n", led_index);
#endif
if (led_index <= 100) {
activated_led = led_index;
trig_SW(true); /* Enable analog switch for signal routing */
if (NRF_SUCCESS != led_select(led_index)) {
DBG_PRINTF("ERR!!! LED Select\r\n");
return NRF_ERROR_INTERNAL;
}
} else {
DBG_PRINTF("ERR!!! led_index Failed! %d\r\n", led_index);
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/**
* @brief Turn off LED
* - Charles KWON
*
* Deactivates LED and disables the analog switch trigger.
*
* @param[in] led_index 99 = all LEDs off, 98 = clear state
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on invalid index
*
* @note Calls trig_SW(false) to disable signal path
*/
ret_code_t led_off(uint8_t led_index)
{
uint32_t err_code = NRF_SUCCESS;
trig_SW(false); /* Disable analog switch */
#if FEATURE_PRINTF
DBG_PRINTF("led_off\r\n");
#endif
if (led_index == 99) {
LED_ALLOFF(); /* Turn off all LEDs */
activated_led = 99;
} else if (led_index == 98) {
LED99(); /* Clear LED state */
DBG_PRINTF("clear \r\n");
activated_led = 98;
} else {
DBG_PRINTF("ERR!!! led_index Failed! %d\r\n", led_index);
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/*============================================================================*/
/* Gain Control Functions - Charles KWON */
/*============================================================================*/
/**
* @brief Set modulation gain via MCP4725 DAC
* - Charles KWON
*
* Configures the DAC for lock-in amplifier modulation mode.
* Used when measuring with the MOD photodetector channel.
*
* @param[in] mod_gain DAC value (0-2000)
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on failure
*
* @note Initializes SW I2C if not already done
* @note Activates MOD channel (PD index 2)
*/
ret_code_t led_pd_mod_set(uint16_t mod_gain)
{
uint32_t err_code = NRF_SUCCESS;
if (mod_gain <= 2000) {
sw_i2c_init_once(); /* Ensure I2C is initialized */
mcp4725_writeFastMode(mod_gain);
if (NRF_SUCCESS != pd_on(2)) { /* Enable MOD channel */
DBG_PRINTF("ERR!!! MOD_on\r\n");
return NRF_ERROR_INTERNAL;
}
} else {
DBG_PRINTF("ERR!!! lockin Test Failed!\r\n");
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/**
* @brief Set PD gain matching value for specified LED
* - Charles KWON
*
* Configures the PD amplifier gain based on the LED index.
* Automatically selects the appropriate PD channel:
* - LED 0-23 -> PD0
* - LED 24-47 -> PD1
* - LED 99 -> Default PD (led_off_pd)
*
* @param[in] led_index LED index for gain lookup
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on failure
*/
ret_code_t led_pd_matching_value_set(uint8_t led_index)
{
uint32_t err_code = NRF_SUCCESS;
if (led_index <= 100) {
/* Set DAC gain from lookup table */
if (NRF_SUCCESS != pd_gain_set(led_index)) {
DBG_PRINTF("ERR!!! pd_gain_set\r\n");
return NRF_ERROR_INTERNAL;
}
/* Determine PD channel based on LED index */
uint8_t pd_index;
if (led_index < 24) {
pd_index = 0; /* PD0 for LED 0-23 */
} else if ((led_index < 48) && (led_index > 23)) {
pd_index = 1; /* PD1 for LED 24-47 */
} else if (led_index == 99) {
pd_index = led_off_pd; /* Default PD when off */
}
/* Activate the selected PD channel */
if (NRF_SUCCESS != pd_on(pd_index)) {
DBG_PRINTF("ERR!!! pd_on\r\n");
return NRF_ERROR_INTERNAL;
}
} else {
DBG_PRINTF("ERR!!! led_indexFailed! %d\r\n", led_index);
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/*============================================================================*/
/* Photodetector Control Functions - Charles KWON */
/*============================================================================*/
/**
* @brief Turn on specified photodetector
* - Charles KWON
*
* Activates one of the 4 PD channels via FSA5157P6X analog switch.
*
* PD Channels:
* - 0: PD0 (for LED 0-23)
* - 1: PD1 (for LED 24-47)
* - 2: MOD (lock-in modulation)
* - 3: MOD2 (secondary modulation)
*
* @param[in] pd_index Photodetector index (0-3)
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on failure
*/
ret_code_t pd_on(uint8_t pd_index)
{
uint32_t err_code = NRF_SUCCESS;
#if FEATURE_FOR_SCOPE
/* Debug pulse for oscilloscope timing */
nrf_gpio_pin_set(PD_CLK_26);
nrf_gpio_pin_clear(PD_CLK_26);
#endif
#if FEATURE_PRINTF
DBG_PRINTF("pd_on, %d ===== \r\n", pd_index);
#endif
if (pd_index <= 3) {
activated_pd = pd_index;
if (NRF_SUCCESS != pd_select(pd_index)) {
DBG_PRINTF("ERR!!! pd_on Failed! %d\r\n", pd_index);
return NRF_ERROR_INTERNAL;
}
} else {
DBG_PRINTF("ERR!!! pd_index Failed! %d\r\n", pd_index);
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/**
* @brief Turn off photodetector
* - Charles KWON
*
* Deactivates all PD channels. Only accepts index 99 for safety.
*
* @param[in] pd_index Must be 99 for all-off operation
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on invalid index
*/
ret_code_t pd_off(uint8_t pd_index)
{
uint32_t err_code = NRF_SUCCESS;
#if FEATURE_PRINTF
DBG_PRINTF("pd_off\r\n");
#endif
if (pd_index == 99) {
PD_ALLOFF();
activated_pd = 99;
} else {
DBG_PRINTF("ERR!!! PD Off Failed! %d\r\n", pd_index);
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/*============================================================================*/
/* LED Power EEPROM Functions - Charles KWON */
/*============================================================================*/
/**
* @brief Read all 24 LED power values from ROM
* - Charles KWON
*
* Reads LED power calibration values from DS3930 EEPROM.
* Each read has 1ms delay for EEPROM access timing.
*
* @param[out] data Output buffer for 24 uint16_t values
*/
void led_power_read_48(uint16_t *data)
{
for (uint8_t i = 0; i < 24; i++) {
data[i] = LED_READ_ROM(i);
nrf_delay_ms(1); /* EEPROM access delay */
}
}
/**
* @brief Read single LED power value from ROM
* - Charles KWON
*
* @param[in] led_index LED index (0-47)
* @return LED power value, or NRF_ERROR_INTERNAL on invalid index
*/
int16_t led_power_read(uint8_t led_index)
{
int16_t led_power;
if (led_index <= 47) {
led_power = LED_READ_ROM(led_index);
} else {
DBG_PRINTF("ERR!!! led_index Failed! %d\r\n", led_index);
return NRF_ERROR_INTERNAL;
}
return led_power;
}
/**
* @brief Save LED power value to ROM
* - Charles KWON
*
* Writes LED power calibration value to DS3930 EEPROM.
*
* @param[in] led_index LED index (0-47)
* @param[in] led_power Power value (0-255)
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on failure
*/
ret_code_t led_power_save_mem(uint8_t led_index, int16_t led_power)
{
uint32_t err_code = NRF_SUCCESS;
if ((led_index <= 47) || (led_power <= 255)) {
if (NRF_SUCCESS != LED_WRITE_ROM(led_index, led_power)) {
DBG_PRINTF("ERR!!! DS3930 1\r\n");
err_code = NRF_ERROR_INTERNAL;
}
} else {
DBG_PRINTF("ERR!!! led_index || pd_index Failed! %d, %d\r\n", led_index, led_power);
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/**
* @brief Save same LED power value to all 48 LEDs
* - Charles KWON
*
* Writes identical power value to all LED EEPROM locations.
* Useful for factory reset or uniform calibration.
*
* @param[in] led_index Unused parameter
* @param[in] led_power Power value to set for all LEDs
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on any write failure
*
* @note 10ms delay between writes for EEPROM programming time
*/
ret_code_t led_power_save_mem_6(uint8_t led_index, int16_t led_power)
{
uint32_t err_code = NRF_SUCCESS;
for (uint8_t i = 0; i < 48; i++) {
if (NRF_SUCCESS != LED_WRITE_ROM(i, led_power)) {
DBG_PRINTF("ERR!!! DS3930 1\r\n");
err_code = NRF_ERROR_INTERNAL;
}
nrf_delay_ms(10); /* EEPROM programming delay */
}
return err_code;
}
/**
* @brief Save array of LED power values to all 48 LEDs
* - Charles KWON
*
* Writes individual power values for each LED from input array.
*
* @param[in] led_power Array of 48 power values (uint8_t)
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on any write failure
*
* @note 10ms delay between writes for EEPROM programming time
*/
ret_code_t led_power_save_mem_48(uint8_t *led_power)
{
uint32_t err_code = NRF_SUCCESS;
for (uint8_t i = 0; i < 48; i++) {
if (NRF_SUCCESS != LED_WRITE_ROM(i, (int16_t)(led_power[i]))) {
DBG_PRINTF("ERR!!! DS3930 1\r\n");
err_code = NRF_ERROR_INTERNAL;
}
nrf_delay_ms(10); /* EEPROM programming delay */
}
return err_code;
}
/**
* @brief Set LED power (placeholder function)
* - Charles KWON
*
* Currently not implemented. Reserved for future LED current control.
*
* @param[in] led_index LED index
* @return NRF_SUCCESS always
*/
ret_code_t led_power_set(uint8_t led_index)
{
uint32_t err_code = NRF_SUCCESS;
return err_code;
}
/*============================================================================*/
/* DAC Gain Control Functions - Charles KWON */
/*============================================================================*/
/**
* @brief Set PD gain via MCP4725 DAC based on LED-PD matching table
* - Charles KWON
*
* Looks up the calibrated DAC value for the specified LED from
* led_pd_dac_v[] array and programs the MCP4725 DAC.
*
* @param[in] activated_led LED index for gain lookup (0-47, 99=off)
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on invalid index
*
* @note Uses SW I2C for MCP4725 communication
* @note LED 99 uses led_off_dac_v as default gain
*/
ret_code_t pd_gain_set(uint8_t activated_led)
{
uint32_t err_code = NRF_SUCCESS;
#if FEATURE_PRINTF
DBG_PRINTF("<<pd_gain_set L%d, P%d>>\r\n", activated_led, pd_index);
#endif
if (activated_led <= 47) {
sw_i2c_init_once(); /* Ensure I2C is ready */
mcp4725_writeFastMode(led_pd_dac_v[activated_led]);
} else if (activated_led == 99) {
mcp4725_writeFastMode(led_off_dac_v); /* Use default off-state gain */
} else {
DBG_PRINTF("ERR!!! led_index Failed! %d\r\n", activated_led);
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/**
* @brief Set immediate DAC gain value
* - Charles KWON
*
* Directly programs the MCP4725 DAC with specified value.
* Used for manual gain adjustment and testing.
*
* @param[in] imm_dac DAC value (0-2000)
* @return NRF_SUCCESS on success, NRF_ERROR_INTERNAL on out-of-range
*/
ret_code_t imm_gain_set(uint16_t imm_dac)
{
uint32_t err_code = NRF_SUCCESS;
if (imm_dac <= 2000) {
sw_i2c_init_once();
mcp4725_writeFastMode(imm_dac);
DBG_PRINTF("dac_v %d\r\n", imm_dac);
} else {
DBG_PRINTF("ERR!!! range Failed! %d\r\n", activated_led);
return NRF_ERROR_INTERNAL;
}
return err_code;
}
/*============================================================================*/
/* Hardware Selection Functions - Charles KWON */
/*============================================================================*/
/**
* @brief Select and activate specific LED via GPIO multiplexer
* - Charles KWON
*
* Programs the CAT9532 LED driver to activate the specified LED.
* LED selection is done via I2C commands to set the appropriate
* output pins on the LED driver IC.
*
* @param[in] led_index LED index (0-47 for specific LED, 99=clear/off)
* @return NRF_SUCCESS on success, NRF_ERROR_NOT_FOUND on invalid index
*
* @note 1ms delay after selection for GPIO stabilization
* @note LED macros (LED0, LED1, etc.) are defined in LED_Parse.h
*/
ret_code_t led_select(uint8_t led_index)
{
uint32_t err_code = NRF_SUCCESS;
switch (led_index) {
case 0: LED0(); break;
case 1: LED1(); break;
case 2: LED2(); break;
case 3: LED3(); break;
case 4: LED4(); break;
case 5: LED5(); break;
case 6: LED6(); break;
case 7: LED7(); break;
case 8: LED8(); break;
case 9: LED9(); break;
case 10: LED10(); break;
case 11: LED11(); break;
case 12: LED12(); break;
case 13: LED13(); break;
case 14: LED14(); break;
case 15: LED15(); break;
case 16: LED16(); break;
case 17: LED17(); break;
case 18: LED18(); break;
case 19: LED19(); break;
case 20: LED20(); break;
case 21: LED21(); break;
case 22: LED22(); break;
case 23: LED23(); break;
case 24: LED24(); break;
case 25: LED25(); break;
case 26: LED26(); break;
case 27: LED27(); break;
case 28: LED28(); break;
case 29: LED29(); break;
case 30: LED30(); break;
case 31: LED31(); break;
case 32: LED32(); break;
case 33: LED33(); break;
case 34: LED34(); break;
case 35: LED35(); break;
case 36: LED36(); break;
case 37: LED37(); break;
case 38: LED38(); break;
case 39: LED39(); break;
case 40: LED40(); break;
case 41: LED41(); break;
case 42: LED42(); break;
case 43: LED43(); break;
case 44: LED44(); break;
case 45: LED45(); break;
case 46: LED46(); break;
case 47: LED47(); break;
case 99: LED99(); break; /* All LEDs off / clear state */
default:
err_code = NRF_ERROR_NOT_FOUND;
break;
}
/* GPIO stabilization delay */
nrf_delay_ms(1);
return err_code;
}
/**
* @brief Select photodetector channel
* - Charles KWON
*
* Programs the FSA5157P6X analog switch to route the selected
* PD output to the ADC input.
*
* PD Channel Mapping:
* - 0: PD0 - Primary photodetector (LED 0-23)
* - 1: PD1 - Secondary photodetector (LED 24-47)
* - 2: MOD - Lock-in amplifier modulation channel
* - 3: MOD2 - Secondary modulation channel
*
* @param[in] pd_index Photodetector index (0-3)
* @return NRF_SUCCESS on success, NRF_ERROR_NOT_FOUND on invalid index
*
* @note All PD channels are turned off before selecting new one
*/
ret_code_t pd_select(uint8_t pd_index)
{
uint32_t err_code = NRF_SUCCESS;
PD_ALLOFF(); /* Ensure clean state before switching */
switch (pd_index) {
case 0: PD0(); break; /* Photodetector 0 */
case 1: PD1(); break; /* Photodetector 1 */
case 2: MOD(); break; /* Modulation channel */
case 3: MOD2(); break; /* Secondary modulation */
default:
err_code = NRF_ERROR_NOT_FOUND;
break;
}
return err_code;
}
/*============================================================================*/
/* Timer Control Functions - Charles KWON */
/*============================================================================*/
/**
* @brief Start measurement send timer
* - Charles KWON
*
* Starts the single-shot timer for sequenced BLE data transmission.
*/
void mea_send_timer_start(void)
{
APP_ERROR_CHECK(app_timer_start(m_mea_send_loop_timer_id,
APP_TIMER_TICKS(MEA_SEND_LOOP_INTERVAL), NULL));
}
/**
* @brief Stop measurement send timer
* - Charles KWON
*/
void mea_send_timer_stop(void)
{
APP_ERROR_CHECK(app_timer_stop(m_mea_send_loop_timer_id));
}
/**
* @brief Initialize measurement send timer
* - Charles KWON
*
* Creates the single-shot timer used for sequenced BLE transmission.
* Must be called during system initialization.
*/
void mea_send_timer_init(void)
{
APP_ERROR_CHECK(app_timer_create(&m_mea_send_loop_timer_id,
APP_TIMER_MODE_SINGLE_SHOT, mea_send_loop));
}