Logic game - Arduino Uno code


#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"

#define I2C_ADDRESS 0x3C

// class and instance
SSD1306AsciiAvrI2c oled;


int g[3];  // 3 gates assigned 1 type: AND OR XOR NAND
char n[4]={0,1,2,3}; // 4 types of gates
int r; // random #
volatile int next=0;


void randomize() {
  // output example g[0]= 3, g[1] = 2, g[2] = 0
  n[0]=0;n[1]=1;n[2]=2;n[3]=3;
  for (int i = 0; i <3; i++) {
    r=random(0,4);
    while (n[r] == 4) {// invalid #
      r=random(0,4);
    }
    g[i]=n[r];
    n[r]=4; // already used
  }
}

//------------------------------------------
void reveal() {
    int i = 2;
    oled.setFont(font8x8);
    oled.clear();
    oled.setCursor(25,1);
    oled.set1X();
    do {

      oled.print(i+1);
      if (g[i] == 0) {
        oled.print(":AND ");
      } else if (g[i] == 1) {
        oled.print(":OR ");
      } else if (g[i] == 2) {
        oled.print(":XOR ");
      } else if (g[i] == 3) {
        oled.print(":NAND ");
      }
      if (i==2) {  //    3:AND
          i = 0; // 1:XOR 2:NAND
          oled.setCursor(0,3);
      } else {
          i++;
      }
    } while (i < 2);
}
//------------------------------------------

void proceed() {
  next++;
  if (next > 5) {
    next = 5;
  }
}

void setup() {
  while (((r = analogRead(0)) == 0) or ((r = analogRead(0)) == 1023)) {}; // exclude 0 and 1023
  randomSeed(r);
 // randomSeed(millis());
  // Serial.begin(9600);
  // use pulldown resistors on PINB[0,1,2,3]
  DDRB = 0x00; // all inputs PB0-PB5
  PORTB = 0x00; // no pullups

  DDRD |= 0xE0;   //  1110 0000
  PORTD = 0x00;  // no pullups
  attachInterrupt(digitalPinToInterrupt(2), proceed, RISING); // PD2, pin 4


  oled.begin(&Adafruit128x32, I2C_ADDRESS);
  // oled.setI2cClock(frequency) to change from the default frequency.

    oled.setFont(Adafruit5x7);
    oled.clear();
    oled.set1X();
    oled.setCursor(0,0);
    oled.println("Which gates are used?");
    oled.println("AND, OR, XOR, NAND.  ");
    oled.println("Use red switches to  ");
    oled.println("work out the gates.  ");
  while (next == 0) { delay(50); }
    oled.clear();
    oled.home();
    oled.println("3 gates, no doubles! ");
    oled.println("Press Next to begin  ");
    oled.println("and again to see what");
    oled.println("logic gates were used");
  while (next == 1) { delay(50); }
    randomize();
    oled.clear();
    oled.setCursor(5,2);
    oled.set2X();
    oled.println("GAME ON");
}

void logic_gates(int gate, int pin1, int pin2, int sbit) {
  if (gate == 0) {  //AND
    if (((PINB & bit(pin1)) == bit(pin1)) && ((PINB & bit(pin2)) == bit(pin2))) {
       PORTD |= sbit;
    }  else {
       PORTD &= ~(sbit);
    }
  } else if (gate == 1) {  //OR
    if (((PINB & bit(pin1)) == bit(pin1)) || ((PINB & bit(pin2)) == bit(pin2))) {
       PORTD |= sbit;
    }  else {
       PORTD &= ~(sbit);
    }
  } else if (gate == 2) {  //XOR
    if ((((PINB & bit(pin1)) == bit(pin1)) && ((PINB & bit(pin2)) == 0)) || (((PINB & bit(pin1)) == 0) && ((PINB & bit(pin2)) == bit(pin2)))) {    // 0000 1100 AND
       PORTD |= sbit;
    }  else {
       PORTD &= ~(sbit);
    }
  } else if (gate == 3) {  //NAND
    if (((PINB & bit(pin1)) == bit(pin1)) && ((PINB & bit(pin2)) == bit(pin2))) {    // 0000 1100 AND
       PORTD &= ~(sbit);
    }  else {
       PORTD |= sbit;
    }
  }
}

void loop() {

  if (next == 2) {
    logic_gates(g[0],0,1,0x20); // input from PB0 PB1, pin 14,15, output goes to PD5, pin 11, sbit 0010 0000
    logic_gates(g[1],2,3,0x40); // input from PB2, PB3, pin 16,17, output goes to PD6, pin 12, sbit  0100 0000
    logic_gates(g[2],4,5,0x80); // input from PB4(PD5), PB5(PD6), pin 18,19  output goes to PD7, pin 13, sbit  1000 0000
  } else if (next == 3) {
    reveal(); // next updated to 4
    next = 4;
  } else if (next == 5) {
    randomize();
    oled.clear();
    oled.setCursor(5,2);
    oled.set2X();
    oled.println("GAME ON");
    next = 2;
  }
}