Files
firmware-test/project/ble_peripheral/ble_app_bladder_patch/full_agc.c
Charles Kwon a8ba31871e Initial commit: MT firmware project
- BLE peripheral applications
- dr_piezo and bladder_patch projects

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 17:26:39 +09:00

1034 lines
37 KiB
C

/*******************************************************************************
TEST medi50 Dec 23
******************************************************************************/
#include "sdk_common.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "nrf.h"
#include "boards.h"
#include "app_error.h"
#include "nrf_drv_saadc.h"
#include "nrfx_gpiote.h" //
#include "nrf_drv_ppi.h" //
#include "app_timer.h"
#include "nrf_drv_timer.h"
#include "nrf_delay.h"
//#include "fstorage.h"
#include "measurements.h"
#include "main_timer.h"
#include "battery_saadc.h"
#include "main.h"
#include "full_agc.h"
#include "mcp4725_i2c.h"
#include "ad5272_i2c.h"
#include "ble_nus.h"
#include "cat_interface.h"
#include <cmd_parse.h>
#include "debug_print.h"
#include "i2c_manager.h" //add cj 25/10/12
#if FEATURE_AGC_FLOAT
#define FULL_AGC_REF_VOLTAGE_IN_MILLIVOLTS 600.0f /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define FULL_AGC_PRE_SCALING_COMPENSATION 6.0f /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
#define FULL_AGC_ADC_RES_10BITS 1024.0f /**< Maximum digital value for 10-bit ADC conversion. */
#else
#define FULL_AGC_REF_VOLTAGE_IN_MILLIVOLTS 600 /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define FULL_AGC_PRE_SCALING_COMPENSATION 6 /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
#define FULL_AGC_ADC_RES_10BITS 1024 /**< Maximum digital value for 10-bit ADC conversion. */
#endif
#define LED_NUM 24
/**@brief Macro to convert the result of ADC conversion in millivolts.
*
* @param[in] ADC_VALUE ADC result.
*
* @retval Result converted to millivolts.
*/
#define FULL_AGC_VOUT_IN_MILLI_VOLTS(ADC_VALUE)\
((((ADC_VALUE) * FULL_AGC_REF_VOLTAGE_IN_MILLIVOLTS) / FULL_AGC_ADC_RES_10BITS) * FULL_AGC_PRE_SCALING_COMPENSATION)
#define DAC_MIN 125
#define DAC_MAX 1365
extern uint16_t led_pd_dac_v[LED_NUM];
extern volatile bool processing;
uint8_t full_agc_LED_list[48];
uint8_t full_agc_PD_list[1];
//uint8_t full_agc_LED_a[25] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
//uint8_t full_agc_LED_a[24] = {0,1,2,3,4,5,10,11,12,13,14,15,20,21,22,23,24,25,30,31,32,33,34,35};
uint8_t full_agc_LED_a[24] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
uint8_t full_agc_PD_a[1] = {0};
//const uint8_t full_agc_LED_b[24] = {40,41,42,43,44,45,50,51,52,53,54,55,60,61,62,63,64,65,70,71,72,73,74,75};
const uint8_t full_agc_LED_b[24] = {24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47};
uint8_t full_agc_PD_b[1] = {1};
//const uint8_t full_agc_LED_c[48] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47};
//uint8_t full_agc_PD_c[1] = {2};
static int8_t LED_NO = 24;
static int8_t pd_no = -1;
static int8_t led_no = -1;
#define SAMPLES_IN_BUFFER 4
static nrf_saadc_value_t full_agc_buf[2][SAMPLES_IN_BUFFER];
//static nrf_saadc_value_t full_agc_buf; //origin
bool full_agc_a_start = false;
bool full_agc_b_start = false;
bool full_agc_c_start = false;
bool full_agc_completed = false;
APP_TIMER_DEF(m_full_agc_loop_timer_id);
#define FULL_AGC_LOOP_INTERVAL 2 //4
APP_TIMER_DEF(m_full_agc_send_timer_id);
//
#if FEATURE_DELAY
#define FULL_AGC_SEND_INTERVAL 500
#else
#define FULL_AGC_SEND_INTERVAL 100
#endif
#if FEATURE_AGC_FLOAT
static double agc_read_h = 0;
static double agc_read_l = 0;
static double agc_read_ref = 0;
static double m_full_agc_in_milli_volts = 0.0f;
#else
static uint16_t agc_read_h = 0;
static uint16_t agc_read_l = 0;
static uint16_t agc_read_ref = 0;
static uint16_t m_full_agc_in_milli_volts = 0;
#endif
static uint16_t cnt_js = 0;// skip when 1~3
static bool agc_mode = false;
static uint16_t array_buff[48] = {0,};
static uint16_t idx = 0;
static uint8_t order_cnt =0;
//uint16_t agc_read_v[PD_NUM][LED_NUM] = {0,};
//uint16_t agc_read_v[LED_NUM] = {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* PD0 */
//000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000};
uint16_t agc_read_v[LED_NUM] = {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000}; /* PD0 */ //24 cj edit 25/10/30
uint16_t agc_A_0[LED_NUM] = {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* PD0 */
};
uint16_t agc_A_1[LED_NUM] = {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* PD1 */
};
uint16_t agc_A_2[LED_NUM] = {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* MOD1 */
};
uint16_t agc_B_0[LED_NUM] = {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* PD1\0 */
};
uint16_t agc_B_1[LED_NUM] = {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* PD1 */
};
uint16_t agc_B_2[LED_NUM] = {1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000,1000, 1000, 1000, 1000, 1000, 1000, /* MOD1 */
};
extern which_cmd_t cmd_type_t;
char agc_tx_buffer[BLE_NUS_MAX_DATA_LEN];
char agc_tx_buffer_r[BLE_NUS_MAX_DATA_LEN];
bool agc_ble_send_order = false;
extern volatile bool ble_connection_st;
uint8_t agc_bin_buffer[BLE_NUS_MAX_DATA_LEN];
//static nrf_ppi_channel_t m_ppi_channel; //
/**@brief Function for handling the ADC interrupt.
*
* @details This function will fetch the conversion result from the ADC, convert the value into
* percentage and send it to peer.
*/
//void format_data(uint16_t *buffer, const char *tag, const uint16_t *data_array, size_t length) {
// // Store the tag as ASCII values in the buffer
// size_t tag_length = strlen(tag);
// uint16_t tag1 = (uint16_t)(tag[0])+(uint16_t)(tag[1]*256);
// uint16_t tag2 = (uint16_t)(tag[2])+(uint16_t)(tag[3]*256);
//// for (size_t i = 0; i < tag_length && i < 4; i++) { // Adjust according to the length of the tag
//// buffer[i] = (uint16_t)tag[i]; // Store ASCII value of each character
//// }
// buffer[0] = tag1;
// buffer[1] = tag2;
//
// // Append data values after the tag
// for (size_t i = 0; i < length; i++) {
// buffer[i +2] = data_array[i];
// }
//}
static void full_agc_voltage_handler(nrf_drv_saadc_evt_t const * p_event) /* ADC_GAIN reading */
{
uint16_t min_data = 0;
//uint8_t re_i =0;
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
uint32_t err_code;
// adc_result[0] = p_event->data.done.p_buffer[0];
// adc_result[1] = p_event->data.done.p_buffer[1];
// adc_result[2] = p_event->data.done.p_buffer[2];
// adc_result[3] = p_event->data.done.p_buffer[3];
//adc_result = p_event->data.done.p_buffer;
err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
// DBG_PRINTF("check\r\n");
APP_ERROR_CHECK(err_code);
/*m_full_agc_in_milli_volts = FULL_AGC_VOUT_IN_MILLI_VOLTS(adc_result);
DBG_PRINTF("millivolt,%d,", FULL_AGC_VOUT_IN_MILLI_VOLTS(adc_result));
DBG_PRINTF("%d,", FULL_AGC_VOUT_IN_MILLI_VOLTS(adc_result1));
DBG_PRINTF("%d,", FULL_AGC_VOUT_IN_MILLI_VOLTS(adc_result2));
DBG_PRINTF("%d,", FULL_AGC_VOUT_IN_MILLI_VOLTS(adc_result3));*/
for(uint8_t i=0; i < SAMPLES_IN_BUFFER ; i++) {
min_data+=p_event->data.done.p_buffer[i];
}
//adc_result[0]=p_event->data.done.p_buffer;
//DBG_PRINTF("%d,%d\r\n", FULL_AGC_VOUT_IN_MILLI_VOLTS(p_event->data.done.p_buffer[0]),FULL_AGC_VOUT_IN_MILLI_VOLTS(p_event->data.done.p_buffer[SAMPLES_IN_BUFFER-1]));
m_full_agc_in_milli_volts = (uint16_t)(FULL_AGC_VOUT_IN_MILLI_VOLTS(min_data)*0.25);
//m_full_agc_in_milli_volts = min_data;
//DBG_PRINTF("%d\r\n", m_full_agc_in_milli_volts); //
/*if(m_full_agc_in_milli_volts<500 )
{
m_full_agc_in_milli_volts = FULL_AGC_VOUT_IN_MILLI_VOLTS(adc_result);
cnt_js++;
DBG_PRINTF("millivolt2 %d\r\n", m_full_agc_in_milli_volts);
}*/
}
}
/**
* 2025-12-09 redesigned by Charles KWON
* @brief Full AGC (Automatic Gain Control) Measurement State Machine
*
* Performs LED-PD gain calibration across all 48 LED channels.
* Called periodically by app_timer.
*
* Process:
* 1. Turn on LED and PD sequentially
* 2. Measure high/low voltage with AGC mode toggle
* 3. Calculate DAC value and store gain
* 4. Move to next LED-PD pair
* 5. Send results via BLE/UART and save to EEPROM
*
* LED-PD Configuration:
* - LED_NO (48): Total LED channels
* - PD_NO (2): Photodiode channels per LED
*/
static void full_agc_measurement(void)
{
/* State flags for multi-step processing */
static bool mode_behind = false;
static bool sampling_behind = false;
static bool agc_processing_behind = false;
/* DAC calculation variables */
static double Vref = 3.3f; /* Reference voltage (same as Vdd) */
static double dac_value_h = 0.0f; /* High mode DAC value */
static double dac_value_l = 0.0f; /* Low mode DAC value */
#if FEATURE_DETAIL_VALUE_AGC
static double avg_num = 0.0f; /* Average for statistics */
#endif
static uint16_t dac_reg_h = 0; /* High mode DAC register */
static uint16_t dac_reg_l = 0; /* Low mode DAC register */
static uint16_t max_num = 0; /* Maximum difference value */
static uint16_t zero_count = 0; /* Zero count for statistics */
static uint16_t sum_num = 0; /* Sum for average calculation */
static uint16_t diff_volt = 0; /* Voltage difference (H - L) */
/* Delay counter for non-blocking wait */
static int delay_ticks_counter = 0;
/*========================================
* Delay Wait Check (Non-blocking)
*========================================*/
if (delay_ticks_counter > 0) {
delay_ticks_counter--;
// DBG_PRINTF("COUNTER ~108ms before part B...\r\n");
return;
}
/*========================================
* Initial State: First LED-PD Setup
*========================================*/
if (led_no == -1) {
led_no = 0;
pd_no = 0;
led_on(full_agc_LED_list[led_no]);
pd_on(full_agc_PD_list[pd_no]);
// nrf_delay_ms(10);
DBG_PRINTF("LED-1\r\n");
delay_ticks_counter = 100; /* Wait ~100 ticks for stabilization */
DBG_PRINTF("Finished part A. Pausing for ~108ms before part B...\r\n");
return;
}
/*========================================
* Main Processing: LED 0-47
*========================================*/
if ((led_no >= 0) && (led_no <= 47)) {
/*----------------------------------------
* Step 1: AGC Mode Toggle
*----------------------------------------*/
if (mode_behind == false) {
mode_behind = true;
/* Toggle AGC mode (high/low) */
if (agc_mode == false) {
agc_mode = true;
} else if (agc_mode == true) {
agc_mode = false;
}
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("agc_mode [%d]\r\n", agc_mode);
#endif
AGC_GAIN_SW(agc_mode);
return;
}
/*----------------------------------------
* Step 2: ADC Sampling
*----------------------------------------*/
if (sampling_behind == false) {
sampling_behind = true;
ret_code_t err_code = nrf_drv_saadc_sample();
// DBG_PRINTF("sample_cnt %d\r\n", cnt_js);
cnt_js++;
APP_ERROR_CHECK(err_code);
return;
}
/*----------------------------------------
* Step 3: AGC Processing
*----------------------------------------*/
if (agc_processing_behind == false) {
/*--- High Mode Processing ---*/
if (agc_mode == true) {
/* Check for zero reading - resample if needed */
if (m_full_agc_in_milli_volts == 0) {
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("<1>ReSampling +++++ mode = %d, led_no = %d(%d), pd_no = %d(%d)\r\n",
agc_mode, led_no, full_agc_LED_list[led_no], pd_no, full_agc_PD_list[pd_no]);
#endif
agc_mode = false;
mode_behind = false;
sampling_behind = false;
return;
}
/* Store high mode reading */
agc_read_h = m_full_agc_in_milli_volts;
m_full_agc_in_milli_volts = 0.0f;
/* Calculate DAC value: Dn = (Vout/Vref) x 4096 */
dac_value_h = (((agc_read_h / Vref) * 4096.0f) / 1000.0f); /* Unit: mV */
dac_reg_h = (uint16_t)(dac_value_h + 0.5f); /* Round to nearest integer */
// DBG_PRINTF("PD %d,%d,%d,%d\r\n", full_agc_LED_list[led_no], full_agc_PD_list[pd_no], agc_read_h, dac_reg_h);
#if FEATURE_FOR_SCOPE
/* Scope trigger pulse */
nrf_gpio_pin_set(ADC_CLK_18);
nrf_gpio_pin_clear(ADC_CLK_18);
nrf_gpio_pin_set(ADC_CLK_18);
nrf_gpio_pin_clear(ADC_CLK_18);
#endif
/* Store DAC value to gain array */
// AGC range limiting (commented out)
// if (dac_reg_h < DAC_MIN) {
// dac_reg_h = DAC_MIN;
// } else if (dac_reg_h > DAC_MAX) {
// dac_reg_h = DAC_MAX;
// }
led_pd_dac_v[full_agc_LED_list[led_no]] = dac_reg_h;
#if FEATURE_DETAIL_VALUE_AGC
#if FEATURE_AGC_FLOAT
DBG_PRINTF("mode = %d, led_no = %d(%d), pd_no = %d(%d), \t%lf(mV)->DAC %d\r\n",
agc_mode, led_no, full_agc_LED_list[led_no], pd_no, full_agc_PD_list[pd_no],
agc_read_h, dac_reg_h);
#else
DBG_PRINTF("mode = %d, led_no = %d(%d), pd_no = %d(%d), \t%d(mV)->DAC %d\r\n",
agc_mode, led_no, full_agc_LED_list[led_no], pd_no, full_agc_PD_list[pd_no],
agc_read_h, dac_reg_h);
#endif
#endif
/* Apply gain to MCP4725 DAC */
sw_i2c_init_once(); // cj add
pd_gain_set(full_agc_LED_list[led_no]);
mode_behind = false;
sampling_behind = false;
/*--- Low Mode Processing ---*/
} else if (agc_mode == false) {
/* Check for zero reading - resample if needed */
if (m_full_agc_in_milli_volts == 0) {
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("<2>ReSampling +++++ mode = %d, led_no = %d(%d), pd_no = %d(%d)\r\n",
agc_mode, led_no, full_agc_LED_list[led_no], pd_no, full_agc_PD_list[pd_no]);
#endif
agc_mode = true;
mode_behind = false;
sampling_behind = false;
// DBG_PRINTF("sample_cnt2 %d\r\n", cnt_js);
return;
}
/* Store low mode reading */
agc_read_l = m_full_agc_in_milli_volts;
m_full_agc_in_milli_volts = 0.0f;
/* Calculate DAC value: Dn = (Vout/Vref) x 4096 */
dac_value_l = (((agc_read_l / Vref) * 4096.0f) / 1000.0f); /* Unit: mV */
dac_reg_l = (uint16_t)(dac_value_l + 0.5f); /* Round to nearest integer */
#if FEATURE_FOR_SCOPE
/* Scope trigger pulse */
nrf_gpio_pin_set(ADC_CLK_18);
nrf_gpio_pin_clear(ADC_CLK_18);
#endif
/* Store low mode value */
agc_read_v[full_agc_LED_list[led_no]] = dac_reg_l;
/* Calculate voltage difference (high - low) */
agc_read_ref = fabsf(agc_read_h - agc_read_l);
diff_volt = (uint16_t)(agc_read_ref + 0.5f);
// DBG_PRINTF("PD2 %d,%d,%d,%d\r\n", full_agc_LED_list[led_no], full_agc_PD_list[pd_no], agc_read_l, dac_reg_l);
/* Store difference for analysis */
array_buff[idx] = diff_volt;
idx++;
#if FEATURE_DETAIL_VALUE_AGC
#if FEATURE_AGC_FLOAT
DBG_PRINTF("mode = %d, led_no = %d(%d), pd_no = %d(%d), \t%f(mV), \t\t\tDiff = %d\r\n\r\n",
agc_mode, led_no, full_agc_LED_list[led_no], pd_no, full_agc_PD_list[pd_no],
agc_read_l, diff_volt);
#else
DBG_PRINTF("mode = %d, led_no = %d(%d), pd_no = %d(%d), \t%d(mV), \t\t\tDiff = %d\r\n\r\n",
agc_mode, led_no, full_agc_LED_list[led_no], pd_no, full_agc_PD_list[pd_no],
agc_read_l, diff_volt);
#endif
#endif
agc_processing_behind = true;
}
return;
}
/*----------------------------------------
* Step 4: Reset and Advance to Next
*----------------------------------------*/
mode_behind = false;
sampling_behind = false;
agc_processing_behind = false;
agc_mode = false;
dac_value_h = 0.0f;
dac_reg_h = 0;
diff_volt = 0;
/*--- Advance PD Channel ---*/
if (pd_no < PD_NO - 1) {
pd_no++;
pd_on(full_agc_PD_list[pd_no]);
// nrf_delay_ms(4);
// DBG_PRINTF("PD-1\r\n");
}
/*--- Advance LED Channel ---*/
else if (pd_no >= PD_NO - 1) {
pd_no = 0;
if (led_no < LED_NO - 1) {
led_no++;
led_on(full_agc_LED_list[led_no]);
pd_on(full_agc_PD_list[pd_no]);
// nrf_delay_ms(100);
/* Add delay at LED package boundary (every 6 LEDs) */
if (full_agc_LED_list[led_no] % 6 == 0) {
delay_ticks_counter = 5;
DBG_PRINTF("LED_PACKAGE\r\n");
}
DBG_PRINTF("LED+1\r\n");
}
/*========================================
* Final State: All LEDs Completed
*========================================*/
else if (led_no >= LED_NO - 1) {
pd_no = -1;
led_no = -1;
#if FEATURE_DETAIL_VALUE_AGC
/* Print LED-PD gain array */
DBG_PRINTF("\r\nLED-PD Gain Array =\r\n");
for (uint16_t i = 0; i < PD_NUM; i++) {
for (uint16_t j = 0; j < LED_NUM; j++) {
DBG_PRINTF("%d,\t", led_pd_dac_v[i][j]);
}
DBG_PRINTF("\r\n");
}
DBG_PRINTF("\r\n");
#endif
/*--- Check BLE connection ---*/
if (ble_connection_st == 0) {
full_agc_send_timer_stop();
full_agc_end();
DBG_PRINTF("Full AGC STOP 1\r\n");
}
/*--- A Mode -> B Mode Transition ---*/
else if (full_agc_a_start == true) {
full_agc_a_start = false;
full_agc_b_start = true;
full_agc_start();
}
/*--- B Mode Complete ---*/
else if (full_agc_b_start == true) {
full_agc_b_start = false;
// full_agc_c_start = true;
// full_agc_start();
full_agc_completed = true;
full_agc_end();
// C Mode (commented out)
// else if (full_agc_c_start == true) {
// full_agc_c_start = false;
// full_agc_completed = true;
// full_agc_end();
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("Full AGC, Completed!\r\n");
#endif
/*--- Calculate Statistics ---*/
for (uint16_t i = 0; i < idx; i++) {
#if FEATURE_DETAIL_VALUE_AGC
if (i % 25 == 0) DBG_PRINTF("\r\n");
DBG_PRINTF("%d, \t", array_buff[i]);
#endif
sum_num += array_buff[i];
if (array_buff[i] == 0) zero_count++;
if (max_num < array_buff[i]) {
max_num = array_buff[i];
}
}
#if FEATURE_DETAIL_VALUE_AGC
avg_num = (double)sum_num / idx;
DBG_PRINTF("\r\n\r\n");
DBG_PRINTF("Max_number = %d\r\n", max_num);
DBG_PRINTF("Avg_number = %.2f\r\n", avg_num);
DBG_PRINTF("Zero_count = %d\r\n", zero_count);
DBG_PRINTF("Zero_Percentage = %.2f%%\r\n", (double)zero_count / idx * 100);
DBG_PRINTF("\r\n");
#endif
/* Clear buffer */
for (uint16_t i = 0; i < 48; i++) {
array_buff[i] = 0;
}
#if FEATURE_DETAIL_VALUE_AGC
avg_num = 0.0f;
#endif
max_num = 0;
zero_count = 0;
sum_num = 0;
idx = 0;
#if FEATURE_DETAIL_VALUE_AGC
/* Print low mode values */
DBG_PRINTF("agc_read_v = \r\n");
for (uint16_t i = 0; i < PD_NUM; i++) {
for (uint16_t j = 0; j < LED_NUM; j++) {
DBG_PRINTF("%d, \t", agc_read_v[i][j]);
}
DBG_PRINTF("\r\n");
}
DBG_PRINTF("\r\n");
#endif
/*========================================
* Send Results via UART or BLE
*========================================*/
if (cmd_type_t == CMD_UART) {
/* UART output */
DBG_PRINTF("Tagc, ");
for (uint16_t j = 0; j < LED_NUM; j++) {
DBG_PRINTF("%d, ", led_pd_dac_v[j]);
}
DBG_PRINTF("\r\n");
// Extended UART output (commented out)
// for (uint16_t i = 0; i < PD_NUM; i++) {
// DBG_PRINTF("Tagc-B%d, ", i);
// for (uint16_t j = 0; j < LED_NUM; j++) {
// DBG_PRINTF("%d, ", agc_read_v[i][j]);
// }
// DBG_PRINTF("\r\n");
// }
// DBG_PRINTF("\r\n");
} else if (cmd_type_t == CMD_BLE) {
/* BLE output */
battery_timer_stop();
/* Copy gain values to transmit buffers */
for (uint16_t j = 0; j < LED_NO; j++) {
agc_A_0[j] = led_pd_dac_v[j];
}
for (uint16_t j = 0; j < LED_NO; j++) {
agc_A_1[j] = led_pd_dac_v[j + LED_NO];
}
// Text format output (commented out)
// sprintf(agc_tx_buffer, "send_process\r\n\r\n");
// sprintf(agc_tx_buffer, "Tagc\t%d,\t%d,\t...");
// sprintf(agc_tx_buffer, "Tagc-A0,\t%d,\t%d,\t...");
// data_tx_handler(agc_tx_buffer);
// sprintf(agc_tx_buffer, "Tagc-A1,\t%d,\t%d,\t...");
// data_tx_handler(agc_tx_buffer);
/* Binary format: "rag:" + 48 x uint16 */
format_data(agc_bin_buffer, "rag:", led_pd_dac_v, 96);
binary_tx_handler(agc_bin_buffer, 50);
/* Debug: Print buffer hex */
for (uint16_t i = 0; i < 50; i++) {
DBG_PRINTF("%02X ", agc_bin_buffer[i]);
}
DBG_PRINTF("\r\n");
/* Debug: Print values */
DBG_PRINTF("Tagc,");
for (uint16_t j = 0; j < LED_NUM; j++) {
DBG_PRINTF("%d, ", led_pd_dac_v[j]);
}
/* Save to EEPROM */
eeprom_control(OFF);
eeprom_write_uint16_array(0x0480, led_pd_dac_v, 48);
nrf_delay_ms(10);
// eeprom_control(ON);
// full_agc_send_timer_start();
DBG_PRINTF("AGC_Gain Write!\r\n");
}
}
}
}
}
}
void full_agc_start(void)
{
cnt_js=0;
if(full_agc_a_start == true) {
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("\r\n===== Full_AGC_A start ====================\r\n");
DBG_PRINTF("LED : ");
#endif
full_agc_PD_list[0] = full_agc_PD_a[0];
//memcpy(full_agc_LED_a, full_agc_LED_a_init, sizeof(full_agc_LED_a_init));
for(uint8_t i =0; i < LED_NO; i++) {
full_agc_LED_list[i] = full_agc_LED_a[i];
//full_agc_LED_list[i] = i+1;
//#if FEATURE_DETAIL_VALUE_AGC
// DBG_PRINTF("%d ", full_agc_LED_list[i]);
//#endif
}
// DBG_PRINTF("led\r\n ");
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("\r\n");
DBG_PRINTF("PD : ");
#endif
//for(uint8_t i =0; i < PD_NO; i++) {
// full_agc_PD_list[i] = full_agc_PD_a[i];
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("%d ", full_agc_PD_list[i]);
#endif
// }
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("\r\n\r\n");
#endif
}
else if(full_agc_b_start == true) {
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("\r\n===== Full_AGC_B start ====================\r\n");
DBG_PRINTF("LED : ");
#endif
for(uint8_t i =0; i < LED_NO; i++) {
full_agc_LED_list[i] = full_agc_LED_b[i];
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("%d ", full_agc_LED_list[i]);
#endif
// DBG_PRINTF("%d ", full_agc_LED_list[i]);
//#endif
}
// DBG_PRINTF("b_led\r\n ");
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("\r\n");
DBG_PRINTF("PD : ");
#endif
full_agc_PD_list[0] = full_agc_PD_b[0];
#if FEATURE_DETAIL_VALUE_AGC
DBG_PRINTF("\r\n\r\n");
#endif
}
pd_no = -1;
led_no = -1;
}
void full_agc_end(void)
{
//
// for(uint8_t i =0; i < LED_NO; i++) {
// full_agc_LED_list[i] = 0;
// }
hw_i2c_init_once();
full_agc_timer_stop();
full_agc_uninit();
battery_timer_start();
led_off(99);
pd_off(99);
DBG_PRINTF("end_process\r\n\r\n");
processing = false;
//config_save();
}
void full_agc_adc_init(void)
{
ret_code_t err_code = nrf_drv_saadc_init(NULL, full_agc_voltage_handler);
APP_ERROR_CHECK(err_code);
nrf_saadc_channel_config_t config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6); /* FSA5157P6X Voltage Output Measurement */
err_code = nrf_drv_saadc_channel_init(0, &config);
APP_ERROR_CHECK(err_code);
// err_code = nrf_drv_saadc_buffer_convert(&full_agc_buf,SAMPLES_IN_BUFFER);
// APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_buffer_convert(full_agc_buf[0],SAMPLES_IN_BUFFER);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_buffer_convert(full_agc_buf[1],SAMPLES_IN_BUFFER);
APP_ERROR_CHECK(err_code);
}
void full_agc_uninit(void)
{
nrf_drv_saadc_uninit();
nrf_drv_saadc_channel_uninit(0);
}
void full_agc_loop(void * p_context) /* For x ms */
{
UNUSED_PARAMETER(p_context);
full_agc_measurement();
}
void full_agc_timer_start(void)
{
APP_ERROR_CHECK(app_timer_start(m_full_agc_loop_timer_id, APP_TIMER_TICKS(FULL_AGC_LOOP_INTERVAL), NULL));
}
void full_agc_timer_stop(void)
{
APP_ERROR_CHECK(app_timer_stop(m_full_agc_loop_timer_id));
}
void full_agc_timer_init(void)
{
APP_ERROR_CHECK(app_timer_create(&m_full_agc_loop_timer_id, APP_TIMER_MODE_REPEATED, full_agc_loop));
}
void full_agc_mesurement_start(void)
{
agc_ble_send_order = false;
full_agc_completed = false;
battery_timer_stop();
order_cnt =0;
full_agc_a_start = true;
for(uint8_t i =0; i < LED_NO; i++) {
DBG_PRINTF("%d ", full_agc_LED_list[i]);
}
DBG_PRINTF("led/r/n ");
full_agc_start();
nrf_delay_ms(5);
full_agc_adc_init();
nrf_delay_ms(5);
full_agc_timer_start();
}
void full_agc_send_loop(void * p_context) /* For x ms */
{
UNUSED_PARAMETER(p_context);
static bool send_step = false;
full_agc_send_timer_stop();
if(send_step == false) {
if(order_cnt >= 6) {
order_cnt = 0;
send_step = true;
}else if(order_cnt < 6) {
switch(order_cnt) {
case 0:
for(uint16_t j = 0; j < LED_NO; j++){
agc_A_0[j] = led_pd_dac_v[j];
agc_B_0[j] = agc_read_v[j];
}
break;
case 1:
for(uint16_t j = 0; j < LED_NO; j++){
agc_A_1[j] = led_pd_dac_v[LED_NO+j];
agc_B_1[j] = agc_read_v[LED_NO+j];
}
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
default:
DBG_PRINTF("ERR!!!, Out of range <1>\r\n");
break;
}
order_cnt++;
}
}else if(send_step == true) {
if(order_cnt >= 6) {
if(ble_connection_st == 1) {
battery_timer_start();
}
order_cnt = 0;
send_step = false;
return;
}else if(order_cnt < 3) {
if(agc_ble_send_order == false) {
switch(order_cnt){
case 0:
sprintf(agc_tx_buffer,"Tagc-A0,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d\r\n", agc_A_0[0], agc_A_0[1], agc_A_0[2], agc_A_0[3], agc_A_0[4], agc_A_0[5], agc_A_0[6], agc_A_0[7], agc_A_0[8], agc_A_0[9], agc_A_0[10], agc_A_0[11], agc_A_0[12], agc_A_0[13], agc_A_0[14], agc_A_0[15], agc_A_0[16], agc_A_0[17], agc_A_0[18], agc_A_0[19], agc_A_0[20], agc_A_0[21], agc_A_0[22], agc_A_0[23]);
break;
case 1:
break;
case 2:
sprintf(agc_tx_buffer, "Tagc-A1,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d\r\n", agc_A_1[0], agc_A_1[1], agc_A_1[2], agc_A_1[3], agc_A_1[4], agc_A_1[5], agc_A_1[6], agc_A_1[7], agc_A_1[8], agc_A_1[9], agc_A_1[10], agc_A_1[11], agc_A_1[12], agc_A_1[13], agc_A_1[14], agc_A_1[15], agc_A_1[16], agc_A_1[17], agc_A_1[18], agc_A_1[19], agc_A_1[20], agc_A_1[21], agc_A_1[22], agc_A_1[23]);
break;
case 3:
break;
case 4:
break;
case 5:
break;
// case 3:
// sprintf(agc_tx_buffer, "Tagc-B%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d\r\n", order_cnt, agc_B_0[0], agc_B_0[1], agc_B_0[2], agc_B_0[3], agc_B_0[4], agc_B_0[5], agc_B_0[6], agc_B_0[7], agc_B_0[8], agc_B_0[9], agc_B_0[10], agc_B_0[11], agc_B_0[12], agc_B_0[13], agc_B_0[14], agc_B_0[15], agc_B_0[16], agc_B_0[17], agc_B_0[18], agc_B_0[19], agc_B_0[20], agc_B_0[21], agc_B_0[22], agc_B_0[23], agc_B_0[24]);
// break;
//
// case 4:
// sprintf(agc_tx_buffer, "Tagc-B%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d\r\n", order_cnt, agc_B_1[0], agc_B_1[1], agc_B_1[2], agc_B_1[3], agc_B_1[4], agc_B_1[5], agc_B_1[6], agc_B_1[7], agc_B_1[8], agc_B_1[9], agc_B_1[10], agc_B_1[11], agc_B_1[12], agc_B_1[13], agc_B_1[14], agc_B_1[15], agc_B_1[16], agc_B_1[17], agc_B_1[18], agc_B_1[19], agc_B_1[20], agc_B_1[21], agc_B_1[22], agc_B_1[23], agc_B_1[24]);
// break;
//
// case 5:
// sprintf(agc_tx_buffer, "Tagc-B%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d\r\n", order_cnt, agc_B_2[0], agc_B_2[1], agc_B_2[2], agc_B_2[3], agc_B_2[4], agc_B_2[5], agc_B_2[6], agc_B_2[7], agc_B_2[8], agc_B_2[9], agc_B_2[10], agc_B_2[11], agc_B_2[12], agc_B_2[13], agc_B_2[14], agc_B_2[15], agc_B_2[16], agc_B_2[17], agc_B_2[18], agc_B_2[19], agc_B_2[20], agc_B_2[21], agc_B_2[22], agc_B_2[23], agc_B_2[24]);
// break;
default:
DBG_PRINTF("ERR!!!, Out of range <2>\r\n");
break;
}
if(ble_connection_st == 0) {
full_agc_end();
full_agc_send_timer_stop();
DBG_PRINTF("Full AGC STOP 2\r\n");
}
else{
data_tx_handler(agc_tx_buffer);
order_cnt++;
if(order_cnt == 10) {
agc_ble_send_order = true;
order_cnt = 0;
}
}
}else if(agc_ble_send_order == true) {
// switch(order_cnt){
// case 0:
// sprintf(agc_tx_buffer, "Tagc-B%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d\r\n", order_cnt, agc_B_0[0], agc_B_0[1], agc_B_0[2], agc_B_0[3], agc_B_0[4], agc_B_0[5], agc_B_0[6], agc_B_0[7], agc_B_0[8], agc_B_0[9], agc_B_0[10], agc_B_0[11], agc_B_0[12], agc_B_0[13], agc_B_0[14], agc_B_0[15], agc_B_0[16], agc_B_0[17], agc_B_0[18], agc_B_0[19], agc_B_0[20], agc_B_0[21], agc_B_0[22], agc_B_0[23], agc_B_0[24]);
// break;
//
// case 1:
// sprintf(agc_tx_buffer, "Tagc-B%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d\r\n", order_cnt, agc_B_1[0], agc_B_1[1], agc_B_1[2], agc_B_1[3], agc_B_1[4], agc_B_1[5], agc_B_1[6], agc_B_1[7], agc_B_1[8], agc_B_1[9], agc_B_1[10], agc_B_1[11], agc_B_1[12], agc_B_1[13], agc_B_1[14], agc_B_1[15], agc_B_1[16], agc_B_1[17], agc_B_1[18], agc_B_1[19], agc_B_1[20], agc_B_1[21], agc_B_1[22], agc_B_1[23], agc_B_1[24]);
// break;
//
// case 2:
// sprintf(agc_tx_buffer, "Tagc-B%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d,\t%d\r\n", order_cnt, agc_B_2[0], agc_B_2[1], agc_B_2[2], agc_B_2[3], agc_B_2[4], agc_B_2[5], agc_B_2[6], agc_B_2[7], agc_B_2[8], agc_B_2[9], agc_B_2[10], agc_B_2[11], agc_B_2[12], agc_B_2[13], agc_B_2[14], agc_B_2[15], agc_B_2[16], agc_B_2[17], agc_B_2[18], agc_B_2[19], agc_B_2[20], agc_B_2[21], agc_B_2[22], agc_B_2[23], agc_B_2[24]);
// break;
//
//
//
// default:
// DBG_PRINTF("ERR!!!, Out of range <2>\r\n");
// break;
// }
if(ble_connection_st == 0) {
full_agc_end();
full_agc_send_timer_stop();
//DBG_PRINTF("Full AGC STOP 3\r\n");
}
else{
// data_tx_handler(agc_tx_buffer);
order_cnt++;
}
}
}
}
if(ble_connection_st == 0) {
order_cnt = 0;
full_agc_send_timer_stop();
// DBG_PRINTF("Full AGC STOP 4\r\n");
}
else{
full_agc_send_timer_start();
}
}
void full_agc_send_timer_start(void)
{
APP_ERROR_CHECK(app_timer_start(m_full_agc_send_timer_id, APP_TIMER_TICKS(FULL_AGC_SEND_INTERVAL), NULL));
}
void full_agc_send_timer_stop(void)
{
APP_ERROR_CHECK(app_timer_stop(m_full_agc_send_timer_id));
}
void full_agc_send_timer_init(void)
{
APP_ERROR_CHECK(app_timer_create(&m_full_agc_send_timer_id, APP_TIMER_MODE_SINGLE_SHOT, full_agc_send_loop));
}