From dd2d740787e4e37bc105c0b9707f8648103f5470 Mon Sep 17 00:00:00 2001 From: Alex Swedenburg Date: Thu, 12 Nov 2015 08:52:02 -0700 Subject: [PATCH 1/7] Config changes for TXINH --- audio.h | 6 ++++++ config.c | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/audio.h b/audio.h index 3f6017a..2702b9d 100644 --- a/audio.h +++ b/audio.h @@ -198,6 +198,12 @@ struct audio_s { } octrl[NUM_OCTYPES]; + struct { + int enabled; + int gpio; + int invert; + } txinh; + /* Transmit timing. */ int dwait; /* First wait extra time for receiver squelch. */ diff --git a/config.c b/config.c index d0ebee6..59fe26b 100644 --- a/config.c +++ b/config.c @@ -1450,6 +1450,30 @@ void config_init (char *fname, struct audio_s *p_audio_config, } /* end of PTT */ +/* + * TXINH - Input for TX inhibit signal + */ + + else if (strcasecmp(t, "TXINH") == 0) { + t = strtok (NULL, " ,\t\n\r"); + if (t == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: Missing GPIO number for TXINH.\n", + line); + continue; + } + + p_audio_config->achan[channel].txinh.enabled = 1; + + if (*t == '-') { + p_audio_config->achan[channel].txinh.gpio = atoi(t+1); + p_audio_config->achan[channel].txinh.invert = 1; + } + else { + p_audio_config->achan[channel].txinh.gpio = atoi(t); + p_audio_config->achan[channel].txinh.invert = 0; + } + } /* end of TXINH */ /* * DWAIT - Extra delay for receiver squelch. From 0d7003bb98f753516a2ca0f56eca4b39cd84f572 Mon Sep 17 00:00:00 2001 From: Alex Swedenburg Date: Thu, 12 Nov 2015 13:01:25 -0700 Subject: [PATCH 2/7] Init for TXINH --- ptt.c | 190 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 103 insertions(+), 87 deletions(-) diff --git a/ptt.c b/ptt.c index f412971..d3f120e 100644 --- a/ptt.c +++ b/ptt.c @@ -155,6 +155,102 @@ static HANDLE ptt_fd[MAX_CHANS][NUM_OCTYPES]; static char otnames[NUM_OCTYPES][8]; +void export_gpio(int gpio, int invert, int direction) +{ + HANDLE fd; + char stemp[80]; + struct stat finfo; + int err; + + fd = open("/sys/class/gpio/export", O_WRONLY); + if (fd < 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Permissions do not allow ordinary users to access GPIO.\n"); + dw_printf ("Log in as root and type this command:\n"); + dw_printf (" chmod go+w /sys/class/gpio/export /sys/class/gpio/unexport\n"); + exit (1); + } + sprintf (stemp, "%d", gpio); + if (write (fd, stemp, strlen(stemp)) != strlen(stemp)) { + int e = errno; + /* Ignore EBUSY error which seems to mean */ + /* the device node already exists. */ + if (e != EBUSY) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error writing \"%s\" to /sys/class/gpio/export, errno=%d\n", stemp, e); + dw_printf ("%s\n", strerror(e)); + exit (1); + } + } + close (fd); + +/* + * We will have the same permission problem if not root. + * We only care about "direction" and "value". + */ + sprintf (stemp, "sudo chmod go+rw /sys/class/gpio/gpio%d/direction", gpio); + err = system (stemp); + sprintf (stemp, "sudo chmod go+rw /sys/class/gpio/gpio%d/value", gpio); + err = system (stemp); + + sprintf (stemp, "/sys/class/gpio/gpio%d/value", gpio); + + if (stat(stemp, &finfo) < 0) { + int e = errno; + text_color_set(DW_COLOR_ERROR); + dw_printf ("Failed to get status for %s \n", stemp); + dw_printf ("%s\n", strerror(e)); + exit (1); + } + + if (geteuid() != 0) { + if ( ! (finfo.st_mode & S_IWOTH)) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Permissions do not allow ordinary users to access GPIO.\n"); + dw_printf ("Log in as root and type these commands:\n"); + dw_printf (" chmod go+rw /sys/class/gpio/gpio%d/direction", gpio); + dw_printf (" chmod go+rw /sys/class/gpio/gpio%d/value", gpio); + exit (1); + } + } + +/* + * Set direction and initial value. + */ + + sprintf (stemp, "/sys/class/gpio/gpio%d/direction", gpio); + fd = open(stemp, O_WRONLY); + if (fd < 0) { + int e = errno; + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error opening %s\n", stemp); + dw_printf ("%s\n", strerror(e)); + exit (1); + } + + char gpio_val[8]; + if (direction) { + if (invert) { + strcpy (gpio_val, "high"); + } + else { + strcpy (gpio_val, "low"); + } + } + else { + strcpy (gpio_val, "in"); + } + + if (write (fd, gpio_val, strlen(gpio_val)) != strlen(gpio_val)) { + int e = errno; + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error writing direction to %s\n", stemp); + dw_printf ("%s\n", strerror(e)); + exit (1); + } + close (fd); +} + void ptt_init (struct audio_s *audio_config_p) { int ch; @@ -326,6 +422,7 @@ void ptt_init (struct audio_s *audio_config_p) using_gpio = 1; } } + if (audio_config_p->achan[ch].txinh.enabled) using_gpio = 1; } } @@ -343,7 +440,7 @@ void ptt_init (struct audio_s *audio_config_p) if (stat("/sys/class/gpio/export", &finfo) < 0) { text_color_set(DW_COLOR_ERROR); dw_printf ("This system is not configured with the GPIO user interface.\n"); - dw_printf ("Use a different method for PTT control.\n"); + dw_printf ("Use a different method for PTT, DCD, or TXINH control.\n"); exit (1); } @@ -367,7 +464,7 @@ void ptt_init (struct audio_s *audio_config_p) /* Unexpected because we could do it before. */ text_color_set(DW_COLOR_ERROR); dw_printf ("This system is not configured with the GPIO user interface.\n"); - dw_printf ("Use a different method for PTT control.\n"); + dw_printf ("Use a different method for PTT, DCD, or TXINH control.\n"); exit (1); } @@ -392,93 +489,12 @@ void ptt_init (struct audio_s *audio_config_p) int ot; for (ot = 0; ot < NUM_OCTYPES; ot++) { if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIO) { - char stemp[80]; - struct stat finfo; - int err; - - fd = open("/sys/class/gpio/export", O_WRONLY); - if (fd < 0) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("Permissions do not allow ordinary users to access GPIO.\n"); - dw_printf ("Log in as root and type this command:\n"); - dw_printf (" chmod go+w /sys/class/gpio/export /sys/class/gpio/unexport\n"); - exit (1); - } - sprintf (stemp, "%d", audio_config_p->achan[ch].octrl[ot].ptt_gpio); - if (write (fd, stemp, strlen(stemp)) != strlen(stemp)) { - int e = errno; - /* Ignore EBUSY error which seems to mean */ - /* the device node already exists. */ - if (e != EBUSY) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("Error writing \"%s\" to /sys/class/gpio/export, errno=%d\n", stemp, e); - dw_printf ("%s\n", strerror(e)); - exit (1); - } - } - close (fd); - -/* - * We will have the same permission problem if not root. - * We only care about "direction" and "value". - */ - sprintf (stemp, "sudo chmod go+rw /sys/class/gpio/gpio%d/direction", audio_config_p->achan[ch].octrl[ot].ptt_gpio); - err = system (stemp); - sprintf (stemp, "sudo chmod go+rw /sys/class/gpio/gpio%d/value", audio_config_p->achan[ch].octrl[ot].ptt_gpio); - err = system (stemp); - - sprintf (stemp, "/sys/class/gpio/gpio%d/value", audio_config_p->achan[ch].octrl[ot].ptt_gpio); - - if (stat(stemp, &finfo) < 0) { - int e = errno; - text_color_set(DW_COLOR_ERROR); - dw_printf ("Failed to get status for %s \n", stemp); - dw_printf ("%s\n", strerror(e)); - exit (1); - } - - if (geteuid() != 0) { - if ( ! (finfo.st_mode & S_IWOTH)) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("Permissions do not allow ordinary users to access GPIO.\n"); - dw_printf ("Log in as root and type these commands:\n"); - dw_printf (" chmod go+rw /sys/class/gpio/gpio%d/direction", audio_config_p->achan[ch].octrl[ot].ptt_gpio); - dw_printf (" chmod go+rw /sys/class/gpio/gpio%d/value", audio_config_p->achan[ch].octrl[ot].ptt_gpio); - exit (1); - } - } - -/* - * Set output direction with initial state off. - */ - - sprintf (stemp, "/sys/class/gpio/gpio%d/direction", audio_config_p->achan[ch].octrl[ot].ptt_gpio); - fd = open(stemp, O_WRONLY); - if (fd < 0) { - int e = errno; - text_color_set(DW_COLOR_ERROR); - dw_printf ("Error opening %s\n", stemp); - dw_printf ("%s\n", strerror(e)); - exit (1); - } - - char hilo[8]; - if (audio_config_p->achan[ch].octrl[ot].ptt_invert) { - strcpy (hilo, "high"); - } - else { - strcpy (hilo, "low"); - } - if (write (fd, hilo, strlen(hilo)) != strlen(hilo)) { - int e = errno; - text_color_set(DW_COLOR_ERROR); - dw_printf ("Error writing initial state to %s\n", stemp); - dw_printf ("%s\n", strerror(e)); - exit (1); - } - close (fd); + export_gpio(audio_config_p->achan[ch].octrl[ot].ptt_gpio, audio_config_p->achan[ch].octrl[ot].ptt_invert, 1); } } + if (audio_config_p->achan[ch].txinh.enabled) { + export_gpio(audio_config_p->achan[ch].txinh.gpio, audio_config_p->achan[ch].txinh.invert, 0); + } } } #endif From 401db2d1d5e562345ff54890ed6ae4c63fdec56f Mon Sep 17 00:00:00 2001 From: Alex Swedenburg Date: Thu, 12 Nov 2015 14:20:41 -0700 Subject: [PATCH 3/7] Add TXINH check to hdlc_data_detect_any --- hdlc_rec.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/hdlc_rec.c b/hdlc_rec.c index e645ee1..f832204 100644 --- a/hdlc_rec.c +++ b/hdlc_rec.c @@ -42,6 +42,13 @@ #include "demod_9600.h" /* for descramble() */ #include "ptt.h" +#if __WIN32__ +#else +#include +#include +#include +#endif + //#define TEST 1 /* Define for unit testing. */ @@ -125,6 +132,8 @@ static void dcd_change (int chan, int subchan, int state); * ***********************************************************************************/ +static struct audio_s *save_audio_config_p; + static int was_init = 0; void hdlc_rec_init (struct audio_s *pa) @@ -137,6 +146,8 @@ void hdlc_rec_init (struct audio_s *pa) assert (pa != NULL); + save_audio_config_p = pa; + for (j=0; j= 0 && chan < MAX_CHANS); - return (composite_dcd[chan] != 0); + if (composite_dcd[chan] != 0) busy = 1; + +#if __WIN32__ +#else + + if (save_audio_config_p->achan[chan].txinh.enabled) { + int fd; + char stemp[80]; + + sprintf (stemp, "/sys/class/gpio/gpio%d/value", save_audio_config_p->achan[chan].txinh.gpio); + + fd = open(stemp, O_RDONLY); + if (fd < 0) { + int e = errno; + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error opening %s to check TXINH.\n", stemp); + dw_printf ("%s\n", strerror(e)); + return; + } + + if (read (fd, stemp, 1) != 1) { + int e = errno; + text_color_set(DW_COLOR_ERROR); + dw_printf ("Error getting GPIO %d value for TXINH\n", save_audio_config_p->achan[chan].txinh.gpio); + dw_printf ("%s\n", strerror(e)); + } + close (fd); + + char vtemp[2]; + sprintf (vtemp, "%d", save_audio_config_p->achan[chan].txinh.invert); + + if (!strcmp (stemp, vtemp)) busy = 1; + } +#endif + + return busy; } /* end hdlc_rec_data_detect_any */ From b81262f5276f37af05ed201f94253bfde4bc95ac Mon Sep 17 00:00:00 2001 From: Alex Swedenburg Date: Thu, 12 Nov 2015 15:13:20 -0700 Subject: [PATCH 4/7] TXINH testing fixes --- hdlc_rec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hdlc_rec.c b/hdlc_rec.c index f832204..08b92a0 100644 --- a/hdlc_rec.c +++ b/hdlc_rec.c @@ -45,6 +45,7 @@ #if __WIN32__ #else #include +#include #include #include #endif @@ -664,7 +665,7 @@ int hdlc_rec_data_detect_any (int chan) text_color_set(DW_COLOR_ERROR); dw_printf ("Error opening %s to check TXINH.\n", stemp); dw_printf ("%s\n", strerror(e)); - return; + return busy; } if (read (fd, stemp, 1) != 1) { @@ -682,7 +683,7 @@ int hdlc_rec_data_detect_any (int chan) } #endif - return busy; + return (busy != 1); } /* end hdlc_rec_data_detect_any */ From 42a23988a6d11bc94f890320cc2a7305f12fe06b Mon Sep 17 00:00:00 2001 From: Alex Swedenburg Date: Thu, 12 Nov 2015 16:02:29 -0700 Subject: [PATCH 5/7] Disable obnoxious white background on arm targets --- hdlc_rec.c | 2 +- textcolor.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hdlc_rec.c b/hdlc_rec.c index 08b92a0..bac7e12 100644 --- a/hdlc_rec.c +++ b/hdlc_rec.c @@ -665,7 +665,7 @@ int hdlc_rec_data_detect_any (int chan) text_color_set(DW_COLOR_ERROR); dw_printf ("Error opening %s to check TXINH.\n", stemp); dw_printf ("%s\n", strerror(e)); - return busy; + return (busy != 1); } if (read (fd, stemp, 1) != 1) { diff --git a/textcolor.c b/textcolor.c index e0fd3a1..d4dfc9a 100644 --- a/textcolor.c +++ b/textcolor.c @@ -111,19 +111,19 @@ static const char clear_eos[] = "\e[0J"; /* expected bright/bold (1) to get bright white background. */ /* Makes no sense but I stumbled across that somewhere. */ -static const char background_white[] = "\e[5;47m"; +static const char background_white[] = "\e[49m"; /* Whenever a dark color is used, the */ /* background is reset and needs to be set again. */ -static const char black[] = "\e[0;30m" "\e[5;47m"; -static const char red[] = "\e[1;31m" "\e[5;47m"; -static const char green[] = "\e[1;32m" "\e[5;47m"; -static const char yellow[] = "\e[1;33m" "\e[5;47m"; -static const char blue[] = "\e[1;34m" "\e[5;47m"; -static const char magenta[] = "\e[1;35m" "\e[5;47m"; -static const char cyan[] = "\e[1;36m" "\e[5;47m"; -static const char dark_green[] = "\e[0;32m" "\e[5;47m"; +static const char black[] = "\e[0;39m" "\e[49m"; +static const char red[] = "\e[1;31m" "\e[49m"; +static const char green[] = "\e[1;32m" "\e[49m"; +static const char yellow[] = "\e[1;33m" "\e[49m"; +static const char blue[] = "\e[1;34m" "\e[49m"; +static const char magenta[] = "\e[1;35m" "\e[49m"; +static const char cyan[] = "\e[1;36m" "\e[49m"; +static const char dark_green[] = "\e[0;32m" "\e[49m"; /* Clear from cursor to end of screen. */ From c15c3ee0fd8a8338807036722a7f69672d798b6a Mon Sep 17 00:00:00 2001 From: Alex Swedenburg Date: Thu, 12 Nov 2015 19:25:04 -0700 Subject: [PATCH 6/7] Tested TXINH, fixed it --- hdlc_rec.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hdlc_rec.c b/hdlc_rec.c index bac7e12..ada1982 100644 --- a/hdlc_rec.c +++ b/hdlc_rec.c @@ -48,6 +48,7 @@ #include #include #include +#include #endif @@ -644,7 +645,7 @@ static void dcd_change (int chan, int subchan, int state) int hdlc_rec_data_detect_any (int chan) { int subchan; - int busy; + int busy = 0; assert (chan >= 0 && chan < MAX_CHANS); @@ -668,7 +669,8 @@ int hdlc_rec_data_detect_any (int chan) return (busy != 1); } - if (read (fd, stemp, 1) != 1) { + char vtemp[2]; + if (read (fd, vtemp, 1) != 1) { int e = errno; text_color_set(DW_COLOR_ERROR); dw_printf ("Error getting GPIO %d value for TXINH\n", save_audio_config_p->achan[chan].txinh.gpio); @@ -676,14 +678,11 @@ int hdlc_rec_data_detect_any (int chan) } close (fd); - char vtemp[2]; - sprintf (vtemp, "%d", save_audio_config_p->achan[chan].txinh.invert); - - if (!strcmp (stemp, vtemp)) busy = 1; + if (atoi(vtemp) == save_audio_config_p->achan[chan].txinh.invert) busy = 1; } #endif - return (busy != 1); + return (busy != 0); } /* end hdlc_rec_data_detect_any */ From 9b36294efac34b7d56dfed2da2b0f537265111d1 Mon Sep 17 00:00:00 2001 From: Alex Swedenburg Date: Fri, 13 Nov 2015 09:13:10 -0700 Subject: [PATCH 7/7] TXINH logic was reversed --- hdlc_rec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hdlc_rec.c b/hdlc_rec.c index ada1982..f7370a8 100644 --- a/hdlc_rec.c +++ b/hdlc_rec.c @@ -678,7 +678,7 @@ int hdlc_rec_data_detect_any (int chan) } close (fd); - if (atoi(vtemp) == save_audio_config_p->achan[chan].txinh.invert) busy = 1; + if (atoi(vtemp) != save_audio_config_p->achan[chan].txinh.invert) busy = 1; } #endif