cimdit/cimdit.ino

167 lines
4.1 KiB
C++

/**
* \file cimdit.ino
* \brief main functions
* \author GrumpyDeveloper (Sascha Nitsch)
* \copyright 2022 Sascha Nitsch
* Licensed under MIT license
*
*/
// defines
#include "defines.h"
// library includes
#include <HID-Project.h>
#ifdef HAVE_DISPLAY
#include "cimditssd1306.h"
#endif
// own includes
#include "cimdithal.h"
#include "cimditprofile.h"
/// 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;
#ifdef HAVE_DISPLAY
/// our display
CimditSSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_ADDRESS);
#endif
// our profile handling class
CimditProfile profile;
/// initial setup
void setup() {
Serial.begin(115200);
hal.begin();
attachInterrupt(digitalPinToInterrupt(7), rotInt, RISING);
// initialize USB related things
Keyboard.begin();
Mouse.begin();
Gamepad.begin();
Wire.begin();
Wire.setClock(400000);
#ifdef HAVE_DISPLAY
// init display
display.begin();
display.clearDisplay();
display.setTextSize(2,2);
display.setCursor(28, 8);
display.write("cimdit");
display.display();
#endif
profile.begin();
}
/// protection string
const char protectString[] = "cimdit:";
/// current position in protection string
uint8_t protectPos = 0;
/// main loop
void loop() {
hal.readFromHardware(outstandingRotInterrupt);
if (outstandingRotInterrupt) {
outstandingRotInterrupt = false;
return;
}
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;
}
}
}
}
if (hal.m_millis < nextUpdate && hal.m_millis > ROLLOVER_INTERVAL) return;
nextUpdate = hal.m_millis + UPDATE_INTERVAL;
uint8_t rotaryChanged = hal.rotaryChanged();
if (rotaryChanged) {
for (uint8_t i = 0; i < 8; ++i) {
if (rotaryChanged & 1) {
int8_t delta = hal.getEncoder(i);
profile.rotaryAction(i, delta);
}
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);
profile.axisAction(i, analog);
}
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);
profile.buttonAction(i, pressed);
}
buttonsChanged >>= 1;
} else {
buttonsChanged >>= 8;
i += 7;
}
}
}
}