/*
  Rotary Encoder volume control example

  Usage: rotate the knob to control the value,
  click the knob to change between volume/bass/treble.

  Original sketch:
  https://wokwi.com/arduino/projects/304919215794553409

  Released under the MIT license.
  Copyright (C) 2021, Uri Shaked.
*/

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/Picopixel.h>
#include "cffencoder.h"
const unsigned char fanBmp[] PROGMEM = {
  0x00, 0x0f, 0xc0, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0xff, 0xfe, 0x00,
  0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0x00,
  0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xf8, 0x00,
  0x00, 0x7f, 0xf0, 0x00, 0x00, 0x3f, 0xc3, 0xc0, 0x1f, 0x0f, 0xcf, 0xf0, 0x3f, 0xc5, 0xbf, 0xfc,
  0x7f, 0xf3, 0xbf, 0xfe, 0xff, 0xfb, 0xbf, 0xfe, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x7f, 0xff, 0x3f, 0xfe,
  0x7f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf8, 0x1f, 0xfc, 0x3f, 0xf0,
  0x0f, 0xf0, 0x1f, 0xe0, 0x07, 0xe0, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#define ENCODER_CLK 4
#define ENCODER_DT  5
#define ENCODER_SW  6

uint8_t volume = 50;
uint8_t bass = 25;
uint8_t treble = 65;

uint32_t ms;

typedef enum {
  SET_VOLUME,
  SET_BASS,
  SET_TREBLE,
} Mode;

Mode mode = SET_VOLUME;
int8_t ctrDelta;

Adafruit_SSD1306 display(128, 64, &Wire, -1);

void nextMode() {
  switch (mode) {
    case SET_VOLUME:
      mode = SET_BASS;
      break;

    case SET_BASS:
      mode = SET_TREBLE;
      break;

    case SET_TREBLE:
      mode = SET_VOLUME;
      break;
  }
}

void drawBar(const char *label, int16_t r, int16_t c, byte l, byte h) {
  byte lenLabel = strlen(label);
  byte centerLabel = (lenLabel / 2) * 6;
  byte cLabel = ((l + 2) / 2) - centerLabel + c;
  //Serial.println(cLabel);
  display.setCursor(cLabel, r - 9);
  display.print(label);
  display.drawRoundRect(c, r, l + c + 2, h + 2, 2, WHITE);
}


void updateDisplay(bool init = false) {
  static byte currMode = mode;
  if (init) {
    //Serial.println(mode);
    display.clearDisplay();
    display.setFont();
    display.setTextColor(1);

    drawBar("Volume", 12, 10, 90, 5);
    display.fillRect(11, 13, volume, 5, WHITE);
    display.setCursor(31, 2);
    display.print(">");

    drawBar("Bass", 30, 10, 90, 5);
    display.fillRect(11, 31, bass, 5, WHITE);

    drawBar("Treble", 50, 10, 90, 5);
    display.fillRect(11, 51, treble, 5, WHITE);
  }

  if (currMode == mode) {
    if (mode == SET_VOLUME) {
      volume = constrain(volume + ctrDelta, 0, 100);
      display.fillRect(11, 13, 100, 5, BLACK);
      display.fillRect(11, 13, volume, 5, WHITE);

    } else if (mode == SET_BASS) {
      bass = constrain(bass + ctrDelta, 0, 100);
      display.fillRect(11, 31, 100, 5, BLACK);
      display.fillRect(11, 31, bass, 5, WHITE);
    } else if (mode == SET_TREBLE) {
      treble = constrain(treble + ctrDelta, 0, 100);
      display.fillRect(11, 51, 100, 5, BLACK);
      display.fillRect(11, 51, treble, 5, WHITE);
    }
  } else {
    // ->(currMode != mode) is(true)
    if (currMode == SET_VOLUME) {
      display.setCursor(31, 2);
      display.setTextColor(0);
      display.print(">");
    } else if (currMode == SET_BASS) {
      display.setCursor(37, 20);
      display.setTextColor(0);
      display.print(">");
    } else if (currMode == SET_TREBLE) {
      display.setCursor(31, 40);
      display.setTextColor(0);
      display.print(">");
    }

    if (mode == SET_VOLUME) {
      display.setCursor(31, 2);
      display.setTextColor(1);
      display.print(">");
    } else if (mode == SET_BASS) {
      display.setCursor(37, 20);
      display.setTextColor(1);
      display.print(">");
    } else if (mode == SET_TREBLE) {
      display.setCursor(31, 40);
      display.setTextColor(1);
      display.print(">");
    }
    currMode = mode;
  }
  ms = millis();
  display.display();
  Serial.print("t:");
  Serial.println(millis() - ms);

}
int h = 25;
  int setVal = 30;

void form0() {
  display.drawBitmap(92, 5, fanBmp, 32, 32, WHITE);
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println(F("Ambiente"));
  display.setCursor(0, 40);
  display.println(F("SET"));
  display.drawFastHLine(0, 32, 87, WHITE);
  display.drawFastVLine(87, 0, 64, WHITE);
  display.display();
}

void stampaValori() {
  
  display.fillRect(25, 48, 35, 15, BLACK);
  display.fillRect(25, 15, 35, 15, BLACK);
  display.fillRect(92, 48, 35, 20, BLACK);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(25, 15);
  display.print(h);
  display.println("%");
  display.setCursor(25, 48);
  display.print(setVal);
  display.println(F("%"));
 
  display.setCursor(92, 48);
  display.println(1 ? "OFF" : "ON");
}

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

  pinMode(LED_BUILTIN, OUTPUT);
  Wire.setClock(400000);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  Wire.setClock(400000);
  pinMode(ENCODER_SW, INPUT_PULLUP);
  pinMode(ENCODER_CLK, INPUT_PULLUP);
  pinMode(ENCODER_DT, INPUT_PULLUP);

  init_encoder(ENCODER_CLK, ENCODER_DT);
  display.clearDisplay();
  display.setFont();

  form0();
  for (uint8_t i = 0; i < 100; i++) {
    stampaValori();
    display.display();
    h++;
    setVal++;
  }
  Serial.println("End,");
  //updateDisplay(true);

}

long int modeLastChanged = 0;
int prevClk = HIGH;

void loop() {
  ms = millis();
  if (digitalRead(ENCODER_SW) == LOW && millis() - modeLastChanged > 100) {
    modeLastChanged = millis();
    nextMode();
    updateDisplay();

  }

  int8_t e = rencoder();
  if (e != 0 && e != ERR_UNCFG) {
    ctrDelta = e == HIGH ? 5 : -5;

    updateDisplay();
    //Serial.println(millis() - ms);
  }
  //delay(1);

}
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:GND.2
uno:RESET.2
uno:0
uno:1
uno:13
uno:3.3V
uno:AREF
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
uno:A6
uno:A7
uno:5V
uno:RESET
uno:GND.1
uno:VIN
uno:12.2
uno:5V.2
uno:13.2
uno:11.2
uno:RESET.3
uno:GND.3
encoder1:CLK
encoder1:DT
encoder1:SW
encoder1:VCC
encoder1:GND
oled2:GND
oled2:VCC
oled2:SCL
oled2:SDA