From 3d2b6a0aa279838c32125fec639c9b3b173ffe52 Mon Sep 17 00:00:00 2001 From: c vw Date: Wed, 13 Jul 2022 10:20:30 +0200 Subject: [PATCH] Added support for CW Keying via MIDI/GPIO while using "internal CW" (paddle connected to radio). --- actions.c | 42 ++++++++++++++++++++++++++++++++++++++---- actions.h | 1 + gpio.c | 2 ++ iambic.c | 3 --- new_discovery.c | 21 ++++++++++++++++++--- new_protocol.c | 15 +++++++-------- old_protocol.c | 15 +++++++-------- 7 files changed, 73 insertions(+), 26 deletions(-) diff --git a/actions.c b/actions.c index cc3bb55..8dfe013 100644 --- a/actions.c +++ b/actions.c @@ -187,10 +187,12 @@ ACTION_TABLE ActionTable[] = { // CW Keydown (MIDI and GPIO) // CW speed (only MIDI) // CW side tone frequency (only MIDI) +// CW PTT (MIDI and GPIO) // {CW_KEYER_KEYDOWN, "CW Key\n(keyer)", NULL, MIDI_KEY | CONTROLLER_SWITCH}, {CW_KEYER_SPEED, "CW Speed\n(keyer)", NULL, MIDI_KNOB}, {CW_KEYER_SIDETONE, "CW pitch\n(keyer)", NULL, MIDI_KNOB}, + {CW_KEYER_PTT, "PTT\n(CW keyer)", NULL, MIDI_KEY | CONTROLLER_SWITCH}, {ACTIONS, "", NULL, TYPE_NONE} }; @@ -239,7 +241,7 @@ static inline double KnobOrWheel(PROCESS_ACTION *a, double oldval, double minval // // This interface puts an "action" into the GTK idle queue, -// but CW actions are processed immediately +// but "CW key" actions are processed immediately // void schedule_action(enum ACTION action, enum ACTION_MODE mode, gint val) { PROCESS_ACTION *a; @@ -247,6 +249,7 @@ void schedule_action(enum ACTION action, enum ACTION_MODE mode, gint val) { case CW_LEFT: case CW_RIGHT: #ifdef LOCALCW + cw_key_hit=1; keyer_event(action==CW_LEFT,mode==PRESSED); #else g_print("CW_Left/Right but compiled without LOCALCW\n"); @@ -256,9 +259,9 @@ void schedule_action(enum ACTION action, enum ACTION_MODE mode, gint val) { // // hard "key-up/down" action WITHOUT break-in // intended for external keyers (MIDI or GPIO connected) - // which take care of PTT themselves + // which take care of PTT themselves. // - if (mode==PRESSED && cw_keyer_internal==0) { + if (mode==PRESSED && (cw_keyer_internal==0 || CAT_cw_is_active)) { cw_key_down=960000; // max. 20 sec to protect hardware cw_key_up=0; cw_key_hit=1; @@ -1243,7 +1246,38 @@ int process_action(void *data) { g_idle_add(ext_vfo_update,NULL); } break; - + case CW_KEYER_PTT: + // + // If you do CW with the key attached to the radio, and use a foot-switch for + // PTT, then this should trigger the standard PTT event. However, if you have the + // the key attached to the radio and want to use an external keyer (e.g. + // controlled by a contest logger), then "internal CW" muste temporarily be + // disabled in the radio (while keying from piHPSDR) in the radio. + // This is exactly the same situation as when using CAT + // CW commands together with "internal" CW (status variable CAT_cw_is_active), + // so the mechanism is already there. Therefore, the present case is just + // the same as "PTT" except that we set/clear the "CAT CW" condition. + // + // If the "CAT CW" flag is already cleared when the PTT release arrives, this + // means that the CW message from the keyer has been aborted by hitting the + // CW key. In this case, the radio takes care of "going RX". + // + switch (a->mode) { + case PRESSED: + CAT_cw_is_active = 1; + mox_update(1); + break; + case RELEASED: + if (CAT_cw_is_active == 1) { + CAT_cw_is_active = 0; + mox_update(0); + } + break; + default: + // should not happen + break; + } + break; case CW_KEYER_SIDETONE: if (a->mode==ABSOLUTE) { // diff --git a/actions.h b/actions.h index 2772f57..7ffbb4d 100644 --- a/actions.h +++ b/actions.h @@ -151,6 +151,7 @@ enum ACTION { CW_KEYER_KEYDOWN, CW_KEYER_SPEED, CW_KEYER_SIDETONE, + CW_KEYER_PTT, ACTIONS }; diff --git a/gpio.c b/gpio.c index 2c134e9..7bbdb96 100644 --- a/gpio.c +++ b/gpio.c @@ -521,9 +521,11 @@ static void process_edge(int offset,int value) { if(ENABLE_CW_BUTTONS) { if(offset==CWL_BUTTON) { keyer_event(1, CW_ACTIVE_LOW ? (value==PRESSED) : value); + cw_key_hit=1; // this is to stop CAT CW messages that may be running found=TRUE; } else if(offset==CWR_BUTTON) { keyer_event(1, CW_ACTIVE_LOW ? (value==PRESSED) : value); + cw_key_hit=1; // this is to stop CAT CW messages that may be running found=TRUE; } } diff --git a/iambic.c b/iambic.c index 98b24fc..0b8b673 100644 --- a/iambic.c +++ b/iambic.c @@ -284,8 +284,6 @@ void keyer_event(int left, int state) { // This is to remember whether the key stroke interrupts a running CAT CW // Since in this case we return to RX after vox delay. if (CAT_cw_is_active) enforce_cw_vox=1; - // This is for aborting CAT CW messages if a key is hit. - cw_key_hit = 1; } if (left) { // left paddle hit or released @@ -422,7 +420,6 @@ static void* keyer_thread(void *arg) { if (*kdash) { // send manual dashes cw_key_down=960000; // max. 20 sec to protect hardware cw_key_up=0; - cw_key_hit=1; gpio_cw_sidetone_set(1); key_state=STRAIGHT; } diff --git a/new_discovery.c b/new_discovery.c index 7661377..37d50d1 100644 --- a/new_discovery.c +++ b/new_discovery.c @@ -332,11 +332,26 @@ gpointer new_discover_receive_thread(gpointer data) { discovered[devices].info.network.interface_length=sizeof(interface_addr); strcpy(discovered[devices].info.network.interface_name,interface_name); discovered[devices].supported_receivers=2; - fprintf(stderr,"new_discover: found %d protocol=%d device=%d software_version=%d status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", - devices, - discovered[devices].protocol, + // + // Info not yet made use of: + // + // buffer[12]: P2 version supported (e.g. 39 for 3.9) + // buffer[20]: number of DDCs + // buffer[23]: beta version number (if nonzero) + // E.g. if buffer[13] is 21 and buffer[23] is 18 this + // means firmware Version 2.1.18 + // + // We put the additional info to stderr at least since it might be + // useful for debugging/development but do not store it in the + // "discovered" data structure. + // + + fprintf(stderr,"new_discover: P2(%d) device=%d (%dRX) software_version=%d(.%d) status=%d address=%s (%02X:%02X:%02X:%02X:%02X:%02X) on %s\n", + buffer[12] & 0xFF, discovered[devices].device, + buffer[20] & 0xFF, discovered[devices].software_version, + buffer[23] & 0xFF, discovered[devices].status, inet_ntoa(discovered[devices].info.network.address.sin_addr), discovered[devices].info.network.mac_address[0], diff --git a/new_protocol.c b/new_protocol.c index 5717d34..aeaf5fa 100644 --- a/new_protocol.c +++ b/new_protocol.c @@ -1947,18 +1947,17 @@ static void process_high_priority() { alex_reverse_power_average = (alex_reverse_power + 3*alex_reverse_power_average) >> 2; supply_volts=((buffer[49]&0xFF)<<8)|(buffer[50]&0xFF); - if (cw_keyer_internal) { - // Stops CAT cw transmission if paddle hit in "internal" CW - if (dash || dot) cw_key_hit=1; - } else { + // Stops CAT cw transmission if paddle hit + if (dash || dot) { + CAT_cw_is_active=0; + cw_key_hit=1; + } #ifdef LOCALCW - // - // report "key hit" event to the local keyer - // (local keyer will stop CAT cw if necessary) + if (!cw_keyer_internal) { if (dash != previous_dash) keyer_event(0, dash); if (dot != previous_dot ) keyer_event(1, dot ); -#endif } +#endif if(previous_ptt!=local_ptt) { g_idle_add(ext_mox_update,GINT_TO_POINTER(local_ptt)); diff --git a/old_protocol.c b/old_protocol.c index 3bff3fa..728e81c 100644 --- a/old_protocol.c +++ b/old_protocol.c @@ -907,18 +907,17 @@ static void process_control_bytes() { dash=(control_in[0]&0x02)==0x02; dot=(control_in[0]&0x04)==0x04; - if (cw_keyer_internal) { - // Stops CAT cw transmission if paddle hit in "internal" CW - if (dash || dot) cw_key_hit=1; - } else { + // Stops CAT cw transmission if paddle hit in "internal" CW + if (dash || dot) { + cw_key_hit=1; + CAT_cw_is_active=0; + } #ifdef LOCALCW - // - // report "key hit" event to the local keyer - // (local keyer will stop CAT cw if necessary) + if (!cw_keyer_internal) { if (dash != previous_dash) keyer_event(0, dash); if (dot != previous_dot ) keyer_event(1, dot ); -#endif } +#endif if(previous_ptt!=local_ptt) { g_idle_add(ext_mox_update,(gpointer)(long)(local_ptt)); -- 2.45.2