/*******************************************************************************
 TEST medi50  Dec 23
 if(resetCount>=3) return true; 3 COUNT 25/11/04 CJ CHUN
 
 ******************************************************************************/

#include "sdk_common.h"
#include <stdlib.h>			
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nrf.h"
#include "boards.h"
#include "app_error.h"
#include "nrf_drv_saadc.h"
#include "app_timer.h"
#include "nrfx_gpiote.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "nrf_delay.h"
#include "ada2200_spi.h"
#include "battery_saadc.h"
#include "ble_nus.h"
#include "meas_pd_voltage_simple.h"
#include "main.h"
#include <cmd_parse.h>
//#include "fstorage.h"
#include "power_control.h"
#include "debug_print.h"

#define PD_REF_VOLTAGE_IN_MILLIVOLTS   		600.0f                                     /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define PD_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 PD_ADC_RES_10BITS             		1023.0f                                    /**< Maximum digital value for 10-bit ADC conversion. */



// remark for avoid warning error
// static nrf_saadc_value_t pressure_adc_buf[2];   // chanul 2ea for simple each 1ea



/**@brief Macro to convert the result of ADC conversion in millivolts.



 *
 * @param[in]  ADC_VALUE   ADC result.
 *
 * @retval     Result converted to millivolts.
 */
#define PD_VOUT_IN_MILLI_VOLTS(ADC_VALUE)\
				(((((ADC_VALUE) * PD_REF_VOLTAGE_IN_MILLIVOLTS) / PD_ADC_RES_10BITS) * PD_PRE_SCALING_COMPENSATION)*2)

#define SIM_SAMPLES_IN_BUFFER 		128
static nrf_saadc_value_t pd_adc_buf[2][SIM_SAMPLES_IN_BUFFER];

uint8_t simple_samples_in_buffer = 8;

#define SAMPLE_CYCLE_CNT 		128

float simple_cycle_buff[SAMPLE_CYCLE_CNT]; /* For Cycle-8, Cycle-16, Cycle-24, Cycle-32 */ 
float simple_cycle_send_buff = 0.0f;
int16_t bi_simple_cycle_buff[SAMPLE_CYCLE_CNT];
uint16_t ubi_simple_cycle_buff[SAMPLE_CYCLE_CNT];/* For Cycle-8, Cycle-16, Cycle-24, Cycle-32 */ 
int16_t bi_simple_cycle_send_buff = 0;
extern uint8_t ble_bin_buffer[BLE_NUS_MAX_DATA_LEN]	;
static nrf_ppi_channel_t	m_ppi_channel;
extern uint8_t m_pd_adc_cnt;
extern char		ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
extern bool lock_check;
extern which_cmd_t cmd_type_t;
#if FEATURE_CHAMBER_AUTO_TEST
extern auto_meas_mode_t auto_test_mode;
#endif
extern volatile bool ble_connection_st;
extern bool ble_got_new_data;
bool con_single;
uint8_t rep = 0;
extern uint8_t resetCount;  //cj add
//APP_TIMER_DEF(m_simple_send_loop_timer_id);

//#define SIMPLE_SEND_LOOP_INTERVAL 100

#define PATTERN_LENGTH 8
#define NORMAL_AMPLITUDE_THRESHOLD  40  // values above ~50 in magnitude are normal

bool is_lockin_pattern(int16_t *pattern, uint8_t length) {
    int16_t avg_amplitude = 0;
    uint8_t positive_count = 0;
    uint8_t negative_count = 0;

    // Calculate average amplitude and count positives/negatives
    for (uint8_t i = 0; i < length; i++) {
        int16_t value = pattern[i];
        avg_amplitude += abs(value);

        if (value >= 0) {
            positive_count++;
        } else {
            negative_count++;
        }
    }

    avg_amplitude /= length;
    DBG_PRINTF("lock avg amplitude=%d,p_c=%d,n_c=%d\r\n\r\n", avg_amplitude,positive_count,negative_count);
    // Check conditions:
    // - Large enough average amplitude
    // - Exactly 1 positive and (length - 1) negative values
		if(resetCount>=3) return true;
		
    if (avg_amplitude > NORMAL_AMPLITUDE_THRESHOLD &&
        positive_count == 1 && negative_count == (length - 1)) {
        return true;  // lock-in (normal) pattern
    } else {
			  
        return false; // abnormal pattern
    }
}


