
#include <stdint.h>

#include "app_timer.h"
#include "io.h"
#include "app.h"
#include "ba.h"
#include "led.h"
#include "lmp.h"
#include "si7050.h"
#include "ble_nus.h"
#include "nrf_soc.h"
#include "nrf_gpio.h"
#include "mcp3425.h"

//Not used:
//#include "nrf.h"
//#include "charger.h"
//#include "blog.h"

enum 
{
  ERROR_CAL = -100,
  ERROR_PPM = -101
};

#define CAL_TIME      (60000)
#define WARM_TIME     (20000)
#define BREATHE_TIME  (10000)
#define DONE_TIME     (120000)
#define ADC_NRF       (0x00)
#define ADC_MCP       (0x01)
#define ADC_BOTH      (0X02)


//#define BURN_IN_SAMPLE_PERIOD (56*6*1000) //every 5.6 minutes -- 512 samples is 47.78 hours

static uint8_t m_app_mode;
static uint8_t adc_mode = ADC_NRF;
//static uint16_t m_app_show_blog_index;
//static uint16_t m_adc_max;
//static int m_ppm_result;

static void (*m_send_str)(const char * str);

#define APP_TIMER_TIMEOUT_TICKS 1667
#define APP_TIMER_MS_COUNT 50

static volatile uint32_t m_timer_msec;
static volatile uint32_t m_counter_msec;
static volatile uint16_t sample_count;
APP_TIMER_DEF(m_app_timer_id);

static void timeout_handler(void * context);
static void update_stream_adc();
//static void update_run_bac();
//static void update_run_bac_battery_percentage();
//static void update_run_bac_battery_voltage();
//static void update_run_battery_percentage();
static void manage_power(void);
static void tia_gain_inc();
static void tia_gain_dec();
static void tia_load_inc();
static void tia_load_dec();
static void ref_bias_inc();
static void ref_bias_dec();
static void sho_lmp_ref(void);
static void sho_lmp_tia(void);
static void sho_si_user(void);
static void sho_lmp_lock(void);
static void sho_lmp_stat(void);
static void sho_lmp_mode(void);

void app_init(void (*send_str)(const char*))
{
  app_timer_create(&m_app_timer_id, APP_TIMER_MODE_REPEATED, timeout_handler);
  app_timer_start(m_app_timer_id, APP_TIMER_TIMEOUT_TICKS, (void*)0);
  m_send_str = send_str;
  m_app_mode = APP_MANAGE_POWER;

//check to see if burn in is complete -- if it isn't -- start burning in
  /*#if BURN_IN_ENABLED != 0
  if( (blog_is_complete() == 0) )
  {
    m_app_mode = APP_START_BURN_IN;
  }
  #endif*/
}

void app_set_mode(uint8_t mode)
{
  /*if( (m_app_mode == APP_BURN_IN) || (m_app_mode == APP_START_BURN_IN) )
  {
    return;
  }*/
  m_app_mode = mode;
}

