// https://programmersqtcpp.blogspot.com/2022/04/arduino-lcd-con-sprintf.html
#include <Wire.h>
//#include <U8glib.h>
//#include <IRremote.h>
#include <IRremote.hpp>
//#include "RTClib.h"
//#include <U8x8lib.h>
#include <JC_Button.h>
Button btnEncoder(7);
#define IR_RECEIVE_PIN 2 // Signal Pin of IR receiver
//IRrecv receiver(PIN_RECEIVER);
static
const uint8_t SEQ_TAB[7][4] = {
{ 0, 4, 1, 0 } // 0
, { 2, 1, 1, 0 } // 1
, { 2, 3, 1, 2 } // 2
, { 2, 3, 3, 0 } // 3
, { 5, 4, 4, 0 } // 4
, { 5, 4, 6, 5 } // 5
, { 5, 6, 6, 0 } // 6
};
// dichiarazione preventiva di GCounter
template <typename T>
class GCounter;
// classe Encoder
class Encoder {
public:
// default ctor
// Encoder encoder;
void begin(uint8_t a, uint8_t b, void (*userFunc)(void)) {
m_pinA = a;
m_pinB = b;
attachInterrupt(digitalPinToInterrupt(m_pinA), userFunc, CHANGE);
attachInterrupt(digitalPinToInterrupt(m_pinB), userFunc, CHANGE);
}
int16_t getCounter() {
int16_t s = counter;
clear();
m_isChanged = false;
return s;
}
void clear() {
m_oldCounter = counter = 0;
}
bool isChanged() { return m_isChanged; }
enum ptrType_e {enullptr, eiptr, efptr};
void isrEvent() {
uint8_t ab = (digitalRead(m_pinB) << 1)
| digitalRead(m_pinA);
if (3 == m_seq && 3 == ab) {
counter++;
// non gli sta bene la forward declare di GCounter
// dovrò usare qualche funzione di libreria stl
/*GCounter<int> *gc = (GCounter<int> *)pGcounter;
gc->inc();*/
//Serial.println(counter);
} else if (6 == m_seq && 3 == ab) {
counter--;
}
if (counter != m_oldCounter) {
m_oldCounter = counter;
m_isChanged = true;
}
m_seq = SEQ_TAB[m_seq][ab];
}
void setGCounter(GCounter<int> *iptr) {
pGcounter = iptr;
ptyp = eiptr;
}
void setGCounter(GCounter<float> *fptr) {
pGcounter = fptr;
ptyp = efptr;
}
private:
uint8_t m_seq;
volatile int16_t counter;
int16_t m_oldCounter;
bool m_isChanged;
uint8_t m_pinA;
uint8_t m_pinB;
void *pGcounter;
ptrType_e ptyp = enullptr;
};
template <typename T>
class GCounter {
public:
GCounter(T v, T l, T h, T s ) {
oldCounter = counter = v;
low = l;
high = h;
step = s;
toRange();
}
// restituisce il valore del contatore counter
T value() {
oldCounter = counter;
m_isChanged = false;
return counter;
}
void inc() {}
// void setEncoder(Encoder *ePtr)
// Obligatorio assegnare un puntatore ad oggetto
// di classe Encoder
void setEncoder(Encoder *ePtr) {
m_enc = ePtr;
ePtr->clear();
}
bool isChanged() {
return m_isChanged;
}
void run() {
if (m_enc == nullptr && !m_enc->isChanged())
return;
int16_t i = m_enc->getCounter();
counter += i * step;
toRange();
if (counter != oldCounter) {
oldCounter = counter;
m_isChanged = true;
}
}
private:
// void toRange()
// riporta il valore al range specificato con:
// l low value
// h high value
void toRange() {
if (counter > high) {
counter = high;
} else if (counter < low) {
counter = low;
}
}
bool m_isChanged;
Encoder *m_enc; // puntatore a classe Encoder
T oldCounter;
T counter;
T low; // valore minimo
T high; // valore massimo consentito
T step; // di quanto incrementa/decrementa counter
};
Encoder enc0;
GCounter<int16_t> acounter(-1000, -100, 100, 1);
GCounter<float> bcounter(-63, -63, 0, 0.5);
//GCounter *gptr = &bcounter;
float vf = 101.5;
// errore: -std=c++1z deduce il tipo dalla variabile
//GCounter vfc(vf, 0.0, 200.0, 1.0);
//U8X8_SSD1306_128X64_NONAME_HW_I2C oled(/* reset=*/U8X8_PIN_NONE);
/*void oledInit() {
oled.setBusClock(400000);
oled.begin();
oled.setPowerSave(0);
}*/
//uint8_t m_seq;
void isrEnc() {
enc0.isrEvent();
}
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
btnEncoder.begin();
//pinMode(18, INPUT_PULLUP);
//pinMode(19, INPUT_PULLUP);
enc0.begin(19, 18, isrEnc);
//bcounter.setEncoder(&enc0);
IrReceiver.begin(IR_RECEIVE_PIN);
//oledInit();
}
uint8_t state;
void loop() {
//uint8_t signalStates = 0b11011100; // Leggi gli stati dei segnali utilizzando la manipolazione diretta del port
//int status = (~signalStates >> 2) & 0b00111111;
//Serial.println(status);
btnEncoder.read();
switch (state) {
case 0:
bcounter.setEncoder(&enc0);
Serial.println("## Change bcounter ##");
Serial.println(bcounter.value());
state = 1;
break;
case 1:
bcounter.run();
if (bcounter.isChanged()) {
auto v = bcounter.value();
Serial.println(v);
}
if (btnEncoder.wasPressed())
state = 2;
break;
case 2:
acounter.setEncoder(&enc0);
Serial.println("## Change acounter ##");
Serial.println(acounter.value());
state = 3;
break;
case 3:
acounter.run();
if (acounter.isChanged()) {
auto v = acounter.value();
Serial.println(v);
}
if (btnEncoder.wasPressed())
state = 0;
break;
}
} // end void loop()