 ///
/// @file a2d.c
/// @authors k. headley
/// @date 01 jan 2019

/// General description of module here

/// @sa doxygen-examples.c for more examples of Doxygen markup


/////////////////////////
// Terms of use
/////////////////////////
/*
 Copyright Information
 
 Copyright 2002-2019 MBARI
 Monterey Bay Aquarium Research Institute, all rights reserved.
 
 Terms of Use
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version. You can access the GPLv3 license at
 http://www.gnu.org/licenses/gpl-3.0.html
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details
 (http://www.gnu.org/licenses/gpl-3.0.html)
 
 MBARI provides the documentation and software code "as is", with no warranty,
 express or implied, as to the software, title, non-infringement of third party
 rights, merchantability, or fitness for any particular purpose, the accuracy of
 the code, or the performance or results which you may obtain from its use. You
 assume the entire risk associated with use of the code, and you agree to be
 responsible for the entire cost of repair or servicing of the program with
 which you are using the code.
 
 In no event shall MBARI be liable for any damages, whether general, special,
 incidental or consequential damages, arising out of your use of the software,
 including, but not limited to, the loss or corruption of your data or damages
 of any kind resulting from use of the software, any prohibited use, or your
 inability to use the software. You agree to defend, indemnify and hold harmless
 MBARI and its officers, directors, and employees against any claim, loss,
 liability or expense, including attorneys' fees, resulting from loss of or
 damage to property or the injury to or death of any person arising out of the
 use of the software.
 
 The MBARI software is provided without obligation on the part of the
 Monterey Bay Aquarium Research Institute to assist in its use, correction,
 modification, or enhancement.
 
 MBARI assumes no responsibility or liability for any third party and/or
 commercial software required for the database or applications. Licensee agrees
 to obtain and maintain valid licenses for any additional third party software
 required.
 */

/////////////////////////
// Headers 
/////////////////////////
#include "a2d.h"
// temporary for debug
#include "ioserial.h"

/////////////////////////
// Macros
/////////////////////////

#define ADC_SEL ADC1_SEL

/////////////////////////
// Declarations 
/////////////////////////
typedef void (* adc_init_fn) (void);
typedef void (* adc_start_fn)(void);
typedef void (* adc_stop_fn)(void);
typedef uint16_t (* adc_conversion_result_buffer_get_fn)(uint16_t *buffer);
typedef uint16_t (* adc_conversion_result_get_fn)(void);
typedef bool (* adc_is_conversion_complete_fn)( void );
typedef void (* adc_channel_select_fn)( int channel );
typedef void (* adc_callback_fn)(void);
typedef void (* adc_tasks_fn)(void);

typedef struct adc_api_s{
    adc_init_fn init;
    adc_start_fn start;
    adc_stop_fn stop;
    adc_conversion_result_buffer_get_fn result_buffer;
    adc_conversion_result_get_fn result;
    adc_is_conversion_complete_fn conversion_complete;
    adc_channel_select_fn channel_select;
    adc_callback_fn callback;
    adc_tasks_fn tasks;
}adc_api_t;

typedef enum{ADC1_SEL=0,ADC2_SEL,ADC_COUNT}adc_sel_t;

/////////////////////////
// Imports
/////////////////////////

/////////////////////////
// Module Global Variables
/////////////////////////
adc_api_t adc_api[ADC_COUNT]=
{
    {
        ADC1_Initialize,ADC1_Start,ADC1_Stop,
             ADC1_ConversionResultBufferGet,
                ADC1_ConversionResultGet,
                ADC1_IsConversionComplete,
                (adc_channel_select_fn)ADC1_ChannelSelect,
                ADC1_CallBack,ADC1_Tasks
    }
    
//    {
//        ADC2_Initialize,ADC2_Start,ADC2_Stop,
//             ADC2_ConversionResultBufferGet,
//                ADC2_ConversionResultGet,
//                ADC2_IsConversionComplete,
//                (adc_channel_select_fn)ADC2_ChannelSelect,
//                ADC2_CallBack,ADC2_Tasks
//    }
};

float a2d_channel_div[A2D_CH_COUNT]={
    A2D_DIV_CH0,
    A2D_DIV_CH1,
    A2D_DIV_CH2
};

/////////////////////////
// Function Definitions
/////////////////////////




        
#ifdef WITH_ADC

int adRead(int chan) {
    int i, total = 0;
    UINT16 vals[16]={0};
 
    switch(chan){
        case A2D_CH0:
            adc_api[ADC_SEL].channel_select(ADC1_CHANNEL_AN11);
            break;
        case A2D_CH1:
            adc_api[ADC_SEL].channel_select(ADC1_CHANNEL_AN10);
            break;
       case A2D_CH2:
            adc_api[ADC_SEL].channel_select(ADC1_CHANNEL_AN8);
            break;
        default:
            break;
    }

    adc_api[0].start();
    Nop();
    Nop();
    Nop();
    adc_api[ADC_SEL].stop();
    while(!adc_api[ADC_SEL].conversion_complete()){
        for (i = 0; i < 16; i++) {      // average the 16 ADC value
            vals[i] = adc_api[ADC_SEL].result();
            total += vals[i];
         }
     }

    total = total >> 4;
    return (total);
}

/// scaled voltage reading
double adVolts(int chan, int num) {
    UINT32 total = 0;
    int i=0;
    double volts=0.0;
    
    if(chan>=0 && chan<A2D_CH_COUNT){
        for (i = 0; num > i; i++) {
            total += adRead(chan);
        }
        //the a2d_channel_div adjusts for input voltage divider
        volts = total * A2D_VREF * a2d_channel_div[chan]; 
        volts = volts / (num * 1024);
    }
    return (volts);
}


#else
#warning "WITH_ADC undefined - using adc stubs"
int adRead(int chan)
{
    return 0;
}


double adVolts(int chan, int num)
{
    return 0.0;
}

#endif /// WITH_ADC