Skip to content

Commit

Permalink
Add gpio command to rigctl(d) usable with pttport setting CM108
Browse files Browse the repository at this point in the history
e.g. to set gpio2 on use 'gpio GPIO2 1" and off "gpio GPIO2 0"
Should work with GPIO1-4
New API funcions rig_cm108_get_bit rig_cm108_set_bit
#1121
  • Loading branch information
mdblack98 committed Jul 22, 2023
1 parent d28ce6b commit 9ad070c
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 18 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Version 5.x -- future
* Change FT1000MP Mark V model names to align with FT1000MP

Version 4.6
* Added rig_cm108_get/set_bit to API and get/set_gpio to rigctl(d) for GPIO1,2,3,4 access on CM108
* Added BG2FX FX4/C/CR/L
* Fixed IC7610 to use new 0x25 0x26 command added in latest firmware
* Fix W command in rigctld to work propery -- can take terminating char or # of bytes to expect
Expand Down
25 changes: 25 additions & 0 deletions doc/man1/rigctl.1
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,31 @@ Examples:
.BR client_version " \(aq" \fIString\fP "\(aq
.EX
Client can send its version to rigctld and get feedback on compatibility, deprecation, and alternatives
.TP
.BR hamlib_version
.EX
Returns hamlib version with ISO8601 date/time
.
.TP
.BR test
.EX
Performs test routines. Under development.
.
.TP
.BR set_gpio " \(aq" \fIGPIO#\fP "\(aq
.EX
Sets GPIO1, GPIO2, GPIO3, GPIO4 on the GPIO ptt port
Can also use 1,2,3,4
.
.TP
.BR XXXX
.EX
Stuff
.
.TP
.BR XXXX
.EX
Stuff
.
.SH READLINE
.
Expand Down
46 changes: 46 additions & 0 deletions doc/man1/rigctld.1
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,52 @@ CW Skimmer is started and "set_lock_mode 0" when CW Skimmer is stopped.
.BR get_lock_mode
Returns current lock mode status 1=On, 2=Off (only useful with rigctld)
.
.TP
.BR send_raw " \(aq" \fITerminator\fP "\(aq \(aq" \fIString\fP \(aq
.EX
Can send ASCII string or 0xnn values -- there can be no spaces in the command string.
Possible terminator values are CR, LF, ;, ICOM, 0-100 (bytes to read), or -1 meaning unknown (will timeout on read)
Examples:
send_raw ; FA;MD;
send_raw icom 0xFE;0xFE;0x94;0x03;0xFD
send_raw -1 0xFE;0xFE;0x94;0x03;0xFD
send_raw 14 0xFE;0xFE;0x94;0x03;0xFD
.
.TP
.BR client_version " \(aq" \fIString\fP "\(aq
.EX
Client can send its version to rigctld and get feedback on compatibility, deprecation, and alternatives
.TP
.BR hamlib_version
.EX
Returns hamlib version with ISO8601 date/time
.
+.TP
+.BR hamlib_version
+.EX
+Returns hamlib version with ISO8601 date/time
+.
+.TP
+.BR test
+.EX
+Performs test routines. Under development.
+.
+.TP
+.BR set_gpio " \(aq" \fIGPIO#\fP "\(aq
+.EX
+Sets GPIO1, GPIO2, GPIO3, GPIO4 on the GPIO ptt port
+Can also use 1,2,3,4
+.
+.TP
+.BR XXXX
+.EX
+Stuff
+.
+.TP
+.BR XXXX
+.EX
+Stuff
.
.SH PROTOCOL
.
Expand Down
4 changes: 4 additions & 0 deletions include/hamlib/rig.h
Original file line number Diff line number Diff line change
Expand Up @@ -3694,6 +3694,10 @@ extern HAMLIB_EXPORT(int) rig_is_model(RIG *rig, rig_model_t model);

extern HAMLIB_EXPORT(char*) rig_date_strget(char *buf, int buflen, int localtime);

enum GPIO { GPIO1, GPIO2, GPIO3, GPIO4 };
extern HAMLIB_EXPORT(int) rig_cm108_get_bit(hamlib_port_t *p, enum GPIO gpio, int *bit);
extern HAMLIB_EXPORT(int) rig_cm108_set_bit(hamlib_port_t *p, enum GPIO gpio, int bit);


//! @endcond

Expand Down
126 changes: 109 additions & 17 deletions src/cm108.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx)

