Sketch 6 ICs breakout board

Arduino Ide sketch code for 6 ICs breakout board

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_MCP4728.h>

#include "RTClib.h"
#include "Adafruit_FRAM_I2C.h"

#define LDAC_GPIO0 0
//#define DinPin 6
//#define SclkPin 0
//#define FsCsPin 7

Adafruit_MCP4728 mcp;

// Rotary encoder
#define ENC_A 14
#define ENC_B 15
#define rotencpushpin 11
volatile int counter = 0;
int countersubmenu = 0;
int countersubmenuitem = 0;
int countermenu = 0;
bool submenu = false;
unsigned long _lastIncReadTime = micros();
unsigned long _lastDecReadTime = micros();
//int _pauseLength = 25000;
int _pauseLength = 150000;
int _fastIncrement = 10;
bool rotencpush = false;
unsigned long lastmillis = 0;

// Analog read
#define PinZaip 27
#define PinS0dop 6
#define PinS1dop 7
#define PinS2dop 10

// Digital read
//#define PinNotG
#define PinY22 22

// Digital write
#define PinG8 8
#define PinD9 9

// Open collector output
#define PinOc2 2
#define PinOc3 3
#define PinOc4 4
#define PinOc5 5

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1  // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES 10  // Number of snowflakes in the animation example

#define LOGO_HEIGHT 16
#define LOGO_WIDTH 32 // This is version one of my Logo as an example. It needs quite a bit of work yet.
static const unsigned char PROGMEM logo_bmp[] = { B00000001, B11110000, B00001111, B10000000,
                                                  B00000011, B11111000, B00011111, B11000000,
                                                  B00000111, B11111100, B00111111, B11100000,
                                                  B00011111, B11111111, B11111111, B11111000,
                                                  B01110000, B00001110, B01110000, B00001110,
                                                  B11100000, B00011100, B00111000, B00000111,
                                                  B11000000, B00111000, B00011100, B00000011,
                                                  B10000000, B01110000, B00001110, B00000001,
                                                  B11000000, B00111000, B00011100, B00000011,
                                                  B11100000, B00011100, B00111100, B00000111,
                                                  B01110000, B00001111, B11110000, B00001110,
                                                  B00011111, B00000111, B11100000, B11111000,
                                                  B00000111, B11111111, B11111111, B11100000,
                                                  B00000111, B11111000, B00011111, B11000000,
                                                  B00000011, B11110000, B00001111, B11000000,
                                                  B00000001, B11100000, B00000111, B10000000 };

bool SDok = true;
bool displayok = true;
bool framok = true;
bool rtcok = true;
bool dacok = true;
bool rotenbuttonpush = false;
RTC_DS3231 rtc;
Adafruit_FRAM_I2C fram = Adafruit_FRAM_I2C();

char daysOfTheWeek[7][12] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
char daysOfTheWeekFull[7][12] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
unsigned long lasttimeloop = 0;
volatile bool pushpin = false;  // 20230806

typedef enum sc_id {
  channel_a,
  channel_b,
  channel_c,
  channel_d,
  channel_e,
  channel_f,
  channel_g,
  channel_h,
} sc_id_t;