void app_ble_handler(uint8_t *p_data, uint16_t length)
{
  char reply[BLE_NUS_MAX_DATA_LEN] = {0};
  char strbuf[BLE_NUS_MAX_DATA_LEN] = {0};
  int tmp;
  uint16_t vref;
  memset(strbuf, 0, BLE_NUS_MAX_DATA_LEN);
  memset(reply, 0, BLE_NUS_MAX_DATA_LEN);
  memcpy(strbuf, p_data, length);

  if (strbuf[0] == 'a' && strbuf[1] == 'd' && strbuf[2] == 'c' && strbuf[3] != 0)
  {
    switch (strbuf[3])
    {
      case 'n':
        adc_mode = ADC_NRF;
        sprintf(reply, "ADC is NRF");
      m_send_str(reply);
      break;
      case 'm':
        adc_mode = ADC_MCP;
        sprintf(reply, "ADC is MCP");
        m_send_str(reply);
      break;
      case 'b':
        adc_mode = ADC_BOTH;
        sprintf(reply, "ADC is BOTH");
        m_send_str(reply);
      break;     
    }
  }
  else if( !strcmp(strbuf, "00") || !strcmp(strbuf, "adcq") )
  {
    switch (adc_mode)
    {
      case ADC_NRF:
        sprintf(reply, "T, NRF, CNT");
      break;
      case ADC_MCP:
        sprintf(reply, "T, CMP, CNT");
      break;
      case ADC_BOTH:
        sprintf(reply, "T, NRF, CMP, CNT");
      break;
    }
    m_send_str(reply);
    m_timer_msec = 0;
    m_counter_msec = 0;
    m_app_mode = APP_STREAM_ADC;
  } 
  else if( !strcmp(strbuf, "01") || !strcmp(strbuf, "stop") )
  {
    sprintf(reply, "stopped");
    m_send_str(reply);
    m_app_mode = APP_MANAGE_POWER;
    m_timer_msec = 0;
    sample_count = 0;
    //ba_set_sensor_enable(0);
    led_off();
  } 
  /*else if ( !strcmp(strbuf, "11") || !strcmp(strbuf, "bacq") ) 
  {
    m_timer_msec = 0;
    m_app_mode = APP_PRODUCTION_AVG_RUN;
  }*/ 
  /*else if (!strcmp(strbuf, "12") || !strcmp(strbuf, "ppmq") ) 
  {
    if( m_app_mode == APP_MANAGE_POWER )
    {
      m_app_mode = APP_START;
    } 
    else 
    {
      //can't start again right now
      m_send_str("send stop first");
    }
  }*/ 
  /*else if( !strcmp(strbuf, "22") || !strcmp(strbuf, "batt%q") ) 
  {
    m_timer_msec = 0;
    m_app_mode = APP_PRODUCTION_BATT_PERC;
  }*/
  /*else if (!strcmp(strbuf, "111") || !strcmp(strbuf, "battvq") ) 
  {
    m_timer_msec = 0;
    m_app_mode = APP_PRODUCTION_AVG_RUN_W_BATT_VOLT;
  }*/
  /*else if (!strcmp(strbuf, "112") || !strcmp(strbuf, "bac,battvq") ) 
  {
    m_timer_msec = 0;
    m_app_mode = APP_PRODUCTION_AVG_RUN_W_BATT_PERC;
  }*/
  /*else if( !strcmp(strbuf, "sleep") )
  {
    m_app_mode = APP_SLEEP;
  }*/
  /*else if( !strcmp(strbuf, "blogq") )
  {
   sprintf(reply, "blog:%d", blog_get_entries());
    m_send_str(reply);
    m_app_mode = APP_SHOW_BLOG;
    m_counter_msec = 0;
    m_timer_msec = 0;
    m_app_show_blog_index = 0;
  }*/
  /*else if( !strcmp(strbuf, "battq") )
  {
    sprintf(reply, "batt:%d:%d", charger_get_batt_voltage(), charger_is_active());
    m_send_str(reply);
  }*/
  else if( !strcmp(strbuf, "scale1") )
  {
    ba_set_adc_mode(BA_ADC_SCALING_INPUT_ONE_THIRD);
    m_send_str("one third scale");
  }
  else if( !strcmp(strbuf, "scale2") )
  {
    ba_set_adc_mode(BA_ADC_SCALING_INPUT_TWO_THIRDS);
    m_send_str("two thirds scale");
  } 
  else if( !strcmp(strbuf, "scale3") )
  {
    ba_set_adc_mode(BA_ADC_FULL_SCALE);
    m_send_str("full scale");
  } 
  /*else if( !strcmp(strbuf, "avg") )
  {
    ba_set_avg_mode(BA_AVG_MODE_AVG);
    m_send_str("avg mode");
  } 
  else if( !strcmp(strbuf, "raw") )
  {
    ba_set_avg_mode(BA_AVG_MODE_RAW);
    m_send_str("raw mode");
  } 
  else if( !strcmp(strbuf, "sum") )
  {
    ba_set_avg_mode(BA_AVG_MODE_SUM);
    m_send_str("sum mode");
  }*/
  /*else if( !strcmp(strbuf, "ledq") )
  {
    led_flash(500);
  }*/ 
  else if ( !strcmp(strbuf, "versionq") ) 
  {
    sprintf(reply, "%s %s", VERSION_DATE, VERSION_TIME);
    m_send_str(reply);
  } 
  /*else if( strbuf[0] =='v' ) 
  {
    tmp = atoi(&strbuf[1]);
    //sscanf(strbuf, "v%i", &tmp);
    vref = ba_vref_target();
    ba_set_vref_target(tmp);
    sprintf(reply, "vref=%d->%d", vref, ba_vref_target());
    m_send_str(reply);
  }*/
  else if (strbuf[0] == 't') 
  {
    uint32_t errorcode;
    int8_t powers[] = {-40,-30,-20,-16,-12,-8,-4,0,3,4};
    int numpowers = sizeof(powers)/sizeof(int8_t);
    tmp = atoi(&strbuf[1]);
    if (tmp >= numpowers)
    {
      sprintf(reply,"Value must be less than %d",numpowers);
      m_send_str(reply);
      return;
    }
    errorcode = sd_ble_gap_tx_power_set(powers[tmp]);
    if (errorcode == NRF_SUCCESS)
    {
      sprintf(reply,"TX: %d dBm",powers[tmp]);
      m_send_str(reply);
      return;
    } 
    else 
    {
      sprintf(reply,"TX %d dBm failed",powers[tmp]);
      m_send_str(reply);
      return;
    }
  }
  /*
  else if (strbuf[0] == 'i' && strbuf[1] == '2' && strbuf[2] == 'c' && strbuf[3] == 'l')
  {
    nrf_gpio_cfg_output(8);
    nrf_gpio_pin_clear(8);
    nrf_gpio_cfg_output(9);
    nrf_gpio_pin_clear(9);
    m_send_str("i2c lines are set high");
  } 
  else if (strbuf[0] == 'i' && strbuf[1] == '2' && strbuf[2] == 'c' && strbuf[3] == 'h')
  {
    nrf_gpio_cfg_output(8);
    nrf_gpio_pin_set(8);
    nrf_gpio_cfg_output(9);
    nrf_gpio_pin_set(9);
    m_send_str("i2c lines are set high");
  }
  */
  else if (strbuf[0] == 'l' && strbuf[1] == 'm' && strbuf[2] == 'p' && strbuf[4] =='q')
  {
    nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enable lmp twi io
    switch (strbuf[3])
    {
      case 't':
        sho_lmp_tia(); 
        break;
      case 'r':
        sho_lmp_ref();
        break;
      case 'm':
        sho_lmp_mode();
        break;
      case 'l':
        sho_lmp_lock();
        break;
      case 's':
        sho_lmp_stat();
      break;
    }
  }
  else if (strbuf[0] == 'l' && strbuf[1] == 'm' && strbuf[2] == 'p')
  {
    if (strbuf[3] != 'l' && strbuf[3] != 'u' && strbuf[3] != 'g' && strbuf[3] != 'h')
    {
      tmp = strbuf[4] & 0x0F;
      if (strbuf[4] >'9')
        tmp += 9;
      if (strbuf[5] >= '0')
      {
        tmp = tmp << 4 | (strbuf[5] & 0x0F);
        if (strbuf[5] > '9')
          tmp += 9;
      }
     nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enble lmp twi io
    }
    switch (strbuf[3])
    {
    case 't':
        lmp_unlock();
        sho_lmp_tia();
        lmp_write_tiacn(tmp & 0x1F);
        sho_lmp_tia();
        lmp_lock();
        break;
      case 'r':
        lmp_unlock(); 
        sho_lmp_ref();
        lmp_write_refcn(tmp);
        sho_lmp_ref();
        lmp_lock();
 	break;
      case 'm':
        sho_lmp_mode();
        lmp_write_modecn(tmp & 0x87);
        sho_lmp_mode();
        break;
      case 'l':
        sho_lmp_lock();
        lmp_lock();
        sho_lmp_lock();
        break;
      case 'u':
        sho_lmp_lock();
        lmp_unlock();
        sho_lmp_lock();
        break;
      case 'g':
        lmp_enable();
        sprintf(reply, "LMP_ENA_WR: 0x01");
        m_send_str(reply);
        break;
      case 'h':
        lmp_disable();
        sprintf(reply, "LMP_ENA_WR: 0x00");
        m_send_str(reply);
      break;
    }
    nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enble lmp twi io
  }
  else if (strbuf[0] == 's' && strbuf[1] == 'i' && strbuf[2] == 't' && strbuf[3] == 'q')
  {
    sprintf(reply, "SI_TMP_RD: %u", si_rd_temp_hold());
    m_send_str(reply);
  }
 else if (strbuf[0] == 's' && strbuf[1] == 'i' && strbuf[2] == 'u' && strbuf[3] =='q')
  {
    sho_si_user();
  }
  else if (strbuf[0] == 's' && strbuf[1] == 'i' && strbuf[2] == 'u' && strbuf[3] >= '0')
  {
    tmp = strbuf[3] & 0x0F;
    if (strbuf[3] >'9')
      tmp += 9;
    if (strbuf[4] >= '0')
    {
      tmp = tmp << 4 | (strbuf[4] & 0x0F);
      if (strbuf[4] > '9')
        tmp += 9;
    }
    sho_si_user();
    si_wr_user(tmp & 0x81);
    sho_si_user();
  }
  else if (strbuf[0] == 'b')
  {
    switch(strbuf[1])
    {
      case 'g':
        if (strbuf[2] == 'u')
          tia_gain_inc();
        else if (strbuf[2] == 'd')
          tia_gain_dec();
      break;
      case 'l':
        if (strbuf[2] == 'u')
          tia_load_inc();
        else if (strbuf[2] == 'd')
          tia_load_dec();
      break;
      case 'b':
        if (strbuf[2] == 'u')
          ref_bias_inc();
        else if (strbuf[2] == 'd')
          ref_bias_dec();
      break;
    }
  }
  else if (!strcmp(strbuf, "mcpi"))
  {
    mcp_init();
    sprintf(reply, "MCP INIT");
    m_send_str(reply);
  }
  else if (!strcmp(strbuf, "mcpd"))
  {
    uint32_t sample_config = mcp_rd();
    uint16_t temp = (uint16_t) sample_config;
    uint16_t sample = ((temp & 0xFF00) >> 8) | ((temp & 0x00FF) << 8);
    sprintf(reply, "MCP ADC: %d,%d",temp, sample);
    m_send_str(reply);
  }
  else if (!strcmp(strbuf, "mcpc"))
  {
    uint32_t sample_config = mcp_rd();
    uint8_t config = (uint8_t) (sample_config >> 16);
    sprintf(reply, "MCP CONFIG: %x", config);
    m_send_str(reply);
  }
}
void app_update()
{
  //int ppm = 0;
  char buffer[20];
  uint16_t sample;
  int i;
  //int tmp;
  switch(m_app_mode) 
  {
    case APP_STREAM_ADC:
      update_stream_adc();
    break;
    /*case APP_START:
      led_flash(1000);
      ba_init_ppm();
      m_timer_msec = 0;
      m_counter_msec = 0;
      m_app_mode = APP_CAL;
      m_adc_max = 0;
    break;*/
    /*case APP_CAL:
      if( m_counter_msec >= 250 )
      {
        m_counter_msec = 0;
        ba_init_ppm();
        sample = ba_get_ppm_sample();
        if( (sample >= 550) || (m_timer_msec > CAL_TIME) )
        {
          m_timer_msec = 0;
          m_counter_msec = 0;
          ba_init_ppm();
          m_app_mode = APP_WARMUP;
        }
        sprintf(buffer, "cal:-1:%d",sample);
        m_send_str(buffer);
      }
    break;*/
    /*case APP_WARMUP:  //take 4 samples per second for 30 seconds
      if( m_counter_msec >= 250 )
      {
        m_counter_msec = 0;
        sample = ba_get_ppm_sample();//take a sample
        if( sample > m_adc_max )
        {
          m_adc_max = sample;
        }
        sprintf(buffer, "warm:%ld:%d",(WARM_TIME - m_timer_msec)/1000+1,sample);
        m_send_str(buffer);
        if( m_timer_msec >= WARM_TIME )
        {
          m_app_mode = APP_BREATH;
          led_flash(250);
          m_timer_msec = 0;
        }
      }
    break;*/
    /*case APP_BREATH:
      if( m_counter_msec >= 250 )
      {
        m_counter_msec = 0;
        sample = ba_get_ppm_sample();
        if( sample > m_adc_max )
        {
          m_adc_max = sample;
        }
        if ( (ba_is_ppm_done() == 0) && (m_timer_msec < BREATHE_TIME*2) )
        {
          sprintf(buffer, "breathe:%ld:%d",(BREATHE_TIME-m_timer_msec)/1000+1,sample);
          m_send_str(buffer);
        }
        else 
        {
          m_app_mode = APP_DONE;
          led_flash(2000);
          m_timer_msec = 0;
          ppm = ba_calc_ppm_bac();
          if( ppm < 0 )
          {
            ppm = 0;
          }
          m_ppm_result = ppm;
        }
      }
    break;*/
    /*case APP_DONE:
      if( m_counter_msec >= 250 )
      {
        m_counter_msec = 0;
        //stop here, do the PPM calc and the PPM to BAC calculation
        sprintf(buffer, "done:%ld:%i:%d",(DONE_TIME - m_timer_msec)/1000+1, m_ppm_result, m_adc_max);
        m_send_str(buffer);
      }
      if( m_timer_msec > DONE_TIME )
      {
        led_off();
        m_app_mode = APP_MANAGE_POWER;
        m_timer_msec = 0;
      }
    break;*/
    /*case APP_PRODUCTION_AVG_RUN: update_run_bac(); 
    break;*/
    /*case APP_PRODUCTION_BATT_PERC: update_run_battery_percentage(); 
    break;*/
    /*case APP_PRODUCTION_AVG_RUN_W_BATT_VOLT: update_run_bac_battery_voltage();  
    break;*/
    /*case APP_PRODUCTION_AVG_RUN_W_BATT_PERC: update_run_bac_battery_percentage(); 
    break;*/
    case APP_MANAGE_POWER:
      //check for the charger connection
      //ba_set_sensor_enable(false);
      manage_power();
    break;
    /*case APP_START_BURN_IN:
      //turn on the power to the sensor
      m_timer_msec = 0;
      ba_set_sensor_enable(1);
      m_counter_msec = 0;
      m_timer_msec = 0;
      led_flash(3000);
      m_app_mode = APP_BURN_IN;
    break;*/
    /*case APP_BURN_IN:
      if( m_timer_msec >= BURN_IN_SAMPLE_PERIOD )
      { //log a new value every three minutes
        m_timer_msec = 0;
        sample = ba_read_sensor();
        blog_set_entry(sample);
        tmp = -1;
        if( (blog_current_entry() % 10) == 0 )
        {
          tmp = blog_save();
        }
        if( blog_is_complete() )
        {
          led_off();
          ba_set_sensor_enable(0);
          m_app_mode = APP_MANAGE_POWER;
          if( tmp == -1 )
          {
            tmp = blog_save();
          }
          NVIC_SystemReset();
        }
        sprintf(buffer, "burn:%d,%d,%d", blog_current_entry(), sample, tmp);
        m_send_str(buffer);
      }
      if( m_counter_msec >= 1000 )
      {
        m_counter_msec = 0;
        sprintf(buffer, "T:%ld\n", m_timer_msec);
        m_send_str(buffer);
      }
    break;*/
    /*case APP_SHOW_BLOG:
      if( m_counter_msec >= 100 )
      {
        m_counter_msec = 0;
        for(i=0; i < 6; i++)
        {
          if( m_app_show_blog_index < blog_get_entries() )
          {
            sprintf(buffer, "burn[%d]=%d", m_app_show_blog_index, blog_get(m_app_show_blog_index));
            m_send_str(buffer);
          }
          else 
          {
            m_app_mode = APP_MANAGE_POWER;
            break;
          }
          m_app_show_blog_index++;
        }
      }
    break;*/
    default:
      //ba_set_sensor_enable(false);
      manage_power();
    break;
  }
}