case RIG_PTT_CM108:
{
ssize_t nw;
ssize_t bytes;
char out_rep[] =
{
0x00, // report number
Expand Down Expand Up @@ -227,9 +227,9 @@ int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx)
}

// Send the HID packet
nw = write(p->fd, out_rep, sizeof(out_rep));
bytes = write(p->fd, out_rep, sizeof(out_rep));

if (nw < 0)
if (bytes < 0)
{
return -RIG_EIO;
}
Expand Down Expand Up @@ -295,30 +295,122 @@ int cm108_ptt_get(hamlib_port_t *p, ptt_t *pttx)
*/
int cm108_dcd_get(hamlib_port_t *p, dcd_t *dcdx)
{
int bytes;

rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);

// On the CM108 and compatible chips the squelch line on the radio is
// wired to Volume Down input pin. The state of this pin is reported
// in HID messages from the CM108 device, but I am not sure how
// to query this state on demand.
return RIG_OK;
}
#endif

int cm108_set_bit(hamlib_port_t *p, enum GPIO gpio, int bit)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);

switch (p->type.dcd)
ssize_t bytes;
char out_rep[] =
{
case RIG_DCD_CM108:
0x00, // report number
// HID output report
0x00,
bit ? (1 << (gpio - 1)) : 0, // set GPIO
1 << (gpio - 1), // Data direction register (1=output)
0x00
};
rig_debug(RIG_DEBUG_VERBOSE, "%s: out_rep = 0x%02x 0x%02x\n", __func__,
out_rep[2], out_rep[3]);

// Build a packet for CM108 HID to turn GPIO bit on or off.
// Packet is 4 bytes, preceded by a 'report number' byte
// 0x00 report number
// Write data packet (from CM108 documentation)
// byte 0: 00xx xxxx Write GPIO
// byte 1: xxxx dcba GPIO3-0 output values (1=high)
// byte 2: xxxx dcba GPIO3-0 data-direction register (1=output)
// byte 3: xxxx xxxx SPDIF

// Send the HID packet
bytes = write(p->fd, out_rep, sizeof(out_rep));

if (bytes < 0)
{
return -RIG_ENIMPL;
return -RIG_EIO;
}

default:
rig_debug(RIG_DEBUG_ERR,
"%s: unsupported DCD type %d\n",
__func__,
p->type.dcd);
return -RIG_ENAVAIL;
return RIG_OK;
}

int cm108_get_bit(hamlib_port_t *p, enum GPIO gpio, int *bit)
{
ssize_t bytes;
char reply[4];
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
char in_rep[] =
{
0x00, // report number
0x01, // HID input report
0x00,
0x00
};

// Send the HID packet
bytes = write(p->fd, in_rep, sizeof(in_rep));

if (bytes < 0)
{
return -RIG_EIO;
}

bytes = read(p->fd, reply, sizeof(reply));

if (bytes <= 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: read error: %s\n", __func__, strerror(errno));
return -RIG_EPROTO;
}

int mask = 1 << (gpio - 1);
*bit = (reply[1] & mask) != 0;
rig_debug(RIG_DEBUG_VERBOSE,
"%s: mask=0x%02x, reply=0x%02x 0x%02x 0x%02x 0x%02x, bit=%d\n", __func__, mask,
reply[0], reply[1], reply[2], reply[3], *bit);
return RIG_OK;
}
#endif

int rig_cm108_get_bit(hamlib_port_t *p, enum GPIO gpio, int *bit)
{
if (gpio < 1 || gpio > 4)
{
rig_debug(RIG_DEBUG_ERR, "%s: gpio must be 1,2,3,4 for cm108\n", __func__);
return -RIG_EINVAL;
}

cm108_get_bit(p, gpio, bit);
rig_debug(RIG_DEBUG_TRACE, "%s: gpio=%d bit=%d\n", __func__, gpio, *bit);
return RIG_OK;
}


