// 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;
template<typename T>
void t_constrain(T &val, T min, T max) {
if (val < min)
val = min;
if (val > max)
val = max;
}
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();
float v = 10;
t_constrain(v, -63.5f, 0.0f);
Serial.println(v);
}
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()
mega:SCL
mega:SDA
mega:AREF
mega:GND.1
mega:13
mega:12
mega:11
mega:10
mega:9
mega:8
mega:7
mega:6
mega:5
mega:4
mega:3
mega:2
mega:1
mega:0
mega:14
mega:15
mega:16
mega:17
mega:18
mega:19
mega:20
mega:21
mega:5V.1
mega:5V.2
mega:22
mega:23
mega:24
mega:25
mega:26
mega:27
mega:28
mega:29
mega:30
mega:31
mega:32
mega:33
mega:34
mega:35
mega:36
mega:37
mega:38
mega:39
mega:40
mega:41
mega:42
mega:43
mega:44
mega:45
mega:46
mega:47
mega:48
mega:49
mega:50
mega:51
mega:52
mega:53
mega:GND.4
mega:GND.5
mega:IOREF
mega:RESET
mega:3.3V
mega:5V
mega:GND.2
mega:GND.3
mega:VIN
mega:A0
mega:A1
mega:A2
mega:A3
mega:A4
mega:A5
mega:A6
mega:A7
mega:A8
mega:A9
mega:A10
mega:A11
mega:A12
mega:A13
mega:A14
mega:A15
oled1:GND
oled1:VCC
oled1:SCL
oled1:SDA
ir1:GND
ir1:VCC
ir1:DAT
encoder1:CLK
encoder1:DT
encoder1:SW
encoder1:VCC
encoder1:GND