about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZach DeCook <zachdecook@librem.one>2024-06-08 19:59:13 -0400
committerZach DeCook <zachdecook@librem.one>2024-06-08 19:59:13 -0400
commit7e21c52bc226d58d96718f69617009ef13eba4ae (patch)
tree2393dc72062ede72ca336fe3875aa027e27a3972
parent6beaded1374943a90b1e0e5c244a95132c6b28f1 (diff)
downloadHexBoard-7e21c52bc226d58d96718f69617009ef13eba4ae.tar.gz
Use virtual buttons to detect hardware revision
-rw-r--r--HexBoard.ino55
1 files changed, 40 insertions, 15 deletions
diff --git a/HexBoard.ino b/HexBoard.ino
index 9f2a87f..aa93b84 100644
--- a/HexBoard.ino
+++ b/HexBoard.ino
@@ -61,7 +61,6 @@
     the code into a library at that point.
   */
 // @init
-  #define HARDWARE_VERSION 1      // 1 = v1.1 board. 2 = v1.2 board.
   #include <Arduino.h>            // this is necessary to talk to the Hexboard!
   #include <Wire.h>               // this is necessary to deal with the pins and wires
   #define SDAPIN 16
@@ -70,6 +69,11 @@
   #include <numeric>              // need that GCD function, son
   #include <string>               // standard C++ library string classes (use "std::string" to invoke it); these do not cause the memory corruption that Arduino::String does.
   #include <queue>                // standard C++ library construction to store open channels in microtonal mode (use "std::queue" to invoke it)
+// Software-detected hardware revision
+  #define HARDWARE_UNKNOWN 0
+  #define HARDWARE_V1_1 1
+  #define HARDWARE_V1_2 2
+  byte Hardware_Version = 0;       // 0 = unknown, 1 = v1.1 board. 2 = v1.2 board.
 // @helpers
   /*
     C++ returns a negative value for 
@@ -921,7 +925,8 @@
   */
   #define LED_COUNT 140
   #define COLCOUNT 10