void simple_ppi_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    uint32_t gpiote_event_addr = nrf_drv_gpiote_in_event_addr_get(ADA2200_SYNCO_PIN);	
    uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          gpiote_event_addr,
                                          saadc_sample_task_addr);
    APP_ERROR_CHECK(err_code);
}


void simple_ppi_uninit(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_uninit();
    APP_ERROR_CHECK(err_code);
}


void simple_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    APP_ERROR_CHECK(err_code);
}


void simple_sampling_event_disable(void)
{
	ret_code_t err_code = nrf_drv_ppi_channel_disable(m_ppi_channel);
	APP_ERROR_CHECK(err_code);
}


/**@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.
 */
static void simple_voltage_handler(nrf_drv_saadc_evt_t const * p_event)	/* PD Voltage reading */
{
	ret_code_t err_code;

    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {	
		
			err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, simple_samples_in_buffer);
			APP_ERROR_CHECK(err_code);

			for(uint8_t i = 0; i < simple_samples_in_buffer; i++) {
				bi_simple_cycle_buff[i] = p_event->data.done.p_buffer[i];
			}

		simple_mesurement_stop();

		simple_cycle_send_buff = 0;
		bi_simple_cycle_send_buff = 0;

		for(uint8_t i = 0; i < simple_samples_in_buffer; i++) {
			
			simple_cycle_buff[i] = PD_VOUT_IN_MILLI_VOLTS(bi_simple_cycle_buff[i]);
			//simple_cycle_buff[i] = simple_cycle_buff[i] * -1;
			bi_simple_cycle_send_buff += bi_simple_cycle_buff[i];
			simple_cycle_send_buff += simple_cycle_buff[i];
			}
		}


		if(con_single==true)
		{ 
			//return;				
		}	
		
		else
			{
		if(cmd_type_t == CMD_UART) {
			DBG_PRINTF("Th%f\r\n\r\n", simple_cycle_send_buff);
			DBG_PRINTF( "MOD: %f,%f,%f,%f,%f,%f,%f,%f\r\n", simple_cycle_buff[0], simple_cycle_buff[1], simple_cycle_buff[2], simple_cycle_buff[3], simple_cycle_buff[4]
			, simple_cycle_buff[5], simple_cycle_buff[6], simple_cycle_buff[7]);
		} else if(cmd_type_t == CMD_BLE) {	
//			if(lock_check == true){
 			DBG_PRINTF("Th%f\r\n\r\n", simple_cycle_send_buff);
			DBG_PRINTF( "MOD: %f,%f,%f,%f,%f,%f,%f,%f\r\n", simple_cycle_buff[0], simple_cycle_buff[1], simple_cycle_buff[2], simple_cycle_buff[3], simple_cycle_buff[4]
			, simple_cycle_buff[5], simple_cycle_buff[6], simple_cycle_buff[7]);
				
			for(uint8_t i = 0; i < simple_samples_in_buffer; i++) {
				ubi_simple_cycle_buff[i] = (uint16_t)bi_simple_cycle_buff[i];
			}
			
			format_data(ble_bin_buffer, "rsh:",  ubi_simple_cycle_buff, (m_pd_adc_cnt*2));
									
						binary_tx_handler(ble_bin_buffer,(m_pd_adc_cnt+2));
					
		}
		
		
	
	}
		if (lock_check == true)	{
			if (is_lockin_pattern(bi_simple_cycle_buff,8) == false){
		
		if(device_reactivated() == 0) 
		{
			DBG_PRINTF("reset!!\r\n");
		}
					
	}
	resetCount++;
	DBG_PRINTF("Reset Count :%d \r\n",resetCount);
}
  else
	{
	}
}




