From: c vw <dl1ycf@darc.de>
Date: Mon, 28 Oct 2019 14:38:06 +0000 (+0100)
Subject: Added knobs to many RIT functions, RIT_STEP, etc.
X-Git-Url: https://git.rkrishnan.org/pf/content/en/cyclelanguage?a=commitdiff_plain;h=af4185e751d88219fa9a69cb420439b2b30e32fe;p=pihpsdr.git

Added knobs to many RIT functions, RIT_STEP, etc.
---

diff --git a/midi.h b/midi.h
index c17101e..a72803e 100644
--- a/midi.h
+++ b/midi.h
@@ -48,41 +48,42 @@
 //
 enum MIDIaction {
   ACTION_NONE=0,	// No-Op (unassigned key)
-  MIDI_AGC,			// AGC level
+  MIDI_AGC,		// AGC level
   AGCATTACK,		// AGC ATTACK (cycle fast/med/slow etc.)
   ATT,			// Step attenuator or Programmable attenuator
   AF_GAIN,		// AF gain
   BAND_DOWN,		// cycle through bands downwards
   BAND_UP,		// cycle through bands upwards
   COMPRESS,		// TX compressor value
-  MIDI_CTUN,			// CTUN on/off
+  MIDI_CTUN,		// CTUN on/off
   FILTER_UP,		// cycle through filters upwards
   FILTER_DOWN,		// cycle through filters downwards
   MIC_VOLUME,		// MIC gain
-  MIDI_LOCK,			// disable frequency changes
+  MIDI_LOCK,		// disable frequency changes
   MODE_UP,		// cycle through modes upwards
   MODE_DOWN,		// cycle through modes downwards
-  MIDI_MOX,			// toggle "mox" state
-  MIDI_NB,			// cycle through NoiseBlanker states (none, NB, NB2)
-  MIDI_NR,			// cycle through NoiseReduction states (none, NR, NR2)
+  MIDI_MOX,		// toggle "mox" state
+  MIDI_NB,		// cycle through NoiseBlanker states (none, NB, NB2)
+  MIDI_NR,		// cycle through NoiseReduction states (none, NR, NR2)
   PRE,			// preamp on/off
   PAN_HIGH,		// "high" value of current panadapter
   PAN_LOW,		// "low" value of current panadapter
-  MIDI_PS,			// PURESIGNAL on/off
-  MIDI_RIT_CLEAR,		// clear RIT value
+  MIDI_PS,		// PURESIGNAL on/off
+  RIT_STEP,		// cycle through RIT values
+  RIT_TOGGLE,  		// RIT on/off
   RIT_VAL,		// change RIT value
   MIDI_SPLIT,		// Split on/off
   SWAP_VFO,		// swap VFO A/B frequency
-  MIDI_TUNE,			// toggle "tune" state
+  MIDI_TUNE,		// toggle "tune" state
   TX_DRIVE,		// RF output power
   VFO,			// change VFO frequency
   VFOA,			// change VFO-A frequency
   VFOB,			// change VFO-B frequency
   VFO_A2B,		// VFO A -> B
   VFO_B2A,		// VFO B -> A
-  VOX, 			// VOX on/off
   VFO_STEP_UP,		// cycle through vfo steps upwards;
   VFO_STEP_DOWN,	// cycle through vfo steps downwards;
+  VOX, 			// VOX on/off
 };
 
 //
