#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SCREEN_MIDDLE SCREEN_HEIGHT/2
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int w = 128, h = 64; // OLED width and height
int a, b, x, y, z, c[64]; // for bars
int rollover = 100; // for dots
int xVal = 0; // trace location. left edge of OLED = 0

int hist[200]; // jremington
int n = 10000; // jremington

void setup() {
  Serial.begin(9600);

  // jrem(); // must be in setup(), and comment-out the OLED lines in setup()

  randomSeed(analogRead(A0));
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
  display.display();
}

void loop() {
  // jrem(); // if in loop(), first value is 0 to 199, second value keeps increasing
  // dots(); // fill the screen with dots
  bars(); // bar graph
  // center(); // move dot left and right
  // life();
  // trace();
}

void trace() {
  int yVal = map(analogRead(A0), 0, 1023, SCREEN_HEIGHT / 2, -SCREEN_HEIGHT / 2); // INPUT min/max

  display.drawLine(xVal, 0, xVal, 63, BLACK); // verticle line to erase old trace
  display.drawPixel(xVal - 1, SCREEN_MIDDLE + yVal, WHITE); // the trace
  display.display();

  xVal++; // move to next pixel
  if (xVal == 128) { // if at OLED right edge
    xVal = 0; // reset xVal to left edge
  }
}

void jrem() { // jremington
  //random number distribution histogram, Arduino Uno
  // int hist[200];
  // int n = 10000;
  while (!Serial);
  for (int i = 0; i < n; i++) hist[random(200)]++;
  for (int i = 0; i < 200; i++) {
    Serial.print(i);
    Serial.print(", ");
    Serial.println(hist[i]);
  }
}

void life() {
  int x = random(128);
  int y = random(64);
  int z = random(2);

  if (z)
    display.drawPixel(x, y, 1);
  else
    display.drawPixel(x, y, 0);
  display.display();
}

void center() {
  // start center, add -1, 0, 1 (move left, no move, move right)
  display.drawLine(w / 2, h / 2 + 1, w / 2, h, WHITE); // reference line
  display.display();

  x = w / 2; // middle of OLED
  y = random(-1, 2); // -1, 0, 1
  x += y; // left, none, right

  display.drawPixel(z, 31, BLACK); // erase old pixel
  display.drawPixel(x, 31, WHITE); // draw new pixel
  display.display();
  z = x; // new pixel becomes old pixel
}

void bars() { // rotating axes 90 degrees causes spurious verticle pixels near mid screen
  b = random(h); // column
  c[b]++; // accumulate columns
  if (c[b] > 127)
    c[b] = 0;
  a = c[b]; // for cleaner drawPixel()
  display.drawPixel(a, b, WHITE);
  display.display();
}

void dots() {
  display.drawPixel(random(128), random(64), WHITE);
  display.display();
  x++;
  if (x == rollover) { // 100 = 10^2
    x = 0;
    // Serial.print("x");
    y++;
    if (y == rollover) { // 100 * 100 = 10^4
      y = 0;
      Serial.println(rollover * rollover);
      z++;
      if (z == rollover) { // 100 * 100 * 100 = 10^6
        z = 0;
        Serial.println(rollover * rollover * rollover);
      }
    }
  }
}