© 2022 EasyEDA Some rights reserved
1.Easy to use and quick to get started
2.The process supports design scales of 300 devices or 1000 pads
3.Supports simple circuit simulation
4.For students, teachers, creators
1.Brand new interactions and interfaces
2.Smooth support for design sizes of over 30,000 devices or 100,000 pads
3.More rigorous design constraints, more standardized processes
4.For enterprises, more professional users
Std EditionDahl Design SW1
Profile:Sim racing custom PCB. Built and tested.
Project source: Cloned from DAHL F
Schematic and PCB layout for Dahl Design SW1 sim racing steering wheel. The PCB has been build and tested, working as intended.
Essentially two ATmega32U4 connected to a single USB output with a SL2.1A USB hub IC. The SL2.1A hub has two additional USB connections available, so possibitilies for adding additional MCUs or a screen, like VoCore or Nextion. This SL2.1A chip has been tested with a VoCore screen and three other peripherals, working perfectly. In case of adding a screen, I recommend a 100µF cap close to the +5V going to screen. I also recommend having a look at my PCB layout for placing decoupling capacitors and isolated ground plane for crystal resonators.
Included in this project is also ICSP headers for both MCUs, this is necessary to burn bootloader. I used an Arduino UNO as ISP programmer, simply burning the bootloader through Arduino IDE without any issues. The PCB is then recognized as two Arduino Leonardos.
There is room for all connections on a single ATmega32U4 in this project, but I split the LEDs from the buttons to make use of SimHub (https://www.simhubdash.com/) for LED control.
Feel free to use any element of this schematic, you'll find me in SimHub discord if you have any questions. I can also provide .stl or .step files for the build.
Finished product:
Code written and flashed with Arduino IDE. Requires libraries: Joystick, Multimap and MegunoLink:
/*
Dahl Design SW1 Firmware v1.9. By Andreas Dahl January 2022
Version 1.7 :
- First official release.
Version 1.8 :
- Improved logic for all encoders, now perfecly working; pulse on each detent 20 ms and no chance for triggering in the wrong direction.
Version 1.9 :
- Added debouncing on upshift and downshift switches.
*/
#include <Joystick.h>
#include <MultiMap.h>
#include <Filter.h>
#define BUTTONCOUNT 69
//Defining joystick parameters
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD,
BUTTONCOUNT, //Button count
0, //Hat switch count
true, //X axis -> Clutch paddles
true, //Y axis -> Clutch bite, only for dash visualization
false, //Z axis
false, //Rx axis
false, //Ry axis
false, //Rz axis
false, //Rudder
false, //Throttle
false, //Accelerator
false, //Brake
false); //Steering
//Row and column pins
uint8_t row[] = {11, 3, 2, 30, 4, 12, 6};
const uint8_t rowCount = sizeof(row) / sizeof(row[0]);
uint8_t col[] = {7, A0, 13, 5, 10, 9, 8};
const uint8_t colCount = sizeof(col) / sizeof(col[0]);
//Analog pins
int rotRPin = A1;
int rotLPin = A4;
int clutchRPin = A2;
int clutchLPin = A5;
int bitePin = A3;
//Status of all buttons
uint8_t state[rowCount][colCount] = {
{0, 0, 0, 0, 0, 0, 0}, //ROW 1,
{0, 0, 0, 0, 0, 0, 0}, //ROW 2
{0, 0, 0, 0, 0, 0, 0}, //ROW 3
{0, 0, 0, 0, 0, 0, 0}, //ROW 4
{0, 0, 0, 0, 0, 0, 0}, //ROW 5
{0, 0, 0, 0, 0, 0, 0}, //ROW 6
{0, 0, 0, 0, 0, 0, 0}, //ROW 7
};
/*
Row 1, column 1 - 7
status[0][0] ---> Right grip encoder A-channel *
status[0][1] ---> Right grip encoder B-channel *
status[0][2] ---> Right 3-way (ON)-OFF-(ON) push UP *
status[0][3] ---> Right 3-way (ON)-OFF-(ON) push DOWN *
status[0][4] ---> Right top 9N OFF-(ON) pushbutton *
status[0][5] ---> Right middle 9N OFF-(ON) pushbutton *
status[0][6] ---> Right lower 9N OFF-(ON) pushbutton *
Row 2, column 1-7
status[1][0] ---> Right 7-way down press
status[1][1] ---> Right 7-way left press
status[1][2] ---> Right 7-way encoder A-channel
status[1][3] ---> Right 7-way right press
status[1][4] ---> Right 7-way push button
status[1][5] ---> Right 7-way encoder B-channel
status[1][6] ---> Right 7-way up press
Row 3, column 1-7
status[2][0] ---> Middle top back-button *
status[2][1] ---> Right top back-button *
status[2][2] ---> Upshift paddle *
status[2][3] ---> Right accessory paddle *
status[2][4] ---> Launch control toggle *
status[2][5] ---> Right thumb encoder A-channel *
status[2][6] ---> Right thumb encoder B-channel *
Row 4, column 1-7
status[3][0] ---> Left grip encoder A-channel *
status[3][1] ---> Left grip encoder B-channel *
status[3][2] ---> Left 3-way (ON)-OFF-(ON) push UP *
status[3][3] ---> Left 3-way (ON)-OFF-(ON) push DOWN *
status[3][4] ---> Left top 9N OFF-(ON) pushbutton *
status[3][5] ---> Left middle 9N OFF-(ON) pushbutton *
status[3][6] ---> Left lower 9N OFF-(ON) pushbutton *
Row 5, column 1-7
status[4][0] ---> Left 7-way left press
status[4][1] ---> Left 7-way encoder A-channel
status[4][2] ---> Left 7-way encoder B-channel
status[4][3] ---> Left 7-way up press
status[4][4] ---> Left 7-way push button
status[4][5] ---> Left 7-way down press
status[4][6] ---> Left 7-way right press
Row 6, column 1-7
status[5][0] ---> Left thumb encoder A-channel *
status[5][1] ---> Left thumb encoder B-channel *
status[5][2] ---> Ignition toggle *
status[5][3] ---> Left top back-button *
status[5][4] ---> Left accessory paddle *
status[5][5] ---> Downshift paddle *
status[5][6] ---> Radio OFF-ON latching pushbutton *
//ROW 7, column 1-7
status[6][0] ---> Pit limiter 9N OFF-(ON) pushbutton *
status[6][1] ---> Bite point lock toggle switch *
status[6][2] ---> Engine start button *
status[1][0] ---> Col 4 empty
status[1][0] ---> Col 5 empty
status[1][0] ---> Col 6 empty
status[1][0] ---> Col 7 empty
*/
//List of buttons and button debounce timers
//Button 1 ---> [0][4] ---> Right top 9N OFF-(ON) pushbutton
//Button 2 ---> [0][5] ---> Right middle 9N OFF-(ON) pushbutton
//Button 3 ---> [0][6] ---> Right lower 9N OFF-(ON) pushbutton
//Button 4 ---> [3][4] ---> Left top 9N OFF-(ON) pushbutton
//Button 5 ---> [3][5] ---> Left middle 9N OFF-(ON) pushbutton
//Button 6 ---> [3][6] ---> Left lower 9N OFF-(ON) pushbutton
//Button 7 ---> [2][3] ---> Right accessory paddle
//Button 8 ---> [5][4] ---> Left accessory paddle
//Button 9 ---> [2][2] ---> Upshift paddle
//Button 10 ---> [5][5] ---> Downshift paddle
//Button 11 ---> [0][2] ---> Right 3-way (ON)-OFF-(ON) push UP
//Button 12 ---> [0][3] ---> Right 3-way (ON)-OFF-(ON) push DOWN
//Button 13 ---> [3][2] ---> Left 3-way (ON)-OFF-(ON) push UP
//Button 14 ---> [3][3] ---> Left 3-way (ON)-OFF-(ON) push DOWN
//Button 15 ---> [0][0] ---> Right grip encoder CCW
//Button 16 ---> [0][1] ---> Right grip encoder CW
//Button 17 ---> [3][0] ---> Left grip encoder CCW
//Button 18 ---> [3][1] ---> Left grip encoder CW
//Button 19 ---> [2][5] ---> Right thumb encoder CCW
//Button 20 ---> [2][6] ---> Right thumb encoder CW
//Button 21 ---> [5][0] ---> Left thumb encoder CW
//Button 22 ---> [5][1] ---> Left thumb encoder CCW
//Button 23 ---> [6][0] ---> Pit limiter 9N OFF-(ON) pushbutton
//Button 24 ---> [5][6] ---> Radio OFF-ON latching pushbutton
//Button 25 ---> [1][6] ---> Right 7-way up press
//Button 26 ---> [1][3] ---> Right 7-way right press
//Button 27 ---> [1][0] ---> Right 7-way down press
//Button 28 ---> [1][1] ---> Right 7-way left press
//Button 29 ---> [1][4] ---> Right 7-way push button
//Button 30 ---> [1][2] ---> Right 7-way encoder CCW
//Button 31 ---> [1][5] ---> Right 7-way encoder CW
//Button 32 ---> [4][3] ---> Left 7-way up press
//Button 33 ---> [4][6] ---> Left 7-way right press
//Button 34 ---> [4][5] ---> Left 7-way down press
//Button 35 ---> [4][0] ---> Left 7-way left press
//Button 36 ---> [4][4] ---> Left 7-way push button
//Button 37 ---> [4][1] ---> Left 7-way encoder CCW
//Button 38 ---> [4][2] ---> Left 7-way encoder CW
//Button 39 ---> [2][1] ---> Right top back-button
//Button 40 ---> [2][0] ---> Middle top back-button
//Button 41 ---> [5][3] ---> Left top back-button
//Button 42 ---> [2][4] ---> Launch control toggle
//Button 43 ---> [5][2] ---> Ignition toggle
//Button 44 ---> [6][2] ---> Engine start button
//Button 45 ---> [6][1] ---> Bite point lock toggle switch
// Global variables for buttons
// Button/encoder pulse duration
uint8_t encoderPulse = 20;
uint8_t funkyPulse = 20;
// Encoder variables
uint8_t enc1C = 0;
uint8_t enc1L = 0;
uint8_t enc1S = 0;
uint8_t enc1P = 0;
uint8_t enc1D = 0;
uint8_t enc2C = 0;
uint8_t enc2L = 0;
uint8_t enc2S = 0;
uint8_t enc2P = 0;
uint8_t enc2D = 0;
uint8_t enc3C = 0;
uint8_t enc3L = 0;
uint8_t enc3S = 0;
uint8_t enc3P = 0;
uint8_t enc3D = 0;
uint8_t enc4C = 0;
uint8_t enc4L = 0;
uint8_t enc4S = 0;
uint8_t enc4P = 0;
uint8_t enc4D = 0;
uint8_t upshiftState = 0;
uint8_t upshiftLock = 0;
uint8_t upshiftCounter = 0;
uint8_t downshiftState = 0;
uint8_t downshiftLock = 0;
uint8_t downshiftCounter = 0;
uint8_t funkystatus1 = 0;
uint8_t zerofetch1 = 0;
uint8_t onefetch1 = 0;
uint8_t funkycount1 = 0;
uint8_t funkycountN1 = 0;
uint8_t funkyStop1 = 0;
uint8_t funkystatus2 = 0;
uint8_t zerofetch2 = 0;
uint8_t onefetch2 = 0;
uint8_t funkycount2 = 0;
uint8_t funkycountN2 = 0;
uint8_t funkyStop2 = 0;
uint8_t b43Counter = 0; //Button 43 counter
uint8_t b43Active = 3; //Button 43 active state
uint8_t rotRC = 0;
uint8_t rotRL = 0;
uint8_t rotLC = 0;
uint8_t rotLL = 0;
// Clutch multiMap arrays
int inR [11] = {190, 195, 200, 210, 230, 270, 320, 370, 425, 490, 555};
int outR [11] = {0, 102, 204, 307, 409, 512, 614, 716, 819, 921, 1023};
int inL [11] = {536, 620, 680, 730, 780, 820, 840, 850, 857, 861, 864};
int outL [11] = {0, 102, 204, 307, 409, 512, 614, 716, 819, 921, 1023};
int inBite [11] = {3, 20, 40, 170, 400, 600, 900, 930, 960, 990, 1015};
int outBite [11] = {0, 102, 204, 307, 409, 512, 614, 716, 819, 921, 1023};
int bite = 600;
uint8_t mapSize = 11;
unsigned long counter;
//Filter variable
ExponentialFilter<float> filteredBite(5,0);
//-----------------------------------------------------------------------------
//-------------------------------SETUP-----------------------------------------
//-----------------------------------------------------------------------------
void setup () {
//Serial.begin(9600);
pinMode(rotRPin, INPUT);
pinMode(rotLPin, INPUT);
pinMode(clutchRPin, INPUT);
pinMode(clutchLPin, INPUT);
pinMode(bitePin, INPUT);
for (int i = 0; i < colCount; i ++) { // All pins pulled up unless told otherwise
pinMode(col[i], INPUT_PULLUP);
}
for (int i = 0; i < rowCount; i ++) { // All pins pulled up unless told otherwise
pinMode(row[i], INPUT_PULLUP);
}
Joystick.begin(0); //Start joystick library magic
}
//-----------------------------------------------------------------------------
//-------------------------------LOOP------------------------------------------
//-----------------------------------------------------------------------------
void loop() {
//counter++;
//Serial.println(counter);
matrix ();
buttons ();
shifters();
encoder1 ();
encoder2 ();
encoder3 ();
encoder4 ();
funky1 ();
funky2 ();
analog ();
Joystick.sendState();
}
//-----------------------------------------------------------------------------
//------------------------------FUNCTIONS--------------------------------------
//-----------------------------------------------------------------------------
void matrix() {
//Beginning with matrix logics, checking status on all button connectors.
//Based on monitoring the flow to each row pin, setting the pin to GND
for (int i = 0; i < rowCount; i++) { //Engaging row pin after row pin
pinMode(row[i], OUTPUT);
digitalWrite(row[i], LOW);
for (int u = 0; u < colCount; u++) { //Checking all column pins on this row pin
pinMode(col[u], INPUT_PULLUP);
if (digitalRead(col[u]) == 0) {
state[i][u] = 1;
} else {
state[i][u] = 0;
}
pinMode(col[u], INPUT);
}
pinMode(row[i], INPUT_PULLUP); //Disengage the row pin
}
}
void buttons() {
//------------------------------
//Button debounce and activation
//------------------------------
//Button 1
Joystick.setButton(0, state[0][4]);
//Button 2
Joystick.setButton(1, state[0][5]);
//Button 3
Joystick.setButton(2, state[0][6]);
//Button 4
Joystick.setButton(3, state[3][4]);
//Button 5
Joystick.setButton(4, state[3][5]);
//Button 6
Joystick.setButton(5, state[3][6]);
//Button 7
Joystick.setButton(6, state[2][3]);
//Button 8
Joystick.setButton(7, state[5][4]);
//Button 11
Joystick.setButton(10, state[0][2]);
//Button 12
Joystick.setButton(11, state[0][3]);
//Button 13
Joystick.setButton(12, state[3][2]);
//Button 14
Joystick.setButton(13, state[3][3]);
//Button 23
Joystick.setButton(22, state[6][0]);
//Button 24
Joystick.setButton(23, state[5][6]);
//Button 25
Joystick.setButton(24, state[1][6]);
//Button 26
Joystick.setButton(25, state[1][3]);
//Button 27
Joystick.setButton(26, state[1][0]);
//Button 28
Joystick.setButton(27, state[1][1]);
//Button 29 (Right 7-Way pushbutton)
if (state[1][6] + state[1][3] + state[1][0] + state[1][1] == 0 && state[1][4] == 1) {
Joystick.pressButton(28);
} else {
Joystick.releaseButton(28);
}
//Button 32
Joystick.setButton(31, state[4][3]);
//Button 33
Joystick.setButton(32, state[4][6]);
//Button 34
Joystick.setButton(33, state[4][5]);
//Button 35
Joystick.setButton(34, state[4][0]);
//Button 36 (Left 7-Way pushbutton)
if (state[4][3] + state[4][6] + state[4][5] + state[4][0] == 0 && state[4][4] == 1) {
Joystick.pressButton(35);
} else {
Joystick.releaseButton(35);
}
//Button 39
Joystick.setButton(38, state[2][1]);
//Button 40
Joystick.setButton(39, state[2][0]);
//Button 41
Joystick.setButton(40, state[5][3]);
//Button 42
Joystick.setButton(41, state[2][4]);
//Button 43 (Pulsing toggle)
if (state[5][2] != b43Active) {
b43Counter++;
Joystick.setButton(42, 1);
}
if (b43Counter > encoderPulse) {
Joystick.setButton(42, 0);
b43Counter = 0;
b43Active = state[5][2];
}
//Button 44
Joystick.setButton(43, state[6][2]);
//Button 45
Joystick.setButton(44, state[6][1]);
}
void shifters()
{
//Button 9 - Upshift
if (state[2][2] != upshiftState)
{
upshiftLock = 1;
}
if (upshiftLock == 1)
{
upshiftCounter++;
}
if (upshiftCounter > 3 && state[2][2] != upshiftState)
{
upshiftState = state[2][2];
upshiftCounter = 0;
upshiftLock = 0;
}
Joystick.setButton(8, upshiftState);
//Button 10 - Downshift
if (state[5][5] != downshiftState)
{
downshiftLock = 1;
}
if (downshiftLock == 1)
{
downshiftCounter++;
}
if (downshiftCounter > 3 && state[5][5] != downshiftState)
{
downshiftState = state[5][5];
downshiftCounter = 0;
downshiftLock = 0;
}
Joystick.setButton(9, downshiftState);
}
void encoder1() {
//Right grip encoder
//EncS = status
//EncP = pulse trigger on/off
//EncL = last status
//EncC = counter, for pulse duration
//EncD = saving status for pulse
if (!state[0][0] && !state[0][1]) { //Refreshing switch position
enc1S = 1;
}
if (state[0][0] && !state[0][1]) {
enc1S = 2;
}
if (state[0][0] && state[0][1]) {
enc1S = 3;
}
if (!state[0][0] && state[0][1]) {
enc1S = 4;
}
if (enc1L != enc1S && !enc1P) { //Conditions for starting pulse
enc1P = 1;
enc1D = enc1S;
}
if (enc1P) { //Counting pulse duration, initiate button press
enc1C++;
if ((enc1D > enc1L && !(enc1D == 4 && enc1L == 1)) || enc1D == 1 && enc1L == 4) {
Joystick.pressButton(14);
} else {
Joystick.pressButton(15);
}
}
if (enc1C > encoderPulse) {
enc1C = 0;
enc1L = enc1S;
enc1P = 0;
Joystick.releaseButton(14);
Joystick.releaseButton(15);
}
}
void encoder2() {
//Left grip encoder
if (!state[3][0] && !state[3][1]) { //Refreshing switch position
enc2S = 1;
}
if (state[3][0] && !state[3][1]) {
enc2S = 2;
}
if (state[3][0] && state[3][1]) {
enc2S = 3;
}
if (!state[3][0] && state[3][1]) {
enc2S = 4;
}
if (enc2L != enc2S && !enc2P) { //Conditions for starting pulse
enc2P = 1;
enc2D = enc2S;
}
if (enc2P) { //Counting pulse duration, initiate button press
enc2C++;
if ((enc2D > enc2L && !(enc2D == 4 && enc2L == 1)) || enc2D == 1 && enc2L == 4) {
Joystick.pressButton(16);
} else {
Joystick.pressButton(17);
}
}
if (enc2C > encoderPulse) {
enc2C = 0;
enc2L = enc2S;
enc2P = 0;
Joystick.releaseButton(16);
Joystick.releaseButton(17);
}
}
void encoder3() {
//Right thumb encoder
if (!state[2][5] && !state[2][6]) { //Refreshing switch position
enc3S = 1;
}
if (state[2][5] && !state[2][6]) {
enc3S = 2;
}
if (state[2][5] && state[2][6]) {
enc3S = 3;
}
if (!state[2][5] && state[2][6]) {
enc3S = 4;
}
if (enc3L != enc3S && !enc3P) { //Conditions for starting pulse
enc3P = 1;
enc3D = enc3S;
}
if (enc3P) { //Counting pulse duration, initiate button press
enc3C++;
if ((enc3D > enc3L && !(enc3D == 4 && enc3L == 1)) || enc3D == 1 && enc3L == 4) {
Joystick.pressButton(18);
} else {
Joystick.pressButton(19);
}
}
if (enc3C > encoderPulse) {
enc3C = 0;
enc3L = enc3S;
enc3P = 0;
Joystick.releaseButton(18);
Joystick.releaseButton(19);
}
}
void encoder4() {
//Left thumb encoder
if (!state[5][0] && !state[5][1]) { //Refreshing switch position
enc4S = 1;
}
if (state[5][0] && !state[5][1]) {
enc4S = 2;
}
if (state[5][0] && state[5][1]) {
enc4S = 3;
}
if (!state[5][0] && state[5][1]) {
enc4S = 4;
}
if (enc4L != enc4S && !enc4P) { //Conditions for starting pulse
enc4P = 1;
enc4D = enc4S;
}
if (enc4P) { //Counting pulse duration, initiate button press
enc4C++;
if ((enc4D > enc4L && !(enc4D == 4 && enc4L == 1)) || enc4D == 1 && enc4L == 4) {
Joystick.pressButton(21);
} else {
Joystick.pressButton(20);
}
}
if (enc4C > encoderPulse) {
enc4C = 0;
enc4L = enc4S;
enc4P = 0;
Joystick.releaseButton(20);
Joystick.releaseButton(21);
}
}
void funky1() {
//Right funkyswitch
// Built-in debounce due to the switch being "10" or "01" between detents, triggering switch only when hitting the next steady detent.
if (!state[1][2] && !state[1][5]) {
funkystatus1 = 1;
}
if (!state[1][2] && state[1][5]) {
funkystatus1 = 2;
onefetch1 = 1;
}
if (state[1][2] && state[1][5]) {
funkystatus1 = 3;
}
if (state[1][2] && !state[1][5]) {
funkystatus1 = 4;
zerofetch1 = 1;
}
if ((zerofetch1 && funkystatus1 == 1) || (onefetch1 && funkystatus1 == 3)) {
funkycount1++;
if (funkycountN1 > 0) {funkyStop1 = 1;}
else {
Joystick.pressButton(29);
}
}
if ((zerofetch1 && funkystatus1 == 3) || (onefetch1 && funkystatus1 == 1)) {
funkycountN1++;
if (funkycount1 > 0) {funkyStop1 = 1;}
else {
Joystick.pressButton(30);
}
}
if ((funkycount1+funkycountN1) > funkyPulse || funkyStop1 ) {
funkycount1 = 0;
funkycountN1 = 0;
funkyStop1 = 0;
onefetch1 = 0;
zerofetch1 = 0;
Joystick.releaseButton(29);
Joystick.releaseButton(30);
}
}
void funky2() {
//Left funkyswitch
// Built-in debounce due to the switch being "10" or "01" between detents, triggering switch only when hitting the next steady detent.
if (!state[4][1] && !state[4][2]) {
funkystatus2 = 1;
}
if (!state[4][1] && state[4][2]) {
funkystatus2 = 2;
onefetch2 = 1;
}
if (state[4][1] && state[4][2]) {
funkystatus2 = 3;
}
if (state[4][1] && !state[4][2]) {
funkystatus2 = 4;
zerofetch2 = 1;
}
if ((zerofetch2 && funkystatus2 == 1) || (onefetch2 && funkystatus2 == 3)) {
funkycount2++;
if (funkycountN2 > 0) {funkyStop2 = 1;}
else {
Joystick.pressButton(36);
}
}
if ((zerofetch2 && funkystatus2 == 3) || (onefetch2 && funkystatus2 == 1)) {
funkycountN2++;
if (funkycount2 > 0) {funkyStop2 = 1;}
else {
Joystick.pressButton(37);
}
}
if ((funkycount2+funkycountN2) > funkyPulse || funkyStop2) {
funkycount2 = 0;
funkycountN2 = 0;
funkyStop2 = 0;
onefetch2 = 0;
zerofetch2 = 0;
Joystick.releaseButton(36);
Joystick.releaseButton(37);
}
}
void analog() {
//Analog inputs; clutches, bitepoint and 12-way switches
int rotR = analogRead(rotRPin); // Buttons 46 - 57 ---> 12-position switch right
int rotL = analogRead(rotLPin); // Buttons 58 - 69 ---> 12-position switch left
int clutchR = analogRead(clutchRPin);
int clutchL = analogRead(clutchLPin);
if (state[6][1]) {
bite = analogRead(bitePin);
}
//Right 12-way switch
rotR = map (rotR, 0, 1015, 0, 11);
if (rotR != rotRL) { //Debounce not needed on this switch, but adding 5 cycles just for the hell of it.
rotRC++;
}
if (rotRC > 5) {
rotRC = 0;
rotRL = rotR;
}
if (rotRL == 0) {
Joystick.pressButton(45);
} else {
Joystick.releaseButton(45);
}
if (rotRL == 1) {
Joystick.pressButton(46);
} else {
Joystick.releaseButton(46);
}
if (rotRL == 2) {
Joystick.pressButton(47);
} else {
Joystick.releaseButton(47);
}
if (rotRL == 3) {
Joystick.pressButton(48);
} else {
Joystick.releaseButton(48);
}
if (rotRL == 4) {
Joystick.pressButton(49);
} else {
Joystick.releaseButton(49);
}
if (rotRL == 5) {
Joystick.pressButton(50);
} else {
Joystick.releaseButton(50);
}
if (rotRL == 6) {
Joystick.pressButton(51);
} else {
Joystick.releaseButton(51);
}
if (rotRL == 7) {
Joystick.pressButton(52);
} else {
Joystick.releaseButton(52);
}
if (rotRL == 8) {
Joystick.pressButton(53);
} else {
Joystick.releaseButton(53);
}
if (rotRL == 9) {
Joystick.pressButton(54);
} else {
Joystick.releaseButton(54);
}
if (rotRL == 10) {
Joystick.pressButton(55);
} else {
Joystick.releaseButton(55);
}
if (rotRL == 11) {
Joystick.pressButton(56);
} else {
Joystick.releaseButton(56);
}
//Left 12-way switch
rotL = map (rotL, 0, 1015, 0, 11);
if (rotL != rotLL) { //This switch needs a proper debounce because of filter capacitor removed from the switch PCB (On first wheel build). Probably not needed on an intact switch.
rotLC++;
}
if (rotLC > 30) {
rotLC = 0;
rotLL = rotL;
}
if (rotLL == 0) {
Joystick.pressButton(57);
} else {
Joystick.releaseButton(57);
}
if (rotLL == 1) {
Joystick.pressButton(58);
} else {
Joystick.releaseButton(58);
}
if (rotLL == 2) {
Joystick.pressButton(59);
} else {
Joystick.releaseButton(59);
}
if (rotLL == 3) {
Joystick.pressButton(60);
} else {
Joystick.releaseButton(60);
}
if (rotLL == 4) {
Joystick.pressButton(61);
} else {
Joystick.releaseButton(61);
}
if (rotLL == 5) {
Joystick.pressButton(62);
} else {
Joystick.releaseButton(62);
}
if (rotLL == 6) {
Joystick.pressButton(63);
} else {
Joystick.releaseButton(63);
}
if (rotLL == 7) {
Joystick.pressButton(64);
} else {
Joystick.releaseButton(64);
}
if (rotLL == 8) {
Joystick.pressButton(65);
} else {
Joystick.releaseButton(65);
}
if (rotLL == 9) {
Joystick.pressButton(66);
} else {
Joystick.releaseButton(66);
}
if (rotLL == 10) {
Joystick.pressButton(67);
} else {
Joystick.releaseButton(67);
}
if (rotLL == 11) {
Joystick.pressButton(68);
} else {
Joystick.releaseButton(68);
}
//Clutch and bite logics
clutchR = multiMap(clutchR, inR, outR, mapSize); //No smoothening on clutch.
clutchR = 1023 - clutchR;
clutchL = multiMap(clutchL, inL, outL, mapSize); //Added smoothening on bite point
filteredBite.Filter(bite);
int smoothBite = filteredBite.Current();
int newBite = multiMap(smoothBite, inBite, outBite, mapSize);
Joystick.setYAxis(newBite);
float floatbite = newBite;
float fraction = floatbite / 1023;
clutchL = clutchL * fraction;
if (clutchL > clutchR) {
Joystick.setXAxis(clutchL);
} else {
Joystick.setXAxis(clutchR);
}
}
int multiMap(int val, int* _in, int* _out, uint8_t size)
{
// take care the value is within range
// val = constrain(val, _in[0], _in[size-1]);
if (val <= _in[0]) return _out[0];
if (val >= _in[size - 1]) return _out[size - 1];
// search right interval
uint8_t pos = 1; // _in[0] allready tested
while (val > _in[pos]) pos++;
// this will handle all exact "points" in the _in array
if (val == _in[pos]) return _out[pos];
// interpolate in the right segment for the rest
return (val - _in[pos - 1]) * (_out[pos] - _out[pos - 1]) / (_in[pos] - _in[pos - 1]) + _out[pos - 1];
}
Unfold