diff --git a/midi2.c b/midi2.c
index d63e17c..e12f254 100644
--- a/midi2.c
+++ b/midi2.c
@@ -95,43 +95,44 @@ static struct {
   enum MIDIaction action;
   const char *str;
 } ActionTable[] = {
-        { AF_GAIN,      "AFGAIN"},
-        { MIDI_AGC,     "AGC"},
-	{ AGCATTACK,   	"AGCATTACK"},
-        { ATT,          "ATT"},
-        { BAND_DOWN,    "BANDDOWN"},
-        { BAND_UP,      "BANDUP"},
-        { COMPRESS,     "COMPRESS"},
-	{ MIDI_CTUN,  	"CTUN"},
-        { FILTER_DOWN,  "FILTERDOWN"},
-        { FILTER_UP,    "FILTERUP"},
-	{ MIDI_LOCK,    "LOCK"},
-        { MIC_VOLUME,   "MICGAIN"},
-	{ MODE_DOWN,	"MODEDOWN"},
-	{ MODE_UP,	"MODEUP"},
-        { MIDI_MOX,     "MOX"},
-	{ MIDI_NB,    	"NOISEBLANKER"},
-	{ MIDI_NR,    	"NOISEREDUCTION"},
-        { PAN_HIGH,     "PANHIGH"},
-        { PAN_LOW,      "PANLOW"},
-        { PRE,          "PREAMP"},
-	{ MIDI_PS,    	"PURESIGNAL"},
-        { MIDI_RIT_CLEAR,"RITCLEAR"},
-        { RIT_VAL,      "RITVAL"},
-	{ MIDI_SPLIT,  	"SPLIT"},
-	{ SWAP_VFO,	"SWAPVFO"},
-        { MIDI_TUNE,    "TUNE"},
-        { TX_DRIVE,     "RFPOWER"},
-        { VFO,          "VFO"},
-        { VFOA,         "VFOA"},
-        { VFOB,         "VFOB"},
-	{ VFO_A2B,	"VFOA2B"},
-	{ VFO_B2A,	"VFOB2A"},
-	{ VOX,   	"VOX"},
-	{ VFO_STEP_UP,  "VFOSTEPUP"},
-	{ VFO_STEP_DOWN,  "VFOSTEPDOWN"},
-        { ACTION_NONE,  "NONE"},
-        { ACTION_NONE,  NULL}
+        { AF_GAIN,      	"AFGAIN"},
+        { MIDI_AGC,     	"AGC"},
+	{ AGCATTACK,   		"AGCATTACK"},
+        { ATT,          	"ATT"},
+        { BAND_DOWN,    	"BANDDOWN"},
+        { BAND_UP,      	"BANDUP"},
+        { COMPRESS,     	"COMPRESS"},
+	{ MIDI_CTUN,  		"CTUN"},
+        { FILTER_DOWN,  	"FILTERDOWN"},
+        { FILTER_UP,    	"FILTERUP"},
+	{ MIDI_LOCK,    	"LOCK"},
+        { MIC_VOLUME,   	"MICGAIN"},
+	{ MODE_DOWN,		"MODEDOWN"},
+	{ MODE_UP,		"MODEUP"},
+        { MIDI_MOX,     	"MOX"},
+	{ MIDI_NB,    		"NOISEBLANKER"},
+	{ MIDI_NR,    		"NOISEREDUCTION"},
+        { PAN_HIGH,     	"PANHIGH"},
+        { PAN_LOW,      	"PANLOW"},
+        { PRE,          	"PREAMP"},
+	{ MIDI_PS,    		"PURESIGNAL"},
+        { RIT_TOGGLE,   	"RITONOFF"},
+	{ RIT_STEP, 		"RITSTEP"},
+        { RIT_VAL,      	"RITVAL"},
+	{ MIDI_SPLIT,  		"SPLIT"},
+	{ SWAP_VFO,		"SWAPVFO"},
+        { MIDI_TUNE,    	"TUNE"},
+        { TX_DRIVE,     	"RFPOWER"},
+        { VFO,          	"VFO"},
+        { VFOA,         	"VFOA"},
+	{ VFO_A2B,		"VFOA2B"},
+        { VFOB,         	"VFOB"},
+	{ VFO_B2A,		"VFOB2A"},
+	{ VFO_STEP_UP,  	"VFOSTEPUP"},
+	{ VFO_STEP_DOWN,	"VFOSTEPDOWN"},
+	{ VOX,   		"VOX"},
+        { ACTION_NONE,  	"NONE"},
+        { ACTION_NONE,  	NULL}
 };
 
 /*
diff --git a/midi3.c b/midi3.c
index af9219a..899eead 100644
--- a/midi3.c
+++ b/midi3.c
@@ -63,24 +63,35 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;    
 	case AF_GAIN: // knob or wheel supported
-	    if (type == MIDI_KNOB) {
+            switch (type) {
+	      case MIDI_KNOB:
 		active_receiver->volume = 0.01*val;
-	    } else  if (type == MIDI_WHEEL) {
+		break;
+	      case MIDI_WHEEL:	
 		dnew=active_receiver->volume += 0.01*val;
 		if (dnew < 0.0) dnew=0.0; if (dnew > 1.0) dnew=1.0;
 		active_receiver->volume = dnew;
-	    } else {
+		break;
+	      default:
+		// do not change volume
+		// we should not come here anyway
 		break;
 	    }
 	    g_idle_add(ext_update_af_gain, NULL);
 	    break;
 	case MIC_VOLUME: // knob or wheel supported
-	    if (type == MIDI_KNOB) {
+	    switch (type) {
+	      case MIDI_KNOB:
 		dnew=-10.0 + 0.6*val;
-	    } else if (type == MIDI_WHEEL) {
+		break;
+	      case MIDI_WHEEL:
 		dnew = mic_gain + val;
 		if (dnew < -10.0) dnew=-10.0; if (dnew > 50.0) dnew=50.0;
-	    } else {
+		break;
+	      default:
+		// do not change mic gain
+		// we should not come here anyway
+		dnew = mic_gain;
 		break;
 	    }
 	    dp=malloc(sizeof(double));
@@ -88,12 +99,18 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_set_mic_gain, (gpointer) dp);
 	    break;
 	case MIDI_AGC: // knob or wheel supported
-	    if (type == MIDI_KNOB) {
+	    switch (type) {
+	      case MIDI_KNOB:
 		dnew = -20.0 + 1.4*val;
-	    } else if (type == MIDI_WHEEL) {
+		break;
+	      case MIDI_WHEEL:
 		dnew=active_receiver->agc_gain + val;
 		if (dnew < -20.0) dnew=-20.0; if (dnew > 120.0) dnew=120.0;
-	    } else {
+		break;
+	      default:
+		// do not change value
+		// we should not come here anyway
+		dnew=active_receiver->agc_gain;
 		break;
 	    }
 	    dp=malloc(sizeof(double));
@@ -101,99 +118,214 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    g_idle_add(ext_set_agc_gain, (gpointer) dp);
 	    break;
 	case TX_DRIVE: // knob or wheel supported
-	    if (type == MIDI_KNOB) {
+	    switch (type) {
+	      case MIDI_KNOB:
 		dnew = val;
-	    } else if (type == MIDI_WHEEL) {
+		break;
+	      case MIDI_WHEEL:
 		dnew=transmitter->drive + val;
 		if (dnew < 0.0) dnew=0.0; if (dnew > 100.0) dnew=100.0;
-	    } else {
+		break;
+	      default:
+		// do not change value
+		// we should not come here anyway
+		dnew=transmitter->drive;
 		break;
 	    }
 	    dp=malloc(sizeof(double));
 	    *dp=dnew;
 	    g_idle_add(ext_set_drive, (gpointer) dp);
 	    break;
-	case BAND_UP:     // key or wheel supported
-	case BAND_DOWN:   // key or wheel supported
-	    if (type == MIDI_KEY) {
+	case BAND_UP:
+	case BAND_DOWN:
+	    switch (type) {
+	      case MIDI_KEY:
 		new=(action == BAND_UP) ? 1 : -1;
-	    } else if (type == MIDI_WHEEL) {
-		new=val;
-	    } else {
 		break;
+	      case MIDI_WHEEL:
+		new=val > 0 ? 1 : -1;
+		break;
+	      case MIDI_KNOB:
+		// cycle through the bands
+		new = ((BANDS-1) * val) / 100 - vfo[active_receiver->id].band;
+		break;
+	      default:
+		// do not change
+		// we should not come here anyway
+		new=0;
+		break;
+	    }
+	    //
+	    // If the band has not changed, do nothing. Otherwise
+	    // vfo.c will loop through the band stacks
+	    //
+	    if (new != 0) {
+	      new+=vfo[active_receiver->id].band;
+	      if (new >= BANDS) new=0;
+	      if (new < 0) new=BANDS-1;
+	      g_idle_add(ext_vfo_band_changed, GINT_TO_POINTER(new));
 	    }
-            new+=vfo[active_receiver->id].band;
-            if (new >= BANDS) new=0;
-            if (new < 0) new=BANDS-1;
-	    g_idle_add(ext_vfo_band_changed, GINT_TO_POINTER(new));
 	    break;
-	case FILTER_UP:      // key or wheel supported
-	case FILTER_DOWN:    // key or wheel supported
-	    if (type == MIDI_KEY) {
+	case FILTER_UP:
+	case FILTER_DOWN:
+	    switch (type) {
+	      case MIDI_KEY:
 		new=(action == FILTER_UP) ? 1 : -1;
-	    } else if (type == MIDI_WHEEL) {
-		new=val;
-	    } else {
+		new+=vfo[active_receiver->id].filter;
+		if (new >= FILTERS) new=0;
+		if (new <0) new=FILTERS-1;
+		break;
+	      case MIDI_WHEEL:
+		new=val > 0 ? 1 : -1;
+		new+=vfo[active_receiver->id].filter;
+		if (new >= FILTERS) new=0;
+		if (new <0) new=FILTERS-1;
+		break;
+	      case MIDI_KNOB:
+		// cycle through all the filters
+		new = ((FILTERS-1) * val) / 100;
+		break;
+	      default:
+		// do not change filter setting
+		// we should not come here anyway
+		new=vfo[active_receiver->id].filter;
 		break;
 	    }
-	    new+=vfo[active_receiver->id].filter;
-	    if (new >= FILTERS) new=0;
-	    if (new <0) new=FILTERS-1;
 	    g_idle_add(ext_vfo_filter_changed, GINT_TO_POINTER(new));
 	    break;
-	case MODE_UP:      // key or wheel supported
-	case MODE_DOWN:    // key or wheel supported
-	    if (type == MIDI_KEY) {
+	case MODE_UP:
+	case MODE_DOWN:
+	    switch (type) {
+	      case MIDI_KEY:
 		new=(action == MODE_UP) ? 1 : -1;
-	    } else if (type == MIDI_WHEEL) {
-		new=val;
-	    } else {
+		new+=vfo[active_receiver->id].mode;
+		if (new >= MODES) new=0;
+		if (new <0) new=MODES-1;
+		break;
+	      case MIDI_WHEEL:
+		new=val > 0 ? 1 : -1;
+		new+=vfo[active_receiver->id].mode;
+		if (new >= MODES) new=0;
+		if (new <0) new=MODES-1;
+		break;
+	      case MIDI_KNOB:
+		// cycle through all the modes
+		new = ((MODES-1) * val) / 100;
+		break;
+	      default:
+		// do not change
+		// we should not come here anyway
+		new=vfo[active_receiver->id].mode;
 		break;
 	    }
-	    new+=vfo[active_receiver->id].mode;
-	    if (new >= MODES) new=0;
-	    if (new <0) new=MODES-1;
 	    g_idle_add(ext_vfo_mode_changed, GINT_TO_POINTER(new));
 	    break;
-	case PAN_LOW:  // only wheel supported
-	    if (type == MIDI_WHEEL) {
+	case PAN_LOW:  // wheel and knob
+	    switch (type) {
+	      case MIDI_WHEEL:
 		if (isTransmitting()) {
 		    // TX panadapter affected
 		    transmitter->panadapter_low += val;
 		} else {
 		    active_receiver->panadapter_low += val;
 		}
+		break;
+	      case MIDI_KNOB:
+		if (isTransmitting()) {
+		    // TX panadapter: use values -100 through -50
+		    new = -100 + val/2;
+		    transmitter->panadapter_low =new;
+		} else {
+		    // RX panadapter: use values -140 through -90
+		    new = -140 + val/2;
+		    active_receiver->panadapter_low = new;
+		}
+		break;
+	      default:
+		// do nothing
+		// we should not come here anyway
+		break;
+	    }
+	    g_idle_add(ext_vfo_update, NULL);
+	    break;
+	case RIT_STEP: // key or wheel supported
+	    // This cycles between RIT increments 1, 10, 100, 1, 10, 100, ...
+	    switch (type) {
+	      case MIDI_KEY:
+		// key cycles through in upward direction
+		val=1;
+		/* FALLTHROUGH */
+	      case MIDI_WHEEL:
+		// wheel cycles upward or downward
+		if (val > 0) {
+		  rit_increment=10*rit_increment;
+		} else {
+		  rit_increment=rit_increment/10;
+		}
+		if (rit_increment < 1) rit_increment=100;
+		if (rit_increment > 100) rit_increment=1;
+		break;
+	      default:
+		// do nothing
+		break;
 	    }
