 #include <MCP4921_DAC12bit.h>
 #include <MCP320x_ADC12bit.h>
 #include <MCP4xx1_DIGPOT8bit.h>
+#include <DG408_AnalogMUX8to1.h>
 //3rd Party Libraries
 #include <SerialCommand.h>
 #include <TimerOne.h>      /*fast microsecond timer with interrupts*/
 #include <Timer.h>         /*multipurpose timer-multiplexing */
 
-#define BAUDRATE 9600
-
+//Communication
+#define BAUDRATE 115200
 #define FLOAT_PRECISION_DIGITS 9
+#define FLOAT_DELTA 1e-20
+#define MAXCOMMANDS 12
+
+//Voltage sensing
+#define ADC_CHANNEL_VOLTAGE 0
 #define V_REF  3.297
 #define V_VGND V_REF/2.0
 #define V_INIT V_VGND
-#define R_CURRSENSE 1e4
+
+//Current sensing
+#define ADC_CHANNEL_CURRENT 1
+#define ADC_CHANNEL_CURRENT_OFFSET 2
 #define DIGPOT_N_INIT 128
-
+#define CURRSENSE_RANGE_MIN 0
+#define CURRSENSE_RANGE_MAX 4
+
+const float _currsense_resistors[]       = {250.0 ,2.50e3,25.0e3 ,250e3  ,2.50e6};      //Ohms
+const float _currsense_autotransitions[] = {4.0e-3,400e-6,40.0e-6,4.00e-6,400e-9, 0.0}; //Amps; last value prevents out of array bounds indexing for autoranging procedure
+volatile int _currsense_range = 0;
+bool         _currsense_auto  = true;
+
+//VSWEEP control
 #define DELTA_V 0.05
 #define V_MIN (-V_REF/2.0 + DELTA_V)
 #define V_MAX ( V_REF/2.0 - DELTA_V)
 
 //SerialCommand parser
-SerialCommand SCmd;
+SerialCommand SCmd(MAXCOMMANDS);
 
 //Sample Timer
 Timer SampleTimer;
 
-//configure the DAC chip
+//configure the DAC chip - on OLM port 2
 MCP4921_DAC12bitClass control_DAC(3,      //slaveSelectLowPin
                                   3,      //ldacLowPin
                                   V_VGND  //reference voltage at mid-scale
                                  );
-//configure the ADC chip
+//configure the ADC chip - on OLM port 2
 MCP320x_ADC12bitClass sense_ADC(5,   //slaveSelectLowPin
                                 V_REF //reference voltage at full-scale
                               );
 
-//configure the DIGPOT chip
+//configure the DIGPOT chip - on OLM port 2
 MCP4xx1_DIGPOT8bitClass  offset_DIGPOT(A1,    //slaveSelectLowPin
                                        100e3  //maxResistance
+                                      );
+
+//configure the MUX chip - on OLM port 4
+DG408_AnalogMUX8to1Class currsense_MUX(10, //addr0
+                                       A3, //addr1
+                                       7   //addr2
                                       );
 
 

    v_start = atof(arg);
    if (v_start < V_MIN || v_start > V_MAX)
    {
      Serial.print("### Error: VSWEEP_START must have (");
      Serial.print(V_MIN,3);
      Serial.print(" <= v_start <= ");
      Serial.print(V_MAX,3);
      Serial.print("), got:");
      Serial.print(v_start,3);
      Serial.print(" ###\n");
      return;
    }
    _sweep_v_start = v_start;
  }
  else
  {
    Serial.println("### Error: VSWEEP_START - requires 1 argument (float v_start) ###");
  }
}


  float WE_current_sense_voltage;     //voltage across current follower sense resistor, ref. to power rails
  float WE_current;                   //compute current into WE
  float WE_current_sense_offset_voltage; //referenced to power rails
  float current_sense_resistance = _currsense_resistors[_currsense_range];
  char *arg;
  arg = SCmd.next();
  if (arg != NULL)
  {
    Serial.println(F("### Error: STATUS? - requires 0 arguments ###"));
  }
  else
  {
    control_voltage = control_DAC.getVoltageOutput() - V_VGND; //shift back from center-rail
    //read signals
    RE_voltage                      = sense_ADC.readSingle(ADC_CHANNEL_VOLTAGE)        - V_VGND;
    WE_current_sense_voltage        = sense_ADC.readSingle(ADC_CHANNEL_CURRENT)        - V_VGND;
    WE_current_sense_offset_voltage = sense_ADC.readSingle(ADC_CHANNEL_CURRENT_OFFSET) - V_VGND;
    //convert to centerline voltage
    WEtoRE_voltage = -RE_voltage;
    //sesning current flows in opposite direction to current flowing into WE
    WE_current     = -WE_current_sense_voltage/current_sense_resistance;
    //format as YAML
    Serial.print(F("#<STATUS>\n"));
    Serial.print(F("---\n"));
    Serial.print(F("control_voltage: "));
    Serial.print(control_voltage, FLOAT_PRECISION_DIGITS);
    Serial.print('\n');
    Serial.print(F("WEtoRE_voltage: "));
    Serial.print(WEtoRE_voltage, FLOAT_PRECISION_DIGITS);
    Serial.print('\n');
    Serial.print(F("WE_current: "));
    Serial.print(WE_current, FLOAT_PRECISION_DIGITS);
    Serial.print('\n');
    Serial.print(F("current_sense_resistance: "));
    Serial.print(current_sense_resistance, FLOAT_PRECISION_DIGITS);
    Serial.print('\n');
    Serial.print(F("WE_current_sense_voltage: "));
    Serial.print(WE_current_sense_voltage, FLOAT_PRECISION_DIGITS);
    Serial.print('\n');
    Serial.print(F("WE_current_sense_offset_voltage: "));
    Serial.print(WE_current_sense_offset_voltage, FLOAT_PRECISION_DIGITS);
    Serial.print('\n');
    Serial.print(F("#</STATUS>\n"));
  }
}

