2022-02-18 18:15:30 +01:00
|
|
|
/**
|
|
|
|
* \file cimdit.ino
|
|
|
|
* \brief main functions
|
|
|
|
* \author GrumpyDeveloper (Sascha Nitsch)
|
|
|
|
* \copyright 2022 Sascha Nitsch
|
|
|
|
* Licensed under MIT license
|
|
|
|
*
|
|
|
|
*/
|
2022-03-12 21:36:54 +01:00
|
|
|
// defines
|
|
|
|
#include "defines.h"
|
2022-02-18 18:15:30 +01:00
|
|
|
|
|
|
|
// library includes
|
|
|
|
#include <HID-Project.h>
|
|
|
|
#ifdef HAVE_DISPLAY
|
2022-03-12 21:36:54 +01:00
|
|
|
#include "cimditssd1306.h"
|
2022-02-18 18:15:30 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// own includes
|
|
|
|
#include "cimdithal.h"
|
2022-03-12 21:36:54 +01:00
|
|
|
#include "cimditprofile.h"
|
2022-02-18 18:15:30 +01:00
|
|
|
|
|
|
|
/// our hardware abstraction layer
|
|
|
|
CimditHAL hal;
|
|
|
|
|
|
|
|
/// flag if the rotary interrupt has been triggered
|
|
|
|
volatile bool outstandingRotInterrupt = false;
|
|
|
|
|
|
|
|
/// interrupt service routine for rotatry change interrupt
|
|
|
|
void rotInt() {
|
|
|
|
outstandingRotInterrupt = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// next update time in ms
|
|
|
|
uint32_t nextUpdate = 0;
|
2022-03-12 21:36:54 +01:00
|
|
|
|
2022-02-18 18:15:30 +01:00
|
|
|
#ifdef HAVE_DISPLAY
|
|
|
|
/// our display
|
2022-03-12 21:36:54 +01:00
|
|
|
CimditSSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_ADDRESS);
|
2022-02-18 18:15:30 +01:00
|
|
|
#endif
|
2022-03-12 21:36:54 +01:00
|
|
|
|
|
|
|
// our profile handling class
|
|
|
|
CimditProfile profile;
|
|
|
|
|
2022-02-18 18:15:30 +01:00
|
|
|
/// initial setup
|
|
|
|
void setup() {
|
|
|
|
Serial.begin(115200);
|
|
|
|
hal.begin();
|
|
|
|
attachInterrupt(digitalPinToInterrupt(7), rotInt, RISING);
|
2022-03-12 21:36:54 +01:00
|
|
|
// initialize USB related things
|
2022-02-18 18:15:30 +01:00
|
|
|
Keyboard.begin();
|
|
|
|
Mouse.begin();
|
|
|
|
Gamepad.begin();
|
2022-03-12 21:36:54 +01:00
|
|
|
Wire.begin();
|
|
|
|
Wire.setClock(400000);
|
2022-02-18 18:15:30 +01:00
|
|
|
#ifdef HAVE_DISPLAY
|
|
|
|
// init display
|
2022-03-12 21:36:54 +01:00
|
|
|
display.begin();
|
2022-02-18 18:15:30 +01:00
|
|
|
display.clearDisplay();
|
2022-03-12 21:36:54 +01:00
|
|
|
display.setTextSize(2,2);
|
|
|
|
display.setCursor(28, 8);
|
|
|
|
display.write("cimdit");
|
2022-02-18 18:15:30 +01:00
|
|
|
display.display();
|
|
|
|
#endif
|
2022-03-12 21:36:54 +01:00
|
|
|
profile.begin();
|
2022-02-18 18:15:30 +01:00
|
|
|
}
|
|
|
|
|
2022-03-12 21:36:54 +01:00
|
|
|
/// protection string
|
|
|
|
const char protectString[] = "cimdit:";
|
|
|
|
|
|
|
|
/// current position in protection string
|
|
|
|
uint8_t protectPos = 0;
|
|
|
|
|
2022-02-18 18:15:30 +01:00
|
|
|
/// main loop
|
|
|
|
void loop() {
|
|
|
|
hal.readFromHardware(outstandingRotInterrupt);
|
|
|
|
if (outstandingRotInterrupt) {
|
|
|
|
outstandingRotInterrupt = false;
|
|
|
|
return;
|
|
|
|
}
|
2022-03-12 21:36:54 +01:00
|
|
|
profile.tick();
|
|
|
|
if (Serial.available()) {
|
|
|
|
// incoming message
|
|
|
|
uint8_t in;
|
|
|
|
while ((in = Serial.read()) != 255) {
|
|
|
|
if (protectString[protectPos++] != in) {
|
|
|
|
protectPos = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (protectPos == sizeof(protectString) - 1) { // good, something for us
|
|
|
|
protectPos = 0;
|
|
|
|
// every line has to start with cimdit: or it will be ignored
|
|
|
|
uint8_t cmd = Serial.read();
|
|
|
|
switch (cmd) {
|
|
|
|
case 'd':
|
|
|
|
profile.userDisplay();
|
|
|
|
break;
|
|
|
|
case 'p': { // print something on display
|
|
|
|
uint8_t timeout = 0;
|
|
|
|
// read number for time to display
|
|
|
|
do {
|
|
|
|
cmd = Serial.read();
|
|
|
|
if (cmd != ',') {
|
|
|
|
timeout = timeout * 10 + cmd - '0';
|
|
|
|
}
|
|
|
|
} while (cmd != ',');
|
|
|
|
char tmp[43] = {0};
|
|
|
|
uint8_t pos = 0;
|
|
|
|
// now we expect the string, terminated by \n
|
|
|
|
do {
|
|
|
|
cmd = Serial.read();
|
|
|
|
if (cmd != '\n') {
|
|
|
|
tmp[pos++] = cmd;
|
|
|
|
}
|
|
|
|
} while (cmd != '\n' && pos < 43 && cmd != 255);
|
|
|
|
profile.setUserString(timeout, tmp);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'f': // read flash
|
|
|
|
profile.printFlash();
|
|
|
|
break;
|
|
|
|
case 'F': // write flash
|
|
|
|
profile.writeFlash();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-18 18:15:30 +01:00
|
|
|
if (hal.m_millis < nextUpdate && hal.m_millis > ROLLOVER_INTERVAL) return;
|
|
|
|
nextUpdate = hal.m_millis + UPDATE_INTERVAL;
|
|
|
|
uint8_t rotaryChanged = hal.rotaryChanged();
|
|
|
|
if (rotaryChanged) {
|
2022-03-12 21:36:54 +01:00
|
|
|
for (uint8_t i = 0; i < 8; ++i) {
|
2022-02-18 18:15:30 +01:00
|
|
|
if (rotaryChanged & 1) {
|
2022-03-12 21:36:54 +01:00
|
|
|
int8_t delta = hal.getEncoder(i);
|
|
|
|
profile.rotaryAction(i, delta);
|
2022-02-18 18:15:30 +01:00
|
|
|
}
|
|
|
|
rotaryChanged >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint16_t analogChanged = hal.analogChanged();
|
|
|
|
if (analogChanged) {
|
|
|
|
for (uint8_t i = 0; i < 4; ++i) {
|
|
|
|
if (analogChanged & 1) {
|
|
|
|
uint16_t analog = hal.getAnalog(i);
|
2022-03-12 21:36:54 +01:00
|
|
|
profile.axisAction(i, analog);
|
2022-02-18 18:15:30 +01:00
|
|
|
}
|
|
|
|
analogChanged >>= 1;
|
|
|
|
}
|
|
|
|
Gamepad.write();
|
|
|
|
}
|
|
|
|
uint64_t buttonsChanged = hal.buttonsChanged();
|
|
|
|
if (buttonsChanged) {
|
|
|
|
for (uint8_t i = 0; i < 64; ++i) {
|
|
|
|
if (buttonsChanged & 0xFF) { // quickcheck for 8 bits at a time
|
|
|
|
if (buttonsChanged & 1) {
|
|
|
|
bool pressed = hal.getButton(i);
|
2022-03-12 21:36:54 +01:00
|
|
|
profile.buttonAction(i, pressed);
|
2022-02-18 18:15:30 +01:00
|
|
|
}
|
|
|
|
buttonsChanged >>= 1;
|
|
|
|
} else {
|
|
|
|
buttonsChanged >>= 8;
|
2022-03-12 21:36:54 +01:00
|
|
|
i += 7;
|
2022-02-18 18:15:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|