From: c vw Date: Thu, 24 Oct 2019 15:20:01 +0000 (+0200) Subject: for HERCULES midi controller X-Git-Url: https://git.rkrishnan.org/%5B/listings/flags/status?a=commitdiff_plain;h=4f7d62c6531bdcb1f6088042ffad663a67810591;p=pihpsdr.git for HERCULES midi controller --- diff --git a/alsa_midi.c b/alsa_midi.c index 6893f8c..4c183a5 100644 --- a/alsa_midi.c +++ b/alsa_midi.c @@ -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); diff --git a/mac_midi.c b/mac_midi.c index 2229f44..429a67d 100644 --- a/mac_midi.c +++ b/mac_midi.c @@ -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 28156d6..48061d7 100644 --- 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 e41484e..8000ec5 100644 --- 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", <3, <2, <1, &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 87f4213..c5ba82e 100644 --- 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.