Hallo,
ja, mit Schnittstellenformulierung muss ich mich auch tiefer befassen.
So, ich konnte das adaptieren. Mit "herkömmlichen" Konstrukturen und 4 Instanzen es waren Flash 4380 Byte, RAM 824 Byte. Mit template und davon die direkte "pin_x" Nutzung sind es Flash 3808 Byte, RAM 326 Byte. Nutze ich noch die templates Variablen relMin und relMax direkt ohne Default-Konstruktur Umweg, steigt der Flash sagenhaft an. Flash 4692 Byte, RAM 310 Byte.
Was mir noch etwas unklar ist, die Zeile template< ... steht irgendwie verloren einfach so da. Woher weiß der Compiler das es zur Klasse gehört? Keine geschweifte Klammer, nix. Die sonstigen Konstruktoren stehen doch innnerhalb der Klasse. Da ist mir der Zusammenhang klar.
using Register = volatile byte *;
// UNO, Nano, Pro Mini usw.
#if defined(__AVR_ATmega328P__) | defined(__AVR_ATmega328__) | defined(__AVR_ATmega168P__) | defined(__AVR_ATmega168__)
constexpr byte pinMaske[] = {0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000,};
constexpr Register portList[] = {&PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTD, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTB, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC,};
constexpr Register ddrList[] = {&DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRD, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRB, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC,};
constexpr Register pinList[] = {&PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PIND, &PINB, &PINB, &PINB, &PINB, &PINB, &PINB, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC,};
// #endif
// Mega
#elif defined(__AVR_ATmega2560__) | defined(__AVR_ATmega1280__)
constexpr byte pinMaske[] = {0b1, 0b10, 0b10000, 0b100000, 0b100000, 0b1000, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10, 0b1, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b10000000, 0b100, 0b10, 0b1, 0b10000000, 0b1000000, 0b100000, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0b1000, 0b100, 0b10, 0b1, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0b10000000,};
constexpr Register portList[] = {&PORTE, &PORTE, &PORTE, &PORTE, &PORTG, &PORTE, &PORTH, &PORTH, &PORTH, &PORTH, &PORTB, &PORTB, &PORTB, &PORTB, &PORTJ, &PORTJ, &PORTH, &PORTH, &PORTD, &PORTD, &PORTD, &PORTD, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTD, &PORTG, &PORTG, &PORTG, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTB, &PORTB, &PORTB, &PORTB, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTF, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK, &PORTK,};
constexpr Register ddrList[] = {&DDRE, &DDRE, &DDRE, &DDRE, &DDRG, &DDRE, &DDRH, &DDRH, &DDRH, &DDRH, &DDRB, &DDRB, &DDRB, &DDRB, &DDRJ, &DDRJ, &DDRH, &DDRH, &DDRD, &DDRD, &DDRD, &DDRD, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRA, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRC, &DDRD, &DDRG, &DDRG, &DDRG, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRL, &DDRB, &DDRB, &DDRB, &DDRB, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRF, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK, &DDRK,};
constexpr Register pinList[] = {&PINE, &PINE, &PINE, &PINE, &PING, &PINE, &PINH, &PINH, &PINH, &PINH, &PINB, &PINB, &PINB, &PINB, &PINJ, &PINJ, &PINH, &PINH, &PIND, &PIND, &PIND, &PIND, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINA, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PINC, &PIND, &PING, &PING, &PING, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINL, &PINB, &PINB, &PINB, &PINB, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINF, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK, &PINK,};
// #endif
#else
#error "This AVR type is currently not yet supported."
#endif
constexpr Register getOutPort(const byte pin) {
return portList[pin];
};
constexpr Register getDdrPort(const byte pin) {
return ddrList[pin];
};
constexpr Register getInPort(const byte pin) {
return pinList[pin];
};
constexpr byte getMaske(const byte pin) {
return pinMaske[pin];
};
template <byte pin_a, byte pin_b, byte raster = 0, int _min = 0, int _max = 0>
//template <byte pin_a, byte pin_b, byte raster = 0, int relMin = 0, int relMax = 0> // erhöht den Flashbedarf
class GrayEncoder // Klassenname "GrayEncoder"
{
protected: // private wird zu protected, nur intern zugängliche Elemente ...
int relMin;
int relMax;
byte shift; // Zählkorrektur wegen Steps pro Rastung
volatile long rel_counter; // relativer Zähler, veränderbar
volatile long abs_counter; // absoluter Zähler, nicht veränderbar
int direction; // Richtungsanzeige +1 / -1
int enc_delta;
int last;
byte phase_a; // erste Phase
byte phase_b; // zweite Phase
long abs_old;
int getPhases() {
int n = 0; // new
phase_a = bool(*getInPort(pin_a) & getMaske(pin_a));
phase_b = bool(*getInPort(pin_b) & getMaske(pin_b));
if ( phase_a ) n = 3;
if ( phase_b ) n ^= 1; // convert gray to binary
return n;
}
void update_RelativCounter () {
long new_abs = abs_counter >> shift; // halbiert, geviertelt oder ... Steps pro Rastung
if ( new_abs != abs_old) {
if (new_abs > abs_old) {
rel_counter++;
}
else {
rel_counter--;
}
abs_old = new_abs;
if (rel_counter < relMin) {
rel_counter = relMax;
}
else if (rel_counter > relMax) {
rel_counter = relMin;
}
}
}
public: // von außen zugängliche Elemente ...
GrayEncoder ():
// Initialisierungsliste
relMin(_min),
relMax(_max),
shift(raster/2),
rel_counter(_min), // Zähler
abs_counter(0), // Zähler
direction(0), // Richtungsanzeige +1 / -1
abs_old(0)
{ }
void init()
{
*getDdrPort(pin_a) &= ~getMaske(pin_a);
*getOutPort(pin_a) |= getMaske(pin_a);
*getDdrPort(pin_b) &= ~getMaske(pin_b);
*getOutPort(pin_b) |= getMaske(pin_b);
last = getPhases(); // power on state
enc_delta = 0;
}
void encode()
{
int n = getPhases();
int diff = last - n;
if ( diff & 1 ) { // bit 0 = value (1)
last = n; // store new as next last
enc_delta = (diff & 2) - 1; // bit 1 = direction (+/-), Zähler
abs_counter += (long) enc_delta;
direction = enc_delta; // Richtungsanzeige (+1 / -1)
}
update_RelativCounter();
}
int getDirection() {return direction; } // Richtungsabfrage
long getRelCounter() {return rel_counter; } // relativen Zählwert abfragen, ist schon angepasst
long getAbsCounter() {return abs_counter >> shift; } // absoluten Zählwert abfragen
int getA() { return phase_a; }
int getB() { return phase_a; }
};
// ---------------------------------------------------------------------------------------
GrayEncoder <37, 36, 4, 10, 20> Encoder1; // Phase A/B
GrayEncoder <37, 36, 4, 0, 10> ALPS_EM20B; // Phase A/B / Raster/ RelMin / RelMax
GrayEncoder <40, 41, 2, 0, 20> ALPS_EC11; // Phase A/B / Raster/ RelMin / RelMax
GrayEncoder <40, 41, 2> ALPS; // Phase A/B / Raster