#ifndef DAC_H
#define DAC_H

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

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

//-----------------
// Type definitions
//-----------------
typedef struct dac_channel dac_channel;
typedef struct dac_funs dac_funs;

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

#define DAC_CALLBACKS(_l)                                    \
    dac_callbacks_t _l = {                                   \
    }                                                        \

extern dac_callbacks_t dac_callbacks;

//-----------------------------------------
// Private data that describe a dac_channel
//-----------------------------------------
struct dac_channel {
  dac_funs *        m_funs;
  dac_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 DAC_CHANNEL(_l,                                      \
                    _funs,                                   \
                    _dev_priv,                               \
                    _span,                                   \
                    _scaling,                                \
                    _offset)                                 \
    dac_channel _l = {                                       \
      &_funs,                                                \
      &dac_callbacks,                                        \
      _dev_priv,                                             \
      _span,                                                 \
      _scaling / _span,                                      \
      _scaling * _offset / _span,                            \
      1.0,                                                   \
      0.0,                                                   \
      _scaling,                                              \
      _offset                                                \
}

//------------------------------
// Low level interface functions
//------------------------------
struct dac_funs {
  void (* dac_write)(dac_channel * a_channel, double a_value); // always a value between -1.0 and 1.0
  bool (* dac_reset)(dac_channel * a_channel);
};

#define DAC_FUNS(_l,                                         \
                 _write,                                     \
                 _reset)                                     \
    dac_funs _l = {                                          \
      _write,                                                \
      _reset                                                 \
    }

//--------------------------------
// Define thedevice driver entries
//--------------------------------
extern cyg_devio_table_t dac_devio;

#endif // DAC_H
