From: c vw Date: Thu, 18 Oct 2018 15:56:51 +0000 (+0200) Subject: Changes related to CW, and corrections throughout X-Git-Url: https://git.rkrishnan.org/pf/content/en/seg/status?a=commitdiff_plain;h=b97d0c0197f226e22d40aee22ae0552594741a31;p=pihpsdr.git Changes related to CW, and corrections throughout --- diff --git a/configure.c b/configure.c index dc512c4..f8fbd93 100644 --- a/configure.c +++ b/configure.c @@ -103,6 +103,7 @@ static GtkWidget *cws_label; static GtkWidget *cws; static GtkWidget *b_enable_cws; static GtkWidget *b_enable_cwlr; +static GtkWidget *b_cw_active_low; #endif static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { @@ -152,6 +153,7 @@ static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data FUNCTION_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(function)); #ifdef LOCALCW ENABLE_CW_BUTTONS=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_cwlr))?1:0; + CW_ACTIVE_LOW=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_cw_active_low))?1:0; CWL_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwl)); CWR_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwr)); ENABLE_GPIO_SIDETONE=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_cws))?1:0; @@ -350,7 +352,7 @@ void configure_gpio(GtkWidget *parent) { gtk_widget_show(cwl); gtk_grid_attach(GTK_GRID(grid),cwl,4,y,1,1); - b_enable_cwlr=gtk_check_button_new_with_label("Enable CW buttons"); + b_enable_cwlr=gtk_check_button_new_with_label("CWLR Enable"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_cwlr), ENABLE_CW_BUTTONS); gtk_widget_show(b_enable_cwlr); gtk_grid_attach(GTK_GRID(grid),b_enable_cwlr,5,y,1,1); @@ -381,6 +383,11 @@ void configure_gpio(GtkWidget *parent) { gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwr),CWR_BUTTON); gtk_widget_show(cwr); gtk_grid_attach(GTK_GRID(grid),cwr,4,y,1,1); + + b_cw_active_low=gtk_check_button_new_with_label("CWLR active-low"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_cw_active_low), CW_ACTIVE_LOW); + gtk_widget_show(b_cw_active_low); + gtk_grid_attach(GTK_GRID(grid),b_cw_active_low,5,y,1,1); #endif y++; @@ -490,56 +497,9 @@ void configure_gpio(GtkWidget *parent) { gtk_container_add(GTK_CONTAINER(content),grid); -/* - GtkWidget *close_button=gtk_dialog_add_button(GTK_DIALOG(dialog),"Save",GTK_RESPONSE_OK); - //gtk_widget_override_font(close_button, pango_font_description_from_string("Arial 20")); -*/ gtk_widget_show_all(dialog); int result=gtk_dialog_run(GTK_DIALOG(dialog)); -/* - ENABLE_VFO_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_encoder))?1:0; - VFO_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_a)); - VFO_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vfo_b)); - ENABLE_VFO_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_vfo_pullup))?1:0; - ENABLE_E1_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_encoder))?1:0; - E1_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_a)); - E1_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E1_b)); - ENABLE_E1_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E1_pullup))?1:0; - ENABLE_E2_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_encoder))?1:0; - E2_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_a)); - E2_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(E2_b)); - ENABLE_E2_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_E2_pullup))?1:0; - ENABLE_E3_ENCODER=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6_encoder))?1:0; - E3_ENCODER_A=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6_a)); - E3_ENCODER_B=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6_b)); - ENABLE_E3_PULLUP=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6_pullup))?1:0; - ENABLE_S1_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S1))?1:0; - S1_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S1)); - ENABLE_S2_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S2))?1:0; - S2_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S2)); - ENABLE_S3_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S3))?1:0; - S3_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S3)); - ENABLE_S4_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S4))?1:0; - S4_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S4)); - ENABLE_S5_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S5))?1:0; - S5_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S5)); - ENABLE_S6_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_S6))?1:0; - S6_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(S6)); - ENABLE_MOX_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_mox))?1:0; - MOX_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mox)); - ENABLE_FUNCTION_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_function))?1:0; - FUNCTION_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(function)); -#ifdef LOCALCW - CWL_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwl)); - CWR_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwr)); -#endif -*/ - - gtk_widget_destroy(dialog); - -// gpio_save_state(); - } #endif diff --git a/cw_menu.c b/cw_menu.c index c2a5738..0b43f0a 100644 --- a/cw_menu.c +++ b/cw_menu.c @@ -63,11 +63,6 @@ static void cw_keyer_internal_cb(GtkWidget *widget, gpointer data) { cw_changed(); } -static void cw_active_level_cb(GtkWidget *widget, gpointer data) { - cw_active_level=cw_active_level==1?0:1; - cw_changed(); -} - static void cw_keyer_speed_value_changed_cb(GtkWidget *widget, gpointer data) { cw_keyer_speed=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); cw_changed(); @@ -245,13 +240,6 @@ void cw_menu(GtkWidget *parent) { gtk_widget_show(cw_keyer_internal_b); gtk_grid_attach(GTK_GRID(grid),cw_keyer_internal_b,0,10,1,1); g_signal_connect(cw_keyer_internal_b,"toggled",G_CALLBACK(cw_keyer_internal_cb),NULL); - - GtkWidget *cw_active_level_b=gtk_check_button_new_with_label("CW Local Active_Low"); - //gtk_widget_override_font(cw_active_level_b, pango_font_description_from_string("Arial 18")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cw_active_level_b), cw_active_level==0); - gtk_widget_show(cw_active_level_b); - gtk_grid_attach(GTK_GRID(grid),cw_active_level_b,1,10,1,1); - g_signal_connect(cw_active_level_b,"toggled",G_CALLBACK(cw_active_level_cb),NULL); #endif gtk_container_add(GTK_CONTAINER(content),grid); diff --git a/ext.c b/ext.c index d49947a..6550d12 100644 --- a/ext.c +++ b/ext.c @@ -36,11 +36,10 @@ // The following calls functions can be called usig g_idle_add -// DL1YCF: added interface for mode change, to be used by rigctl -// (MD command) int ext_vfo_mode_changed(void * data) { - vfo_mode_changed((int) (long) data); + int mode=(uintptr_t) data; + vfo_mode_changed(mode); return 0; } @@ -52,9 +51,6 @@ int ext_discovery(void *data) { int ext_set_frequency(void *data) { setFrequency(*(long long *)data); free(data); - // DL1YCF added return statement - // this one is CRITICAL to avoid free() being called - // repeatedly on the same pointer return 0; } @@ -141,20 +137,6 @@ int ext_radio_change_sample_rate(void *data) { return 0; } -// DL1YCF: because of the new CW algorithm, -// this function is no longer used -int ext_cw_setup() { - radio_cw_setup(); - return 0; -} - -// DL1YCF: because of the new CW algorithm, -// this function is no longer used -int ext_cw_key(void *data) { - radio_cw_key((uintptr_t)data); - return 0; -} - int ext_update_squelch(void *data) { set_squelch(active_receiver); return 0; @@ -167,7 +149,8 @@ int ext_sliders_update(void *data) { #ifdef PURESIGNAL int ext_tx_set_ps(void *data) { - tx_set_ps(transmitter,(uintptr_t)data); + int state=(uintptr_t) data; + tx_set_ps(transmitter, state); return 0; } #endif diff --git a/gpio.c b/gpio.c index 422a4a9..5828b8f 100644 --- a/gpio.c +++ b/gpio.c @@ -155,6 +155,7 @@ int CWR_BUTTON=15; int SIDETONE_GPIO=8; int ENABLE_GPIO_SIDETONE=0; int ENABLE_CW_BUTTONS=1; +int CW_ACTIVE_LOW=1; #endif static volatile int vfoEncoderPos; @@ -850,6 +851,8 @@ void gpio_restore_state() { #ifdef LOCALCW value=getProperty("ENABLE_CW_BUTTONS"); if(value) ENABLE_CW_BUTTONS=atoi(value); + value=getProperty("CW_ACTIVE_LOW"); + if(value) CW_ACTIVE_LOW=atoi(value); value=getProperty("CWL_BUTTON"); if(value) CWL_BUTTON=atoi(value); value=getProperty("CWR_BUTTON"); @@ -956,6 +959,8 @@ void gpio_save_state() { #ifdef LOCALCW sprintf(value,"%d",ENABLE_CW_BUTTONS); setProperty("ENABLE_CW_BUTTONS",value); + sprintf(value,"%d",CW_ACTIVE_LOW); + setProperty("CW_ACTIVE_LOW",value); sprintf(value,"%d",CWL_BUTTON); setProperty("CWL_BUTTON",value); sprintf(value,"%d",CWR_BUTTON); @@ -988,12 +993,9 @@ fprintf(stderr,"setup_encoder_pin: pin=%d updown=%d\n",pin,up_down); #ifdef LOCALCW -// Note we cannot use debouncing, as after the first interrupt, -// we might read the wrong level. So we process all interrupts -// to the keyer. -// The only way to do proper debouncing is to record the wall-clock time -// of the last state change of each of the two buttons, and -// disable further state changes for a short time (5 msec) +// +// We generate interrupts only on falling edge +// static void setup_cw_pin(int pin, void(*pAlert)(void)) { fprintf(stderr,"setup_cw_pin: pin=%d \n",pin); @@ -1008,7 +1010,8 @@ static void cwAlert_left() { if (cw_keyer_internal != 0) return; // as quickly as possible level=digitalRead(CWL_BUTTON); //fprintf(stderr,"cwl button : level=%d \n",level); - keyer_event(CWL_BUTTON, cw_active_level == 0 ? level : (level==0)); + //the second parameter of keyer_event ("state") is TRUE on key-down + keyer_event(CWL_BUTTON, CW_ACTIVE_LOW ? (level==0) : level); } static void cwAlert_right() { @@ -1016,9 +1019,21 @@ static void cwAlert_right() { if (cw_keyer_internal != 0) return; // as quickly as possible level=digitalRead(CWR_BUTTON); //fprintf(stderr,"cwr button : level=%d \n",level); - keyer_event(CWR_BUTTON, cw_active_level == 0 ? level : (level==0)); + keyer_event(CWR_BUTTON, CW_ACTIVE_LOW ? (level==0) : level); } +// +// Two functions added, might be useful somewhere +// +int gpio_left_cw_key() { + int val=digitalRead(CWL_BUTTON); + return CW_ACTIVE_LOW? (val==0) : val; +} + +int gpio_right_cw_key() { + int val=digitalRead(CWR_BUTTON); + return CW_ACTIVE_LOW? (val==0) : val; +} #endif int gpio_init() { diff --git a/gpio.h b/gpio.h index 9563bb6..1075d5d 100644 --- a/gpio.h +++ b/gpio.h @@ -86,7 +86,10 @@ extern int CWR_BUTTON; extern int SIDETONE_GPIO; extern int ENABLE_GPIO_SIDETONE; extern int ENABLE_CW_BUTTONS; +extern int CW_ACTIVE_LOW; void gpio_sidetone(int freq); +int gpio_left_cw_key(); +int gpio_right_cw_key(); #endif void gpio_restore_state(); diff --git a/iambic.c b/iambic.c index f36f594..8386849 100644 --- a/iambic.c +++ b/iambic.c @@ -154,9 +154,7 @@ void keyer_update() { } #ifdef GPIO -void keyer_event(int gpio, int level) { - int state = (level == 0); - +void keyer_event(int gpio, int state) { if (state) { // This is for aborting CAT CW messages if the key is hit. cw_key_hit = 1; @@ -164,7 +162,7 @@ void keyer_event(int gpio, int level) { // PTT has been engaged manually if (running && !cwvox && !mox) { g_idle_add(ext_mox_update, (gpointer)(long) 1); - cwvox=(int) vox_hang; + cwvox=(int) cw_breakin; } } if (gpio == CWL_BUTTON) @@ -224,7 +222,7 @@ fprintf(stderr,"keyer_thread state running= %d\n", running); // If MOX still hanging, continue spinnning/checking and decrement cwvox while (key_state != EXITLOOP || cwvox > 0) { - if (cwvox > 0 && key_state != EXITLOOP && key_state != CHECK) cwvox=(int) vox_hang; + if (cwvox > 0 && key_state != EXITLOOP && key_state != CHECK) cwvox=(int) cw_breakin; switch (key_state) { case EXITLOOP: if (cwvox >0) cwvox--; diff --git a/property.c b/property.c index 110a600..e6bc40d 100644 --- a/property.c +++ b/property.c @@ -79,6 +79,9 @@ void saveProperties(char* filename) { FILE* f=fopen(filename,"w+"); char line[512]; char version[32]; + + fprintf(stderr,"saveProperties: %s\n",filename); + if(!f) { fprintf(stderr,"can't open %s\n",filename); return; diff --git a/radio.c b/radio.c index 3bf10ec..c9bb32c 100644 --- a/radio.c +++ b/radio.c @@ -217,7 +217,6 @@ int cw_keyer_ptt_delay=20; // 0-255ms int cw_keyer_hang_time=300; // ms int cw_keyer_sidetone_frequency=400; // Hz int cw_breakin=1; // 0=disabled 1=enabled -int cw_active_level=1; // 0=active_low 1=active_high int vfo_encoder_divisor=15; @@ -1170,8 +1169,6 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path); value=getProperty("cw_keyer_internal"); if(value) cw_keyer_internal=atoi(value); #endif - value=getProperty("cw_active_level"); - if(value) cw_active_level=atoi(value); value=getProperty("cw_keyer_sidetone_volume"); if(value) cw_keyer_sidetone_volume=atoi(value); value=getProperty("cw_keyer_ptt_delay"); @@ -1373,8 +1370,6 @@ void radioSaveState() { setProperty("cw_keyer_spacing",value); sprintf(value,"%d",cw_keyer_internal); setProperty("cw_keyer_internal",value); - sprintf(value,"%d",cw_active_level); - setProperty("cw_active_level",value); sprintf(value,"%d",cw_keyer_sidetone_volume); setProperty("cw_keyer_sidetone_volume",value); sprintf(value,"%d",cw_keyer_ptt_delay); diff --git a/radio.h b/radio.h index 9421534..943ed24 100644 --- a/radio.h +++ b/radio.h @@ -171,7 +171,6 @@ extern int cw_keyer_ptt_delay; extern int cw_keyer_hang_time; extern int cw_keyer_sidetone_frequency; extern int cw_breakin; -extern int cw_active_level; extern int vfo_encoder_divisor; diff --git a/rigctl.c b/rigctl.c index 268c992..b285bcb 100644 --- a/rigctl.c +++ b/rigctl.c @@ -361,7 +361,6 @@ void send_space(int len) { void rigctl_send_cw_char(char cw_char) { char pattern[9],*ptr; - static char last_cw_char=0; strcpy(pattern,""); ptr = &pattern[0]; switch (cw_char) { @@ -427,19 +426,31 @@ void rigctl_send_cw_char(char cw_char) { case '7': strcpy(pattern,"--...");break; case '8': strcpy(pattern,"---..");break; case '9': strcpy(pattern,"----.");break; - case '.': strcpy(pattern,".-.-.-");break; - case '/': strcpy(pattern,"-..-.");break; - case ',': strcpy(pattern,"--..--");break; - case '!': strcpy(pattern,"-.-.--");break; - case ')': strcpy(pattern,"-.--.-");break; - case '(': strcpy(pattern,"-.--.-");break; +// +// DL1YCF: +// There were some signs I considered wrong, other +// signs missing. Therefore I put the signs here +// from ITU Recommendation M.1677-1 (2009) +// in the order given there. +// + case '.': strcpy(pattern,".-.-.-"); break; + case ',': strcpy(pattern,"--..--"); break; + case ':': strcpy(pattern,"---.."); break; + case '?': strcpy(pattern,"..--.."); break; + case '\'': strcpy(pattern,".----."); break; + case '-': strcpy(pattern,"-....-"); break; + case '/': strcpy(pattern,"-..-."); break; + case '(': strcpy(pattern,"-.--."); break; + case ')': strcpy(pattern,"-.--.-"); break; + case '"': strcpy(pattern,".-..-."); break; + case '=': strcpy(pattern,"-...-"); break; + case '+': strcpy(pattern,".-.-."); break; + case '@': strcpy(pattern,".--.-."); break; +// +// Often used, but not ITU: Ampersand for "wait" +// case '&': strcpy(pattern,".-...");break; - case ':': strcpy(pattern,"---..");break; - case '+': strcpy(pattern,".-.-.");break; - case '-': strcpy(pattern,"-....-");break; - case '_': strcpy(pattern,".--.-.");break; - case '@': strcpy(pattern,"..--.-");break; - default: strcpy(pattern," "); + default: strcpy(pattern,""); } while(*ptr != '\0') { @@ -451,19 +462,20 @@ void rigctl_send_cw_char(char cw_char) { } ptr++; } - // The last character sent already has one dotlen included. - // Therefore, if the character was a "space", we need an additional - // inter-word pause of 6 dotlen, else we need a inter-character - // pause of 2 dotlens. - // Note that two or more adjacent space characters result in a - // single inter-word distance. This also gets rid of trailing - // spaces in the KY command. + + // The last element (dash or dot) sent already has one dotlen space appended. + // If the current character is another "printable" sign, we need an additional + // pause of 2 dotlens to form the inter-character spacing of 3 dotlens. + // However if the current character is a "space" we must produce an inter-word + // spacing (7 dotlens) and therefore need 6 additional dotlens + // We need no longer take care of a sequence of spaces since adjacent spaces + // are now filtered out while filling the CW character (ring-) buffer. + if (cw_char == ' ') { - if (last_cw_char != ' ') send_space(6); + send_space(6); // produce inter-word space of 7 dotlens } else { - send_space(2); + send_space(2); // produce inter-character space of 3 dotlens } - last_cw_char=cw_char; } // @@ -476,23 +488,52 @@ void rigctl_send_cw_char(char cw_char) { // sending each word with a separate KY command // produces perfectly readable CW. // +// UPDATE: we maintain a ring buffer such that +// the contents of several KY commands +// can be buffered +// static gpointer rigctl_cw_thread(gpointer data) { int i; char c; - char local_buf[30]; + char last_char=0; + char ring_buf[130]; + char *write_buf=ring_buf; + char *read_buf =ring_buf; + char *p; + int num_buf=0; while (server_running) { // wait for cw_buf become filled with data // (periodically look every 100 msec) - cw_key_hit=0; - if (!cw_busy) { + if (!cw_busy && num_buf ==0) { + cw_key_hit=0; usleep(100000L); continue; } - strncpy(local_buf, cw_buf, 30); - cw_busy=0; // mark buffer free again + + // if new data available and space in buffer, copy it + // If there are several adjacent spaces, take only the first one. + // This also swallows the "tails" of the KY commands which + // (according to Kenwood) have to be padded with spaces up + // to the maximum length (24) + + if (cw_busy && num_buf < 100) { + p=cw_buf; + while ((c=*p++)) { + if (last_char == ' ' && c == ' ') continue; + *write_buf++ = c; + last_char=c; + num_buf++; + if (write_buf - ring_buf == 128) write_buf=ring_buf; // wrap around + } + cw_busy=0; // mark buffer free again + } + // these values may have changed, so recompute them here + // This means that we can change the speed (KS command) while + // the buffer is being sent + dotlen = 1200000L/(long)cw_keyer_speed; dashlen = (dotlen * 3 * cw_keyer_weight) / 50L; dotsamples = 57600 / cw_keyer_speed; @@ -506,7 +547,7 @@ static gpointer rigctl_cw_thread(gpointer data) // forever here, so allow at most 500 msec i=10; while (!mox && (i--) > 0) usleep(50000L); - // still no MOX? --> silently discard CW message and give up + // still no MOX? --> silently discard CW character and give up if (!mox) { CAT_cw_is_active=0; continue; @@ -516,10 +557,6 @@ static gpointer rigctl_cw_thread(gpointer data) usleep(100000L); } // At this point, mox==1 and CAT_cw_active == 1 - i=0; - while(((c=local_buf[i++]) != '\0') && !cw_key_hit && !cw_not_ready) { - rigctl_send_cw_char(c); - } if (cw_key_hit || cw_not_ready) { // // CW transmission has been aborted, either due to manually @@ -535,19 +572,27 @@ static gpointer rigctl_cw_thread(gpointer data) // CAT CW commands. We need this long time since // hamlib waits 0.5 secs after receiving a "KY1" message before trying to // send the next bunch - for (i=0; i< 50; i++) { - cw_busy=0; // mark buffer free - usleep(20000L); - } + cw_busy=-1; // mark buffer purge situation + usleep(1000000L); + cw_busy=0; + write_buf=read_buf=ring_buf; + num_buf=0; } else { + rigctl_send_cw_char(*read_buf++); + if (read_buf - ring_buf == 128) read_buf=ring_buf; // wrap around + num_buf--; // - // CAT CW message has been sent. - // If the next message is pending, continue. - // Otherwise remove PTT and wait for next CAT - // CW command. - if (cw_busy) continue; + // Character has been sent. + // If there are more to send, or the next message is pending, continue. + // Otherwise remove PTT and wait for next CAT CW command. + if (cw_busy || num_buf > 0) continue; CAT_cw_is_active=0; g_idle_add(ext_ptt_update ,(gpointer)0); + // wait up to 500 msec for MOX having gone + // otherwise there might be a race condition when sending + // the next character really soon + i=10; + while (mox && (i--) > 0) usleep(50000L); } } // We arrive here if the rigctl server shuts down. @@ -556,6 +601,7 @@ static gpointer rigctl_cw_thread(gpointer data) // of a transmission rigctl_cw_thread_id = NULL; cw_busy=0; + CAT_cw_is_active=0; g_idle_add(ext_ptt_update ,(gpointer)0); return NULL; } @@ -2170,8 +2216,11 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) { // - if we can accept new data (buffer space available) : "KY0;" // - if buffer is full: "KY1;" // + // Note: cw_buse == -1 indicates a "purge KY" situation, where + // all KY commands are accepted and data is discared silently + // In this case cw_busy is left untouched here. if (len <= 2) { - if (cw_busy) { + if (cw_busy == 1) { send_resp(client_sock,"KY1;"); } else { send_resp(client_sock,"KY0;"); @@ -2181,7 +2230,7 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) { // "busy" is correctly queried. // - Note further that the space immediately following "KY" is *not* // part of the message. - if (!cw_busy && len > 3) { + if ((cw_busy==0) && (len > 3)) { // A CW text will be sent. Copy incoming data to buffer strncpy(cw_buf, cmd_input+3, 29); // Kenwood protocol allows for at most 24 characters, so @@ -2189,6 +2238,7 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) { cw_buf[29]=0; cw_busy=1; } + // cwbusy == -1 or empty text: do nothing } } else if(strcmp(cmd_str,"LK")==0) {