# include <Adafruit_NeoPixel.h>
# include <ezButton.h>

# define SIZE 7

unsigned int puzzleBits = 0xffbf;  // only low order SIZE bits matter fff7 for four places

const byte xLED = 12;    // heart beat

ezButton button[] = {8, 9, 10, 11, 5, 6, 4, };

unsigned int mask0[16] = {
  0,    // the zero switch always works
  1,
  2,
  4,
  8,
  0x10,
  0x20,
  0x40,
  0x80,
  0x100,
};

unsigned int mask1[16] = {
  0,    // the zero switch always works
  0,
  1,
  3,
  7,
  0xf,
  0x1f,
  0x3f,
  0x7f,
  0xff,
};

# define N_REAL SIZE  // until features
# define PIN  7

// Global variables for lights and CAN communication
Adafruit_NeoPixel led(N_REAL, PIN, NEO_GRB + NEO_KHZ800);


void setup() {
  Serial.begin(115200); Serial.println("first things first");

  pinMode(xLED, OUTPUT);

  for (byte ii = 0; ii < SIZE; ii++)
    button[ii].setDebounceTime(20);

  led.begin();
  led.setPixelColor(1, 0x80009c0);
  led.show();
  delay(777);
}


unsigned int BinaryToGray(unsigned int num)
{
    return num ^ (num >> 1); // The operator >> is shift right. The operator ^ is exclusive or.
}

void publish(byte theBits)
{
  byte mask = 1;
  led.clear();
  for (byte ii = 0;  ii < 7; ii++, mask <<= 1) {
    led.setPixelColor(ii, theBits & mask ? 0xff0000 : 0x303030);
  }
  led.show();
}

void loop()
{
  static unsigned long lastTime;
  unsigned long now = millis();

  static int counter;
  byte bits;

  if (now - lastTime > 500) {

    bits = counter; //  ^ (counter >> 1);
//    publish(bits);
    Serial.print(counter); Serial.print("  "); Serial.println(bits, 2);
    counter++;
    counter &= 0x7f;

    lastTime = now;


    digitalWrite(xLED, !digitalRead(xLED));
  }

//return;

  for (unsigned char ii = 0; ii < SIZE; ii++)
    button[ii].loop();

  led.clear();

  for (unsigned char ii = 0; ii < SIZE; ii++) {
    if (button[ii].isPressed()) {
      bool toggleOK;
      toggleOK = !(puzzleBits & mask0[ii]) && (puzzleBits & mask1[ii]) == mask1[ii];
      toggleOK |= !ii;

      if (toggleOK) {
Serial.print(ii); Serial.println(" toggling");
//        if (puzzleBits & mask0[ii + 1]) puzzleBits &= ~mask0[ii + 1];
//        else puzzleBits |= mask0[ii + 1];
        puzzleBits ^= mask0[ii + 1];
      }
    }
  }

  for (unsigned char ii = 0; ii < SIZE; ii++)
    led.setPixelColor(ii, puzzleBits & (0x1 << ii) ? 0xff0000 : 0x0000ff);

  led.show();
//  delay(100);  kills ezButton?
}


// buttons and lamps
void loop0()
{
  for (unsigned char ii = 0; ii < SIZE; ii++)
    button[ii].loop();

  led.clear();
  for (unsigned char ii = 0; ii < SIZE; ii++)
    if (button[ii].isPressed())
      led.setPixelColor(ii, 0xff0000);

  led.show();

  delay(100);
}

// publish show-killing error and die
void fork(char *msg)
{
  Serial.print("Error, forked : ");
  Serial.println(msg);

  for (; ; );
}

HOT BEAT