Skip to content

Commit

Permalink
Add support for GPIO PTT.
Browse files Browse the repository at this point in the history
  • Loading branch information
JeroenVreeken committed May 28, 2016
1 parent 2dae9a1 commit 1bf736d
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 3 deletions.
12 changes: 10 additions & 2 deletions include/hamlib/rig.h
Expand Up @@ -172,7 +172,9 @@ typedef enum rig_port_e {
RIG_PORT_PARALLEL, /*!< Parallel port */
RIG_PORT_USB, /*!< USB port */
RIG_PORT_UDP_NETWORK, /*!< UDP Network socket type */
RIG_PORT_CM108 /*!< CM108 GPIO */
RIG_PORT_CM108, /*!< CM108 GPIO */
RIG_PORT_GPIO, /*!< GPIO */
RIG_PORT_GPION, /*!< GPIO inverted */
} rig_port_t;

/**
Expand Down Expand Up @@ -419,7 +421,9 @@ typedef enum {
RIG_PTT_SERIAL_RTS, /*!< PTT control through serial RTS signal */
RIG_PTT_PARALLEL, /*!< PTT control through parallel port */
RIG_PTT_RIG_MICDATA, /*!< Legacy PTT (CAT PTT), supports RIG_PTT_ON_MIC/RIG_PTT_ON_DATA */
RIG_PTT_CM108 /*!< PTT control through CM108 GPIO pin */
RIG_PTT_CM108, /*!< PTT control through CM108 GPIO pin */
RIG_PTT_GPIO, /*!< PTT control through GPIO pin */
RIG_PTT_GPION, /*!< PTT control through inverted GPIO pin */
} ptt_type_t;

/**
Expand Down Expand Up @@ -1381,6 +1385,10 @@ typedef struct hamlib_port {
char *vendor_name; /*!< Vendor name (opt.) */
char *product; /*!< Product (opt.) */
} usb; /*!< USB attributes */
struct {
int on_value;
int value;
} gpio;
} parm; /*!< Port parameter union */
} hamlib_port_t;

Expand Down
2 changes: 1 addition & 1 deletion src/Makefile.am
Expand Up @@ -4,7 +4,7 @@ RIGSRC = rig.c serial.c serial.h misc.c misc.h register.c register.h event.c \
event.h cal.c cal.h conf.c tones.c tones.h rotator.c locator.c rot_reg.c \
rot_conf.c rot_conf.h iofunc.c iofunc.h ext.c mem.c settings.c \
parallel.c parallel.h usb_port.c usb_port.h debug.c network.c network.h \
cm108.c cm108.h idx_builtin.h token.h par_nt.h
cm108.c cm108.h gpio.c gpio.h idx_builtin.h token.h par_nt.h

lib_LTLIBRARIES = libhamlib.la
libhamlib_la_SOURCES = $(RIGSRC)
Expand Down
98 changes: 98 additions & 0 deletions src/gpio.c
@@ -0,0 +1,98 @@
/*
* Hamlib Interface - gpio support
* Copyright (c) 2016 by Jeroen Vreeken
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

#include "gpio.h"

#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int gpio_open(hamlib_port_t *port, int on_value)
{
char pathname[FILPATHLEN];
FILE *fexp, *fdir;
int fd;

port->parm.gpio.on_value = on_value;

snprintf(pathname, FILPATHLEN, "/sys/class/gpio/export");
fexp = fopen(pathname, "w");
if (!fexp) {
rig_debug(RIG_DEBUG_ERR, "Export GPIO \"%s\": %s\n", port->pathname, strerror(errno));
return -RIG_EIO;
}
fprintf(fexp, "%s\n", port->pathname);
fclose(fexp);

snprintf(pathname, FILPATHLEN, "/sys/class/gpio/gpio%s/direction", port->pathname);
fdir = fopen(pathname, "w");
if (!fdir) {
rig_debug(RIG_DEBUG_ERR, "GPIO\"%s\" direction: %s\n", port->pathname, strerror(errno));
return -RIG_EIO;
}
fprintf(fdir, "out\n");
fclose(fdir);

snprintf(pathname, FILPATHLEN, "/sys/class/gpio/gpio%s/value", port->pathname);
fd = open(pathname, O_WRONLY);
if (fd < 0) {
rig_debug(RIG_DEBUG_ERR, "GPIO\"%s\" opening value file %s: %s\n", port->pathname, pathname, strerror(errno));
return -RIG_EIO;
}

port->fd = fd;
return fd;
}

int gpio_close(hamlib_port_t *port)
{
return close(port->fd);
}

int gpio_ptt_set(hamlib_port_t *port, ptt_t pttx)
{
char *val;
port->parm.gpio.value = pttx != RIG_PTT_OFF;

if ((port->parm.gpio.value && port->parm.gpio.on_value) ||
(!port->parm.gpio.value && !port->parm.gpio.on_value)) {
val = "1\n";
} else {
val = "0\n";
}

if (write(port->fd, val, strlen(val)) <= 0)
return -RIG_EIO;
return RIG_OK;
}

int gpio_ptt_get(hamlib_port_t *port, ptt_t *pttx)
{
if (port->parm.gpio.value)
return RIG_PTT_ON;
else
return RIG_PTT_OFF;
}

38 changes: 38 additions & 0 deletions src/gpio.h
@@ -0,0 +1,38 @@
/*
* Hamlib Interface - gpio support header
* Copyright (c) 2016 by Jeroen Vreeken
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

#ifndef _GPIO_H
#define _GPIO_H

#include <hamlib/rig.h>


__BEGIN_DECLS

/* Hamlib internal use, see rig.c */
int gpio_open(hamlib_port_t *p, int on_value);
int gpio_close(hamlib_port_t *p);
int gpio_ptt_set(hamlib_port_t *p, ptt_t pttx);
int gpio_ptt_get(hamlib_port_t *p, ptt_t *pttx);

