]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
CW: add new menu entry for enabling and syncing CW MIDI keyer
authorRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Wed, 9 Nov 2022 07:07:12 +0000 (12:37 +0530)
committerRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Wed, 9 Nov 2022 07:22:14 +0000 (12:52 +0530)
Automatically syncs the CW WPM speed

alsa_midi.c
alsa_midi.h
cw_menu.c
midi.h
midi2.c
radio.c
radio.h
rigctl.c

index 9cae879241f0884f516439ee6c8a9570738398bd..c55b25b33cebe1b9c6cdbd507180ccee5b12f68a 100644 (file)
@@ -55,6 +55,7 @@ static enum {
 static gboolean configure=FALSE;
 
 static snd_rawmidi_t *input;
+snd_rawmidi_t *cw_midi_output = NULL;
 
 void configure_midi_device(gboolean state) {
   configure=state;
@@ -203,7 +204,7 @@ int register_midi_device(char *myname) {
     for(i=0;i<n_midi_devices;i++) {
         if(strcmp(myname,midi_devices[i].name)==0) {
            strcpy(portname,midi_devices[i].port);
-            if ((ret = snd_rawmidi_open(&input, NULL, midi_devices[i].port, SND_RAWMIDI_NONBLOCK)) < 0) {
+            if ((ret = snd_rawmidi_open(&input, &cw_midi_output, midi_devices[i].port, SND_RAWMIDI_NONBLOCK)) < 0) {
                g_print("%s: cannot open port \"%s\": %s\n", __FUNCTION__, midi_devices[i].port, snd_strerror(ret));
                break;
             }
index 02acc84b04bd436033d6e6a344a5bc4a468bd5e4..2a62ca15ce8372f5e029cd830509adf46e30327c 100644 (file)
@@ -3,10 +3,13 @@ typedef struct _midi_device {
   char *port;
 } MIDI_DEVICE;
 
+#include <alsa/asoundlib.h>
+
 #define MAX_MIDI_DEVICES 10
 
 extern MIDI_DEVICE midi_devices[MAX_MIDI_DEVICES];
 extern int n_midi_devices;
+extern snd_rawmidi_t *cw_midi_output;
 
 extern void get_midi_devices();
 extern int register_midi_device(char *myname);
index bc00e21a36a42adde1a5b5c3f16e089574d8960b..3cd51636247da9210b5267605f138b8355a1c8a1 100644 (file)
--- a/cw_menu.c
+++ b/cw_menu.c
@@ -48,6 +48,7 @@ void cw_changed() {
 // NewProtocol: rely on periodically sent HighPrio packets
 #ifdef LOCALCW
   keyer_update();
+  midi_keyer_update();
 #endif
 //
 // speed and side tone frequency are displayed in the VFO bar
@@ -84,6 +85,11 @@ static void cw_keyer_internal_cb(GtkWidget *widget, gpointer data) {
   cw_changed();
 }
 
+static void cw_keyer_midi_cb(GtkWidget *widget, gpointer data) {
+  cw_keyer_midi = cw_keyer_midi == 1 ? 0: 1;
+  cw_changed();
+}
+
 static void cw_keyer_spacing_cb(GtkWidget *widget, gpointer data) {
   cw_keyer_spacing=cw_keyer_spacing==1?0:1;
   cw_changed();
@@ -288,6 +294,13 @@ void cw_menu(GtkWidget *parent) {
   gtk_widget_show(cw_keyer_spacing_b);
   gtk_grid_attach(GTK_GRID(grid),cw_keyer_spacing_b,0,11,1,1);
   g_signal_connect(cw_keyer_spacing_b,"toggled",G_CALLBACK(cw_keyer_spacing_cb),NULL);
+
+  GtkWidget *cw_keyer_midi_b=gtk_check_button_new_with_label("CW handled in MIDI Keyer");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_keyer_midi_b), cw_keyer_midi);
+  gtk_widget_show(cw_keyer_midi_b);
+  gtk_grid_attach(GTK_GRID(grid),cw_keyer_midi_b,0,12,1,1);
+  g_signal_connect(cw_keyer_midi_b,"toggled",G_CALLBACK(cw_keyer_midi_cb),NULL);
+
 #endif
 
   gtk_container_add(GTK_CONTAINER(content),grid);
diff --git a/midi.h b/midi.h
index 841980a175b693e81a178d0844765640e2bd1f41..ea3729efc401ab5bf67e355eba1afff5344ff84f 100644 (file)
--- a/midi.h
+++ b/midi.h
@@ -291,3 +291,5 @@ int MIDIstop();
 
 void DoTheMidi(int code, enum ACTIONtype type, int val);
 #endif
+
+void midi_keyer_update();
diff --git a/midi2.c b/midi2.c
index 6b227909cb77a74cf4c7724cf1e6c61620946bfd..a8967db1b53b88169c8dd7f7a861bfe21ca59e13 100644 (file)
--- a/midi2.c
+++ b/midi2.c
@@ -23,6 +23,7 @@
 #include "actions.h"
 #include "midi.h"
 
+#include "alsa_midi.h"
 
 struct cmdtable MidiCommandsTable;
 
@@ -430,3 +431,18 @@ g_print("%s:TAB:Insert desc=%p in CMDS[%d] table\n",__FUNCTION__,desc,key);
 
     return 0;
 }
+
+void midi_keyer_update(void) {
+    // read the global cw_keyer_speed and send midi commands
+    char wpmctrl[4] = {0xb1, 0, cw_keyer_speed}; // 0xb0, lower nibble is channel number.
+
+    int status;
+    if (cw_midi_output != NULL) {
+       fprintf(stderr, "MIDI Keyer: setting WPM to %d\n", cw_keyer_speed);
+       if ((status = snd_rawmidi_write(cw_midi_output, wpmctrl, 4)) < 0) {
+           fprintf(stderr, "Problem writing to MIDI output: %s", snd_strerror(status));
+       }
+    } else {
+       fprintf(stderr, "MIDI device is not open yet\n");
+    }
+}
diff --git a/radio.c b/radio.c
index 49412b0ddc310260c606d63ccda9ef2cfe785cb9..0287e98822fe8600649043c01aa467d212edbc27 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -253,6 +253,8 @@ int cw_keyer_mode = KEYER_MODE_A;
 int cw_keyer_weight = 50;              // 0-100
 int cw_keyer_spacing = 0;              // 0=on 1=off
 int cw_keyer_internal = 1;             // 0=external 1=internal
+int cw_keyer_midi = 0;                 // 0 = (external) midi keyer
+                                      // disabled, 1 = enabled
 int cw_keyer_sidetone_volume = 50;     // 0-127
 int cw_keyer_ptt_delay = 20;           // 0-255ms
 int cw_keyer_hang_time = 500;          // ms
@@ -460,6 +462,11 @@ void reconfigure_radio() {
     if (!duplex) {
       reconfigure_transmitter(transmitter, display_width, rx_height);
     }
+#ifdef MIDI
+    if (cw_keyer_midi == 1) {
+      midi_keyer_update();
+    }
+#endif
   }
 }
 
@@ -670,6 +677,10 @@ static void create_visual() {
     g_print("Initialize keyer.....\n");
     keyer_update();
   }
+
+  if (cw_keyer_midi == 1) {
+      midi_keyer_update();
+  }
 #endif
 
 #ifdef CLIENT_SERVER
@@ -1214,6 +1225,9 @@ void start_radio() {
     if (register_midi_device(midi_device_name) < 0) {
       midi_enabled = FALSE;
     }
+    if (cw_keyer_midi == 1) {
+       midi_keyer_update();
+    }
   } else {
     midi_enabled = FALSE;
   }
@@ -1864,8 +1878,11 @@ void radioRestoreState() {
     if (value)
       cw_keys_reversed = atoi(value);
     value = getProperty("cw_keyer_speed");
-    if (value)
+    if (value) {
       cw_keyer_speed = atoi(value);
+      // if we have the midikeyer, set the speed to this value
+      midi_keyer_update();
+    }
     value = getProperty("cw_keyer_mode");
     if (value)
       cw_keyer_mode = atoi(value);
@@ -1879,6 +1896,11 @@ void radioRestoreState() {
     value = getProperty("cw_keyer_internal");
     if (value)
       cw_keyer_internal = atoi(value);
+
+    value = getProperty("cw_keyer_midi");
+    if (value)
+      cw_keyer_midi = atoi(value);
+
 #endif
     value = getProperty("cw_keyer_sidetone_volume");
     if (value)
@@ -2293,6 +2315,10 @@ void radioSaveState() {
     setProperty("cw_keyer_spacing", value);
     sprintf(value, "%d", cw_keyer_internal);
     setProperty("cw_keyer_internal", value);
+
+    sprintf(value, "%d", cw_keyer_midi);
+    setProperty("cw_keyer_midi", value);
+
     sprintf(value, "%d", cw_keyer_sidetone_volume);
     setProperty("cw_keyer_sidetone_volume", value);
     sprintf(value, "%d", cw_keyer_ptt_delay);
@@ -2600,6 +2626,9 @@ int remote_start(void *data) {
                         gdk_cursor_new(GDK_ARROW));
 #ifdef MIDI
   MIDIstartup();
+  if (cw_keyer_midi == 1) {
+      midi_keyer_update();
+  }
 #endif
   for (int i = 0; i < receivers; i++) {
     gint timer_id = gdk_threads_add_timeout_full(
diff --git a/radio.h b/radio.h
index 4e723a5a86e88d0fdbfc88e900aaa4b6ab314037..2cc368a4f3b247bd5dc4dd71ce9be712be46edf2 100644 (file)
--- a/radio.h
+++ b/radio.h
@@ -217,6 +217,7 @@ extern int cw_keyer_mode;
 extern int cw_keyer_weight;
 extern int cw_keyer_spacing;
 extern int cw_keyer_internal;
+extern int cw_keyer_midi;
 extern int cw_keyer_sidetone_volume;
 extern int cw_keyer_ptt_delay;
 extern int cw_keyer_hang_time;
index ded7e857b273523614b7e1b6065ae39008d77a65..b3a9ea2a3ba0a537a9ca2d1a69c194c0e8d73a53 100644 (file)
--- a/rigctl.c
+++ b/rigctl.c
@@ -1282,6 +1282,9 @@ gboolean parse_extended_cmd(char *command, CLIENT *client) {
                 cw_keyer_speed = speed;
 #ifdef LOCALCW
                 keyer_update();
+#endif
+#ifdef MIDI
+               midi_keyer_update();
 #endif
                 vfo_update();
             }
@@ -3147,6 +3150,7 @@ int parse_cmd(void *data) {
           cw_keyer_speed = speed;
 #ifdef LOCALCW
           keyer_update();
+         midi_keyer_update();
 #endif
           vfo_update();
         }