// https://programmersqtcpp.blogspot.com/2022/01/arduinolcd-testo-scorrevoleadvanced.html
//#include <IRremote.h>
#include <IRremote.hpp>
#include <Wire.h>
#include "U8glib.h"
#include "RTClib.h"
#include <U8x8lib.h>
#include "iapps.h"
#include <avr/sleep.h>
//RTC_DS1307 rtc;
//DateTime dateTime;
#define PIN_RECEIVER 2 // Signal Pin of IR receiver
U8X8_SSD1306_128X64_NONAME_HW_I2C oled(/* reset=*/U8X8_PIN_NONE);
uint32_t uiVolTimer;
struct TextField {
uint8_t flags;
uint8_t *font;
char *buff;
uint8_t row;
uint8_t col;
};
#define INVERT (1 << 7)
#define IS_SHOW (1 << 6)
#define DRAW_2x2 (1 << 5)
TextField muteField = {
.flags = INVERT | 6,
.font = u8x8_font_8x13_1x2_r,
.buff = " Mute ",
.row = 6,
.col = 9
};
TextField heatingField = {
.flags = 7,
.font = u8x8_font_px437wyse700a_2x2_r,
.buff = "HEATING",
.row = 2,
.col = 1
};
TextField volumeField = {
.flags = 3 | DRAW_2x2,
.font = u8x8_font_px437wyse700a_2x2_r,
.buff = nullptr,
.row = 1,
.col = 1
};
TextField dBField = {
.flags = 2,
.font = u8x8_font_8x13_1x2_r,
.buff = "dB",
.row = 3,
.col = 14
};
TextField sourceMiniField = {
.flags = 5,
.font = u8x8_font_8x13_1x2_r,
.buff = nullptr,
.row = 6,
.col = 2
};
TextField workingTimeField = {
.flags = 8,
.font = u8x8_font_px437wyse700a_2x2_r,
//.buff = "71582788",
.buff = nullptr,
.row = 2,
.col = 0
};
GLB_STATE g_state = AT_PWR_OFF;
GLB_STATE g_prevState = AT_PWR_OFF;
GLB_PWR_STATE g_pwrState = PWR_OFF;
uint32_t heatingTimer;
uint32_t saveMillis;
void clearField(TextField &text) {
uint8_t len = text.flags & 0x0f;
char ibuff[len + 1];
ibuff[len] = '\0';
memset(ibuff, " ", len);
bool is2x2 = text.flags & DRAW_2x2;
oled.setFont(text.font);
if (is2x2)
oled.draw2x2String(text.col, text.row, ibuff);
else
oled.drawString(text.col, text.row, ibuff);
}
bool isShowField(TextField &text) {
return text.flags & IS_SHOW;
}
void setShowField(TextField &text, bool tf) {
if (tf)
text.flags |= IS_SHOW;
else
text.flags &= ~IS_SHOW;
}
void printField(TextField &text) {
if (text.buff == nullptr)
return;
bool is2x2 = text.flags & DRAW_2x2;
oled.setFont(text.font);
oled.setInverseFont(text.flags & INVERT);
if (is2x2)
oled.draw2x2String(text.col, text.row, text.buff);
else
oled.drawString(text.col, text.row, text.buff);
oled.setInverseFont(false);
}
void setup() {
Serial.begin(115200);
// aggiungendo rtc si presentano problemi di memoria
/*if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}*/
oled.setBusClock(400000);
appsInit();
IrReceiver.begin(PIN_RECEIVER);
oled.begin();
oled.setPowerSave(0);
if (appsPwrState()) {
g_state = AT_PWR_ON;
} else {
g_state = AT_PWR_OFF;
}
} // end void setup()
uint32_t workingTime = 0;
void mainState(uint8_t command) {
static bool saveMute = false;
switch(g_state) {
case AT_PWR_ON:
g_pwrState = PWR_ON;
setPwrOn();
oled.setPowerSave(0);
oled.clearDisplay();
// !!! CHANGE STATE !!!
g_state = HEATING;
appsServiceMute(true);
uiCurrentInput();
uiMute();
heatingTimer = millis();
break;
case HEATING:
if (!isShowField(heatingField)) {
printField(heatingField);
setShowField(heatingField, true);
} else
if (millis() - heatingTimer >= HEATING_TIME) {
// !!! CHANGE STATE !!!
g_state = RUN;
Serial.println("Heating end");
clearField(heatingField);
setShowField(heatingField, false);
appsPwrOn();
uiCurrentInput();
appsServiceMute(appsLastMute());
uiMute();
}
break;
case RUN:
if (isShowField(volumeField) && millis() - uiVolTimer > 1000) {
uiClearVolume();
uiCurrentInput();
}
break;
case AT_PWR_OFF:
if (g_pwrState == PWR_ON) {
oled.clearDisplay();
oled.setPowerSave(1);
// !!! CHANGE STATE !!!
g_state = AT_SLEEP;
appsPwrOff();
appsSetLastWorkTime(workingTime);
workingTime = 0;
} else if (millis() - saveMillis > 500) {
g_state = AT_SLEEP;
}
break;
case AT_SLEEP:
g_pwrState = PWR_OFF;
setPwrOff();
//set_sleep_mode (SLEEP_MODE_PWR_DOWN);
//noInterrupts ();
//g_pwrState = PWR_OFF;
// !!! CHANGE STATE !!!
g_state = AT_PWR_OFF;
//sleep_enable();
//interrupts ();
//sleep_cpu ();
// questo while simula lo sleep cpu.
while (digitalRead(2) == HIGH) {
if (pwrBtn.read()) {
break;
}
}
saveMillis = millis();
break;
}
}
bool wasPressedFor;
void loop() {
static uint32_t prevTime;
pwrBtn.read();
muteBtn.read();
nextBtn.read();
prevBtn.read();
volPlusBtn.read();
volMinusBtn.read();
if (g_state == RUN
|| g_state == AT_PWR_ON
|| g_state == HEATING) {
// 1000(secondi) o 60000U(minuti)
if (millis() - prevTime > 60000U) {
// accumula tempo in secondi o minuti
workingTime++;
prevTime = millis();
}
}
uint8_t command = 0;
// Checks received an IR signal
if (IrReceiver.decode()) {
command = IrReceiver.decodedIRData.command;
//translateIR();
Serial.println(command);
IrReceiver.resume(); // Receive the next value
} else {
if (!wasPressedFor && pwrBtn.pressedFor(200)) {
wasPressedFor = true;
command = CMD_POWER;
}
if (wasPressedFor && pwrBtn.releasedFor(200)) {
wasPressedFor = false;
}
if (nextBtn.wasPressed()) {
command = CMD_NEXT;
}
if (prevBtn.wasPressed()) {
command = CMD_PREV;
}
if (volPlusBtn.isPressed(150)) {
command = CMD_PLUS;
}
if (volMinusBtn.isPressed(150)) {
command = CMD_MINUS;
}
if (muteBtn.wasPressed()) {
command = CMD_PLAY;
}
}
runCommand(command);
mainState(command);
} // end void loop()
void clsRow0() {
oled.setCursor(0, 0);
oled.print(" "); // 16 spazi
}
void lcdPrint(char* text)
{
clsRow0();
oled.setCursor(0, 0);
oled.print(text);
/*oled.print(" (");
oled.print(receiver.decodedIRData.command);
oled.print(")");*/
}
void uiClearVolume() {
clearField(volumeField);
clearField(dBField);
setShowField(dBField, false);
setShowField(volumeField, false);
}
void uiCurrentVolume() {
if (!isShowField(dBField)) {
printField(dBField);
setShowField(dBField, true);
}
char str[4];
str[3] = '\0';
sprintf(str, "%#3d", appsCurrentVolume());
volumeField.buff = str;
printField(volumeField);
setShowField(volumeField, true);
if (isShowField(volumeField))
uiVolTimer = millis();
}
void uiClearCurrentInput() {
oled.setFont(u8x8_font_8x13_1x2_r);
oled.draw2x2String(3, 1, " ");
}
void uiCurrentInput() {
clearField(sourceMiniField);
sourceMiniField.buff = appsCurrentInputName();
printField(sourceMiniField);
if (g_state != RUN)
return;
if (isShowField(volumeField)) {
uiClearVolume();
setShowField(volumeField, false);
}
oled.setFont(u8x8_font_8x13_1x2_r);
switch (appsCurrentInput()) {
case 0:
oled.draw2x2String(3, 1, "PHONO");
break;
case 1:
oled.draw2x2String(2, 1, " CD ");
break;
case 2:
oled.draw2x2String(2, 1, " AUX1");
break;
case 3:
oled.draw2x2String(2, 1, " AUX2");
break;
}
}
void uiMute() {
if (appsMuteState() == true) {
printField(muteField);
} else {
clearField(muteField);
}
}
void uiWorkingTime() {
if (!isShowField(workingTimeField)) {
uint32_t hour = (appsLastWorkTime() + workingTime) / 60;
uint8_t len = workingTimeField.flags & 0x0f;
char ibuff[len + 1];
sprintf(ibuff, "%#8u", hour);
workingTimeField.buff = ibuff;
uiClearCurrentInput();
printField(workingTimeField);
setShowField(workingTimeField, true);
} else {
clearField(workingTimeField);
setShowField(workingTimeField, false);
uiCurrentInput();
}
}
void runCommand(uint8_t command) {
// Takes command based on IR code received
switch (command) {
case CMD_POWER:
if (g_pwrState == PWR_ON) {
// !!! CHANGE STATE !!!
g_state = AT_PWR_OFF;
} else {
// !!! CHANGE STATE !!!
g_state = AT_PWR_ON;
}
//lcdPrint("POWER");
break;
case CMD_MENU:
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("MENU");
break;
case CMD_TEST:
if (isShowField(volumeField))
return;
//lcdPrint("TEST");
uiWorkingTime();
Serial.println(appsLastWorkTime() + workingTime);
break;
case CMD_PLUS:
if (isShowField(workingTimeField))
return;
/*if (g_pwrState == PWR_OFF)
return;*/
//lcdPrint("PLUS");
if (isShowField(volumeField))
appsIncVol();
uiCurrentVolume();
break;
case 194:
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("BACK");
break;
case CMD_PREV:
if (isShowField(workingTimeField))
return;
/*if (g_pwrState == PWR_OFF)
return;*/
//lcdPrint("PREV.");
if (!isShowField(volumeField))
appsPrevInput();
uiCurrentInput();
break;
case CMD_PLAY:
//lcdPrint("PLAY");
if (g_state == RUN) {
appsToggleMute();
uiMute();
}
break;
case CMD_NEXT:
if (isShowField(workingTimeField))
return;
/*if (g_pwrState == PWR_OFF)
return;*/
//lcdPrint("NEXT");
if (!isShowField(volumeField))
appsNextInput();
uiCurrentInput();
break;
case CMD_MINUS:
if (isShowField(workingTimeField))
return;
/*if (g_pwrState == PWR_OFF)
return;*/
//lcdPrint("MINUS");
if (isShowField(volumeField))
appsDecVol();
uiCurrentVolume();
break;
case 176:
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("key: C");
break;
case CMD_ZERO:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 0");
appsSetCurrentInput(0);
uiCurrentInput();
break;
case CMD_UNO:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 1");
appsSetCurrentInput(1);
uiCurrentInput();
break;
case CMD_DUE:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 2");
appsSetCurrentInput(2);
uiCurrentInput();
break;
case CMD_TRE:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 3");
appsSetCurrentInput(3);
uiCurrentInput();
break;
case CMD_QUATTRO:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 4");
appsSetCurrentInput(4);
uiCurrentInput();
break;
case CMD_CINQUE:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 5");
appsSetCurrentInput(5);
uiCurrentInput();
break;
case CMD_SEI:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 6");
appsSetCurrentInput(6);
uiCurrentInput();
break;
case CMD_SETTE:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 7");
appsSetCurrentInput(7);
uiCurrentInput();
break;
case 74:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 8");
appsSetCurrentInput(8);
uiCurrentInput();
break;
case 82:
if (isShowField(workingTimeField))
return;
if (g_pwrState == PWR_OFF)
return;
//lcdPrint("num: 9");
appsSetCurrentInput(9);
uiCurrentInput();
break;
default:
/*clsRow0();
oled.setCursor(0, 0);
oled.print(receiver.decodedIRData.command);
oled.print(" other button");*/
break;
}
}