// CD74HC4067
// 16-Channel Analog Multiplexer
// Demultiplexing not implemented for this simulation.
// https://www.ti.com/lit/ds/symlink/cd74hc4067.pdf
#include <ArduinoJson.h>
#define COM1 34
#define COM2 35
#define COM3 36
#define COM4 39

DynamicJsonDocument doc_mux_adc(2048);

const uint8_t controlPinsMux1[] = { 18, 19, 22, 23 }; //S0, S1, S2, S3
const uint8_t controlPinsMux2[] = { 13, 14, 15, 16 }; //S0, S1, S2, S3
const uint8_t controlPinsMux3[] = { 27, 26, 25}; //A, B, C
const uint8_t controlPinsMux4[] = { 2,32,33}; //A, B, C
const uint8_t muxChannels16 [16][2][4] = {
  {{0,0,0,0},{0,0,0,0}},
  {{1,0,0,0},{1,0,0,0}},
  {{0,1,0,0},{0,1,0,0}},
  {{1,1,0,0},{1,1,0,0}},
  {{0,0,1,0},{0,0,1,0}},
  {{1,0,1,0},{1,0,1,0}},
  {{0,1,1,0},{0,1,1,0}},
  {{1,1,1,0},{1,1,1,0}},
  {{0,0,0,1},{0,0,0,1}},
  {{1,0,0,1},{1,0,0,1}},
  {{0,1,0,1},{0,1,0,1}},
  {{1,1,0,1},{1,1,0,1}},
  {{0,0,1,1},{0,0,1,1}},
  {{1,0,1,1},{1,0,1,1}},
  {{0,1,1,1},{0,1,1,1}},
  {{1,1,1,1},{1,1,1,1}}
};
const uint8_t muxChannels8 [8][2][3] = {
  {{0,0,0},{0,0,0}},
  {{1,0,0},{1,0,0}},
  {{0,1,0},{0,1,0}},
  {{1,1,0},{1,1,0}},
  {{0,0,1},{0,0,1}},
  {{1,0,1},{1,0,1}},
  {{0,1,1},{0,1,1}},
  {{1,1,1},{1,1,1}}
  
};

void setup_mux(){
  for (int i = 0;i < 4;i++){
    pinMode(controlPinsMux1[i], OUTPUT);
    pinMode(controlPinsMux2[i], OUTPUT);
  
    if(i<3){
      pinMode(controlPinsMux3[i], OUTPUT);
      pinMode(controlPinsMux4[i], OUTPUT);
    }
    
}
}
float* readMux16(int channel,bool single_ended)
{
  static float data[2] = {};
  for(int i = 0; i < 4; i ++)
  {
    
    digitalWrite(controlPinsMux1[i], muxChannels16[channel][0][i]);
    digitalWrite(controlPinsMux2[i], muxChannels16[channel][1][i]);
    
  }
  //delay(100);
 
  if(single_ended){
    data[0] = analogRead(COM1);
    data[1] = analogRead(COM2);
  }
  if(!single_ended) data[0] = (analogRead(COM2)-analogRead(COM1));
  return data;
}

float* readMux8(int channel,bool single_ended)
{
  static float data[2] = {};
  for(int i = 0; i < 3; i ++)
  {
    digitalWrite(controlPinsMux3[i], muxChannels8[channel][0][i]);
    digitalWrite(controlPinsMux4[i], muxChannels8[channel][1][i]);
    
  }
  //delay(100);
  if(single_ended){
    data[0] = analogRead(COM3);
    data[1] = analogRead(COM4);
  }
  else data[0] = analogRead(COM4)-analogRead(COM3);
  return data;
}

void readMuxADC(bool single_ended = false){
  
  //DynamicJsonDocument doc(2048);
  if (!single_ended){
    for(int i = 0; i < 16; i++)
      {
        float* data = readMux16(i,single_ended);
        doc_mux_adc["A" + String(i+1)] = data[0];
      }
      for(int i = 0; i < 8; i++)
      {
        float* data = readMux8(i,single_ended);
        doc_mux_adc["A" + String(i+17)] = data[0];
      }
       //for(int i=1;i<=24;i++){
       //doc_mux_adc["A"+String(i)] = doc["A"+String(i)];
     //}
    }
  else{
    for(int i = 0; i < 16; i++)
      {
        
        float* data = readMux16(i,single_ended);
        doc_mux_adc["A" + String(i+1)] = data[0];
        doc_mux_adc["A" + String(i+17)] = data[1];
      }
      for(int i = 0; i < 8; i++)
      {
        float* data = readMux8(i,single_ended);
      
        doc_mux_adc["A" + String(i+33)] = data[0];
        doc_mux_adc["A" + String(i+41)] = data[1];
      }
      //for(int i=1;i<=48;i++){
       //doc_mux_adc["A"+String(i)] = doc["A"+String(i)];
     //}
    }
   
    
   //doc.clear();
   //doc.garbageCollect();
  }


void setup()
{
  Serial.begin(115200);
  setup_mux();
  delay(50);

  readMuxADC(true);
  serializeJsonPretty(doc_mux_adc,Serial);
  Serial.println();
}

void loop()
{
 
 
  
 
}
CD74HC4067Breakout
CD74HC4067Breakout
CD74HC4051bBreakout
CD74HC4051bBreakout