#include <msp430.h>
#include <stdint.h>

// Number of each type of component for this architecture
#define NUM_PGA 4
#define NUM_COMP 2
#define NUM_PWM 4
#define NUM_ADC 9 // (There is just one ADC which is being muxed over 9 channels)
#define NUM_INT 4

// PGA Mode Options
#define INVERTING_PGA 6
#define BUFFER 3
#define GENERAL_PURPOSE 2
#define NON_INVERTING_PGA 1
#define DAC_MODE 4
#define INVERTING_PGA_PAIR 5
#define DISABLED 0
#define ENABLED 1

// PGA/COMP Input Options
#define GPIO 0
#define DAC 1
#define PGA0 2
#define PGA1 3
#define PGA2 4
#define PGA3 5

//Global Options
#define LOW_POWER 0
#define PERFORMANCE 1
#define VREF_2_5V 0
#define VREF_2_0V 1
#define VREF_1_5V 2

// Inputs/Ouptut Options - Each GPIO will have a predefined mapping to the header connections
// Connections between PGAs are made through common GPIO declarations
#define GPIO_INPUT PSEL_0 //Positive/Negative GPIO Input
#define DAC_INPUT PSEL_1  //Positive DAC Input
#define PAIR_INPUT PSEL_2 //Positive Pair OA Input

// Software Configurable Analog (PGA) have a mode selection, an Input selection, and values for
// Gain and DAC - all FR23x/LEGO app note related code should include this header. ADC is on SAC0/SAC1 and
// connected to SAC2 and SAC3 by jumpering P5.3 to P3.5 and P3.1 to P5.2

// PGA Configuration
#define PGA_LOWPOWER 1 // All OpAmps will be conifigured in low power mode instead of high performance.
#define VOLTAGE_REFERENCE 2  // All Opamps will be configured to use the same reference

#define PGA0_MODE NON_INVERTING_PGA //ANY MODE
#define PGA0_INPUTP PAIR_INPUT //GPIO_INPUT OR DAC_INPUT OR PAIRED INPUT
#define PGA0_GAIN 1 //1, 2, 4, 8, 16, 25, 32 in Inverting MODE
#define PGA0_DAC 0 //Any 12 Bit Value

#define PGA2_MODE DAC_MODE   //ANY MODE EXCEPT INVERTING PGA_PAIR
#define PGA2_INPUTP DAC_INPUT //GPIO_INPUT, DAC_INPUT, OR PAIR_INPUT
#define PGA2_GAIN 1 //1, 2, 4, 8, 16, 25, 32 in Inverting MODE
#define PGA2_DAC 0 //Any 12 Bit Value

#define PGA1_MODE NON_INVERTING_PGA //ANY MODE
#define PGA1_INPUTP PAIR_INPUT //GPIO_INPUT OR DAC_INPUT
#define PGA1_GAIN  1 //1, 2, 3, 5, 9, 17, 26, 33 in NON Inverting MODE
#define PGA1_DAC 50 //Any 12 Bit Value

#define PGA3_MODE DAC_MODE //ANY MODE EXCEPT INVERTING PGA_PAIR
#define PGA3_INPUTP DAC_INPUT //GPIO_INPUT, DAC_INPUT, OR PAIR_INPUT
#define PGA3_GAIN 1 //1, 2, 3, 5, 9, 17, 26, 33 in NON Inverting MODE
#define PGA3_DAC 0 //Any 12 Bit Value

#define COMP0_MODE ENABLED
#define COMP0_INPUTP PGA0
#define COMP0_INPUTN PGA2
#define COMP0_DAC 32

#define COMP1_MODE ENABLED
#define COMP1_INPUTP PGA1
#define COMP1_INPUTN PGA3
#define COMP1_DAC 32

typedef struct
{
    uint8_t mode;
    uint8_t inputP;
    uint16_t gain;
    uint16_t dac;
} SCA_pgaParams;

typedef struct
{
    uint8_t mode;
    uint8_t inputP;
    uint8_t inputN;
    uint16_t dac;
} SCA_compParams;

typedef struct
{
  int dutyValue;
} SCA_pwmParams;

typedef struct {
  unsigned int adcResult1;
  unsigned int adcResult4;
  unsigned int adcResult5;
  unsigned int adcResult6;
  unsigned int adcResult7;
  unsigned int adcResult8;
  unsigned int adcResult9;
  unsigned int adcResult10;
  unsigned int adcResult11;
} SCA_adcResults;

typedef struct {
    uint8_t mode;
} SCA_adcParams;

typedef struct
{
    uint8_t powerMode;
    uint8_t voltageReference;
    uint16_t wakeFrequency;
} SCA_globalParams;

typedef struct
{
  uint8_t mode;
} SCA_intParams;

extern SCA_pgaParams pgaParams[NUM_PGA];
extern SCA_compParams compParams[NUM_COMP];
extern SCA_pwmParams pwmParams[NUM_PWM];
extern SCA_intParams intParams[NUM_INT];
extern SCA_adcParams adcParams[NUM_ADC];
extern SCA_globalParams globalParams;
SCA_adcResults adcResults;
unsigned int ADC_Result;
unsigned int Send_Data;

extern void SCA_configGlobal(SCA_globalParams *globalParams);
extern void SCA_configPGA(SCA_pgaParams *pgaParams, uint8_t index);
extern void SCA_configPWM(SCA_pwmParams *pwmParams, uint8_t index);
extern void SCA_configINT(SCA_intParams *intParams, uint8_t index);
extern void SCA_configCOMP(SCA_compParams *compParams, uint8_t index);
extern void SCA_initGPIO();
extern void SCA_getADC(SCA_adcResults *adcResults, uint8_t);
