159 lines
3.9 KiB
C++
159 lines
3.9 KiB
C++
/**
|
|
* \file cimdit.ino
|
|
* \brief main functions
|
|
* \author GrumpyDeveloper (Sascha Nitsch)
|
|
* \copyright 2022 Sascha Nitsch
|
|
* Licensed under MIT license
|
|
*
|
|
*/
|
|
|
|
/// use a custom keyboard layout
|
|
#define HID_CUSTOM_LAYOUT
|
|
/// use german keyboard layout
|
|
#define LAYOUT_GERMAN
|
|
#define HAVE_DISPLAY
|
|
#ifdef HAVE_DISPLAY
|
|
/// no splash screen on OLED
|
|
#define SSD1306_NO_SPLASH
|
|
/// OLED display width, in pixels
|
|
#define SCREEN_WIDTH 128
|
|
/// OLED display height, in pixels
|
|
#define SCREEN_HEIGHT 32
|
|
/// OLED screen address
|
|
#define SCREEN_ADDRESS 0x3C
|
|
#endif
|
|
|
|
// library includes
|
|
#include <HID-Project.h>
|
|
#ifdef HAVE_DISPLAY
|
|
#include <Adafruit_SSD1306.h>
|
|
#endif
|
|
|
|
// own includes
|
|
#include "cimdithal.h"
|
|
|
|
/// update usb devices every x ms if needed
|
|
#define UPDATE_INTERVAL 100
|
|
|
|
/// 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
|
|
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
|
|
#endif
|
|
/// display
|
|
///
|
|
/// initial setup
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
hal.begin();
|
|
attachInterrupt(digitalPinToInterrupt(7), rotInt, RISING);
|
|
// initialize USB related things
|
|
Keyboard.begin();
|
|
Mouse.begin();
|
|
Gamepad.begin();
|
|
#ifdef HAVE_DISPLAY
|
|
// init display
|
|
display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
|
|
display.clearDisplay();
|
|
display.display();
|
|
#endif
|
|
}
|
|
|
|
/// main loop
|
|
void loop() {
|
|
hal.readFromHardware(outstandingRotInterrupt);
|
|
if (outstandingRotInterrupt) {
|
|
outstandingRotInterrupt = false;
|
|
return;
|
|
}
|
|
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 < 7; ++i) {
|
|
if (rotaryChanged & 1) {
|
|
// temporary debug output
|
|
Serial.print(F("rot "));
|
|
Serial.print(i);
|
|
Serial.print(F(" => "));
|
|
Serial.println(hal.getEncoder(i));
|
|
// end of temporary debug output
|
|
}
|
|
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);
|
|
// temporary debug output
|
|
int16_t analogMapped16 = map(analog, 0, 1024, -32767, 32768);
|
|
int8_t analogMapped8 = map(analog, 0, 1024, -127, 127);
|
|
switch(i) {
|
|
case 0:
|
|
Gamepad.xAxis(analogMapped16);
|
|
break;
|
|
case 1:
|
|
Gamepad.yAxis(analogMapped16);
|
|
break;
|
|
case 2:
|
|
Gamepad.zAxis(analogMapped8);
|
|
break;
|
|
case 3:
|
|
Gamepad.rxAxis(analogMapped16);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
Serial.print(F("analog "));
|
|
Serial.print(i);
|
|
Serial.print(F(": "));
|
|
Serial.println(analogMapped16);
|
|
// end of temporary debug output
|
|
}
|
|
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) {
|
|
// temporary debug output
|
|
Serial.print(F("button "));
|
|
Serial.print(i);
|
|
Serial.print(F(" "));
|
|
bool pressed = hal.getButton(i);
|
|
Serial.println(pressed);
|
|
if (i<32) {
|
|
if (pressed)
|
|
Gamepad.press(i+1);
|
|
else
|
|
Gamepad.release(i+1);
|
|
}
|
|
// end of temporary debug output
|
|
}
|
|
buttonsChanged >>= 1;
|
|
} else {
|
|
buttonsChanged >>= 8;
|
|
i += 8;
|
|
}
|
|
}
|
|
}
|
|
}
|