void timeout_handler(void * context)
{
  m_timer_msec += APP_TIMER_MS_COUNT;
  m_counter_msec += APP_TIMER_MS_COUNT;
}
void update_stream_adc()
{
  char buffer[BLE_NUS_MAX_DATA_LEN] = {0};
  float temp;
  uint16_t nrf_adc = 0;
  uint32_t mcp_sample_config = 0;
  uint16_t mcp_adc_temp = 0;
  uint16_t mcp_adc = 0;

  //ba_set_sensor_enable(true);
  if( m_counter_msec > 500 )
  {
    //RAR, modified to return temp from SI in Deg C, adc in counts
    m_counter_msec = 0;
    sample_count += 1;
    temp = ((si_rd_temp_hold() * 175.72) / 65536) - 46.85;
  if (adc_mode == ADC_NRF)
    {
      nrf_adc = ba_read_sensor();
      sprintf(buffer, "%-4.1f, %-5d, %-5d", temp, nrf_adc, sample_count);
    }
    else if (adc_mode == ADC_MCP)
    {
      mcp_sample_config = mcp_rd();
      mcp_adc_temp = (uint16_t) (mcp_sample_config);
      mcp_adc = ((mcp_adc_temp & 0xFF00) >> 8) | ((mcp_adc_temp & 0x00FF) << 8);
      sprintf(buffer, "%-4.1f, %-5d, %-5d", temp, mcp_adc, sample_count);
    }
    else if (adc_mode == ADC_BOTH)
    {
      nrf_adc = ba_read_sensor();
      mcp_sample_config = mcp_rd();
      mcp_adc_temp = (uint16_t) (mcp_sample_config);
      mcp_adc = ((mcp_adc_temp & 0xFF00) >> 8) | ((mcp_adc_temp & 0x00FF) << 8);
      sprintf(buffer, "%-4.1f,%-5d,%-5d,%-5d", temp, nrf_adc, mcp_adc, sample_count);
    }
    m_send_str(buffer);
  }
}

