From 8f6c90f9d32d64a670069853019e7be70da486c3 Mon Sep 17 00:00:00 2001 From: Ramakrishnan Muthukrishnan Date: Wed, 9 Nov 2022 12:37:12 +0530 Subject: [PATCH] CW: add new menu entry for enabling and syncing CW MIDI keyer Automatically syncs the CW WPM speed --- alsa_midi.c | 3 ++- alsa_midi.h | 3 +++ cw_menu.c | 13 +++++++++++++ midi.h | 2 ++ midi2.c | 16 ++++++++++++++++ radio.c | 31 ++++++++++++++++++++++++++++++- radio.h | 1 + rigctl.c | 4 ++++ 8 files changed, 71 insertions(+), 2 deletions(-) diff --git a/alsa_midi.c b/alsa_midi.c index 9cae879..c55b25b 100644 --- a/alsa_midi.c +++ b/alsa_midi.c @@ -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 + #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); diff --git a/cw_menu.c b/cw_menu.c index bc00e21..3cd5163 100644 --- 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 841980a..ea3729e 100644 --- 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 6b22790..a8967db 100644 --- 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 49412b0..0287e98 100644 --- 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 4e723a5..2cc368a 100644 --- 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; diff --git a/rigctl.c b/rigctl.c index ded7e85..b3a9ea2 100644 --- 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(); } -- 2.45.2