+	    g_idle_add(ext_vfo_update, NULL);
 	    break;
-	case MIDI_RIT_CLEAR:  // only key supported
+	case RIT_TOGGLE:  // only key supported
 	    if (type == MIDI_KEY) {
-		// this clears the RIT value and disables RIT
-		vfo[active_receiver->id].rit = new;
-		vfo[active_receiver->id].rit_enabled = 0;
+		// enable/disable RIT
+		new=vfo[active_receiver->id].rit_enabled;
+		vfo[active_receiver->id].rit_enabled = new ? 0 : 1;
 	        g_idle_add(ext_vfo_update, NULL);
 	    }
 	    break;
-	case RIT_VAL:	// only wheel supported
-	    if (type == MIDI_WHEEL) {
-		// This changes the RIT value. If a value of 0 is reached,
-		// RIT is disabled
+	case RIT_VAL:	// wheel or knob
+	    switch (type) {
+	      case MIDI_WHEEL:
+		// This changes the RIT value incrementally,
+	  	// but we restrict the change to +/ 9.999 kHz
 		new = vfo[active_receiver->id].rit + val*rit_increment;
 		if (new >  9999) new= 9999;
 		if (new < -9999) new=-9999;
 		vfo[active_receiver->id].rit = new;
-		vfo[active_receiver->id].rit_enabled = (new != 0);
-	        g_idle_add(ext_vfo_update, NULL);
+		break;
+	      case MIDI_KNOB:
+	 	// knob: adjust in the range +/ 50*rit_increment
+		new = (val-50) * rit_increment;
+		vfo[active_receiver->id].rit = new;
+		break;
+	      default:
+		// do nothing
+		// we should not come here anyway
+		break;
 	    }
+	    g_idle_add(ext_vfo_update, NULL);
 	    break;
-	case PAN_HIGH:  // only wheel supported
-	    if (type == MIDI_WHEEL) {
+	case PAN_HIGH:  // wheel or knob
+	    switch (type) {
+	      case MIDI_WHEEL:
 		if (mox) {
 		    // TX panadapter affected
 		    transmitter->panadapter_high += val;
 		} else {
 		    active_receiver->panadapter_high += val;
 		}
+		break;
+	    case MIDI_KNOB:
+		// Adjust "high water" in the range -50 ... 0 dBm
+		new = -50 + val/2;
+		if (mox) {
+		    transmitter->panadapter_high = new;
+		} else {
+		    active_receiver->panadapter_high = new;
+		}
+		break;
+	      default:
+		// do nothing
+		// we should not come here anyway
+		break;
 	    }
+	    g_idle_add(ext_vfo_update, NULL);
 	    break;
 	case PRE:	// only key supported, and only CHARLY25
 	    if (filter_board == CHARLY25 && type == MIDI_KEY) {
@@ -223,49 +355,58 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    break;
 	case ATT:	// Key for ALEX attenuator, wheel or knob for slider
 	    switch(type) {
-		case MIDI_KEY:
-		    if (filter_board == ALEX && active_receiver->adc == 0) {
-		      new=active_receiver->alex_attenuation + 1;
-		      if (new > 3) new=0;
-		      g_idle_add(ext_set_alex_attenuation, GINT_TO_POINTER(new));
-		      g_idle_add(ext_update_att_preamp, NULL);
-		    }
-		    break;
-		case MIDI_WHEEL:
-		case MIDI_KNOB:
-		    if (type == MIDI_WHEEL) {
-		      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));
-		    *dp=new;
-		    g_idle_add(ext_set_attenuation_value,(gpointer) dp);
-		    break;
-		default:
-		    break;
+	      case MIDI_KEY:
+		if (filter_board == ALEX && active_receiver->adc == 0) {
+		  new=active_receiver->alex_attenuation + 1;
+		  if (new > 3) new=0;
+		  g_idle_add(ext_set_alex_attenuation, GINT_TO_POINTER(new));
+		  g_idle_add(ext_update_att_preamp, NULL);
+		}
+		break;
+	      case MIDI_WHEEL:
+		  new=adc_attenuation[active_receiver->adc] + val;
+		  if (new > 31) new=31;
+		  if (new < 0 ) new=0;
+		  dp=malloc(sizeof(double));
+		  *dp=new;
+		  g_idle_add(ext_set_attenuation_value,(gpointer) dp);
+		  break;
+	      case MIDI_KNOB:
+		new=(31*val)/100;
+		dp=malloc(sizeof(double));
+		*dp=new;
+		g_idle_add(ext_set_attenuation_value,(gpointer) dp);
+		break;
+	      default:
+		// do nothing
+		// we should not come here anyway
+		break;
 	    }
 	    break;
 	case COMPRESS:
-	    // Use values in the range 0 ... 20
-	    if (type == MIDI_WHEEL) {
-              dnew=transmitter->compressor_level + val;
-	      if (dnew > 20.0) dnew=20.0;
-	      if (dnew < 0 ) dnew=0;
-	    } else if (type == MIDI_KNOB){
-	      dnew=(20.0*val)/100.0;
-	    } else {
+	    switch (type) {
+	      case MIDI_WHEEL:
+		dnew=transmitter->compressor_level + val;
+		if (dnew > 20.0) dnew=20.0;
+		if (dnew < 0 ) dnew=0;
+		break;
+	      case MIDI_KNOB:
+		dnew=(20.0*val)/100.0;
+		break;
+	      default:
+		// do not change
+		// we should not come here anyway
+		dnew=transmitter->compressor_level;
 		break;
 	    }
 	    transmitter->compressor_level=dnew;
+	    // automatically engange compressor if level > 0.5
 	    if (dnew < 0.5) transmitter->compressor=0;
 	    if (dnew > 0.5) transmitter->compressor=1;
 	    g_idle_add(ext_set_compression, NULL);
 	    break;
 	case MIDI_NB: // only key supported
-	    // cycle through NoiseBlanker settings
+	    // cycle through NoiseBlanker settings: OFF, NB, NB2
             if (type == MIDI_KEY) {
 	      if (active_receiver->nb) {
 		active_receiver->nb = 0;
@@ -281,7 +422,7 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	    }
 	    break;
 	case MIDI_NR: // only key supported
-	    // cycle through NoiseReduction settings
+	    // cycle through NoiseReduction settings: OFF, NR1, NR2
 	    if (type == MIDI_KEY) {
 	      if (active_receiver->nr) {
 		active_receiver->nr = 0;
@@ -365,11 +506,22 @@ void DoTheMidi(enum MIDIaction action, enum MIDItype type, int val) {
 	      g_idle_add(ext_vfo_update, NULL);
 	    }
 	    break;
-        case VFO_STEP_UP:
-	    g_idle_add(ext_update_vfo_step, GINT_TO_POINTER(1));
-            break;
+        case VFO_STEP_UP: // key or wheel supported
         case VFO_STEP_DOWN:
-	    g_idle_add(ext_update_vfo_step, GINT_TO_POINTER(-1));
+	    switch (type) {
+	      case MIDI_KEY:
+		new =  (action == VFO_STEP_UP) ? 1 : -1;
+		g_idle_add(ext_update_vfo_step, GINT_TO_POINTER(new));
+		break;
+	      case MIDI_WHEEL:
+		new = (val > 0) ? 1 : -1;
+		g_idle_add(ext_update_vfo_step, GINT_TO_POINTER(new));
+		break;
+	      default:
+		// do nothing
+		// we should not come here anyway
+		break;
+	    }
             break;
 	case ACTION_NONE:
 	    // No error message, this is the "official" action for un-used controller buttons.
diff --git a/radio.c b/radio.c
index faa0ee7..d7a2e10 100644
--- a/radio.c
+++ b/radio.c
@@ -414,10 +414,6 @@ void start_radio() {
   }
 
 
-#ifdef MIDI
-  MIDIstartup();
-#endif
-
 #ifdef __APPLE__
   sem_unlink("PROPERTY");
   property_sem=sem_open("PROPERTY", O_CREAT | O_EXCL, 0700, 0);
@@ -951,6 +947,14 @@ void start_radio() {
 
   gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_ARROW));
 
+  //
+  // MIDIstartup must not be called before the radio is completely set up, since
+  // then MIDI can asynchronously trigger actions
+  //
+#ifdef MIDI
+  MIDIstartup();
+#endif
+
 }
 
 void disable_rigctl() {