/*void update_run_bac()
{

  char buffer[20];
  uint16_t tmp;
  timer++;
  tmp = ba_read_sensor();
  if (timer <= THREE_SECONDS_20_MS) 
  {
    ba_set_sensor_enable(true);
    firstVal = tmp;
    minVal = tmp;
  } 
  else if (timer > THREE_SECONDS_20_MS && timer <= SEVEN_SECONDS_20_MS) 
  {
    if (tmp < minVal)
    {
      minVal = tmp;
    }
  } 
  else 
  {
    val = (float) firstVal / (float) minVal;
    if (minVal > firstVal)
    {
      bac = 0.0;
    } 
    else 
    {
      bac = (0.4283 * val) - 0.4283;
    }
    snprintf((char *) adc_array, BLE_NUS_MAX_DATA_LEN, "%.2f", bac);
    tmp = ba_calc_bac(firstVal, minVal) *1000;
    snprintf(buffer, BLE_NUS_MAX_DATA_LEN, "%i.%02i", (int)tmp/1000, ((int)tmp % 1000)/10);
    m_send_str(buffer);	// Transmits BAC Measurement
    m_app_mode = POWER_MANAGE;
  }
}*/

/*static void update_run_bac_battery_percentage()
{
  timer++;
  tmp = ba_read_sensor();
  if (timer <= THREE_SECONDS_20_MS) 
  {
    ba_set_sensor_enable(true);
    firstVal = tmp;
    minVal = tmp;
  } 
  else if (timer > THREE_SECONDS_20_MS && timer <= SEVEN_SECONDS_20_MS) 
  {
    if (tmp < minVal)
    {
      minVal = tmp;
    }
  } 
  else 
  {
    val = (float) firstVal / (float) minVal;
    if (minVal > firstVal)
    {
      bac = 0.0;
    } 
    else 
    {
      bac = (0.4283 * val) - 0.4283;
    }
    snprintf(buffer, BLE_NUS_MAX_DATA_LEN, "%.2f", bac);
    m_send_str(buffer); // Transmits BAC Measurement
    bat = BatteryVoltage * 0.0035; // 3.6V/1023 = 0.003519
    // if (bat >= 1.2 && bat < 1.4)
    // batperc = 10;
    if (bat >= 1.6 && bat < 1.8)
    {
      batperc = 25;
    } else if (bat >= 1.8 && bat < 1.9)
    {
      batperc = 50;
    } else if (bat >= 1.9 && bat < 2.0)
    {
      batperc = 75;
    } else if (bat >= 2.0)
    {
      batperc = 100;
    }
    snprintf(buffer, BLE_NUS_MAX_DATA_LEN, "%.0f", batperc);
    m_send_str(buffer); // Transmits BATTTERY % Measurement
    m_app_mode = POWER_MANAGE;
  }
}*/

