// 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);
// 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);
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)
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) {
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;
}
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;
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;
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;
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;
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;
}
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
*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;
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) {
}
}
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
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));
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.