/*
Forum: https://forum.arduino.cc/t/anderung-button-box/1291200
Wokwi: https://wokwi.com/projects/406127235095478273
*/
#include <Keypad.h>
#include "Joystick.h"
#define ENABLE_PULLUPS
#define NUMROTARIES 4
//#defin
#define NUMROWS 5
#define NUMCOLS 5
byte buttons[NUMROWS][NUMCOLS] = {
{ 0, 1, 2, 3, 4 },
{ 5, 6, 7, 8, 9 },
{ 10, 11, 12, 13, 14 },
{ 15, 16, 17, 18, 19 },
{ 20, 21, 22, 23 },
};
struct rotariesdef {
byte pin1;
byte pin2;
int ccwchar;
int cwchar;
volatile unsigned char state;
};
/*
rotariesdef rotaries[NUMROTARIES]{
{ 0, 1, 24, 25, 0 },
{ 2, 3, 26, 27, 0 },
{ 4, 5, 28, 29, 0 },
{ 6, 7, 30, 31, 0 },
};
*/
rotariesdef rotaries[NUMROTARIES] {
{ A0, A1, 24, 25, 0 },
{ A2, A3, 26, 27, 0 },
{ A4, A5, 28, 29, 0 },
{ A6, A7, 30, 31, 0 },
};
#define DIR_CCW 0x10
#define DIR_CW 0x20
#define R_START 0x0
#ifdef HALF_STEP
#define R_CCW_BEGIN 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5
const unsigned char ttable[6][4] = {
// R_START (00)
{ R_START_M, R_CW_BEGIN, R_CCW_BEGIN, R_START },
// R_CCW_BEGIN
{ R_START_M | DIR_CCW, R_START, R_CCW_BEGIN, R_START },
// R_CW_BEGIN
{ R_START_M | DIR_CW, R_CW_BEGIN, R_START, R_START },
// R_START_M (11)
{ R_START_M, R_CCW_BEGIN_M, R_CW_BEGIN_M, R_START },
// R_CW_BEGIN_M
{ R_START_M, R_START_M, R_CW_BEGIN_M, R_START | DIR_CW },
// R_CCW_BEGIN_M
{ R_START_M, R_CCW_BEGIN_M, R_START_M, R_START | DIR_CCW },
};
#else
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6
const unsigned char ttable[7][4] = {
// R_START
{ R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START },
// R_CW_FINAL
{ R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW },
// R_CW_BEGIN
{ R_CW_NEXT, R_CW_BEGIN, R_START, R_START },
// R_CW_NEXT
{ R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START },
// R_CCW_BEGIN
{ R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START },
// R_CCW_FINAL
{ R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW },
// R_CCW_NEXT
{ R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START },
};
#endif
byte rowPins[NUMROWS] = { 21, 20, 19, 18, 15 };
byte colPins[NUMCOLS] = { 14, 16, 10, 9, 8 };
Keypad buttbx = Keypad(makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS);
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,
JOYSTICK_TYPE_JOYSTICK, 32, 0,
false, false, false, false, false, false,
false, false, false, false, false);
// Für die LED Steuerung
const byte led1Pin = 12;
const byte led2Pin = 11;
// Die den Button zugeordneten Werte, die zum "Zündung an" (button1)
// und zum "Motor starten" (button2)
const byte button1 = 0; // Bei Wokwi BLAU
const byte button2 = 1; // Bei Wokwi ROT
byte button1State = HIGH; // Ledstatus, der beim nächsten Tastendruck button1 gesetzt werden soll
void setup() {
Joystick.begin();
rotary_init();
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
setLed1(LOW);
setLed2(LOW);
}
void loop() {
CheckAllEncoders();
CheckAllButtons();
}
void setLed1(byte state) {
digitalWrite(led1Pin, state);
}
void setLed2(byte state) {
digitalWrite(led2Pin, state);
}
void setLeds(byte state) {
setLed1(state);
setLed2(state);
}
void handleLeds(byte kchar) {
switch (kchar) {
case button1:
Serial.print("ZÜNDUNG ");
Serial.println((button1State == HIGH) ? "Ein" : "Aus");
setLeds(button1State);
button1State = !button1State;
break;
case button2:
if (button1State) {
Serial.println("Die Zündung ist aus!");
} else {
Serial.println("Motor wird gestarted");
}
setLeds(LOW);
button1State = HIGH;
break;
}
}
void CheckAllButtons(void) {
if (buttbx.getKeys()) {
for (int i = 0; i < LIST_MAX; i++) {
if (buttbx.key[i].stateChanged) {
switch (buttbx.key[i].kstate) {
case PRESSED:
handleLeds(buttbx.key[i].kchar);
case HOLD:
Joystick.setButton(buttbx.key[i].kchar, 1);
break;
case RELEASED:
case IDLE:
Joystick.setButton(buttbx.key[i].kchar, 0);
break;
}
}
}
}
}
void rotary_init() {
for (int i = 0; i < NUMROTARIES; i++) {
pinMode(rotaries[i].pin1, INPUT);
pinMode(rotaries[i].pin2, INPUT);
#ifdef ENABLE_PULLUPS
digitalWrite(rotaries[i].pin1, HIGH);
digitalWrite(rotaries[i].pin2, HIGH);
#endif
}
}
unsigned char rotary_process(int _i) {
unsigned char pinstate = (digitalRead(rotaries[_i].pin2) << 1) | digitalRead(rotaries[_i].pin1);
rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate];
return (rotaries[_i].state & 0x30);
}
void CheckAllEncoders(void) {
for (int i = 0; i < NUMROTARIES; i++) {
unsigned char result = rotary_process(i);
if (result == DIR_CCW) {
Joystick.setButton(rotaries[i].ccwchar, 1);
delay(50);
Joystick.setButton(rotaries[i].ccwchar, 0);
};
if (result == DIR_CW) {
Joystick.setButton(rotaries[i].cwchar, 1);
delay(50);
Joystick.setButton(rotaries[i].cwchar, 0);
};
}
}