Full code is here (well at least the full code to see the issue, still a lot to code for the project to be done but I can't pass the initialization ...)
//**************************************************************//
// Name : Octopus_Version 4
// Author :
// Date : July 2022 - Modified :
// Version : 4.02
// Board : Arduino Micro
// Note : Use the button structure and keep track of LED status
// Based on a project by Stoo //****************************************************************
#include <MIDI.h>
#include <midi_defs.h>
#include <midi_message.h>
#include <midi_namespace.h>
#include <midi_settings.h>
#include <stdlib.h>
#include <Keyboard.h>
#include <Bounce2.h>
#include <Arduino.h>
#include <String.h>
#define DEBUG_MODE true //set to true for debug output, false for no debug output
#define DEBUG_MSG \
if (DEBUG_MODE) Serial
const int NUM_PAGES = 4;
const int NUM_BUTTONS = 10;
const int NUMBER_LED_RING = 6;
const int TIME_LONGPRESS = 500;
const int NUM_PIN_ON_SHIFT_REGISTER = 8;
const uint8_t BUTTON_ARDUINO_PINS[NUM_BUTTONS] = {2, 3, 4, 5, 6, 7, 8, 9, A1, A2};
const uint8_t LED_PINS[NUMBER_LED_RING * 2] = {0,2,1,8,3,8,4,8,5,6,7,8};
//using 8 for LED not hooked, the structure follows button1 color 1,button 1 color 2 etc...
/* Line 6 HX Stomp constants
* -------------------------
*/
const int STOMP_MODE = 0;
const int SCROLL_MODE = 1;
const int PRESET_MODE = 2;
const int SNAP_MODE = 3;
const int DEFAULT_PROGRAM = 20;
/* Shift register constants
* ------------------------
*
* A TPIC6B595 shift register is used to control the ring LED
* Those LED are 9V control with a common ground
* I am using a TPIC6B595 and PNP diodes to deal with the common ground and 9V.
* 9V is provided directly from ON/OFF switch
*/
const int SER_Pin = 10; //pin 14 on the TPIC6B595 pin 10 on the Arduino with {color} cable
const int RCLK_Pin = 11; //pin 12 on the TPIC6B595 pin 11 on the Arduino with cable
const int SRCLK_Pin = 12; //pin 11 on the TPIC6B595 pin 12 on the Arduino with cable
/* Instantiation of the MDI port
* -----------------------------
*
* I am using Serial1 instead of Serial so Serial can be use to output debug messages
* The MIDI object is called midiOut
* Forcing the baud rate to 31250 for the MIDI connection.*/
#define UARTE0_BASE_ADDR 0x40002000 // As per nRF52840 Product spec - UARTE
#define UART_BAUDRATE_REG_OFFSET 0x524 // As per nRF52840 Product spec - UARTE
#define UART0_BAUDRATE_REGISTER (*(( unsigned int *)(UARTE0_BASE_ADDR + UART_BAUDRATE_REG_OFFSET)))
#define BAUD31250 0x00800000 //31250
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midiOut);
/*GLOBAL VARIABLE*/
int currentPage = 1;
bool LEDHaveChanged = true;
unsigned long loopTime;
/* Structures Definition
* ---------------------
*/
struct myButton {
int buttonNumber; //Physical position on the board
int ArduinoPin {8};
bool buttonPressed {false}; //Was the button Pressed during the loop
int ShiftRegisterLEDPin[2] {8,8};
bool colorStatus[2] {LOW, LOW}; //2 because 2 color per button
Bounce BtnBounce;
long buttonPressTimeStamp;
long buttonReleaseTimeStamp;
bool BtnLongPress {false};
void setLEDStatus(int color, boolean value) {
this->colorStatus[color-1]= value;
//-1 because I want to work with color 1 and color 2
}
bool getLEDStatus(int color){
return colorStatus[color-1];
}
bool isLongPress() {
if (buttonReleaseTimeStamp - buttonPressTimeStamp > TIME_LONGPRESS) {
return true;
}
else{
return false;
}
}
};
struct myPage {
int pageNumber {99};
int HXmode {98};
struct myButton ListObjButton[NUM_BUTTONS];
myButton getBtn(int Btn) {
return ListObjButton[Btn-1];
}
void setHXmode(int mode){
DEBUG_MSG.print("set HXmode to :");
DEBUG_MSG.print(mode,1);
DEBUG_MSG.print(" For page Number :");
DEBUG_MSG.println(this->pageNumber,1);
this->HXmode = mode;
}
};
struct myPage ListObjPage[NUM_PAGES];
/* Useful functions
* ---------------- */
struct myPage getPage(int pageNb) {
//This function is use so I can work with page number without dealing with the -1 for hte index starting at 0
return ListObjPage[pageNb-1];
}
struct myButton getBtn(int BtNb, int pageNb = currentPage) {
//This function is use so I can work with page number without dealing with the -1 for hte index starting at 0
return getPage(pageNb).ListObjButton[BtNb-1];
}
/* Printing Functions
* ------------------
*/
void printBtn(int page){
for (int indexBtn = 1; indexBtn < NUM_BUTTONS + 1; indexBtn ++){
DEBUG_MSG.print("\tButton: ");
DEBUG_MSG.print(indexBtn,1);
DEBUG_MSG.print(", pg ");
DEBUG_MSG.println(page,1);
DEBUG_MSG.print("\t\tbuttonNumber = ");
DEBUG_MSG.println(ListObjPage[page-1].ListObjButton[indexBtn-1].buttonNumber,1);
DEBUG_MSG.print("\t\tbuttonPressed = ");
DEBUG_MSG.println(ListObjPage[page-1].ListObjButton[indexBtn-1].buttonPressed);
DEBUG_MSG.print("\t\tLong press status = ");
DEBUG_MSG.println(ListObjPage[page-1].ListObjButton[indexBtn-1].isLongPress());
DEBUG_MSG.print("\t\tArduinoPin = ");
DEBUG_MSG.println(ListObjPage[page-1].ListObjButton[indexBtn-1].ArduinoPin);
for (int indexColor=1; indexColor < 3; indexColor++){
DEBUG_MSG.print("\t\tColor ");
DEBUG_MSG.print(indexColor,1);
DEBUG_MSG.print(" = ");
DEBUG_MSG.println(ListObjPage[page-1].ListObjButton[indexBtn-1].getLEDStatus(indexColor));
DEBUG_MSG.print("\t\tColor ");
DEBUG_MSG.print(indexColor,1);
DEBUG_MSG.print(" Pin = ");
DEBUG_MSG.println(ListObjPage[page-1].ListObjButton[indexBtn-1].ShiftRegisterLEDPin[indexColor-1],1);
}
}
}
void printPage(int pg,bool showBtn = true){
DEBUG_MSG.print("Page :");
DEBUG_MSG.println(pg,1);
DEBUG_MSG.print("\tpageNumber = ");
DEBUG_MSG.println(getPage(pg).pageNumber,1);
DEBUG_MSG.print("\tHXmode = ");
DEBUG_MSG.println(getPage(pg).HXmode,1);
if (showBtn){ printBtn(pg);}
}
void printPages(bool showBtn = true) {
//This function print the status of a page - used for debugging.
for (int indexPg = 1; indexPg < NUM_PAGES + 1; indexPg ++){
printPage(indexPg,showBtn);
}
}
/* Initialization Functions
* -------------------------
*/
void initializePages() {
DEBUG_MSG.println(__func__);
for (int indexPg = 1; indexPg < NUM_PAGES + 1; indexPg ++){
ListObjPage[indexPg-1].pageNumber = indexPg;
switch (indexPg) {
case 1:
ListObjPage[indexPg-1].HXmode = SNAP_MODE;
break;
case 2:
ListObjPage[indexPg-1].HXmode = STOMP_MODE;
break;
case 3:
ListObjPage[indexPg-1].HXmode = SCROLL_MODE;
break;
case 4:
ListObjPage[indexPg-1].HXmode = SNAP_MODE;
break;
}
initializeBtn(indexPg);
}
}
void initializeBtn(int pg) {
DEBUG_MSG.println(__func__);
int HXMode = getPage(pg).HXmode;
for (int indexBtn = 1; indexBtn < NUM_BUTTONS + 1; indexBtn ++){
ListObjPage[pg-1].ListObjButton[indexBtn-1].buttonNumber = indexBtn;
ListObjPage[pg-1].ListObjButton[indexBtn-1].ArduinoPin = BUTTON_ARDUINO_PINS[indexBtn-1];
//The first 6 buttons have a LED with 2 color,
//I am assigning the pin on the shift register for the 2 LED
if((indexBtn-1)*2 < NUMBER_LED_RING*2 ){
ListObjPage[pg-1].ListObjButton[indexBtn-1].ShiftRegisterLEDPin[0] = LED_PINS[(indexBtn-1)*2]; //color 1 pin
ListObjPage[pg-1].ListObjButton[indexBtn-1].ShiftRegisterLEDPin[1] = LED_PINS[(indexBtn-1)*2+1]; //color 2 pin
}else{
//No LED for this button, I set the PIN to 99
DEBUG_MSG.println(indexBtn,1);
ListObjPage[pg-1].ListObjButton[indexBtn-1].ShiftRegisterLEDPin[0] = 99;
ListObjPage[pg-1].ListObjButton[indexBtn-1].ShiftRegisterLEDPin[1] = 99;
}
switch (HXMode) {
case STOMP_MODE:
ListObjPage[pg-1].ListObjButton[indexBtn-1].setLEDStatus(1, HIGH);
break;
case SNAP_MODE:
if (indexBtn == 6){ListObjPage[pg-1].ListObjButton[indexBtn-1].setLEDStatus(2, HIGH);}
else{ListObjPage[pg-1].ListObjButton[indexBtn-1].setLEDStatus(1, HIGH);};
break;
case SCROLL_MODE:
if (indexBtn == 1){ListObjPage[pg-1].ListObjButton[indexBtn-1].setLEDStatus(2, HIGH);}
if (indexBtn == 2){ListObjPage[pg-1].ListObjButton[indexBtn-1].setLEDStatus(1, HIGH);}
if (indexBtn == 6){ListObjPage[pg-1].ListObjButton[indexBtn-1].setLEDStatus(1, HIGH);}
break;
}
LEDHaveChanged = true;
}
}
void resetLEDToLOW(){
DEBUG_MSG.println(__func__);
for (int indexPg = 1; indexPg < NUM_PAGES+1; indexPg++){
for (int indexBtn = 1; indexBtn < NUM_BUTTONS+1; indexBtn++){
ListObjPage[indexPg-1].ListObjButton[indexBtn-1].setLEDStatus(1, LOW);
ListObjPage[indexPg-1].ListObjButton[indexBtn-1].setLEDStatus(2, LOW);
}
}
printPages();
}
int getPinLED(int pin) {
//NEED REVIEW
//Return the LED for a given Shift register Pin
for (int indexPin=0; indexPin < 2* NUMBER_LED_RING + 1; indexPin++) {
if(LED_PINS[indexPin]==pin){
DEBUG_MSG.println(indexPin,1);
return indexPin;
}
}
DEBUG_MSG.println("ERROR");
DEBUG_MSG.println(pin,1);
return -1;
}
void writeRegisters() {
//Need to make sure this only change if something has changed.
DEBUG_MSG.println(__func__);
if (LEDHaveChanged) {
digitalWrite(RCLK_Pin, LOW);
bool value = LOW;
//For debug
int color = 0;
int button = 0;
for (int indexPin=0; indexPin < NUM_PIN_ON_SHIFT_REGISTER; indexPin++){
//The pin are from 0 to
//I can use indexPin to refer to them directly without the need for a lookup table
digitalWrite(SRCLK_Pin, LOW);
//Find the button for that Pin
for (int indexBtn=1;indexBtn < NUM_BUTTONS + 1 ;indexBtn++){
if(ListObjPage[currentPage -1 ].ListObjButton[indexBtn-1].ShiftRegisterLEDPin[0] == indexPin ){
value = ListObjPage[currentPage -1 ].ListObjButton[indexBtn-1].getLEDStatus(1);
button = indexBtn;
color = 1;
break;
}
else if (ListObjPage[currentPage -1 ].ListObjButton[indexBtn-1].ShiftRegisterLEDPin[1] == indexPin){
value = ListObjPage[currentPage -1 ].ListObjButton[indexBtn-1].getLEDStatus(2);
color = 2;
button = indexBtn;
break;
}
else {
//The pin is not associated with a LED. I send LOW to the shift register
DEBUG_MSG.print("WARNING: PIN ");
DEBUG_MSG.print(indexPin,1);
DEBUG_MSG.print(" on the shift register is not associated with a button.");
break;
}
}
digitalWrite(SER_Pin,value);
digitalWrite(SRCLK_Pin, HIGH);
//To delete when it works.
DEBUG_MSG.print("Arduino Pin ");
DEBUG_MSG.println(indexPin,1);
DEBUG_MSG.print("\tPage ");
DEBUG_MSG.println(currentPage,1);
DEBUG_MSG.print("\tButton ");
DEBUG_MSG.println(button,1);
DEBUG_MSG.print("\tColor ");
DEBUG_MSG.println(color,1);
DEBUG_MSG.print("\tValue = ");
DEBUG_MSG.println(value);
}
digitalWrite(RCLK_Pin, HIGH);
LEDHaveChanged = false;
}
}
void testLEDs(){
// This function cycles the LED
//First I save the current status
// struct myButton currentBtnStatus[NUM_BUTTONS];
DEBUG_MSG.println(__func__);
//currentBtnStatus = getPage(currentPage).ListObjButton;
resetLEDToLOW();
writeRegisters();
/*
for (int indexCol = 1; indexCol < 3;indexCol++) {
for (int indexBtn = 1; indexBtn < NUM_BUTTONS + 1; indexBtn++){
setLED(indexBtn, indexCol, HIGH);
writeRegisters();
delay(400);
}
resetLEDToLOW();
writeRegisters();
}
delay(200);
// getPage(currentPage).ListObjButton = currentBtnStatus;
*/
}
void readButtons(unsigned long time) {
int nbOfBtnPressed= 0; //How many button are pressed during this loop
DEBUG_MSG.println("Reading Button");
//Read the button and see which ones are pressed.
for (int indexBtn = 1; indexBtn < NUM_BUTTONS + 1; indexBtn ++) {
getPage(currentPage).getBtn(indexBtn).buttonPressed = false;
getPage(currentPage).getBtn(indexBtn).BtnBounce.update();
if (getPage(currentPage).getBtn(indexBtn).BtnBounce.read() == LOW) {
nbOfBtnPressed++;
}
if (getPage(currentPage).getBtn(indexBtn).BtnBounce.fell()) {
getPage(currentPage).getBtn(indexBtn).buttonPressTimeStamp = time;
DEBUG_MSG.print("Btn ");
DEBUG_MSG.print(indexBtn,1);
DEBUG_MSG.println("was pressed ");
}
if (getPage(currentPage).getBtn(indexBtn).BtnBounce.rose()) {
getPage(currentPage).getBtn(indexBtn).buttonReleaseTimeStamp = time;
getPage(currentPage).getBtn(indexBtn).buttonPressed = true;
DEBUG_MSG.print("Btn ");
DEBUG_MSG.print(indexBtn,1);
DEBUG_MSG.println("was released ");
}
}
printPage(currentPage);
}
void setup() {
DEBUG_MSG.println(__func__);
/*
*The pin13 is used to show if the unit is powered.
*it extends the internal Arduino LED into an external LED.
*A 220 Ω resistor needs to be added.
*The LED is located above the ON/OFF switch of the Octopus
*/
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); //Turning on the status LED
//Shift register pins.
pinMode(SER_Pin, OUTPUT);
pinMode(RCLK_Pin, OUTPUT);
pinMode(SRCLK_Pin, OUTPUT);
//Using the Serial for debug messages.
if (DEBUG_MODE) {
Serial.begin(9600);
while (!SerialUSB){
; //Wait for the serial to connect.
}
}
delay(2000);
initializePages();
printPages(true);
testLEDs();
//Keyboard is use to control YouTube, GB etc... via a USB cable
Keyboard.begin();
DEBUG_MSG.println("Keyboard Initialized");
Serial1.begin(31250); // setup serial for MIDI
UART0_BAUDRATE_REGISTER = BAUD31250; //Apparently there is a bug in the arduino so i have to set the baud rate this way
DEBUG_MSG.println("MIDI Initialized");
midiOut.sendProgramChange(DEFAULT_PROGRAM, 1);
midiOut.sendControlChange(71,SNAP_MODE, 1);
}
void loop(){
;
//Turn on the power status LED.
//digitalWrite(LED_BUILTIN, HIGH);
//readButtons(millis());
}