/*void update_run_bac_battery_voltage()
{
  timer++;
  tmp = ba_read_sensor();
  if (timer <= THREE_SECONDS_20_MS) 
  {
    ba_set_sensor_enable(true);
    firstVal = tmp;
    minVal = tmp;
  } 
  else if (timer > THREE_SECONDS_20_MS && timer <= SEVEN_SECONDS_20_MS) 
  {
    if (tmp < minVal)
    {
      minVal = tmp;
    }
  } else 
  {
    val = (float) firstVal / (float) minVal;
    if (minVal > firstVal)
    {
      bac = 0.0;
    } else 
    {
      bac = (0.4283 * val) - 0.4283;
    }
    snprintf((char *) adc_array, BLE_NUS_MAX_DATA_LEN, "%.2f", bac);
    ba_print_bac(buffer, ba_calc_bac(firstVal, minVal) );
    m_send_str(buffer);	// Transmits BAC Measurement
    bat = BatteryVoltage * 0.0035;  // 3.6V/1023 = 0.003519
    snprintf(buffer, BLE_NUS_MAX_DATA_LEN, "%.1f", bat);
    m_send_str(buffer);	// Transmits BATTTERY Voltage Measurement
    m_app_mode = POWER_MANAGE;
  }
}*/

//void update_run_battery_percentage();

