/******************************************************************************* TEST medi50 Dec 23 ******************************************************************************/ #include "sdk_common.h" #include #include #include #include #include #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 #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)); }