#ifndef ADC_H
#define ADC_H

//----------------------------------
// Includes and forward declarations
//----------------------------------
#include <pkgconf/system.h>
#include <pkgconf/io_adc.h>

#include <cyg/infra/cyg_type.h>
#include <cyg/io/io.h>
#include <cyg/io/devtab.h>
#include <cyg/io/adcio.h>
#include <cyg/hal/drv_api.h>

//-----------------
// Type definitions
//-----------------
typedef struct adc_channel adc_channel;
typedef struct adc_funs adc_funs;

//----------------------------------------------------------------------------
// Callback functions to allow low level device driver to access higher layers
//----------------------------------------------------------------------------
typedef struct {
} adc_callbacks_t;

#define ADC_CALLBACKS(_l)                    \
  adc_callbacks_t _l = {                     \
  }

extern adc_callbacks_t adc_callbacks;

//------------------------------------------
// Private data that describe an adc channel
//------------------------------------------
struct adc_channel {
  adc_funs *        m_funs;
  adc_callbacks_t * m_callbacks;
  void *            m_dev_priv;
  cyg_uint16        m_span;
  double            m_scaling;
  double            m_offset;
  double            m_scaling_cal;
  double            m_offset_cal;
  double            m_scaling_usr;
  double            m_offset_usr;
}; 

#define ADC_CHANNEL(_l,                       \
                    _funs,                    \
                    _dev_priv,                \
                    _span,                    \
                    _scaling,                 \
                    _offset)                  \
    adc_channel _l = { &_funs,                \
                       &adc_callbacks,        \
                       _dev_priv,             \
                       _span,                 \
                       _scaling * _span,      \
                       _offset * _scaling,    \
                       1.0,                   \
                       0.0,                   \
                       _scaling,              \
                       _offset                \
    }

//------------------------------
// Low level interface functions
//------------------------------
struct adc_funs {
  double (* adc_read)(adc_channel * a_channel); // Will allways return a value between -1.0 and 1.0
  bool (* adc_reset)(adc_channel * a_channel);
};

#define ADC_FUNS(_l,                          \
                 _read,                       \
                 _reset)                      \
  adc_funs _l = {                             \
    _read,                                    \
    _reset                                    \
  }

//---------------------------------
// Define the device driver entries
//---------------------------------
extern cyg_devio_table_t adc_devio;

#endif // ADC_H
