#include <SPI.h>
#include <Joystick.h> // https://github.com/MHeironimus/ArduinoJoystickLibrary
// Define Human Interface Device
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
116, 0, // Button Count, Hat Switch Count
false, false, false, // X and Y, but no Z Axis
true, true, false, // No Rx, Ry, or Rz
false, false, // No rudder or throttle
false, false, false); // No accelerator, brake, or steering
// Define delay variables
byte us = 50; // logic diagram timing (µs)
byte dly = 100; // waiting time at the end of loop (ms)
// Define PWM Connection to LED Backlight
int BackLightPWM = 5;
// Define Connections to 74HC165 cascade -- Switch INPUTS shift register cascade
byte ssPinButtons = 10; //Load for 165 shift regs. #1-8
int clockInhibitPin = 4; //CE
//int clock = 15; // CLK
//int dataIn = 14; // QH
// Define Connections to 74HC165 #9 -- 9th switch INPUTS shift register
int clock9 = 6; // CLK
int load9 = 7; // SH/LD#
int dataButtons9 = 9; // QH
// Define Connections to 74HC595 -- Light OUTPUTS shift register cascade
byte ssPinLeds = 8; //Latch for 595 shift regs. #1-3
// Initialize the axes values of Potentiometers
int potA = 0; // OVHD INTEG LT
int potB = 0; // Dome
// Define Connections to Rotary Encoder
int ENC_A = 2;
int ENC_B = 3;
// Define other variables of the code
//byte switchStates[8];
byte switchStates1, switchStates2, switchStates3, switchStates4, switchStates5, switchStates6, switchStates7, switchStates8, switchStates9;
byte ledStates1, ledStates2, ledStates3;
int BackLightValue = 0; // Brightness of BackLight LEDs
bool prevExtPwrAvSw = 0; // previous state of the switch driving the Ext Pwr AVAIL light
bool currExtPwrAvSw = 0; // current state of the switch driving the Ext Pwr AVAIL light
bool ExtPwrAv = 0; // State of External Power Availability
void setup() {
// Setup PWM for LED Backlight
pinMode(BackLightPWM,OUTPUT);
// Setup 74HC165 connections
pinMode(ssPinButtons, OUTPUT);
pinMode(clockInhibitPin, OUTPUT);
pinMode(load9, OUTPUT);
pinMode(clock9, OUTPUT);
pinMode(dataButtons9, INPUT);
// Setup 74HC595 connections
pinMode(ssPinLeds, OUTPUT);
// Setup SPI
SPI.begin(); // default settings: 4 MHz clock, MSBFirst
// Initialize Joystick Library
Joystick.begin();
Joystick.setXAxisRange(0, 1023);
Joystick.setYAxisRange(0, 1023);
// Set encoder pins and attach interrupts
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENC_A), read_encoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENC_B), read_encoder, CHANGE);
// Setup Serial Monitor
//Serial.begin(9600);
}
void loop() {
// Get data from Potentiometers
potA = analogRead(A0);
potB = analogRead(A2);
// Set brightness of BackLight LEDs
BackLightValue = round(potA/1023.0*255.0);
analogWrite(BackLightPWM,255-BackLightValue);
// Joystick axes
Joystick.setRxAxis(potA);
Joystick.setRyAxis(potB);
/*
// Print to serial monitor
Serial.println("----------");
Serial.print("potA: "); Serial.println(potA);
Serial.print("potB: "); Serial.println(potB);
Serial.print("LEDS: "); Serial.println(BackLightValue);
Serial.print("\r\n");
*/
// Set values of Rot Enc to 0 as default
Joystick.setButton(114, 0);
Joystick.setButton(115, 0);
// Get data from 74HC165s
//digitalWrite (ssPinButtons, HIGH);
digitalWrite (ssPinButtons, LOW);
digitalWrite (ssPinButtons, HIGH); // capture data
//SPI.transfer(&switchStates,8); // read in 8 bytes
digitalWrite(clockInhibitPin, LOW);
switchStates1 = SPI.transfer(0); // read in a byte
switchStates2 = SPI.transfer(0); // read in a byte
switchStates3 = SPI.transfer(0); // read in a byte
switchStates4 = SPI.transfer(0); // read in a byte
switchStates5 = SPI.transfer(0); // read in a byte
switchStates6 = SPI.transfer(0); // read in a byte
switchStates7 = SPI.transfer(0); // read in a byte
switchStates8 = SPI.transfer(0); // read in a byte
digitalWrite(clockInhibitPin, HIGH);
digitalWrite(clock9, HIGH);
delayMicroseconds(us);
digitalWrite(load9, LOW);
delayMicroseconds(us);
digitalWrite(load9, HIGH);
delayMicroseconds(us);
digitalWrite(clockInhibitPin, LOW);
switchStates9 = shiftIn(dataButtons9, clock9, MSBFIRST);
digitalWrite(clockInhibitPin, HIGH);
/*
switchStates1 = switchStates[0];
switchStates2 = switchStates[1];
switchStates3 = switchStates[2];
switchStates4 = switchStates[3];
switchStates5 = switchStates[4];
switchStates6 = switchStates[5];
switchStates7 = switchStates[6];
switchStates8 = switchStates[7];
switchStates9 = switchStates[8];
*/
/*
// Print to serial monitor
Serial.print("Pin States -- 1 -- 1-8:\r\n");
Serial.println(switchStates1, BIN);
Serial.print("Pin States -- 2 -- 9-16:\r\n");
Serial.println(switchStates2, BIN);
Serial.print("Pin States -- 3 -- 17-24:\r\n");
Serial.println(switchStates3, BIN);
Serial.print("Pin States -- 4 -- 25-32:\r\n");
Serial.println(switchStates4, BIN);
Serial.print("Pin States -- 5 -- 33-40:\r\n");
Serial.println(switchStates5, BIN);
Serial.print("Pin States -- 6 -- 41-48:\r\n");
Serial.println(switchStates6, BIN);
Serial.print("Pin States -- 7 -- 49-56:\r\n");
Serial.println(switchStates7, BIN);
Serial.print("Pin States -- 8 -- 57-64:\r\n");
Serial.println(switchStates8, BIN);
Serial.print("Pin States -- 9 -- 65-72:\r\n");
Serial.println(switchStates9, BIN);
Serial.print("\r\n");
Serial.print("\r\n");
*/
// Buttons / LEDs logic:
// Is External Power Available?
currExtPwrAvSw = bitRead(switchStates1,2); // previous state of the button
if (currExtPwrAvSw != prevExtPwrAvSw && currExtPwrAvSw){
ExtPwrAv = !ExtPwrAv; // Change state of Ext Pwr AVAIL light
}
prevExtPwrAvSw = currExtPwrAvSw;
// IF Battery is ON:
if ( bitRead(switchStates1,3) || bitRead(switchStates1,4) ){
// Connnect switch states to LED states
ledStates1 = switchStates1;
ledStates2 = switchStates2;
ledStates3 = switchStates3;
// Empty pins of shift registers:
bitWrite(ledStates1,0,0);
bitWrite(ledStates2,0,0);
bitWrite(ledStates3,0,0);
bitWrite(ledStates3,7,0);
// Special lights:
bitWrite(ledStates1,1,ExtPwrAv); // Ext Pwr Avail light
bitWrite(ledStates1,2,0); // APU Avail
bitWrite(ledStates1,3,0); // Battery1 OFF sign
bitWrite(ledStates1,4,0); // Battery2 OFF sign
bitWrite(ledStates1,6,ExtPwrAv && bitRead(switchStates1,6));
//bitWrite(ledStates2,6,0); // APU On
// Battery OFF lights:
if ( bitRead(switchStates1,3) != bitRead(switchStates1,4) ){
if ( bitRead(switchStates1,3) ){
bitWrite(ledStates1,3,0);
bitWrite(ledStates1,4,1);
} else {
bitWrite(ledStates1,3,1);
bitWrite(ledStates1,4,0);
}
}
// Annunciator lights TEST:
if ( bitRead(switchStates4,6) ){
ledStates1 = B11111110;
ledStates2 = B11111110;
ledStates3 = B01111110;
}
} else {
ledStates1 = B00000000;
ledStates2 = B00000000;
ledStates3 = B00000000;
bitWrite(ledStates1,1,ExtPwrAv); // Ext Pwr Avail light
}
/*
Serial.print("LEDs 1:\r\n");
Serial.println(ledStates1, BIN);
Serial.print("LEDs 2:\r\n");
Serial.println(ledStates2, BIN);
Serial.print("LEDs 3:\r\n");
Serial.println(ledStates3, BIN);
Serial.print("\r\n\r\n");
*/
// Write to LEDs using 74HC595
//digitalWrite (ssPinLeds, HIGH);
digitalWrite (ssPinLeds, LOW);
//digitalWrite (ssPinLeds, HIGH); // transfer data
SPI.transfer(ledStates3);
SPI.transfer(ledStates2);
SPI.transfer(ledStates1);
digitalWrite (ssPinLeds, HIGH); // set ssPinLeds to idle
// Set Joystick Buttons
// Set simple buttons:
Joystick.setButton(0, bitRead(switchStates2,0));
Joystick.setButton(1, bitRead(switchStates3,0));
Joystick.setButton(2, bitRead(switchStates5,0));
Joystick.setButton(3, bitRead(switchStates5,1));
Joystick.setButton(4, bitRead(switchStates5,2));
Joystick.setButton(5, bitRead(switchStates5,3));
Joystick.setButton(6, bitRead(switchStates4,0));
// Set 2 rotary buttons:
setButtons4posSwitch(7, bitRead(switchStates1,0), bitRead(switchStates1,1), bitRead(switchStates1,2));
setButtons4posSwitch(11, bitRead(switchStates4,1), bitRead(switchStates4,2), bitRead(switchStates3,7));
// Set 2-state and 3-state switch states buttons:
// Buttons with lights:
setButtons2posSwitch(15, bitRead(switchStates1,3));
setButtons2posSwitch(17, bitRead(switchStates1,4));
setButtons2posSwitch(19, bitRead(switchStates1,5));
setButtons2posSwitch(21, bitRead(switchStates1,6));
setButtons2posSwitch(23, bitRead(switchStates1,7));
setButtons2posSwitch(25, bitRead(switchStates2,1));
setButtons2posSwitch(27, bitRead(switchStates2,2));
setButtons2posSwitch(29, bitRead(switchStates2,3));
setButtons2posSwitch(31, bitRead(switchStates2,4));
setButtons2posSwitch(33, bitRead(switchStates2,5));
Joystick.setButton(35, bitRead(switchStates2,6));
setButtons2posSwitch(36, bitRead(switchStates2,7));
setButtons2posSwitch(38, bitRead(switchStates3,1));
setButtons2posSwitch(40, bitRead(switchStates3,2));
setButtons2posSwitch(42, bitRead(switchStates3,3));
setButtons2posSwitch(44, bitRead(switchStates3,4));
setButtons2posSwitch(46, bitRead(switchStates3,5));
setButtons2posSwitch(48, bitRead(switchStates3,6));
// A320 Ext Lt switches:
setButtons3posSwitch(50, bitRead(switchStates6,4), bitRead(switchStates6,5));
setButtons2posSwitch(53, bitRead(switchStates6,3));
setButtons2posSwitch(55, bitRead(switchStates7,0));
setButtons3posSwitch(57, bitRead(switchStates6,6), bitRead(switchStates6,7));
setButtons2posSwitch(60, bitRead(switchStates6,2));
setButtons3posSwitch(62, bitRead(switchStates5,4), bitRead(switchStates5,5));
setButtons3posSwitch(65, bitRead(switchStates5,6), bitRead(switchStates5,7));
setButtons3posSwitch(68, bitRead(switchStates6,0), bitRead(switchStates6,1));
// A320 other switches:
Joystick.setButton(71, bitRead(switchStates7,7));
Joystick.setButton(72, bitRead(switchStates7,6));
setButtons2posSwitch(73, bitRead(switchStates7,1));
setButtons3posSwitch(75, bitRead(switchStates7,2), bitRead(switchStates7,3));
setButtons3posSwitch(78, bitRead(switchStates4,6), bitRead(switchStates4,7));
setButtons2posSwitch(81, bitRead(switchStates4,3));
setButtons3posSwitch(83, bitRead(switchStates4,4), bitRead(switchStates4,5));
setButtons3posSwitch(86, bitRead(switchStates7,4), bitRead(switchStates7,5));
// B747 switches:
setButtons2posSwitch(89, bitRead(switchStates8,0));
setButtons2posSwitch(91, bitRead(switchStates8,1));
setButtons2posSwitch(93, bitRead(switchStates8,2));
setButtons2posSwitch(95, bitRead(switchStates8,3));
setButtons2posSwitch(97, bitRead(switchStates8,4));
setButtons2posSwitch(99, bitRead(switchStates8,5));
setButtons2posSwitch(101, bitRead(switchStates9,0));
setButtons3posSwitch(103, bitRead(switchStates8,6), bitRead(switchStates8,7));
setButtons2posSwitch(106, bitRead(switchStates9,1));
setButtons2posSwitch(118, bitRead(switchStates9,2));
setButtons2posSwitch(110, bitRead(switchStates9,3));
setButtons2posSwitch(112, bitRead(switchStates9,4));
delay(dly);
}
int setButtons2posSwitch(byte b0, bool swData){
if (swData){
Joystick.setButton(b0, 0);
Joystick.setButton(b0+1, 1);
}else{
Joystick.setButton(b0, 1);
Joystick.setButton(b0+1, 0);
}
}
int setButtons3posSwitch(byte b0, bool swData1, bool swData2){
if (swData1){
Joystick.setButton(b0, 0);
Joystick.setButton(b0+1, 0);
Joystick.setButton(b0+2, 1);
}else{
if (swData2){
Joystick.setButton(b0, 1);
Joystick.setButton(b0+1, 0);
Joystick.setButton(b0+2, 0);
}else{
Joystick.setButton(b0, 0);
Joystick.setButton(b0+1, 1);
Joystick.setButton(b0+2, 0);
}
}
}
int setButtons4posSwitch(byte b0, bool swData1, bool swData2, bool swData3){
if (swData1){
Joystick.setButton(b0, 0);
Joystick.setButton(b0+1, 0);
Joystick.setButton(b0+2, 1);
Joystick.setButton(b0+3, 0);
}else{
if (swData2){
Joystick.setButton(b0, 0);
Joystick.setButton(b0+1, 0);
Joystick.setButton(b0+2, 0);
Joystick.setButton(b0+3, 1);
}else{
if (swData3){
Joystick.setButton(b0, 1);
Joystick.setButton(b0+1, 0);
Joystick.setButton(b0+2, 0);
Joystick.setButton(b0+3, 0);
}else{
Joystick.setButton(b0, 0);
Joystick.setButton(b0+1, 1);
Joystick.setButton(b0+2, 0);
Joystick.setButton(b0+3, 0);
}
}
}
}
void read_encoder() {
// Encoder interrupt routine for both pins. Updates counter if they are valid and have rotated a full indent
static uint8_t old_AB = 3; // Lookup table index
static int8_t encval = 0; // Encoder value
static const int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; // Lookup table
old_AB <<=2; // Remember previous state
if (digitalRead(ENC_A)) old_AB |= 0x02; // Add current state of pin A
if (digitalRead(ENC_B)) old_AB |= 0x01; // Add current state of pin B
encval += enc_states[( old_AB & 0x0f )];
// Update counter if encoder has rotated a full indent, that is at least 4 steps
if( encval > 3 ) { // Four steps forward
//Serial.println("Left");
Joystick.setButton(115, 1);
encval = 0;
}
else if( encval < -3 ) { // Four steps backward
//Serial.println("Right");
Joystick.setButton(114, 1);
encval = 0;
}
}