__END_DECLS

#endif /* _GPIO_H */
39 changes: 39 additions & 0 deletions src/rig.c
Expand Up @@ -67,6 +67,7 @@
#include "network.h"
#include "event.h"
#include "cm108.h"
#include "gpio.h"

/**
* \brief Hamlib release number
Expand Down Expand Up @@ -127,6 +128,7 @@ const char hamlib_copyright[231] = /* hamlib 1.2 ABI specifies 231 bytes */
#define DEFAULT_CM108_PTT_BITNUM 2
#endif

#define DEFAULT_GPIO_PORT "0"

#define CHECK_RIG_ARG(r) (!(r) || !(r)->caps || !(r)->state.comm_state)

Expand Down Expand Up @@ -331,6 +333,10 @@ RIG * HAMLIB_API rig_init(rig_model_t rig_model)
strncpy(rs->rigport.pathname, DEFAULT_CM108_PORT, FILPATHLEN);
rs->rigport.parm.cm108.ptt_bitnum = DEFAULT_CM108_PTT_BITNUM;
break;

case RIG_PORT_GPIO:
strncpy(rs->rigport.pathname, DEFAULT_GPIO_PORT, FILPATHLEN);
break;

case RIG_PORT_NETWORK:
case RIG_PORT_UDP_NETWORK:
Expand Down Expand Up @@ -575,6 +581,24 @@ int HAMLIB_API rig_open(RIG *rig)
else
cm108_ptt_set(&rs->pttport, RIG_PTT_OFF);
break;
case RIG_PTT_GPIO:
rs->pttport.fd = gpio_open(&rs->pttport, 1);
if (rs->pttport.fd < 0) {
rig_debug(RIG_DEBUG_ERR,
"Cannot open PTT device \"%s\"\n",
rs->pttport.pathname);
status = -RIG_EIO;
} else
gpio_ptt_set(&rs->pttport, RIG_PTT_OFF);
case RIG_PTT_GPION:
rs->pttport.fd = gpio_open(&rs->pttport, 0);
if (rs->pttport.fd < 0) {
rig_debug(RIG_DEBUG_ERR,
"Cannot open PTT device \"%s\"\n",
rs->pttport.pathname);
status = -RIG_EIO;
} else
gpio_ptt_set(&rs->pttport, RIG_PTT_OFF);
default:
rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n",
rs->pttport.type.ptt);
Expand Down Expand Up @@ -727,6 +751,10 @@ int HAMLIB_API rig_close(RIG *rig)
cm108_ptt_set(&rs->pttport, RIG_PTT_OFF);
port_close(&rs->pttport, RIG_PORT_CM108);
break;
case RIG_PTT_GPIO:
case RIG_PTT_GPION:
gpio_ptt_set(&rs->pttport, RIG_PTT_OFF);
port_close(&rs->pttport, RIG_PORT_GPIO);
default:
rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n",
rs->pttport.type.ptt);
Expand Down Expand Up @@ -1302,6 +1330,10 @@ int HAMLIB_API rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
case RIG_PTT_CM108:
return cm108_ptt_set(&rig->state.pttport, ptt);

case RIG_PTT_GPIO:
case RIG_PTT_GPION:
return gpio_ptt_set(&rig->state.pttport, ptt);

case RIG_PTT_NONE:
return -RIG_ENAVAIL; /* not available */
default:
Expand Down Expand Up @@ -1393,6 +1425,13 @@ int HAMLIB_API rig_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)

return cm108_ptt_get(&rig->state.pttport, ptt);

case RIG_PTT_GPIO:
case RIG_PTT_GPION:
if (caps->get_ptt)
return caps->get_ptt(rig, vfo, ptt);

return gpio_ptt_get(&rig->state.pttport, ptt);

case RIG_PTT_NONE:
return -RIG_ENAVAIL; /* not available */

Expand Down
4 changes: 4 additions & 0 deletions tests/rigctl.c
Expand Up @@ -216,6 +216,10 @@ int main (int argc, char *argv[])
ptt_type = RIG_PTT_PARALLEL;
else if (!strcmp(optarg, "CM108"))
ptt_type = RIG_PTT_CM108;
else if (!strcmp(optarg, "GPIO"))
ptt_type = RIG_PTT_GPIO;
else if (!strcmp(optarg, "GPION"))
ptt_type = RIG_PTT_GPION;
else if (!strcmp(optarg, "NONE"))
ptt_type = RIG_PTT_NONE;
else
Expand Down

0 comments on commit 1bf736d

Please sign in to comment.