#ifdef LOCALCW
static GtkWidget *cwl_label;
-static GtkWidget *cwl_gpio_label;
static GtkWidget *cwl;
static GtkWidget *cwr_label;
-static GtkWidget *cwr_gpio_label;
static GtkWidget *cwr;
+static GtkWidget *cws_label;
+static GtkWidget *cws;
+static GtkWidget *b_enable_cws;
+static GtkWidget *b_enable_cwlr;
#endif
static gboolean save_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
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
+ ENABLE_CW_BUTTONS=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_cwlr))?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;
+ SIDETONE_GPIO=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cws));
#endif
gpio_save_state();
gtk_widget_show(S1);
gtk_grid_attach(GTK_GRID(grid),S1,2,y,1,1);
+#ifdef LOCALCW
+ // With LOCALCW, the menu got too long (does not fit on the screen)
+ // Therefore it has been moved to the right of S1/S2/S3
+ // The GPIO side tone is also configured here. Note that
+ // these setting are only active when doing local CW
+ cwl_label=gtk_label_new("CWL GPIO:");
+ gtk_widget_show(cwl_label);
+ gtk_grid_attach(GTK_GRID(grid),cwl_label,3,y,1,1);
+
+ cwl=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwl),CWL_BUTTON);
+ 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");
+ 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);
+#endif
y++;
gtk_widget_show(S2);
gtk_grid_attach(GTK_GRID(grid),S2,2,y,1,1);
+#ifdef LOCALCW
+ cwr_label=gtk_label_new("CWR GPIO:");
+ gtk_widget_show(cwr_label);
+ gtk_grid_attach(GTK_GRID(grid),cwr_label,3,y,1,1);
+
+ cwr=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+ 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);
+#endif
+
y++;
b_enable_S3=gtk_check_button_new_with_label("Enable S3");
gtk_widget_show(S3);
gtk_grid_attach(GTK_GRID(grid),S3,2,y,1,1);
+#ifdef LOCALCW
+ cws_label=gtk_label_new(" SideTone GPIO:");
+ gtk_widget_show(cws_label);
+ gtk_grid_attach(GTK_GRID(grid),cws_label,3,y,1,1);
+
+ cws=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON(cws),SIDETONE_GPIO);
+ gtk_widget_show(cws);
+ gtk_grid_attach(GTK_GRID(grid),cws,4,y,1,1);
+
+ b_enable_cws=gtk_check_button_new_with_label("Enable");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b_enable_cws), ENABLE_GPIO_SIDETONE);
+ gtk_widget_show(b_enable_cws);
+ gtk_grid_attach(GTK_GRID(grid),b_enable_cws,5,y,1,1);
+#endif
y++;
b_enable_S4=gtk_check_button_new_with_label("Enable S4");
y++;
-#ifdef LOCALCW
- cwl_label=gtk_label_new("CWL");
- gtk_widget_show(cwl_label);
- gtk_grid_attach(GTK_GRID(grid),cwl_label,0,y,1,1);
-
- cwl_gpio_label=gtk_label_new("GPIO:");
- gtk_widget_show(cwl_gpio_label);
- gtk_grid_attach(GTK_GRID(grid),cwl_gpio_label,1,y,1,1);
-
- cwl=gtk_spin_button_new_with_range (0.0,100.0,1.0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwl),CWL_BUTTON);
- gtk_widget_show(cwl);
- gtk_grid_attach(GTK_GRID(grid),cwl,2,y,1,1);
-
- y++;
-
- cwr_label=gtk_label_new("CWR");
- gtk_widget_show(cwr_label);
- gtk_grid_attach(GTK_GRID(grid),cwr_label,0,y,1,1);
-
- cwr_gpio_label=gtk_label_new("GPIO:");
- gtk_widget_show(cwr_gpio_label);
- gtk_grid_attach(GTK_GRID(grid),cwr_gpio_label,1,y,1,1);
-
- cwr=gtk_spin_button_new_with_range (0.0,100.0,1.0);
- gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwr),CWR_BUTTON);
- gtk_widget_show(cwr);
- gtk_grid_attach(GTK_GRID(grid),cwr,2,y,1,1);
-
- y++;
-#endif
-
GtkWidget *save_b=gtk_button_new_with_label("Save");
g_signal_connect (save_b, "button_press_event", G_CALLBACK(save_cb), NULL);
gtk_grid_attach(GTK_GRID(grid),save_b,4,y-1,1,1);
#include <poll.h>
#include <sched.h>
#include <wiringPi.h>
+#ifdef LOCALCW
+#include <softTone.h>
+#endif
#include <semaphore.h>
#include "band.h"
int ENABLE_E1_BUTTON=1;
int ENABLE_E2_BUTTON=1;
int ENABLE_E3_BUTTON=1;
-int ENABLE_CW_BUTTONS=1;
#endif
+
#ifdef LOCALCW
-int CWL_BUTTON=18;
-int CWR_BUTTON=19;
+int CWL_BUTTON=14;
+int CWR_BUTTON=15;
+int SIDETONE_GPIO=8;
+int ENABLE_GPIO_SIDETONE=0;
+int ENABLE_CW_BUTTONS=1;
#endif
static volatile int vfoEncoderPos;
if(value) CWL_BUTTON=atoi(value);
value=getProperty("CWR_BUTTON");
if(value) CWR_BUTTON=atoi(value);
+ value=getProperty("SIDETONE_GPIO");
+ if(value) SIDETONE_GPIO=atoi(value);
+ value=getProperty("ENABLE_GPIO_SIDETONE");
+ if(value) ENABLE_GPIO_SIDETONE=atoi(value);
#endif
setProperty("CWL_BUTTON",value);
sprintf(value,"%d",CWR_BUTTON);
setProperty("CWR_BUTTON",value);
+ sprintf(value,"%d",SIDETONE_GPIO);
+ setProperty("SIDETONE_GPIO",value);
+ sprintf(value,"%d",ENABLE_GPIO_SIDETONE);
+ setProperty("ENABLE_GPIO_SIDETONE",value);
#endif
saveProperties("gpio.props");
#ifdef LOCALCW
// Note we cannot use debouncing, as after the first interrupt,
-// we might read the wrong level. So we forward all CW interrupts
+// 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 times
+// of the last state change of each of the two buttons, and
+// disable further state changes for a short time (5 msec)
static void setup_cw_pin(int pin, void(*pAlert)(void)) {
fprintf(stderr,"setup_cw_pin: pin=%d \n",pin);
setup_cw_pin(CWL_BUTTON, cwAlert_left);
setup_cw_pin(CWR_BUTTON, cwAlert_right);
}
+ if (ENABLE_GPIO_SIDETONE) {
+ softToneCreate(SIDETONE_GPIO);
+ }
#endif
return 0;
running=0;
}
+#ifdef LOCALCW
+void gpio_sidetone(int freq) {
+ if (ENABLE_GPIO_SIDETONE) {
+ softToneWrite (SIDETONE_GPIO, freq);
+ }
+}
+#endif
+
int vfo_encoder_get_pos() {
int pos=vfoEncoderPos;
#include <sys/mman.h>
#include <wiringPi.h>
-#include <softTone.h>
#include "gpio.h"
#include "radio.h"
static void* keyer_thread(void *arg);
static pthread_t keyer_thread_id;
-// set to 0 to use the PI's hw:0 audio out for sidetone
-#define SIDETONE_GPIO 0 // this is in wiringPi notation // tried 4 working great.
-
#define MY_PRIORITY (90)
#define MAX_SAFE_STACK (8*1024)
#define NSEC_PER_SEC (1000000000)
#endif
static int cwvox = 0;
+static int first_dot = 0;
int keyer_out = 0;
if (running && !cwvox && !mox) {
g_idle_add(ext_mox_update, (gpointer)(long) 1);
cwvox=(int) vox_hang;
+ first_dot=1;
}
}
if (gpio == CWL_BUTTON) {
if(protocol==NEW_PROTOCOL) schedule_high_priority(9);
//fprintf(stderr,"set_keyer_out keyer_out= %d\n", keyer_out);
if (state) {
- // DL1YCF: we must call cw_hold_key in *any* case, else no
- // CW signal will be produced. We certainly do not
- // want to produce a side tone *only*.
- if (SIDETONE_GPIO) {
- softToneWrite (SIDETONE_GPIO, cw_keyer_sidetone_frequency);
- }
+ gpio_sidetone(cw_keyer_sidetone_frequency);
cw_hold_key(1); // this starts a CW pulse in transmitter.c
} else {
- if (SIDETONE_GPIO) {
- softToneWrite (SIDETONE_GPIO, 0);
- }
+ gpio_sidetone(0);
cw_hold_key(0); // this stops a CW pulse in transmitter.c
}
}
case PREDOT: // need to clear any pending dots or dashes
clear_memory();
key_state = SENDDOT;
+ if (first_dot) { // make the first "dot" or "dash" after automatic
+ kdelay = -15; // PTT switching 15 msec longer
+ first_dot = 0;
+ }
break;
case PREDASH:
clear_memory();
key_state = SENDDASH;
+ if (first_dot) { // make the first "dot" or "dash" after automatic
+ kdelay = -15; // PTT switching 15 msec longer
+ first_dot = 0;
+ }
break;
// dot paddle pressed so set keyer_out high for time dependant on speed
running = 0;
}
- if (SIDETONE_GPIO){
- softToneCreate(SIDETONE_GPIO);
- }
-
#ifdef __APPLE__
cw_event=sem_open("CW", O_CREAT, 0700, 0);
rc = (cw_event == SEM_FAILED);