void simple_adc_init(void)
{
	static nrfx_saadc_config_t default_config;
	default_config.resolution 			= (nrf_saadc_resolution_t)NRFX_SAADC_CONFIG_RESOLUTION;	/* Resolution is 10bits */
	default_config.oversample 			= (nrf_saadc_oversample_t)NRFX_SAADC_CONFIG_OVERSAMPLE;	/* Over Sampling Disabled */
	default_config.interrupt_priority 	= NRFX_SAADC_CONFIG_IRQ_PRIORITY;						/* Interrupt Priority is 0(Highest) */
	default_config.low_power_mode 		= NRFX_SAADC_CONFIG_LP_MODE;							/* Low Power Mode is Disabled */

	static nrf_saadc_channel_config_t config;
	config.resistor_p 	= NRF_SAADC_RESISTOR_DISABLED;
	config.resistor_n 	= NRF_SAADC_RESISTOR_DISABLED;
	config.gain			= NRF_SAADC_GAIN1_6;
	config.reference	= NRF_SAADC_REFERENCE_INTERNAL;
	config.acq_time		= NRF_SAADC_ACQTIME_3US;
	config.mode			= NRF_SAADC_MODE_DIFFERENTIAL;
	config.burst		= NRF_SAADC_BURST_DISABLED;
	config.pin_p		= (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN0);
	config.pin_n		= (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN1);
	
	ret_code_t err_code = nrf_drv_saadc_init(&default_config, simple_voltage_handler);
	APP_ERROR_CHECK(err_code);

	err_code = nrf_drv_saadc_channel_init(0, &config);
	APP_ERROR_CHECK(err_code);
	if(con_single==true){
	err_code = nrf_drv_saadc_buffer_convert(pd_adc_buf[0], SIM_SAMPLES_IN_BUFFER);
	APP_ERROR_CHECK(err_code);
	}
	else{
	err_code = nrf_drv_saadc_buffer_convert(pd_adc_buf[0], simple_samples_in_buffer);
	APP_ERROR_CHECK(err_code);
	}
	
}


void simple_adc_uninit(void)
{
	nrf_drv_saadc_uninit();
	nrf_drv_saadc_channel_uninit(0);
}


void simple_irq_init(void){
    ret_code_t err_code;

	/* Initialize int pin */
	if (!nrfx_gpiote_is_init())
	{
	  err_code = nrfx_gpiote_init();
	  APP_ERROR_CHECK(err_code);
	}

    nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
    in_config.pull = NRF_GPIO_PIN_PULLDOWN;

    err_code = nrfx_gpiote_in_init(ADA2200_SYNCO_PIN, &in_config, NULL);
    APP_ERROR_CHECK(err_code);

    nrfx_gpiote_in_event_enable(ADA2200_SYNCO_PIN, true);
}


void simple_irq_uninit(void){

	nrfx_gpiote_in_event_disable(ADA2200_SYNCO_PIN);
	nrfx_gpiote_in_uninit(ADA2200_SYNCO_PIN);
}


void simple_mesurement_start(void){

	battery_timer_stop();
	nrf_delay_ms(10);
	memset(simple_cycle_buff, 0, SAMPLE_CYCLE_CNT);
	nrf_delay_ms(10);
	simple_irq_init();
	nrf_delay_ms(10);
	simple_adc_init();
	nrf_delay_ms(10);
	simple_ppi_init();
	nrf_delay_ms(10);
	simple_sampling_event_enable();
	nrf_delay_ms(10);
}


void simple_mesurement_stop(void){

	if(ble_connection_st == 1) {
		battery_timer_start();
	}


	simple_sampling_event_disable();
	simple_adc_uninit();
	simple_ppi_uninit();
	simple_irq_uninit();
}