void testdrawbitmap(void) {
  if (displayok) display.clearDisplay();

  if (displayok) display.drawBitmap(
    (display.width() - LOGO_WIDTH) / 2,
    (display.height() - LOGO_HEIGHT) / 2 - 16,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  if (displayok) display.display();
  //delay(1000);
}



void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  pinMode(LDAC_GPIO0, OUTPUT);
  digitalWrite(LDAC_GPIO0, LOW);

  //pinMode(SclkPin, OUTPUT);

  pinMode(PinS0dop, OUTPUT_12MA);
  pinMode(PinS1dop, OUTPUT_12MA);
  pinMode(PinS2dop, OUTPUT_12MA);
  pinMode(PinZaip, INPUT);

  pinMode(PinY22, INPUT);
  pinMode(PinG8, OUTPUT);
  pinMode(PinD9, OUTPUT);


  pinMode(PinOc2, OUTPUT);
  pinMode(PinOc3, OUTPUT);
  pinMode(PinOc4, OUTPUT);
  pinMode(PinOc5, OUTPUT);

  
  unsigned long startmillis = millis();
  Serial.begin(115200);
  while (!Serial && startmillis + 10000 > millis())
    ;

  Wire.setSDA(20);
  Wire.setSCL(21);

  
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    displayok = false;
    
  }

  if (!mcp.begin(0xe1)) {
  //if (!mcp.begin(0xbc)) {
    Serial.println("Failed to find MCP4728 chip");
    dacok = false;
    
  }


  

  if (displayok) testdrawbitmap();

  if (displayok) display.setTextSize(2);       // Normal 1:1 pixel scale
  if (displayok) display.setTextColor(WHITE);  // Draw white text
  if (displayok) display.setCursor(12, 44);    // Start at top-left corner
  if (displayok) display.cp437(true);          // Use full 256 char 'Code Page 437' font

  if (displayok) display.println("Microtron");
  if (displayok) display.display();

  delay(2000);

  // Invert and restore display, pausing in-between
  if (displayok) display.invertDisplay(true);
  delay(1000);
  if (displayok) display.invertDisplay(false);
  delay(1000);

  if (!rtc.begin()) {
    if (Serial) Serial.println("Couldn't find RTC");
    if (Serial) Serial.flush();
    rtcok = false;
    //while (1) delay(10);
  }

  if (rtc.lostPower()) {
    if (Serial) Serial.println("RTC lost power, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }


  if (fram.begin(80, &Wire)) {  // you can stick the new i2c addr in here, e.g. begin(0x51);
    if (Serial) Serial.println("Found I2C FRAM");
  } else {
    if (Serial) Serial.println("I2C FRAM not identified ... check your connections?\r\n");
    //Serial.println("Will continue in case this processor doesn't support repeated start\r\n");
    framok = false;
    //while (1);
  }

  if (framok) {
    // Read the first byte
    uint8_t test = fram.read(0x0);
    if (Serial) Serial.print("Restarted ");
    if (Serial) Serial.print(test);
    if (Serial) Serial.println(" times");
    // Test write ++
    fram.write(0x0, test + 1);
  }

  if (framok && rtcok && displayok) digitalWrite(LED_BUILTIN, LOW);

  // Set encoder pins and attach interrupts
  pinMode(rotencpushpin, INPUT_PULLUP);
  pinMode(ENC_A, INPUT_PULLUP);
  pinMode(ENC_B, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENC_A), read_encoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(ENC_B), read_encoder, CHANGE);

  attachInterrupt(digitalPinToInterrupt(rotencpushpin), encoder_push, FALLING);  // 20230806

  if(dacok)
  {
    mcp.setChannelValue(MCP4728_CHANNEL_A, 4095,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
    mcp.setChannelValue(MCP4728_CHANNEL_B, 2048,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
    mcp.setChannelValue(MCP4728_CHANNEL_C, 1024,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
    mcp.setChannelValue(MCP4728_CHANNEL_D, 0,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);

    digitalWrite(LDAC_GPIO0, HIGH);

    mcp.setChannelValue(MCP4728_CHANNEL_A, 3800,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
    mcp.setChannelValue(MCP4728_CHANNEL_B, 3600,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
    mcp.setChannelValue(MCP4728_CHANNEL_C, 3400,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
    mcp.setChannelValue(MCP4728_CHANNEL_D, 0,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
  }


}

void encoder_push() {  // 20230806
  pushpin = true;
}


void loop() {


  if (pushpin && millis() > lastmillis + 500) {
    rotencpush = true;
    lastmillis = millis();
  }
  pushpin = false;

  if (rotencpush) {
    rotenbuttonpush = true;
    buttonclick();
    //paintscreen();
    rotencpush = false;
  }

  if (!pushpin) {
    rotenbuttonpush = false;
  }

  
  readsensors();
  delay(500);
}

int daccounter = 4095;
void readsensors() {
  if (displayok) display.clearDisplay();
  if (displayok) display.setTextSize(2);       // Normal 1:1 pixel scale
  if (displayok) display.setTextColor(WHITE);  // Draw white text
  if (displayok) display.setCursor(0, 0);      // Start at top-left corner
  if (displayok) display.cp437(true);          // Use full 256 char 'Code Page 437' font

  if (counter < 0) counter = 0;

  int screen = countermenu;
  if (submenu) {
    countersubmenu = counter;
    //screen
  } else {
    countermenu = counter % 6;
    screen = countermenu;
  }

  DateTime now;
  if (rtcok) {
    now = rtc.now();

    if (Serial) Serial.println(datetimewdayfullstr(now));
    if (Serial) Serial.print(" since midnight 1/1/1970 = ");
    if (Serial) Serial.print(now.unixtime());
    if (Serial) Serial.print("s = ");
    if (Serial) Serial.print(now.unixtime() / 86400L);
    if (Serial) Serial.println("d");
  }


  if (screen == 0) {
    if (!submenu) {
      //if(displayok) display.println();
      if (rtcok) {
        if (displayok) display.print(now.year(), DEC);
        if (displayok) display.print('/');
        if (displayok) display.print(now.month(), DEC);
        if (displayok) display.print('/');
        if (displayok) display.println(now.day(), DEC);

        if (displayok) display.print(daysOfTheWeek[now.dayOfTheWeek()]);
        if (displayok) display.print(", ");
        if (displayok) display.println(rotenbuttonpush ? "push" : "home");

        //if(displayok) display.print(") ");
        if (displayok) display.print(now.hour(), DEC);
        if (displayok) display.print(':');
        if (displayok) display.print(now.minute(), DEC);
        if (displayok) display.print(':');
        if (displayok) display.print(now.second(), DEC);
        if (displayok) display.println();
      }

      if (framok) {
        uint8_t test = fram.read(0x0);
        if (displayok) display.print("Start");
        if (displayok) display.print(test);
        if (displayok) display.print(",");
      }

      if (displayok) display.println(counter);
    } else {
      int screensub = countersubmenu % 3;
      countersubmenuitem = screensub;
      if (screensub == 0) {
        if (displayok) display.println("screensub");
        if (displayok) display.println("0 menu 0");
        if (displayok) display.println("Exit");
      } else if (screensub == 1) {
        if (displayok) display.println("screensub");
        if (displayok) display.println("1 menu 0");
        if (displayok) display.println("Execute");

      } else if (screensub == 2) {
        if (displayok) display.println("screensub");
        if (displayok) display.println("2 menu 0");
        if (displayok) display.println("Execute");
      }
    }
  } else if (screen == 1) {
    if (submenu) {
      buttonclick();
      return;
    }
    int read[8] = { 0 };
    read[0] = getZreadingAin(0);
    read[1] = getZreadingAin(1);
    read[2] = getZreadingAin(2);
    read[3] = getZreadingAin(3);
    read[4] = getZreadingAin(4);
    read[5] = getZreadingAin(5);
    read[6] = getZreadingAin(6);
    read[7] = getZreadingAin(7);

    for (int i = 0; i < 8; i++) {
      if (displayok) display.print(read[i]);
      if (i % 2 == 0) {
        if (displayok) display.print(",");
      }
      if (i % 2 == 1) {
        if (displayok) display.println("");
      }
    }
  } else if (screen == 2) {
    if (submenu) {
      buttonclick();
      return;
    }
    if (displayok) display.println("Dig In");
    bool read[8] = { 0 };
    read[0] = getYreadingDin(0);
    read[1] = getYreadingDin(1);
    read[2] = getYreadingDin(2);
    read[3] = getYreadingDin(3);
    read[4] = getYreadingDin(4);
    read[5] = getYreadingDin(5);
    read[6] = getYreadingDin(6);
    read[7] = getYreadingDin(7);

    for (int i = 0; i < 8; i++) {
      if (displayok) display.print(read[i] ? "1" : "0");
      //if(i%2 == 0) { if(displayok) display.print(","); }
      //if(i%2==1) { if(displayok) display.println(""); }
    }
  } else if (screen == 3) {
    if (submenu) {
      buttonclick();
      return;
    }
    if (displayok) display.println("Dig Out");
    bool read[8] = { 0 };
    read[0] = false;
    read[1] = true;
    read[2] = false;
    read[3] = true;
    read[4] = false;
    read[5] = true;
    read[6] = false;
    read[7] = true;

    for (int i = 0; i < 8; i++) {
      setLatch(i, read[i]);
      if (displayok) display.print(read[i] ? "1" : "0");
      //if(i%2 == 0) { if(displayok) display.print(","); }
      //if(i%2==1) { if(displayok) display.println(""); }
    }
  } else if (screen == 4) {
    if (submenu) {
      buttonclick();
      return;
    }
    if (displayok) display.println("Open Coll");
    static int counter4 = 0;
    counter4++;
    int counter4pcval = counter4 % 16;
    bool read[4] = { 0 };
    read[0] = (counter4pcval & 1) > 0 ? true : false;
    read[1] = (counter4pcval & 2) > 0 ? true : false;
    read[2] = (counter4pcval & 4) > 0 ? true : false;
    read[3] = (counter4pcval & 8) > 0 ? true : false;

    for (int i = 0; i < 4; i++) {
      if(i==0) { setOpenCollector(i, HIGH); read[i] = LOW; }
      else setOpenCollector(i, read[i]);
      if (displayok) display.print(read[i] ? "1" : "0");
      
    }
  } else if (screen == 5) {
    if (submenu) {
      buttonclick();
      return;
    }
    if (displayok) display.println("Ana Out");
    if (displayok) display.println("Hi 2 Lo");

    
    daccounter = daccounter - 50;
    if(daccounter < 0) daccounter = 4095;


    setAout(0, daccounter);
    setAout(1, 2048);
    setAout(2, 1024);
    setAout(3, 0);
    setAout(4, 3800);
    setAout(5, 3600);
    setAout(6, 3400);
    setAout(7, 4095 - daccounter);
    
  }



  if (displayok) display.display();

  
}

void read_encoder() {
  // Encoder interrupt routine for both pins. Updates counter
  // if they are valid and have rotated a full indent

  static uint8_t old_AB = 3;                                                                  // Lookup table index
  static int8_t encval = 0;                                                                   // Encoder value
  static const int8_t enc_states[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 };  // Lookup table

  old_AB <<= 2;  // Remember previous state

  if (digitalRead(ENC_A)) old_AB |= 0x02;  // Add current state of pin A
  if (digitalRead(ENC_B)) old_AB |= 0x01;  // Add current state of pin B

  encval += enc_states[(old_AB & 0x0f)];

  // Update counter if encoder has rotated a full indent, that is at least 4 steps
  if (encval > 3) {  // Four steps forward
    int changevalue = 1;
    if ((micros() - _lastIncReadTime) < _pauseLength) {
      changevalue = _fastIncrement * changevalue;
    }
    _lastIncReadTime = micros();
    counter = counter + changevalue;  // Update counter
    encval = 0;
  } else if (encval < -3) {  // Four steps backward
    int changevalue = -1;
    if ((micros() - _lastDecReadTime) < _pauseLength) {
      changevalue = _fastIncrement * changevalue;
    }
    _lastDecReadTime = micros();
    counter = counter + changevalue;  // Update counter
    encval = 0;
  }
}

void buttonclick() {

  if (countermenu == 0) {
    if (countersubmenuitem == 1) {
      void menu1();
      return;
    }
    if (countersubmenuitem == 2) {
      void menu2();
      return;
    }
  }

  submenu = !submenu;

  if (submenu) {
    counter = countersubmenu;
  } else {
    counter = countermenu;
  }

  if (Serial) Serial.println("buttonclick");
}

void menu1() {
}
void menu2() {
}


void setS012(int sval) {
  if (sval < 0 || sval >= 8) return;
  digitalWrite(PinS0dop, (sval & 1) == 1 ? true : false);
  digitalWrite(PinS1dop, (sval & 2) == 2 ? true : false);
  digitalWrite(PinS2dop, (sval & 4) == 4 ? true : false);
}

int getZreadingAin(int sval) {
  setS012(7 - sval);
  delay(1);
  //delayMicroseconds(200);
  return analogRead(PinZaip);
}

bool getYreadingDin(int sval) {
  setS012(sval);
  delay(1);
  //delayMicroseconds(200);
  return digitalRead(PinY22);
}

void setLatch(int sval, bool val) {
  digitalWrite(PinG8, HIGH);
  delay(1);
  //delayMicroseconds(200);
  setS012(sval);
  digitalWrite(PinD9, val);
  delay(1);
  //delayMicroseconds(200);
  digitalWrite(PinG8, LOW);
  delay(2);
  //delayMicroseconds(200);
  digitalWrite(PinG8, HIGH);
}

void setOpenCollector(int unit, bool val) {
  if (unit == 0) digitalWrite(PinOc2, val);
  if (unit == 1) digitalWrite(PinOc3, val);
  if (unit == 2) digitalWrite(PinOc4, val);
  if (unit == 3) digitalWrite(PinOc5, val);
}


void setAout(uint16_t address, uint16_t value) {
  
  if(!dacok) return;
  
  switch(address){
    case 0: setChannel(channel_a, value); break;
    case 1: setChannel(channel_b, value); break;
    case 2: setChannel(channel_c, value); break;
    case 3: setChannel(channel_d, value); break;
    case 4: setChannel(channel_e, value); break;
    case 5: setChannel(channel_f, value); break;
    case 6: setChannel(channel_g, value); break;
    case 7: setChannel(channel_h, value); break;
    default: break;
 }

}

void setChannel(sc_id_t chanId, int value)
{
  if (value < 0 || value > 4095) return;

  if(chanId == channel_a, chanId == channel_b, chanId == channel_c, chanId == channel_d) digitalWrite(LDAC_GPIO0, LOW);
  else digitalWrite(LDAC_GPIO0, HIGH);
  
  if(chanId == channel_a || chanId == channel_e) mcp.setChannelValue(MCP4728_CHANNEL_A, value,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
  else if (chanId == channel_b || chanId == channel_f) mcp.setChannelValue(MCP4728_CHANNEL_B, value,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
  else if (chanId == channel_c || chanId == channel_g) mcp.setChannelValue(MCP4728_CHANNEL_C, value,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
  else if (chanId == channel_d || chanId == channel_h) mcp.setChannelValue(MCP4728_CHANNEL_D, value,MCP4728_VREF_VDD,MCP4728_GAIN_1X,MCP4728_PD_MODE_NORMAL,true);
}

String datestr(DateTime now) {
  char buf[30];
  sprintf(buf, "%4u/%02u/%02u", now.year(), now.month(), now.day());
  return buf;
  
}

String timestr(DateTime now) {
  char buf[30];
  sprintf(buf, "%02u:%02u:%02u", now.hour(), now.minute(), now.second());
  return buf;
}

String daystr(DateTime now) {
  return String(daysOfTheWeek[now.dayOfTheWeek()]);
}

String dayfullstr(DateTime now) {
  return String(daysOfTheWeekFull[now.dayOfTheWeek()]);
}

String datetimestr(DateTime now) {
  return datestr(now) + " " + timestr(now);
}

String datetimewdaystr(DateTime now) {
  return datetimestr(now) + " " + String(daysOfTheWeek[now.dayOfTheWeek()]);
}

String datetimewdayfullstr(DateTime now) {
  return datetimestr(now) + " " + String(daysOfTheWeekFull[now.dayOfTheWeek()]);
}