/*void update_run_battery_percentage()
{
  timer++;
  if (timer <= THREE_SECONDS_20_MS) 
  {
    bat = BatteryVoltage * 0.0035;  // 3.6V/1023 = 0.003519
    //if (bat >= 1.2 && bat < 1.4)
      //batperc = 10;
    if (bat >= 1.6 && bat < 1.8)
    {
      batperc = 25;
    } 
    else if (bat >= 1.8 && bat < 1.9)
    {
      batperc = 50;
    } else if (bat >= 1.9 && bat < 2.0)
    {
      batperc = 75;
    } else if (bat >= 2.0)
    {
      batperc = 100;
    }
    snprintf(buffer, BLE_NUS_MAX_DATA_LEN, "%.0f", batperc);
    m_send_str(buffer);	// Transmits BATTTERY % Measurement
    m_app_mode = POWER_MANAGE;
  }
}*/

static void manage_power(void)
{
  uint32_t err_code = sd_app_evt_wait();
  APP_ERROR_CHECK(err_code);
}

// RAR - Bump LMP REF BIAS up or down (1,2,4,6,8,10,12,14,16,18,20,22,24 %)
//up...
void ref_bias_inc(void)
{
  nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enable lmp twi io
  lmp_unlock();                             //unlock tia and ref registers
  sho_lmp_ref();                            //show ref setting before change
  uint8_t lmpr_set = lmp_read_refcn();      //read ref settings
  uint8_t lmpr_bias = lmpr_set & 0x0F;      //extract bias 
  if (lmpr_bias != 0x0C)                    //if bias not max
  {
    lmpr_bias += 0x01;                      //increment bias
    lmpr_set  &= 0xF0;                      //mask previous bias
    lmpr_set  |= lmpr_bias;                 //replace bias value
    lmp_write_refcn(lmpr_set);              //write new ref settings
  }
  sho_lmp_ref();                            //show ref setting after change
  lmp_lock();                               //lock tia and ref registers
  nrf_gpio_pin_set(LMP_ENABLE_PIN);         //disable lmp io
}
//down...
void ref_bias_dec(void)
{
  nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enable lmp twi io
  lmp_unlock();                             //unlock tia and ref registers
  sho_lmp_ref();                            //show ref setting before change
  uint8_t lmpr_set = lmp_read_refcn();      //read ref settings
  uint8_t lmpr_bias = lmpr_set & 0x0F;      //extract bias 
  if (lmpr_bias != 0x00)                    //if bias not min
  {
    lmpr_bias -= 0x01;                      //decrement bias
    lmpr_set  &= 0xF0;                      //mask previous bias
    lmpr_set  |= lmpr_bias;                 //replace bias
    lmp_write_refcn(lmpr_set);              //write new ref settings
  }
  sho_lmp_ref();                            //show ref setting after change
  lmp_lock();                               //lock tia and ref registers
  nrf_gpio_pin_set(LMP_ENABLE_PIN);         //disable lmp io
}

