mirror of https://github.com/wb2osz/direwolf.git
Merge 9b36294efa
into b14f1d0ff2
This commit is contained in:
commit
751e052674
6
audio.h
6
audio.h
|
@ -198,6 +198,12 @@ struct audio_s {
|
||||||
|
|
||||||
} octrl[NUM_OCTYPES];
|
} octrl[NUM_OCTYPES];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int enabled;
|
||||||
|
int gpio;
|
||||||
|
int invert;
|
||||||
|
} txinh;
|
||||||
|
|
||||||
/* Transmit timing. */
|
/* Transmit timing. */
|
||||||
|
|
||||||
int dwait; /* First wait extra time for receiver squelch. */
|
int dwait; /* First wait extra time for receiver squelch. */
|
||||||
|
|
24
config.c
24
config.c
|
@ -1450,6 +1450,30 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
|
|
||||||
} /* end of PTT */
|
} /* 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.
|
* DWAIT - Extra delay for receiver squelch.
|
||||||
|
|
49
hdlc_rec.c
49
hdlc_rec.c
|
@ -42,6 +42,15 @@
|
||||||
#include "demod_9600.h" /* for descramble() */
|
#include "demod_9600.h" /* for descramble() */
|
||||||
#include "ptt.h"
|
#include "ptt.h"
|
||||||
|
|
||||||
|
#if __WIN32__
|
||||||
|
#else
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//#define TEST 1 /* Define for unit testing. */
|
//#define TEST 1 /* Define for unit testing. */
|
||||||
|
|
||||||
|
@ -125,6 +134,8 @@ static void dcd_change (int chan, int subchan, int state);
|
||||||
*
|
*
|
||||||
***********************************************************************************/
|
***********************************************************************************/
|
||||||
|
|
||||||
|
static struct audio_s *save_audio_config_p;
|
||||||
|
|
||||||
static int was_init = 0;
|
static int was_init = 0;
|
||||||
|
|
||||||
void hdlc_rec_init (struct audio_s *pa)
|
void hdlc_rec_init (struct audio_s *pa)
|
||||||
|
@ -137,6 +148,8 @@ void hdlc_rec_init (struct audio_s *pa)
|
||||||
|
|
||||||
assert (pa != NULL);
|
assert (pa != NULL);
|
||||||
|
|
||||||
|
save_audio_config_p = pa;
|
||||||
|
|
||||||
for (j=0; j<MAX_CHANS; j++)
|
for (j=0; j<MAX_CHANS; j++)
|
||||||
{
|
{
|
||||||
composite_dcd[j] = 0;
|
composite_dcd[j] = 0;
|
||||||
|
@ -632,10 +645,44 @@ static void dcd_change (int chan, int subchan, int state)
|
||||||
int hdlc_rec_data_detect_any (int chan)
|
int hdlc_rec_data_detect_any (int chan)
|
||||||
{
|
{
|
||||||
int subchan;
|
int subchan;
|
||||||
|
int busy = 0;
|
||||||
|
|
||||||
assert (chan >= 0 && chan < MAX_CHANS);
|
assert (chan >= 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 (busy != 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);
|
||||||
|
dw_printf ("%s\n", strerror(e));
|
||||||
|
}
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
if (atoi(vtemp) != save_audio_config_p->achan[chan].txinh.invert) busy = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (busy != 0);
|
||||||
|
|
||||||
} /* end hdlc_rec_data_detect_any */
|
} /* end hdlc_rec_data_detect_any */
|
||||||
|
|
||||||
|
|
190
ptt.c
190
ptt.c
|
@ -155,6 +155,102 @@ static HANDLE ptt_fd[MAX_CHANS][NUM_OCTYPES];
|
||||||
|
|
||||||
static char otnames[NUM_OCTYPES][8];
|
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)
|
void ptt_init (struct audio_s *audio_config_p)
|
||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
|
@ -326,6 +422,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
||||||
using_gpio = 1;
|
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) {
|
if (stat("/sys/class/gpio/export", &finfo) < 0) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("This system is not configured with the GPIO user interface.\n");
|
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);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +464,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
||||||
/* Unexpected because we could do it before. */
|
/* Unexpected because we could do it before. */
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("This system is not configured with the GPIO user interface.\n");
|
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);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,93 +489,12 @@ void ptt_init (struct audio_s *audio_config_p)
|
||||||
int ot;
|
int ot;
|
||||||
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||||
if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIO) {
|
if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIO) {
|
||||||
char stemp[80];
|
export_gpio(audio_config_p->achan[ch].octrl[ot].ptt_gpio, audio_config_p->achan[ch].octrl[ot].ptt_invert, 1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
#endif
|
||||||
|
|
18
textcolor.c
18
textcolor.c
|
@ -111,19 +111,19 @@ static const char clear_eos[] = "\e[0J";
|
||||||
/* expected bright/bold (1) to get bright white background. */
|
/* expected bright/bold (1) to get bright white background. */
|
||||||
/* Makes no sense but I stumbled across that somewhere. */
|
/* 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 */
|
/* Whenever a dark color is used, the */
|
||||||
/* background is reset and needs to be set again. */
|
/* background is reset and needs to be set again. */
|
||||||
|
|
||||||
static const char black[] = "\e[0;30m" "\e[5;47m";
|
static const char black[] = "\e[0;39m" "\e[49m";
|
||||||
static const char red[] = "\e[1;31m" "\e[5;47m";
|
static const char red[] = "\e[1;31m" "\e[49m";
|
||||||
static const char green[] = "\e[1;32m" "\e[5;47m";
|
static const char green[] = "\e[1;32m" "\e[49m";
|
||||||
static const char yellow[] = "\e[1;33m" "\e[5;47m";
|
static const char yellow[] = "\e[1;33m" "\e[49m";
|
||||||
static const char blue[] = "\e[1;34m" "\e[5;47m";
|
static const char blue[] = "\e[1;34m" "\e[49m";
|
||||||
static const char magenta[] = "\e[1;35m" "\e[5;47m";
|
static const char magenta[] = "\e[1;35m" "\e[49m";
|
||||||
static const char cyan[] = "\e[1;36m" "\e[5;47m";
|
static const char cyan[] = "\e[1;36m" "\e[49m";
|
||||||
static const char dark_green[] = "\e[0;32m" "\e[5;47m";
|
static const char dark_green[] = "\e[0;32m" "\e[49m";
|
||||||
|
|
||||||
/* Clear from cursor to end of screen. */
|
/* Clear from cursor to end of screen. */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue