Add gpio command to rigctl(d) usable with pttport setting CM108

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
https://github.com/Hamlib/Hamlib/issues/1121
pull/1347/head
Mike Black W9MDB 2023-07-22 10:32:25 -05:00
rodzic d28ce6b798
commit 9ad070c33f
7 zmienionych plików z 243 dodań i 24 usunięć

1
NEWS
Wyświetl plik

@ -13,6 +13,7 @@ Version 5.x -- future
* Change FT1000MP Mark V model names to align with FT1000MP * Change FT1000MP Mark V model names to align with FT1000MP
Version 4.6 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 * Added BG2FX FX4/C/CR/L
* Fixed IC7610 to use new 0x25 0x26 command added in latest firmware * 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 * Fix W command in rigctld to work propery -- can take terminating char or # of bytes to expect

Wyświetl plik

@ -1398,6 +1398,31 @@ Examples:
.BR client_version " \(aq" \fIString\fP "\(aq .BR client_version " \(aq" \fIString\fP "\(aq
.EX .EX
Client can send its version to rigctld and get feedback on compatibility, deprecation, and alternatives 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 .SH READLINE
. .

Wyświetl plik

@ -1202,6 +1202,52 @@ CW Skimmer is started and "set_lock_mode 0" when CW Skimmer is stopped.
.BR get_lock_mode .BR get_lock_mode
Returns current lock mode status 1=On, 2=Off (only useful with rigctld) 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 .SH PROTOCOL
. .

Wyświetl plik

@ -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); 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 //! @endcond

Wyświetl plik

@ -195,7 +195,7 @@ int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx)
case RIG_PTT_CM108: case RIG_PTT_CM108:
{ {
ssize_t nw; ssize_t bytes;
char out_rep[] = char out_rep[] =
{ {
0x00, // report number 0x00, // report number
@ -227,9 +227,9 @@ int cm108_ptt_set(hamlib_port_t *p, ptt_t pttx)
} }
// Send the HID packet // 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; return -RIG_EIO;
} }
@ -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 cm108_dcd_get(hamlib_port_t *p, dcd_t *dcdx)
{ {
int bytes;
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__); 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.
switch (p->type.dcd)
{
case RIG_DCD_CM108:
{
return -RIG_ENIMPL;
}
default:
rig_debug(RIG_DEBUG_ERR,
"%s: unsupported DCD type %d\n",
__func__,
p->type.dcd);
return -RIG_ENAVAIL;
}
return RIG_OK; return RIG_OK;
} }
#endif #endif
int cm108_set_bit(hamlib_port_t *p, enum GPIO gpio, int bit)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
ssize_t bytes;
char out_rep[] =
{
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_EIO;
}
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;
}
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;
}
/** @} */ /** @} */

Wyświetl plik

@ -189,4 +189,3 @@ int gpio_dcd_get(hamlib_port_t *port, dcd_t *dcdx)
return RIG_OK; return RIG_OK;
} }

Wyświetl plik

@ -267,6 +267,8 @@ declare_proto_rig(send_raw);
declare_proto_rig(client_version); declare_proto_rig(client_version);
declare_proto_rig(hamlib_version); declare_proto_rig(hamlib_version);
declare_proto_rig(test); declare_proto_rig(test);
declare_proto_rig(cm108_get_bit);
declare_proto_rig(cm108_set_bit);
/* /*
@ -384,6 +386,8 @@ static struct test_table test_list[] =
{ 0xa6, "get_vfo_list", ACTION(get_vfo_list), ARG_NOVFO }, { 0xa6, "get_vfo_list", ACTION(get_vfo_list), ARG_NOVFO },
{ 0xa7, "test", ACTION(test), ARG_NOVFO | ARG_IN, "routine" }, { 0xa7, "test", ACTION(test), ARG_NOVFO | ARG_IN, "routine" },
{ 0xa8, "hamlib_version", ACTION(hamlib_version), ARG_NOVFO }, { 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 }, { 0x00, "", NULL },
}; };
@ -5609,3 +5613,51 @@ declare_proto_rig(send_raw)
return RIG_OK; 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;
}