// RAR - Bump TIA GAIN R up or down (EXT(499K),2.73K,3.48K,6.90K,13.62K,32.71K,96.74,205.71K)
//up...
static void tia_gain_inc(void)
{
  nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enable lmp twi io
  lmp_unlock();                             //unlock tia amd ref registers
  sho_lmp_tia();                            //show tia setting before change
  uint8_t tia_set = lmp_read_tiacn();       //read tia settings
  uint8_t tia_gain = tia_set & 0x1C;        //extract gain
  if (tia_gain != 0x1C)                     //if gain not max
  {
    tia_gain += 0x04;                       //increment gain
    tia_set  &= 0xE3;                       //mask previous gain
    tia_set  |= tia_gain;                   //replace gain
    lmp_write_tiacn(tia_set);               //write new tia settings
  }
  sho_lmp_tia();                            //show tia setting after change
  lmp_lock();                               //lock tia and ref registers
  nrf_gpio_pin_set(LMP_ENABLE_PIN);         //disable lmp io
}
//down...
void tia_gain_dec(void)
{
  nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enable lmp twi io
  lmp_unlock();                             //unlock tia and ref registers
  sho_lmp_tia();                            //show tia setting before change
  uint8_t tia_set = lmp_read_tiacn();       //read tia settings
  uint8_t tia_gain = tia_set & 0x1C;        //extract gain
  if (tia_gain != 0x00)                     //if gain not min
  {
    tia_gain -= 0x04;                       //decrement gain
    tia_set  &= 0xE3;                       //mask previous gain
    tia_set  |= tia_gain;                   //replace gain
    lmp_write_tiacn(tia_set);               //write new tia settings
  }
  sho_lmp_tia();                            //show tia setting after change
  lmp_lock();                               //lock tia and ref registers
  nrf_gpio_pin_set(LMP_ENABLE_PIN);         //disable lmp io
}