int rig_cm108_set_bit(hamlib_port_t *p, enum GPIO gpio, int bit)
{
if (gpio < 1 || gpio > 4)
{
rig_debug(RIG_DEBUG_ERR, "%s: gpio must be 1,2,3,4 for cm108\n", __func__);
return -RIG_EINVAL;
}

int retval = cm108_set_bit(p, gpio, bit);

if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: cm108_set_bit: %s\n", __func__, strerror(retval));
return retval;
}

rig_debug(RIG_DEBUG_TRACE, "%s: simulated gpio=%d bit=%d\n", __func__, gpio,
bit);
return RIG_OK;
}


/** @} */
1 change: 0 additions & 1 deletion src/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,3 @@ int gpio_dcd_get(hamlib_port_t *port, dcd_t *dcdx)

return RIG_OK;
}

52 changes: 52 additions & 0 deletions tests/rigctl_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ declare_proto_rig(send_raw);
declare_proto_rig(client_version);
declare_proto_rig(hamlib_version);
declare_proto_rig(test);
declare_proto_rig(cm108_get_bit);
declare_proto_rig(cm108_set_bit);


/*
Expand Down Expand Up @@ -384,6 +386,8 @@ static struct test_table test_list[] =
{ 0xa6, "get_vfo_list", ACTION(get_vfo_list), ARG_NOVFO },
{ 0xa7, "test", ACTION(test), ARG_NOVFO | ARG_IN, "routine" },
{ 0xa8, "hamlib_version", ACTION(hamlib_version), ARG_NOVFO },
{ 0xa9, "get_gpio", ACTION(cm108_get_bit), ARG_NOVFO | ARG_IN1 | ARG_OUT1, "GPIO#", "0/1" },
{ 0xaa, "set_gpio", ACTION(cm108_set_bit), ARG_NOVFO | ARG_IN , "GPIO#", "0/1" },
{ 0x00, "", NULL },
};

Expand Down Expand Up @@ -5609,3 +5613,51 @@ declare_proto_rig(send_raw)

return RIG_OK;
}

declare_proto_rig(cm108_get_bit)
{
rig_debug(RIG_DEBUG_TRACE, "%s:\n", __func__);

int gpio = -1;
int bit = -1;
// try GPIO format first
int n = sscanf(arg1,"GPIO%d", &gpio);
if (n == 0)
n = sscanf(arg1,"%d", &gpio);
if (n != 1) return -RIG_EINVAL;
int retval = rig_cm108_get_bit(&rig->state.pttport, gpio, &bit);
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: %s\n", __func__, strerror(retval));
return retval;
}
rig_debug(RIG_DEBUG_TRACE, "%s: gpio=%d\n", __func__, gpio);
if ((interactive && prompt) || (interactive && !prompt && ext_resp))
{
fprintf(fout, "%s: ", cmd->arg2);
}
fprintf(fout, "%d (simulated)\n", 1);


return RIG_OK;
}

declare_proto_rig(cm108_set_bit)
{
rig_debug(RIG_DEBUG_TRACE, "%s:\n", __func__);
int gpio, bit=-1;
// try GPIO format first
int n = sscanf(arg1,"GPIO%d", &gpio);
if (n == 0)
n = sscanf(arg1,"%d", &gpio);
if (n != 1) return -RIG_EINVAL;
n = sscanf(arg2, "%d", &bit);
if (n != 1) return -RIG_EINVAL;
rig_debug(RIG_DEBUG_TRACE, "%s: set gpio=%d, bit=%d\n", __func__, gpio, bit);
int retval = rig_cm108_set_bit(&rig->state.pttport, gpio, bit);
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: %s\n", __func__, strerror(retval));
}
return retval;
}

0 comments on commit 9ad070c

Please sign in to comment.