-  #define ROWCOUNT 14
+  #define ROWCOUNT 16
+  #define BTN_COUNT COLCOUNT*ROWCOUNT
   /*
     Of the 140 buttons, 7 are offset to the bottom left
     quadrant of the Hexboard and are reserved as command
@@ -956,6 +961,10 @@
   */
   class buttonDef {
   public:
+    #define BTN_STATE_OFF 0
+    #define BTN_STATE_NEWPRESS 1
+    #define BTN_STATE_RELEASED 2
+    #define BTN_STATE_HELD 3
     byte     btnState = 0;        // binary 00 = off, 01 = just pressed, 10 = just released, 11 = held
     void interpBtnPress(bool isPress) {
       btnState = (((btnState << 1) + isPress) & 3);
@@ -1076,7 +1085,7 @@
     buttons from 0 to 139. h[i] refers to the 
     button with the LED address = i.
   */
-  buttonDef h[LED_COUNT];        
+  buttonDef h[BTN_COUNT];
   
   wheelDef modWheel = { &wheelMode, &modSticky,
     &h[assignCmd[4]].btnState, &h[assignCmd[5]].btnState, &h[assignCmd[6]].btnState,
@@ -1104,7 +1113,7 @@
   }
 
   void setupGrid() {
-    for (byte i = 0; i < LED_COUNT; i++) {
+    for (byte i = 0; i < BTN_COUNT; i++) {
       h[i].coordRow = (i / 10);
       h[i].coordCol = (2 * (i % 10)) + (h[i].coordRow & 1);
       h[i].isCmd = 0;
@@ -1115,6 +1124,12 @@
       h[assignCmd[c]].isCmd = 1;
       h[assignCmd[c]].note = CMDB + c;
     }
+    // "flag" buttons
+    for (byte i = 140; i < BTN_COUNT; i++) {
+      h[i].isCmd = 1;
+    }
+    // On version 1.2, "button" 140 is shorted (always connected)
+    h[140].note = HARDWARE_V1_2;
   }
 
 // @LED
@@ -1755,8 +1770,8 @@
 
   byte findNextHeldNote() {
     byte n = UNUSED_NOTE;
-    for (byte i = 1; i <= LED_COUNT; i++) {
-      byte j = positiveMod(arpeggiatingNow + i, LED_COUNT);
+    for (byte i = 1; i <= BTN_COUNT; i++) {
+      byte j = positiveMod(arpeggiatingNow + i, BTN_COUNT);
       if ((h[j].MIDIch) && (!h[j].isCmd)) {
         n = j;
         break;
@@ -1783,7 +1798,7 @@
       synth[i].increment = 0;
       synth[i].counter = 0;
     }
-    for (byte i = 0; i < LED_COUNT; i++) {
+    for (byte i = 0; i < BTN_COUNT; i++) {
       h[i].synthCh = 0;
     }
     if (playbackMode == SYNTH_POLY) {
@@ -1795,7 +1810,7 @@
   
   void updateSynthWithNewFreqs() {
     MIDI.sendPitchBend(pbWheel.curValue, 1);
-    for (byte i = 0; i < LED_COUNT; i++) {
+    for (byte i = 0; i < BTN_COUNT; i++) {
       if (!(h[i].isCmd)) {
         if (h[i].synthCh) {
           setSynthFreq(h[i].frequency,h[i].synthCh);           // pass all notes thru synth again if the pitch bend changes
@@ -2069,6 +2084,9 @@
       case CMDB + 3:
         toggleWheel = !toggleWheel;
         break;
+      case HARDWARE_V1_2:
+        Hardware_Version = h[x].note;
+        break;
       default:
         // the rest should all be taken care of within the wheelDef structure
         break;
@@ -2125,8 +2143,8 @@
   */
   GEMPage  menuPageMain("HexBoard MIDI Controller");
   GEMPage  menuPageTuning("Tuning");
-  GEMItem  menuTuningBack("<< Back", menuPageMain);
   GEMItem  menuGotoTuning("Tuning", menuPageTuning);
+  GEMItem  menuTuningBack("<< Back", menuPageMain);
   GEMPage  menuPageLayout("Layout");
   GEMItem  menuGotoLayout("Layout", menuPageLayout); 
   GEMItem  menuLayoutBack("<< Back", menuPageMain);
@@ -2162,7 +2180,13 @@
     To be honest I don't know how to get just a plain text line to show here other than this!
   */
   void fakeButton() {}
-  GEMItem  menuItemVersion("v1.0.0", fakeButton);
+  GEMItem  menuItemVersion("v1.0.1", fakeButton);
+  SelectOptionByte optionByteHardware[] =  {
+    { "V1.1", HARDWARE_UNKNOWN }, { "V1.1" , HARDWARE_V1_1 },
+    { "V1.2", HARDWARE_V1_2 }
+  };
+  GEMSelect selectHardware( sizeof(optionByteHardware)  / sizeof(SelectOptionByte), optionByteHardware);
+  GEMItem  menuItemHardware("HexBoard", Hardware_Version, selectHardware, GEM_READONLY);
   /*
     This GEMItem runs a given procedure when you select it.
     We must declare or define that procedure first.
@@ -2499,6 +2523,7 @@
     menuPageMain.addMenuItem(menuItemTransposeSteps);
     menuPageMain.addMenuItem(menuGotoTesting);
       menuPageTesting.addMenuItem(menuItemVersion);
+      menuPageTesting.addMenuItem(menuItemHardware);
       menuPageTesting.addMenuItem(menuItemPercep);
       menuPageTesting.addMenuItem(menuItemShiftColor);
       menuPageTesting.addMenuItem(menuItemWheelAlt);
@@ -2584,15 +2609,15 @@
         delayMicroseconds(6);                  // delay while column pin mode
         bool didYouPressHex = (digitalRead(p) == LOW);  // hex is pressed if it returns LOW. else not pressed
         h[i].interpBtnPress(didYouPressHex);
-        if (h[i].btnState == 1) {
+        if (h[i].btnState == BTN_STATE_NEWPRESS) {
           h[i].timePressed = runTime;          // log the time
         }
         pinMode(p, INPUT);                     // Set the selected column pin back to INPUT mode (0V / LOW).
        }
     }
-    for (byte i = 0; i < LED_COUNT; i++) {   // For all buttons in the deck
+    for (byte i = 0; i < BTN_COUNT; i++) {   // For all buttons in the deck
       switch (h[i].btnState) {
-        case 1: // just pressed
+        case BTN_STATE_NEWPRESS: // just pressed
           if (h[i].isCmd) {
             cmdOn(i);
           } else if (h[i].inScale || (!scaleLock)) {
@@ -2600,7 +2625,7 @@
             trySynthNoteOn(i);
           }
           break;
-        case 2: // just released
+        case BTN_STATE_RELEASED: // just released
           if (h[i].isCmd) {
             cmdOff(i);
           } else if (h[i].inScale || (!scaleLock)) {
@@ -2608,7 +2633,7 @@
             trySynthNoteOff(i); 
           }
           break;
-        case 3: // held
+        case BTN_STATE_HELD: // held
           break;
         default: // inactive
           break;