]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
for HERCULES midi controller
authorc vw <dl1ycf@darc.de>
Thu, 24 Oct 2019 15:20:01 +0000 (17:20 +0200)
committerc vw <dl1ycf@darc.de>
Thu, 24 Oct 2019 15:20:01 +0000 (17:20 +0200)
alsa_midi.c
mac_midi.c
midi.h
midi2.c
midi3.c

index 6893f8c56964f05506af88567824123a62f60a9c..4c183a5437170cf3fb8aa316cc2f08bf6cdb1df6 100644 (file)
@@ -125,7 +125,14 @@ static void *midi_thread(void *arg) {
                    // We have a command!
                    switch (command) {
                        case CMD_NOTEON:
-                          NewMidiEvent(MIDI_NOTE, chan, arg1, 1);
+                          // Hercules MIDI controllers generate NoteOn
+                          // messages with velocity == 0 when releasing
+                          // a push-button
+                          if (arg2 == 0) {
+                            NewMidiEvent(MIDI_NOTE, chan, arg1, 0);
+                          } else {
+                            NewMidiEvent(MIDI_NOTE, chan, arg1, 1);
+                          }
                           break;
                        case CMD_NOTEOFF:
                           NewMidiEvent(MIDI_NOTE, chan, arg1, 0);
index 2229f44f75c952219f3d78971b3e6a39f3012ca1..429a67d084c90fb0f8806f89f5837d2b60934899 100644 (file)
@@ -115,7 +115,14 @@ static void ReadMIDIdevice(const MIDIPacketList *pktlist, void *refCon, void *co
                     // We have a command!
                     switch (command) {
                         case CMD_NOTEON:
-                           NewMidiEvent(MIDI_NOTE, chan, arg1, 1);
+                           // Hercules MIDI controllers generate NoteOn
+                           // messages with velocity == 0 when releasing
+                           // a push-button.
+                           if (arg2 == 0) {
+                             NewMidiEvent(MIDI_NOTE, chan, arg1, 0);
+                           } else {
+                             NewMidiEvent(MIDI_NOTE, chan, arg1, 1);
+                           }
                            break;
                         case CMD_NOTEOFF:
                            NewMidiEvent(MIDI_NOTE, chan, arg1, 0);
diff --git a/midi.h b/midi.h
index 28156d6871ae3098fe56d6474d464f942ec4bbb9..48061d7db8f1833a6b3b63759617b732dcdad3a5 100644 (file)
--- a/midi.h
+++ b/midi.h
@@ -160,13 +160,12 @@ struct desc {
    enum MIDIevent    event;      // type of event (NOTE on/off, Controller change, Pitch value)
    int               onoff;       // 1: generate upstream event both for Note-on and Note-off
    enum MIDItype     type;        // Key, Knob, or Wheel
-   int               low_thr3;    // Wheel only: If controller value is <= this value, generate "very fast down"
-   int               low_thr2;    // Wheel only: If controller value is <= this value, generate "     fast down"
-   int               low_thr1;    // Wheel only: If controller value is <= this value, generate "          down"
-   int               up_thr1;     // Wheel only: If controller value is <= this value, generate "          up  "
-   int               up_thr2;     // Wheel only: If controller value is <= this value, generate "     fast up  "
-   int               up_thr3;     // Wheel only: If controller value is <= this value, generate "very fast up  "
-   int               leftright;   // Wheel: if set, swap left/right or up/down; Knob: map 0-127 onto 127-0
+   int               vfl1,vfl2;   // Wheel only: range of controller values for "very fast left"
+   int               fl1,fl2;     // Wheel only: range of controller values for "fast left"
+   int               lft1,lft2;   // Wheel only: range of controller values for "slow left"
+   int               vfr1,vfr2;   // Wheel only: range of controller values for "very fast right"
+   int               fr1,fr2;     // Wheel only: range of controller values for "fast right"
+   int               rgt1,rgt2;   // Wheel only: range of controller values for "slow right"
    int              delay;       // Wheel only: delay (msec) before next message is given upstream
    enum MIDIaction   action;     // SDR "action" to generate
    struct desc       *next;       // Next defined action for a controller/key with that note value (NULL for end of list)
diff --git a/midi2.c b/midi2.c
index e41484e7c83de03b57fc03a80a1029f8513e853a..8000ec514c02dfdd73ae372e3271850ca59aa313 100644 (file)
--- a/midi2.c
+++ b/midi2.c
@@ -39,8 +39,6 @@ void NewMidiEvent(enum MIDIevent event, int channel, int note, int val) {
                    if (desc->type == MIDI_KNOB) {
                        // normalize value to range 0 - 100
                        new = (val*100)/127;
-                       // LEFTRIGHT: swap min/max value
-                       if (desc->leftright) new=100-new;
                        DoTheMidi(desc->action, desc->type, new);
                    } else if (desc->type == MIDI_WHEEL) {
                        if (desc->delay > 0) {
@@ -51,14 +49,12 @@ void NewMidiEvent(enum MIDIevent event, int channel, int note, int val) {
                          last_wheel_tp = tp;
                        }
                        // translate value to direction
-                       if (val <= desc->low_thr1) new=-1;
-                       if (val <= desc->low_thr2) new=-10;
-                       if (val <= desc->low_thr3) new=-100;
-                       if (val >= desc->up_thr1 ) new=1;
-                       if (val >= desc->up_thr2 ) new=10;
-                       if (val >= desc->up_thr3 ) new=100;
-                       // LEFTRIGHT: swap up/down
-                       if (desc->leftright) new=-new;
+                       if ((val >= desc->vfl1) && (val <= desc->vfl2)) new=-100;
+                       if ((val >= desc-> fl1) && (val <= desc-> fl2)) new=-10;
+                       if ((val >= desc->lft1) && (val <= desc->lft2)) new=-1;
+                       if ((val >= desc->rgt1) && (val <= desc->rgt2)) new= 1;
+                       if ((val >= desc-> fr1) && (val <= desc-> fr2)) new= 10;
+                       if ((val >= desc->vfr1) && (val <= desc->vfr2)) new= 100;
                        DoTheMidi(desc->action, desc->type, new);
                        last_wheel_action=desc->action;
                    }
@@ -67,8 +63,6 @@ void NewMidiEvent(enum MIDIevent event, int channel, int note, int val) {
                    if (desc->type == MIDI_KNOB) {
                        // normalize value to 0 - 100
                        new = (val*100)/16383;
-                       // possibly reverse scale
-                       if (desc->leftright) new=100-new;
                        DoTheMidi(desc->action, desc->type, new);
                    }
                    break;
@@ -164,7 +158,7 @@ void MIDIstartup() {
     enum MIDIaction action;
     int chan;
     int swap_lr;
-    int lt3,lt2,lt1,ut1,ut2,ut3;
+    int t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12;
     int onoff, delay;
     struct desc *desc,*dp;
     enum MIDItype type;
@@ -196,8 +190,8 @@ void MIDIstartup() {
         continue; // nothing more in this line
       }
       chan=-1;  // default: any channel
-      lt3=lt2=lt1=-1;
-      ut3=ut2=ut1=128;
+      t1=t3=t5=t7= t9=t11=128;  // range that never occurs
+      t2=t4=t6=t8=t10=t12=-1;   // range that never occurs
       onoff=0;
       swap_lr=0;
       event=EVENT_NONE;
@@ -205,6 +199,11 @@ void MIDIstartup() {
       key=0;
       delay=0;
 
+      //
+      // The KEY=, CTRL=, and PITCH= cases are mutually exclusive
+      // If more than one keyword is in the line, PITCH wins over CTRL
+      // wins over KEY.
+      //
       if ((cp = strstr(zeile, "KEY="))) {
         sscanf(cp+4, "%d", &key);
         event=MIDI_NOTE;
@@ -219,12 +218,23 @@ void MIDIstartup() {
         event=MIDI_PITCH;
        type=MIDI_KNOB;
       }
+      //
+      // If event is still undefined, skip line
+      //
+      if (event == EVENT_NONE) continue;
+
+      //
+      // beware of illegal key values
+      //
+      if (key < 0  ) key=0;
+      if (key > 127) key=127;
+
       if ((cp = strstr(zeile, "CHAN="))) {
         sscanf(cp+5, "%d", &chan);
        chan--;
         if (chan<0 || chan>15) chan=-1;
       }
-      if ((cp = strstr(zeile, "WHEEL"))) {
+      if ((cp = strstr(zeile, "WHEEL")) && (type == MIDI_KNOB)) {
        // change type from MIDI_KNOB to MIDI_WHEEL
         type=MIDI_WHEEL;
       }
@@ -238,7 +248,8 @@ void MIDIstartup() {
         sscanf(cp+6, "%d", &delay);
       }
       if ((cp = strstr(zeile, "THR="))) {
-        sscanf(cp+4, "%d %d %d %d %d %d", &lt3, &lt2, &lt1, &ut1, &ut2, &ut3);
+        sscanf(cp+4, "%d %d %d %d %d %d %d %d %d %d %d %d",
+               &t1,&t2,&t3,&t4,&t5,&t6,&t7,&t8,&t9,&t10,&t11,&t12);
       }
       if ((cp = strstr(zeile, "ACTION="))) {
         // cut zeile at the first blank character following
@@ -247,10 +258,18 @@ void MIDIstartup() {
        *cq=0;
         action=keyword2action(cp+7);
       }
-      if (event == EVENT_NONE || type == TYPE_NONE || key < 0 || key > 127) continue;
-      // Now all entries of the line have been read. Construct descriptor
-//fprintf(stderr,"K=%d C=%d T=%d E=%d A=%d OnOff=%d LeftRight=%d THRs=%d %d %d %d %d %d\n",
-//               key,chan,type, event, action, onoff, swap_lr, lt3,lt2,lt1,ut1,ut2,ut3);
+#if 0
+  fprintf(stderr,"K=%d C=%d T=%d E=%d A=%d OnOff=%d\n",key,chan,type, event, action, onoff);
+  if (t1 <= t2 ) fprintf(stderr,"Range for very fast  left: %d -- %d\n",t1,t2);
+  if (t3 <= t4 ) fprintf(stderr,"Range for      fast  left: %d -- %d\n",t3,t4);
+  if (t5 <= t6 ) fprintf(stderr,"Range for    normal  left: %d -- %d\n",t5,t6);
+  if (t7 <= t8 ) fprintf(stderr,"Range for    normal right: %d -- %d\n",t7,t8);
+  if (t9 <= t10) fprintf(stderr,"Range for      fast right: %d -- %d\n",t9,t10);
+  if (t11<= t12) fprintf(stderr,"Range for very fast right: %d -- %d\n",t11,t12);
+#endif
+      //
+      // All data for a descriptor has been read. Construct it!
+      //
       desc = (struct desc *) malloc(sizeof(struct desc));
       desc->next = NULL;
       desc->action = action;
@@ -258,15 +277,23 @@ void MIDIstartup() {
       desc->event = event;
       desc->onoff = onoff;
       desc->delay = delay;
-      desc->low_thr3 = lt3;
-      desc->low_thr2 = lt2;
-      desc->low_thr1 = lt1;
-      desc->up_thr1  = ut1;
-      desc->up_thr2  = ut2;
-      desc->up_thr3  = ut3;
-      desc->leftright= swap_lr;
+      desc->vfl1  = t1;
+      desc->vfl2  = t2;
+      desc->fl1   = t3;
+      desc->fl2   = t4;
+      desc->lft1  = t5;
+      desc->lft2  = t6;
+      desc->rgt1  = t7;
+      desc->rgt2  = t8;
+      desc->fr1   = t9;
+      desc->fr2   = t10;
+      desc->vfr1  = t11;
+      desc->vfr2  = t12;
       desc->channel  = chan;
-      // insert descriptor
+      //
+      // insert descriptor into linked list.
+      // We have a linked list for each key value to speed up searches
+      //
       if (event == MIDI_PITCH) {
        dp = MidiCommandsTable.pitch;
        if (dp == NULL) {
diff --git a/midi3.c b/midi3.c
index 87f42133682035f5db432ccbf402572fa7d179c4..c5ba82edcc5dcb821a36ecda80d4f86154967f08 100644 (file)
--- a/midi3.c
+++ b/midi3.c
@@ -195,8 +195,8 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
                }
            }
            break;
-       case PRE:       // only key supported
-           if (filter_board == CHARLY25) {
+       case PRE:       // only key supported, and only CHARLY25
+           if (filter_board == CHARLY25 && type == MIDI_KEY) {
                //
                // For hardware other than CHARLY25, we do not
                // switch preamps
@@ -237,7 +237,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
                      new=adc_attenuation[active_receiver->adc] + val;
                      if (new > 31) new=31;
                      if (new < 0 ) new=0;
-                   } else {
+       
                      new=(31*val)/100;
                    }
                    dp=malloc(sizeof(double));
@@ -264,85 +264,106 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
            if (dnew > 0.5) transmitter->compressor=1;
            g_idle_add(ext_set_compression, NULL);
            break;
-       case MIDI_NB:
+       case MIDI_NB: // only key supported
            // cycle through NoiseBlanker settings
-           if (active_receiver->nb) {
+            if (type == MIDI_KEY) {
+             if (active_receiver->nb) {
                active_receiver->nb = 0;
                active_receiver->nb2= 1;
-           } else if (active_receiver->nb2) {
+             } else if (active_receiver->nb2) {
                active_receiver->nb = 0;
                active_receiver->nb2= 0;
-           } else {
+             } else {
                active_receiver->nb = 1;
                active_receiver->nb2= 0;
+             }
+             g_idle_add(ext_vfo_update, NULL);
            }
-           g_idle_add(ext_vfo_update, NULL);
            break;
-       case MIDI_NR:
+       case MIDI_NR: // only key supported
            // cycle through NoiseReduction settings
-           if (active_receiver->nr) {
+           if (type == MIDI_KEY) {
+             if (active_receiver->nr) {
                active_receiver->nr = 0;
                active_receiver->nr2= 1;
-           } else if (active_receiver->nr2) {
+             } else if (active_receiver->nr2) {
                active_receiver->nr = 0;
                active_receiver->nr2= 0;
-           } else {
+             } else {
                active_receiver->nr = 1;
                active_receiver->nr2= 0;
+             }
+             g_idle_add(ext_vfo_update, NULL);
            }
-           g_idle_add(ext_vfo_update, NULL);
            break;
-       case VOX:
+       case VOX: // only key supported
            // toggle VOX
-           vox_enabled = !vox_enabled;
-           g_idle_add(ext_vfo_update, NULL);
+           if (type == MIDI_KEY) {
+             vox_enabled = !vox_enabled;
+             g_idle_add(ext_vfo_update, NULL);
+           }
            break;
-       case MIDI_CTUN:
+       case MIDI_CTUN: // only key supported
            // toggle CTUN
-           new=active_receiver->id;
-           if(!vfo[new].ctun) {
+           if (type == MIDI_KEY) {
+             new=active_receiver->id;
+             if(!vfo[new].ctun) {
                vfo[new].ctun=1;
                vfo[new].offset=0;
-           } else {
+             } else {
                vfo[new].ctun=0;
+             }
+             vfo[new].ctun_frequency=vfo[new].frequency;
+             set_offset(active_receiver,vfo[new].offset);
+             g_idle_add(ext_vfo_update, NULL);
            }
-           vfo[new].ctun_frequency=vfo[new].frequency;
-           set_offset(active_receiver,vfo[new].offset);
-           g_idle_add(ext_vfo_update, NULL);
            break;
-       case MIDI_PS:
+       case MIDI_PS: // only key supported
 #ifdef PURESIGNAL
            // toggle PURESIGNAL
-           new=!(transmitter->puresignal);
-           g_idle_add(ext_tx_set_ps,GINT_TO_POINTER(new));
+           if (type == MIDI_KEY) {
+             new=!(transmitter->puresignal);
+             g_idle_add(ext_tx_set_ps,GINT_TO_POINTER(new));
+           }
 #endif
            break;
-       case MIDI_SPLIT:
+       case MIDI_SPLIT: // only key supported
            // toggle split mode
-           if(!split) {
+           if (type == MIDI_KEY) {
+             if(!split) {
                split=1;
                tx_set_mode(transmitter,vfo[VFO_B].mode);
-           } else {
+             } else {
                split=0;
                tx_set_mode(transmitter,vfo[VFO_A].mode);
+             }
+             g_idle_add(ext_vfo_update, NULL);
            }
-           g_idle_add(ext_vfo_update, NULL);
            break;
-       case VFO_A2B:
-           g_idle_add(ext_vfo_a_to_b, NULL);
+       case VFO_A2B: // only key supported
+           if (type == MIDI_KEY) {
+             g_idle_add(ext_vfo_a_to_b, NULL);
+           }
            break;
-       case VFO_B2A:
-           g_idle_add(ext_vfo_b_to_a, NULL);
+       case VFO_B2A: // only key supported
+           if (type == MIDI_KEY) {
+             g_idle_add(ext_vfo_b_to_a, NULL);
+           }
            break;
-       case MIDI_LOCK:
-           locked=!locked;
-           g_idle_add(ext_vfo_update, NULL);
+       case MIDI_LOCK: // only key supported
+           if (type == MIDI_KEY) {
+             locked=!locked;
+             g_idle_add(ext_vfo_update, NULL);
+           }
            break;
-       case AGCATTACK:
-           new=active_receiver->agc + 1;
-           if (new > AGC_FAST) new=0;
-           active_receiver->agc=new;
-           g_idle_add(ext_vfo_update, NULL);
+       case AGCATTACK: // only key supported
+           // cycle through fast/med/slow AGC attack
+           if (type == MIDI_KEY) {
+             new=active_receiver->agc + 1;
+             if (new > AGC_FAST) new=0;
+             active_receiver->agc=new;
+             g_idle_add(ext_vfo_update, NULL);
+           }
            break;
        case ACTION_NONE:
            // No error message, this is the "official" action for un-used controller buttons.