// RAR - Bump TIA LOAD R up or down (10, 33 50 100)
//up...
void tia_load_inc(void)
{
  nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enable lmp twi io
  lmp_unlock();                             //unlock tia and ref registers
  sho_lmp_tia();                            //show tia setting before change
  uint8_t tia_set = lmp_read_tiacn();       //read tia settings
  uint8_t tia_load = tia_set & 0x03;        //extract load
  if (tia_load != 0x03)                     //if load not max
  {
    tia_load += 0x01;                       //increment load
    tia_set  &= 0xFC;                       //mask previous load
    tia_set  |= tia_load;                   //replace load
    lmp_write_tiacn(tia_set);               //write new tia settings
  }
  sho_lmp_tia();                            //show tia setting after change
  lmp_lock();                               //lock tia and ref registers
  nrf_gpio_pin_set(LMP_ENABLE_PIN);         //disable lmp io
}
//down...
void tia_load_dec(void)
{
  nrf_gpio_pin_clear(LMP_ENABLE_PIN);       //enable lmp twi io
  lmp_unlock();                             //unlock tia and ref registers
  sho_lmp_tia();                            //show tia setting before change
  uint8_t tia_set = lmp_read_tiacn();       //read tia settings
  uint8_t tia_load = tia_set & 0x03;        //extract load
  if (tia_load != 0x00)                     //if load not min
  {
    tia_load -= 0x01;                       //decrement load
    tia_set  &= 0xFC;                       //mask previous load
    tia_set  |= tia_load;                   //replace load
    lmp_write_tiacn(tia_set);               //write new tia settings
  }
  sho_lmp_tia();                            //show tia setting after change
  lmp_lock();                               //lock tia and ref registers
  nrf_gpio_pin_set(LMP_ENABLE_PIN);         //disable lmp io
}

// RAR - Show TIA Settings (Gain R, Load R)
static void sho_lmp_tia(void)
{
  char temp[25]       = {0};
  char g_str[8][10]   = {"499.0K","2.73K","3.48K","6.90K",
                         "13.6K","32.7K","96.7K","205.7K"};
  char r_str[4][10]   = {"10 OHM","33 OHM","50 OHM","100 OHM"};
  uint8_t tia_set     = lmp_read_tiacn();
  uint8_t g_i         = ((tia_set & 0x1c) >> 2);
  uint8_t r_i         = (tia_set & 0x03);
  sprintf(temp, "%s, %s", g_str[g_i], r_str[r_i]);
  m_send_str(temp);
 }

// RAR - Show LMP Reference settings (Source, Zero, Polarity, Bias %)
void sho_lmp_ref(void)
{
  char temp[25]       = {0};
  char s_str[2][6]    = {"INT","EXT"};
  char z_str[4][6]    = {"20%","50%","67%","BYP"};
  char p_str[2][6]    = {"NEG","POS"};
  char b_str[14][6]   = {"0%","1%","2%","4%","6%","8%","10%",
                         "12%","14%","16%","18%","20%","22%","24%"};
  uint8_t ref_set = lmp_read_refcn();
  uint8_t s_i     = ((ref_set & 0x80) >> 7);
  uint8_t z_i     = ((ref_set & 0x60) >> 5);
  uint8_t p_i     = ((ref_set & 0x10) >> 4);
  uint8_t b_i     = (ref_set & 0x0F);
  sprintf(temp, "%s, %s, %s, %s", s_str[s_i], z_str[z_i], p_str[p_i], b_str[b_i]);
  m_send_str(temp);
}

// RAR - Show LMP Mode Settings (FET state, Op Mode)
void sho_lmp_mode(void)
{
  char temp[25]       = {0};
  char f_str[2][10]   = {"FET OFF","FET ON"};
  char m_str[8][10]   = {"SLEEP","2LEAD","STDBY","3LEAD",
                         "INVALID!","INVALID!","TEMP-T","TEMP+T"};
  uint8_t mode_set    = lmp_read_modecn();
  uint8_t f_i         = ((mode_set & 0x80) >> 7);
  uint8_t m_i         = (mode_set & 0x07);
  sprintf(temp, "%s, %s", f_str[f_i], m_str[m_i]);
  m_send_str(temp);
}

// RAR - Show LMP Lock state
void sho_lmp_lock(void)
{
  char temp[25]       = {0};
  char l_str[2][10]   = {"UNLOCKED","LOCKED"};
  uint8_t lock        = lmp_read_lock();
  uint8_t l_i         = lock & 0x01;
  sprintf(temp, "%s", l_str[l_i]);
  m_send_str(temp);
}

// RAR - Show LMP IO state
void sho_lmp_stat(void)
{
  char temp[25]       = {0};
  char s_str[2][10]   = {"NOT READY","READY"};
  uint8_t stat        = lmp_read_status();
  uint8_t s_i         = stat & 0x01;
  sprintf(temp, "%s", s_str[s_i]);
  m_send_str(temp);
}

void sho_si_user(void)
{
  char temp[25]       = {0};
  char v_str[2][10]   = {"VOLTS OK","VOLTS LOW"};
  char r_str[4][10]   = {"14 BITS", "12 BITS", "13 BITS", "11 BITS"};
  uint8_t user        = (lmp_read_status());
  uint8_t v_i         = (user & 0x40) >> 6;
  uint8_t r_i         = (user & 0x01) | ((user & 0x80) >> 6);
  sprintf(temp, "%s, %s", v_str[v_i], r_str[r_i]);
  m_send_str(temp);
}
