[Hamlib-commits] Hamlib -- Ham radio control libraries branch master updated. 897faf00c08028c6f6567
Library to control radio transceivers and receivers
Brought to you by:
n0nb
From: n0nb <n0...@us...> - 2023-08-24 17:39:04
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Hamlib -- Ham radio control libraries". The branch, master has been updated via 897faf00c08028c6f6567bf12cf309c7787b1fc6 (commit) via d049b90aa9041ea6821f88ce92617425e9efffad (commit) via ccab50a7df42dcd9b937c17cdd8cf602a9d22dea (commit) via 470c71dd93633d484525835de5bb438baa48f17e (commit) via 46c0649b234163f4d08927d173d505168ef93436 (commit) via 404ceb8c4b11ff54bfe76cfa2240a8878fc882f2 (commit) via 453a8cc94f98131b04bd136155d9df7523faf393 (commit) via 5113c6a895766ba32bb2aeaa3f04b2a6cac2f175 (commit) via 194906b2900366ea73327252d379e0330edb1fb5 (commit) via 24e407c82c358b09e7714c301bf2d398607b71cb (commit) via 7011b4855461a1fa178e7ddc9469b8826c220ad1 (commit) via cca3891362a0efd56e47eaa10c00bf419bedd215 (commit) via 1b0f0ec42201e418ebcdfa66ad0645ceed069348 (commit) via b40da0f6b0f07d19b79a0869d6fe522037dc3e5f (commit) via 424e8cc04a67bbb240efa2a14c44922eed352bd8 (commit) via 1ad43a44ba437ea095061ec289e51457a2335306 (commit) via 3492be25625a54a1331ac58a2b6daf680217b1e6 (commit) via af86f44eac92b526b017c73a81a72b7265459888 (commit) via d57e4ae185ddf5a1dc5971a080af8984187f2a03 (commit) via 3318766a7c9efcb23c522551fe111d395291e586 (commit) via 3814f2dadf53e2806130934cc8be09027ae3d1ec (commit) via 36dade6e6c25b7c2e8a322960fe045ac1a30f043 (commit) via 57ebd647ebc09c091fd43df2cb662d7ed35e05ab (commit) via 7bd9cbef83681468102dfafd6b2aa3792c4f5a13 (commit) via 7eefc77f5d50cf9198067c9fd879665f8a84da7e (commit) from 4faef9e0316fd118e114c2794baff5b19cadfbf3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 897faf00c08028c6f6567bf12cf309c7787b1fc6 Merge: 46c0649b2 d049b90aa Author: Michael Black <mdb...@ya...> Date: Tue Aug 22 22:25:48 2023 -0500 Merge pull request #1349 from torque/spid-logfix spid: handle a control stream containing log packets commit d049b90aa9041ea6821f88ce92617425e9efffad Author: torque <to...@us...> Date: Tue Aug 22 17:24:29 2023 -0700 spid: flush serial input buffer before command send This seems to take care of the log data pretty much entirely and is possibly a much simpler alternative solution to the previous two commits. However, for full robustness, I think it makes sense to keep all three of these changes together. Also, it's entirely possible that this approach introduces a performance regression: I haven't particularly looked at how the buffer flushing is implemented, but if it ends up doing looped reads with a timeout, this could slow down command processing for the SPID object significantly. Since I've only tested this through the command line interface, I have not taken a close look at performance. diff --git a/rotators/spid/spid.c b/rotators/spid/spid.c index 7c4100bd7..c2f68a9a7 100644 --- a/rotators/spid/spid.c +++ b/rotators/spid/spid.c @@ -168,6 +168,14 @@ static int read_r2p_frame(hamlib_port_t *port, unsigned char *rxbuffer, } } +static int spid_write(hamlib_port_t *p, const unsigned char *txbuffer, + size_t count) +{ + int ret = rig_flush(p); + if (ret < 0) return ret; + return write_block(p, txbuffer, count); +} + static int spid_rot_init(ROT *rot) { rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); @@ -310,7 +318,7 @@ static int spid_rot1prog_rot_set_position(ROT *rot, azimuth_t az, cmdstr[11] = 0x2F; /* K */ cmdstr[12] = 0x20; /* END */ - retval = write_block(&rs->rotport, (unsigned char *) cmdstr, 13); + retval = spid_write(&rs->rotport, (unsigned char *) cmdstr, 13); if (retval != RIG_OK) { @@ -337,7 +345,7 @@ static int spid_rot2prog_rot_set_position(ROT *rot, azimuth_t az, { do { - retval = write_block(&rs->rotport, + retval = spid_write(&rs->rotport, (unsigned char *) "\x57\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1F\x20", 13); if (retval != RIG_OK) @@ -378,7 +386,7 @@ static int spid_rot2prog_rot_set_position(ROT *rot, azimuth_t az, cmdstr[11] = 0x2F; /* K */ cmdstr[12] = 0x20; /* END */ - retval = write_block(&rs->rotport, (unsigned char *) cmdstr, 13); + retval = spid_write(&rs->rotport, (unsigned char *) cmdstr, 13); if (retval != RIG_OK) { @@ -412,7 +420,7 @@ static int spid_rot_get_position(ROT *rot, azimuth_t *az, elevation_t *el) do { - retval = write_block(&rs->rotport, + retval = spid_write(&rs->rotport, (unsigned char *) "\x57\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1F\x20", 13); if (retval != RIG_OK) @@ -484,7 +492,7 @@ static int spid_rot_stop(ROT *rot) do { - retval = write_block(&rs->rotport, + retval = spid_write(&rs->rotport, (unsigned char *) "\x57\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0F\x20", 13); if (retval != RIG_OK) @@ -559,7 +567,7 @@ static int spid_md01_rot2prog_rot_move(ROT *rot, int direction, int speed) moving at all), always send the stop command first. */ spid_rot_stop(rot); - retval = write_block(&rs->rotport, (unsigned char *) cmdstr, 13); + retval = spid_write(&rs->rotport, (unsigned char *) cmdstr, 13); return retval; } commit ccab50a7df42dcd9b937c17cdd8cf602a9d22dea Author: torque <to...@us...> Date: Tue Aug 22 17:23:19 2023 -0700 spid: account for another type of debug message When the settings are saved via the front panel on the MD-01, the following debug messages are printed on COM 0: thread_motionController: settings changed!\r\n thread_protocols: settings changed!\r\n Notably, because these aren't timestamped the way the other debug messages are, they were missing the our debug message sieve and causing protocol errors. Address this by treating anything that doesn't start with the ROT2PROG start byte ('W') as a log frame. diff --git a/rotators/spid/spid.c b/rotators/spid/spid.c index fe46b5af1..7c4100bd7 100644 --- a/rotators/spid/spid.c +++ b/rotators/spid/spid.c @@ -94,12 +94,16 @@ static int read_r2p_frame(hamlib_port_t *port, unsigned char *rxbuffer, // strict numerical bounds that could be used to sanity check the contents // of the reply frame). - int res = 0; unsigned char peek = 0; enum r2p_frame_parser_state pstate = ROT2PROG_PARSER_EXPECT_FRAME_START; - while (1) { + // This will loop infinitely in the case of a badly-behaved serial device + // that is producing log-like frames faster than we can consume them. + // However, this is not expected to be a practical possibility, and there's + // no concrete loop bounds we can use. + while (1) + { switch (pstate) { case ROT2PROG_PARSER_EXPECT_FRAME_START: @@ -108,27 +112,14 @@ static int read_r2p_frame(hamlib_port_t *port, unsigned char *rxbuffer, switch (peek) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - pstate = ROT2PROG_PARSER_EXPECT_CR; - break; - } - - case ROT2PROG_FRAME_START_BYTE: { + case ROT2PROG_FRAME_START_BYTE: rxbuffer[0] = peek; pstate = ROT2PROG_PARSER_EXPECT_FRAME_END; break; - } - default: return -RIG_EPROTO; + default: + pstate = ROT2PROG_PARSER_EXPECT_CR; + break; } break; @@ -168,10 +159,11 @@ static int read_r2p_frame(hamlib_port_t *port, unsigned char *rxbuffer, return -RIG_EPROTO; } - // lie about the number of bytes read + // account for the already-read start byte here return res + 1; - default: return -RIG_EINTERNAL; + default: + return -RIG_EINTERNAL; } } } commit 470c71dd93633d484525835de5bb438baa48f17e Author: torque <to...@us...> Date: Mon Jul 31 23:27:56 2023 -0700 spid: handle a control stream containing log packets I have an MD-01 controller running firmware 2.0.237 that is connected to the computer via the COM0 DB9 port. When it receives a control command to move the rotator, it prints debug logs to the serial output that look like this: input: W3600\x0A4500\x0A\x2F\x20 output: W\x03\x06\x00\x00\x0A\x04\x05\x01\x00\x0A\x20 287925671: in motion\r\n 287925673: Change motion state M0 to mcsStart\r\n 287925678: GO A 0.000000 0.000000 t ---\r\n 287925680: in motion\r\n 287925683: Change motion state M1 to mcsStart\r\n 287925686: GO E 90.000000 91.000000 t ---\r\n 287925690: distance to go M0 too small. End.\r\n 287925694: Change motion state M0 to mcsStopped\r\n 287925698: Stop on motor 0 on angle 0.000000\r\n 287925703: Change motion state M1 to mcsRunning\r\n 287926610: distance to go M1 too small. End.\r\n 287926613: Change motion state M1 to mcsStopped\r\n 287926617: Stop on motor 1 on angle 90.000000\r\n Note that the response frame is not necessarily present in an specific order relative to the log messages: I have seen it come after the logs as well. Because the current implementation just slurps up response bytes without checking the framing or anything, as soon as any of this log data enters the command stream, all subsequent commands will read completely bogus responses. Regardless of whether it's due to a misconfiguration, a weird artifact of the firmware, or something more sinister, the MD-01 is awkwardly interspersing its normal fixed-size-frame response with these line-based log messages. As shown above, the log messages appear to be consistently of the format <timestamp>: <message>\r\n, where <timestamp> is some kind of integer timestamp (possibly relative to unit boot) and <message> is an ASCII string. Due to poor(?) design decisions by the protocol designers, the frame start and end bytes are both printable ASCII characters ('W' and ' ' respectively) and the MD-01 response frame contains no other validation information (such as a CRC), which means that a valid log line could fairly easily contain a character sequence that is indistinguishable from a valid response frame, without actually being a valid response frame. However, since the log messages appear to be reasonably strictly structured, we can make a small number of assumptions that will allow us to reliably separate response frames from log lines without having to fall back on a heuristic-based parsing strategy. These assumptions are as follows: 1. A log line will always begin with an ASCII character in the range [0-9], none of which are the frame start byte. 2. A log line will never contain \r\n in the middle of the line (i.e. multi-line log messages do not exist). This means a log "frame" will always be of the form [0-9]<anything>\r\n. 3. The controller will not emit a response frame in the middle of a log line. 4. The operating system's serial port read buffer is large enough that we won't lose data while accumulating log messages between commands. Provided the above assumptions are true, a simple state machine can be used to parse the response by treating the log lines as a different type of frame. This could be made much more robust by applying additional heuristics for specific packets (e.g. get_position has some reasonably strict numerical bounds that could be used to sanity check the contents of the reply frame). diff --git a/rotators/spid/spid.c b/rotators/spid/spid.c index 072d019ca..fe46b5af1 100644 --- a/rotators/spid/spid.c +++ b/rotators/spid/spid.c @@ -39,6 +39,143 @@ struct spid_rot2prog_priv_data int el_resolution; }; +enum spid_rot2prog_framemagic { + ROT2PROG_FRAME_START_BYTE = 'W', + ROT2PROG_FRAME_END_BYTE = ' ', +}; + +enum r2p_frame_parser_state { + ROT2PROG_PARSER_EXPECT_FRAME_START, + ROT2PROG_PARSER_EXPECT_CR, + ROT2PROG_PARSER_EXPECT_LF, + ROT2PROG_PARSER_EXPECT_FRAME_END, +}; + +static int read_r2p_frame(hamlib_port_t *port, unsigned char *rxbuffer, + size_t count) +{ + // Some MD-01 firmware can apparently print debug messages to the same + // serial port that is used for the control protocol. This awkwardly + // intersperses the normal fixed-size frame response with a line-based + // logs. Theoretically, a valid response frame will not actually be emitted + // in the middle of a log message. + // + // Log messages are of the format <timestamp>: <message>\r\n, where + // <timestamp> is a unix-ish timestamp (inasmuch as it is an integer) and + // <message> is an ASCII string. + + // Due to poor(?) design decisions by the protocol designers, the frame + // start and end bytes are both printable ASCII characters ('W' and ' ' + // respectively) and the MD-01 response frame contains no other validation + // information (such as a CRC), which means that a valid log line can + // contain a character sequence that is indistinguishable from a valid + // response frame, without actually being a valid response frame. + + // However, since the log messages appear to be reasonably strictly + // structured, we can make a small number of assumptions that will allow us + // to reliably separate response frames from log lines without having to + // fall back on a heuristic-based parsing strategy. These assumptions are + // as follows: + + // 1. A log line will always begin with an ASCII character in the range + // [0-9], none of which are the frame start byte. + // 2. A log line will never contain \r\n in the middle of the line (i.e. + // multi-line log messages do not exist). This means a log "frame" will + // always be of the form [0-9]<anything>\r\n. + // 3. The controller will not emit a response frame in the middle of a log + // line. + // 4. The operating system's serial port read buffer is large enough that we + // won't lose data while accumulating log messages between commands. + + // Provided the above assumptions are true, a simple state machine can be + // used to parse the response by treating the log lines as a different type + // of frame. This could be made much more robust by applying additional + // heuristics for specific packets (e.g. get_position has some reasonably + // strict numerical bounds that could be used to sanity check the contents + // of the reply frame). + + + int res = 0; + unsigned char peek = 0; + enum r2p_frame_parser_state pstate = ROT2PROG_PARSER_EXPECT_FRAME_START; + + while (1) { + switch (pstate) + { + case ROT2PROG_PARSER_EXPECT_FRAME_START: + res = read_block(port, &peek, 1); + if (res < 0) return res; + + switch (peek) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + pstate = ROT2PROG_PARSER_EXPECT_CR; + break; + } + + case ROT2PROG_FRAME_START_BYTE: { + rxbuffer[0] = peek; + pstate = ROT2PROG_PARSER_EXPECT_FRAME_END; + break; + } + + default: return -RIG_EPROTO; + } + break; + + case ROT2PROG_PARSER_EXPECT_CR: + res = read_block(port, &peek, 1); + if (res < 0) return res; + + if (peek == '\r') pstate = ROT2PROG_PARSER_EXPECT_LF; + break; + + case ROT2PROG_PARSER_EXPECT_LF: + res = read_block(port, &peek, 1); + if (res < 0) return res; + + if (peek == '\n') + { + pstate = ROT2PROG_PARSER_EXPECT_FRAME_START; + } + else + { + // we have stumbled across a \r that is not immediately + // followed by \n. We could assume this is a weirdly formed + // log message, but I think it makes more sense to be + // defensive here and assume it is invalid for this to + // happen. + return -RIG_EPROTO; + } + break; + + case ROT2PROG_PARSER_EXPECT_FRAME_END: + // we already read the frame start byte + res = read_block(port, rxbuffer + 1, count - 1); + if (res < 0) return res; + + if (rxbuffer[count - 1] != ROT2PROG_FRAME_END_BYTE) + { + return -RIG_EPROTO; + } + + // lie about the number of bytes read + return res + 1; + + default: return -RIG_EINTERNAL; + } + } +} + static int spid_rot_init(ROT *rot) { rig_debug(RIG_DEBUG_TRACE, "%s called\n", __func__); @@ -217,7 +354,7 @@ static int spid_rot2prog_rot_set_position(ROT *rot, azimuth_t az, } memset(cmdstr, 0, 12); - retval = read_block(&rs->rotport, (unsigned char *) cmdstr, 12); + retval = read_r2p_frame(&rs->rotport, (unsigned char *) cmdstr, 12); } while (retval < 0 && retry_read++ < rot->state.rotport.retry); @@ -264,7 +401,7 @@ static int spid_rot2prog_rot_set_position(ROT *rot, azimuth_t az, do { - retval = read_block(&rs->rotport, (unsigned char *) cmdstr, 12); + retval = read_r2p_frame(&rs->rotport, (unsigned char *) cmdstr, 12); } while ((retval < 0) && (retry_read++ < rot->state.rotport.retry)); } @@ -295,12 +432,12 @@ static int spid_rot_get_position(ROT *rot, azimuth_t *az, elevation_t *el) if (rot->caps->rot_model == ROT_MODEL_SPID_ROT1PROG) { - retval = read_block(&rs->rotport, (unsigned char *) posbuf, 5); + retval = read_r2p_frame(&rs->rotport, (unsigned char *) posbuf, 5); } else if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG || rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG) { - retval = read_block(&rs->rotport, (unsigned char *) posbuf, 12); + retval = read_r2p_frame(&rs->rotport, (unsigned char *) posbuf, 12); } else { @@ -367,12 +504,12 @@ static int spid_rot_stop(ROT *rot) if (rot->caps->rot_model == ROT_MODEL_SPID_ROT1PROG) { - retval = read_block(&rs->rotport, (unsigned char *) posbuf, 5); + retval = read_r2p_frame(&rs->rotport, (unsigned char *) posbuf, 5); } else if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG || rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG) { - retval = read_block(&rs->rotport, (unsigned char *) posbuf, 12); + retval = read_r2p_frame(&rs->rotport, (unsigned char *) posbuf, 12); } } while (retval < 0 && retry_read++ < rot->state.rotport.retry); commit 46c0649b234163f4d08927d173d505168ef93436 Author: Mike Black W9MDB <mdb...@ya...> Date: Mon Aug 21 16:33:53 2023 -0500 Fix spacing in k3/k4_stop_morse https://github.com/Hamlib/Hamlib/issues/1366 diff --git a/rigs/kenwood/k3.c b/rigs/kenwood/k3.c index 7298999ad..760dc1b46 100644 --- a/rigs/kenwood/k3.c +++ b/rigs/kenwood/k3.c @@ -2912,7 +2912,7 @@ int k4_stop_voice_mem(RIG *rig, vfo_t vfo) int k4_stop_morse(RIG *rig, vfo_t vfo) { int retval; - retval = kenwood_transaction(rig, "KY@;", NULL, 0); + retval = kenwood_transaction(rig, "KY @;", NULL, 0); return retval; } @@ -2920,7 +2920,7 @@ int k3_stop_morse(RIG *rig, vfo_t vfo) { int retval; char cmd[32]; - SNPRINTF(cmd,sizeof(cmd),"KY%c;", 0x04); + SNPRINTF(cmd,sizeof(cmd),"KY %c;", 0x04); retval = kenwood_transaction(rig, cmd, NULL, 0); return retval; } commit 404ceb8c4b11ff54bfe76cfa2240a8878fc882f2 Author: Mike Black W9MDB <mdb...@ya...> Date: Mon Aug 21 15:16:32 2023 -0500 Change send_morse, stop_morse, send_voice_mem, and stop_voicemem to not require a VFO argument https://github.com/Hamlib/Hamlib/issues/1365 diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index dc322400a..6942abe5b 100644 --- a/tests/rigctl_parse.c +++ b/tests/rigctl_parse.c @@ -350,10 +350,10 @@ static struct test_table test_list[] = { 'w', "send_cmd", ACTION(send_cmd), ARG_IN1 | ARG_IN_LINE | ARG_OUT2 | ARG_NOVFO, "Cmd", "Reply" }, { 'W', "send_cmd_rx", ACTION(send_cmd), ARG_IN | ARG_OUT2 | ARG_NOVFO, "Cmd", "Reply"}, { 'b', "send_morse", ACTION(send_morse), ARG_IN | ARG_NOVFO | ARG_IN_LINE, "Morse" }, - { 0xbb, "stop_morse", ACTION(stop_morse), }, - { 0xbc, "wait_morse", ACTION(wait_morse), }, - { 0x94, "send_voice_mem", ACTION(send_voice_mem), ARG_IN, "Voice Mem#" }, - { 0xab, "stop_voice_mem", ACTION(stop_voice_mem), }, + { 0xbb, "stop_morse", ACTION(stop_morse), ARG_NOVFO}, + { 0xbc, "wait_morse", ACTION(wait_morse), ARG_NOVFO}, + { 0x94, "send_voice_mem", ACTION(send_voice_mem), ARG_NOVFO | ARG_IN, "Voice Mem#" }, + { 0xab, "stop_voice_mem", ACTION(stop_voice_mem), ARG_NOVFO}, { 0x8b, "get_dcd", ACTION(get_dcd), ARG_OUT, "DCD" }, { 0x8d, "set_twiddle", ACTION(set_twiddle), ARG_IN | ARG_NOVFO, "Timeout (secs)" }, { 0x8e, "get_twiddle", ACTION(get_twiddle), ARG_OUT | ARG_NOVFO, "Timeout (secs)" }, commit 453a8cc94f98131b04bd136155d9df7523faf393 Author: Mike Black W9MDB <mdb...@ya...> Date: Mon Aug 21 15:10:41 2023 -0500 Fix K3/K4 stop_morse https://github.com/Hamlib/Hamlib/issues/1366 diff --git a/rigs/kenwood/k3.c b/rigs/kenwood/k3.c index 46457e994..7298999ad 100644 --- a/rigs/kenwood/k3.c +++ b/rigs/kenwood/k3.c @@ -179,6 +179,7 @@ int k4_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt); int k4_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt); int k4_send_voice_mem(RIG *rig, vfo_t vfo, int ch); int k4_stop_voice_mem(RIG *rig, vfo_t vfo); +int k4_stop_morse(RIG *rig, vfo_t vfo); /* * K3 rig capabilities. @@ -508,7 +509,7 @@ const struct rig_caps k4_caps = RIG_MODEL(RIG_MODEL_K4), .model_name = "K4", .mfg_name = "Elecraft", - .version = BACKEND_VER ".27", + .version = BACKEND_VER ".28", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -656,7 +657,7 @@ const struct rig_caps k4_caps = .get_ant = kenwood_get_ant, .send_morse = kenwood_send_morse, .wait_morse = rig_wait_morse, - .stop_morse = k3_stop_morse, + .stop_morse = k4_stop_morse, .send_voice_mem = k4_send_voice_mem, .stop_voice_mem = k4_stop_voice_mem, .power2mW = k3_power2mW, @@ -2908,10 +2909,18 @@ int k4_stop_voice_mem(RIG *rig, vfo_t vfo) return retval; } +int k4_stop_morse(RIG *rig, vfo_t vfo) +{ + int retval; + retval = kenwood_transaction(rig, "KY@;", NULL, 0); + return retval; +} + int k3_stop_morse(RIG *rig, vfo_t vfo) { int retval; - char buf[32]; - retval = kenwood_transaction(rig, "KY;", buf, 4); + char cmd[32]; + SNPRINTF(cmd,sizeof(cmd),"KY%c;", 0x04); + retval = kenwood_transaction(rig, cmd, NULL, 0); return retval; } commit 5113c6a895766ba32bb2aeaa3f04b2a6cac2f175 Author: Mike Black W9MDB <mdb...@ya...> Date: Mon Aug 21 10:31:55 2023 -0500 Add simqrplabs.c diff --git a/simulators/simqrplabs.c b/simulators/simqrplabs.c new file mode 100644 index 000000000..4c1c282ea --- /dev/null +++ b/simulators/simqrplabs.c @@ -0,0 +1,429 @@ +// can run this using rigctl/rigctld and socat pty devices +// gcc -o simyaesu simyaesu.c +#define _XOPEN_SOURCE 700 +// since we are POSIX here we need this +struct ip_mreq +{ + int dummy; +}; + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <hamlib/rig.h> + +#define BUFSIZE 256 + +int mysleep = 20; + +float freqA = 14074000; +float freqB = 14074500; +int filternum = 7; +int datamode = 0; +int vfo, vfo_tx, ptt, ptt_data, ptt_mic, ptt_tune; +int tomode = 0; + +int +getmyline(int fd, char *buf) +{ + char c; + int i = 0; + memset(buf, 0, BUFSIZE); + + while (read(fd, &c, 1) > 0) + { + buf[i++] = c; + + if (c == ';') { return strlen(buf); } + } + + return strlen(buf); +} + +#if defined(WIN32) || defined(_WIN32) +int openPort(char *comport) // doesn't matter for using pts devices +{ + int fd; + fd = open(comport, O_RDWR); + + if (fd < 0) + { + perror(comport); + } + + return fd; +} + +#else +int openPort(char *comport) // doesn't matter for using pts devices +{ + int fd = posix_openpt(O_RDWR); + char *name = ptsname(fd); + + if (name == NULL) + { + perror("pstname"); + return -1; + } + + printf("name=%s\n", name); + + if (fd == -1 || grantpt(fd) == -1 || unlockpt(fd) == -1) + { + perror("posix_openpt"); + return -1; + } + + return fd; +} +#endif + + + +int main(int argc, char *argv[]) +{ + char buf[256]; + char *pbuf; + int n; + int fd = openPort(argv[1]); + int freqa = 14074000, freqb = 140735000; + int modeA = 1, modeB = 2; + + while (1) + { + buf[0] = 0; + + if (getmyline(fd, buf) > 0) { printf("Cmd:%s\n", buf); } + +// else { return 0; } + + if (strcmp(buf, "RM5;") == 0) + { + printf("%s\n", buf); + hl_usleep(mysleep * 1000); + pbuf = "RM5100000;"; + n = write(fd, pbuf, strlen(pbuf)); +// printf("n=%d\n", n); + + if (n <= 0) { perror("RM5"); } + } + + else if (strcmp(buf, "AN0;") == 0) + { + printf("%s\n", buf); + hl_usleep(mysleep * 1000); + pbuf = "AN030;"; + n = write(fd, pbuf, strlen(pbuf)); +// printf("n=%d\n", n); + + if (n <= 0) { perror("AN"); } + } + else if (strcmp(buf, "IF;") == 0) + { + char ifbuf[256]; + printf("%s\n", buf); + hl_usleep(mysleep * 1000); + pbuf = "IF000503130001000+0000000000030000000;"; + // from QMX 1_09 firmware "IF00007074000 +0.0000000002000000 ;" + sprintf(ifbuf, "IF%011d +0.0000000002000000 ;", freqa); + //pbuf = "IF00010138698 +00000000002000000 ; + n = write(fd, ifbuf, strlen(ifbuf)); +// printf("n=%d\n", n); + + if (n <= 0) { perror("IF"); } + + continue; + } + else if (strcmp(buf, "NB;") == 0) + { + hl_usleep(mysleep * 1000); + pbuf = "NB0;"; + n = write(fd, pbuf, strlen(pbuf)); + continue; + } + else if (strcmp(buf, "RA;") == 0) + { + hl_usleep(mysleep * 1000); + pbuf = "RA01;"; + n = write(fd, pbuf, strlen(pbuf)); + continue; + } + else if (strcmp(buf, "RG;") == 0) + { + hl_usleep(mysleep * 1000); + pbuf = "RG055;"; + n = write(fd, pbuf, strlen(pbuf)); + continue; + } + else if (strcmp(buf, "MG;") == 0) + { + hl_usleep(mysleep * 1000); + pbuf = "MG050;"; + n = write(fd, pbuf, strlen(pbuf)); + continue; + } + else if (strcmp(buf, "AG;") == 0) + { + hl_usleep(mysleep * 1000); + pbuf = "AG100;"; + n = write(fd, pbuf, strlen(pbuf)); + continue; + } + else if (strcmp(buf, "FV;") == 0) + { + hl_usleep(mysleep * 1000); + pbuf = "FV1.2;"; + n = write(fd, pbuf, strlen(pbuf)); + continue; + } + else if (strncmp(buf, "IS;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "IS+0000;"); + n = write(fd, buf, strlen(buf)); + printf("%s\n", buf); + continue; + } + else if (strncmp(buf, "IS", 2) == 0) + { + continue; + } + else if (strncmp(buf, "SM;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "SM0035;"); + n = write(fd, buf, strlen(buf)); + printf("%s\n", buf); + continue; + } + else if (strncmp(buf, "PC;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "PC100;"); + n = write(fd, buf, strlen(buf)); + printf("%s\n", buf); + continue; + } + else if (strcmp(buf, "FW;") == 0) + { + //usleep(mysleep * 1000); + pbuf = "FW240"; + n = write(fd, pbuf, strlen(pbuf)); + hl_usleep(20 * 1000); + pbuf = "0;"; + n = write(fd, pbuf, strlen(pbuf)); + continue; + } + else if (strncmp(buf, "FW", 2) == 0) + { + continue; + } + else if (strcmp(buf, "ID;") == 0) + { + printf("%s\n", buf); + hl_usleep(mysleep * 1000); + SNPRINTF(buf, sizeof(buf), "ID%03d;", 10); + n = write(fd, buf, strlen(buf)); +// printf("n=%d\n", n); + + if (n <= 0) { perror("ID"); } + + continue; + } + + else if (strncmp(buf, "AI", 2) == 0) + { + if (strcmp(buf, "AI;")) + { + printf("%s\n", buf); + hl_usleep(mysleep * 1000); + pbuf = "AI0;"; + n = write(fd, pbuf, strlen(pbuf)); + printf("n=%d\n", n); + + if (n <= 0) { perror("AI"); } + } + } + + else if (strcmp(buf, "VS;") == 0) + { + printf("%s\n", buf); + hl_usleep(mysleep * 1000); + pbuf = "VS0;"; + n = write(fd, pbuf, strlen(pbuf)); +// printf("n=%d\n", n); + + if (n < 0) { perror("VS"); } + + continue; + } + else if (strcmp(buf, "EX032;") == 0) + { + static int ant = 0; + ant = (ant + 1) % 3; + printf("%s\n", buf); + hl_usleep(mysleep * 1000); + SNPRINTF(buf, sizeof(buf), "EX032%1d;", ant); + n = write(fd, buf, strlen(buf)); +// printf("n=%d\n", n); + + if (n < 0) { perror("EX032"); } + + continue; + } + else if (strncmp(buf, "EX", 2) == 0) + { + continue; + } + else if (strcmp(buf, "FA;") == 0) + { + SNPRINTF(buf, sizeof(buf), "FA%011d;", freqa); + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strcmp(buf, "FB;") == 0) + { + SNPRINTF(buf, sizeof(buf), "FB%011d;", freqb); + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strncmp(buf, "FA", 2) == 0) + { + sscanf(buf, "FA%d", &freqa); + continue; + } + else if (strncmp(buf, "FB", 2) == 0) + { + sscanf(buf, "FB%d", &freqb); + continue; + } + else if (strncmp(buf, "AI;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "AI0;"); + n = write(fd, buf, strlen(buf)); + continue; + } + + else if (strncmp(buf, "PS;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "PS1;"); + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strncmp(buf, "SA;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "SA0;"); + n = write(fd, buf, strlen(buf)); + } + else if (buf[3] == ';' && strncmp(buf, "SF", 2)==0) + { + SNPRINTF(buf, sizeof(buf), "SF%c%011.0f%c;", buf[2], buf[2] == '0' ? freqA : freqB, + buf[2] == '0' ? modeA + '0' : modeB + '0'); + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strncmp(buf, "SF", 2) == 0) + { + mode_t tmpmode= buf[14]; + + if (buf[2] == '0') { modeA = tmpmode - '0'; } + else { modeB = tmpmode - '0'; } + printf("modeA=%c, modeB=%c\n", modeA, modeB); + + continue; + } + else if (strncmp(buf, "MD;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "MD%d;", + modeA); // not worried about modeB yet for simulator + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strncmp(buf, "MD", 2) == 0) + { + sscanf(buf, "MD%d", &modeA); // not worried about modeB yet for simulator + continue; + } + else if (strncmp(buf, "FL;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "FL%03d;", filternum); + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strncmp(buf, "FL", 2) == 0) + { + sscanf(buf, "FL%d", &filternum); + continue; + } + else if (strcmp(buf, "FR;") == 0) + { + SNPRINTF(buf, sizeof(buf), "FR%d;", vfo); + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strncmp(buf, "FR", 2) == 0) + { + sscanf(buf, "FR%d", &vfo); + } + else if (strcmp(buf, "FT;") == 0) + { + SNPRINTF(buf, sizeof(buf), "FR%d;", vfo_tx); + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strncmp(buf, "FT", 2) == 0) + { + sscanf(buf, "FT%d", &vfo_tx); + } + else if (strncmp(buf, "DA;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "DA%d;", datamode); + n = write(fd, buf, strlen(buf)); + printf("%s\n", buf); + continue; + } + else if (strncmp(buf, "DA", 2) == 0) + { + sscanf(buf, "DA%d", &datamode); + printf("%s\n", buf); + continue; + } + else if (strncmp(buf, "TO;", 3) == 0) + { + SNPRINTF(buf, sizeof(buf), "TO%d;", tomode); + continue; + } + else if (strncmp(buf, "BD;", 3) == 0) + { + continue; + } + else if (strncmp(buf, "BU;", 3) == 0) + { + continue; + } + else if (strncmp(buf, "TX", 2) == 0) + { + ptt = ptt_mic = ptt_data = ptt_tune = 0; + + switch (buf[2]) + { + case ';': ptt = 1; + + case '0': ptt_mic = 1; + + case '1': ptt_data = 1; + + case '2': ptt_tune = 1; + } + + continue; + } + else if (strlen(buf) > 0) + { + fprintf(stderr, "Unknown command: %s\n", buf); + } + + + } + + return 0; +} commit 194906b2900366ea73327252d379e0330edb1fb5 Author: Mike Black W9MDB <mdb...@ya...> Date: Mon Aug 21 10:13:26 2023 -0500 For QRPLabs ignore the IF return length as the differenet models can't agree on the length. QMX adds an extra space on the end with firmware 1_00_09 https://github.com/Hamlib/Hamlib/issues/1372 diff --git a/rigs/kenwood/kenwood.c b/rigs/kenwood/kenwood.c index 0503202c9..77480f5b3 100644 --- a/rigs/kenwood/kenwood.c +++ b/rigs/kenwood/kenwood.c @@ -719,6 +719,8 @@ int kenwood_safe_transaction(RIG *rig, const char *cmd, char *buf, if (checklen && length != expected) /* worth retrying as some rigs occasionally send short results */ { + // QRPLABS can't seem top decide if they give 37 or 38 bytes for IF command + if (strncmp(cmd,"IF",2)==0 && rig->caps->rig_model == RIG_MODEL_QRPLABS) break; struct kenwood_priv_data *priv = rig->state.priv; rig_debug(RIG_DEBUG_ERR, "%s: wrong answer; len for cmd %s: expected = %d, got %d\n", diff --git a/rigs/kenwood/kenwood.h b/rigs/kenwood/kenwood.h index c12a850f3..0fbaaa79f 100644 --- a/rigs/kenwood/kenwood.h +++ b/rigs/kenwood/kenwood.h @@ -28,7 +28,7 @@ #include "token.h" #include "idx_builtin.h" -#define BACKEND_VER "20230626" +#define BACKEND_VER "20230821" #define EOM_KEN ';' #define EOM_TH '\r' diff --git a/simulators/Makefile.am b/simulators/Makefile.am index 7b794947c..85394b19c 100644 --- a/simulators/Makefile.am +++ b/simulators/Makefile.am @@ -8,7 +8,7 @@ DISTCLEANFILES = bin_PROGRAMS = -check_PROGRAMS = simelecraft simicgeneric simkenwood simyaesu simic9100 simic9700 simft991 simftdx1200 simftdx3000 simjupiter simpowersdr simid5100 simft736 simftdx5000 simtmd700 simrotorez simspid simft817 simts590 simft847 simic7300 simic7000 simic7100 simic7200 simatd578 simic905 simts450 simic7600 simic7610 simic705 simts950 simts990 simic7851 simftdx101 simxiegug90 +check_PROGRAMS = simelecraft simicgeneric simkenwood simyaesu simic9100 simic9700 simft991 simftdx1200 simftdx3000 simjupiter simpowersdr simid5100 simft736 simftdx5000 simtmd700 simrotorez simspid simft817 simts590 simft847 simic7300 simic7000 simic7100 simic7200 simatd578 simic905 simts450 simic7600 simic7610 simic705 simts950 simts990 simic7851 simftdx101 simxiegug90 simqrplabs simelecraft_SOURCES = simelecraft.c simkenwood_SOURCES = simkenwood.c commit 24e407c82c358b09e7714c301bf2d398607b71cb Author: Mike Black W9MDB <mdb...@ya...> Date: Sun Aug 20 16:34:35 2023 -0500 Fix github build diff --git a/tests/Makefile.am b/tests/Makefile.am index fb87a2918..b2ec16650 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -43,7 +43,7 @@ endif rigctl_CPPFLAGS = -I$(top_builddir)/tests -I$(top_builddir)/src -I$(srcdir) -I$(top_builddir)/security $(AM_CPPFLAGS) # all the programs need this -LDADD = $(top_builddir)/src/libhamlib.la $(top_builddir)/lib/libmisc.la $(DL_LIBS) +LDADD = $(top_builddir)/src/libhamlib.la $(top_builddir)/lib/libmisc.la $(DL_LIBS) -lm rigmem_CFLAGS = $(AM_CFLAGS) $(LIBXML2_CFLAGS) -I$(top_builddir)/src rigctld_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -I$(top_builddir)/src -I$(top_builddir)/security commit 7011b4855461a1fa178e7ddc9469b8826c220ad1 Author: Mike Black W9MDB <mdb...@ya...> Date: Sun Aug 20 16:16:08 2023 -0500 Add rigfreqwalk diff --git a/tests/rigfreqwalk.c b/tests/rigfreqwalk.c new file mode 100644 index 000000000..403d90008 --- /dev/null +++ b/tests/rigfreqwalk.c @@ -0,0 +1,152 @@ +/* + * Hamlib sample program + */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <math.h> + +#include <hamlib/rig.h> + +#include <hamlib/config.h> + +#define HISTORYSIZE 10 +double history[HISTORYSIZE]; +int nhistory; +int historyinit = 1; + +double compute_mean(double arr[], int length) +{ + double sum = 0.0; + for (int i = 0; i < length; i++) { + sum += arr[i]; + } + return sum / length; +} + +double sigma(double arr[], int length) { + double mean = compute_mean(arr, length); + double sum_of_squares = 0.0; + + for (int i = 0; i < length; i++) { + sum_of_squares += pow(arr[i] - mean, 2); + } + + return sqrt(sum_of_squares / length); +} + +int main(int argc, char *argv[]) +{ + RIG *my_rig; /* handle to rig (nstance) */ + int strength; /* S-Meter level */ + int retcode; /* generic return code from functions */ + + rig_model_t myrig_model; + + + + if (argc != 8) + { + fprintf(stderr,"%s: version 1.0\n", argv[0]); + fprintf(stderr,"Usage: %s [model#] [comport] [baud] [start freq] [stop_freq] [stepsize] [seconds/step]\n", + argv[0]); + return 1; + } + + /* Turn off backend debugging output */ + rig_set_debug_level(RIG_DEBUG_NONE); + + /* + * allocate memory, setup & open port + */ + + hamlib_port_t myport; + myrig_model = atoi(argv[1]); + strncpy(myport.pathname, argv[2], HAMLIB_FILPATHLEN - 1); + myport.parm.serial.rate = atoi(argv[3]); + + my_rig = rig_init(myrig_model); + + if (!my_rig) + { + fprintf(stderr, "Unknown rig num: %d\n", myrig_model); + fprintf(stderr, "Please check riglist.h\n"); + exit(1); /* whoops! something went wrong (mem alloc?) */ + } + + strncpy(my_rig->state.rigport.pathname, argv[2], HAMLIB_FILPATHLEN - 1); + + retcode = rig_open(my_rig); + + if (retcode != RIG_OK) + { + printf("rig_open: error = %s\n", rigerror(retcode)); + exit(2); + } + +// printf("Port %s opened ok\n", SERIAL_PORT); + + long freq1, freq2; + int stepsize, seconds; + int n = sscanf(argv[4], "%ld", &freq1); + n += sscanf(argv[5], "%ld", &freq2); + n += sscanf(argv[6], "%d", &stepsize); + n += sscanf(argv[7], "%d", &seconds); + + if (n != 4) + { + fprintf(stderr, "Error parsing %s/%s/%s/%s as start/stop/step/seconds\n", + argv[4], argv[5], argv[6], argv[7]); + return 1; + } + + printf("Start:%ld Stop:%ld Step:%d Wait:%d\n", freq1, freq2, stepsize, seconds); + + while (1) + { + for (long f = freq1; f <= freq2; f += stepsize) + { + retcode = rig_set_freq(my_rig, RIG_VFO_CURR, (freq_t)f); + if (retcode != RIG_OK) + { + fprintf(stderr, "%s: Error rig_set_freq: %s\n", __func__, rigerror(retcode)); + return 1; + } + sleep(seconds); + retcode = rig_get_strength(my_rig, RIG_VFO_CURR, &strength); + + if (retcode != RIG_OK) + { + int static once=1; + if (once) + { + once = 0; + fprintf(stderr,"rig_get_strength error: %s\n", rigerror(retcode)); + } + strength = 1; + } + history[nhistory++] = strength; + if (historyinit) + { + for(int i=0;i<HISTORYSIZE;++i) history[i] = strength; + historyinit = 0; + } + nhistory %= HISTORYSIZE; + double s = sigma(history, HISTORYSIZE); + char timebuf[64]; + rig_date_strget(timebuf, sizeof(timebuf), 1); + printf("%s\t%ld\t%d\t%f\n", timebuf, f, strength, s); + fflush(stdout); + + } + } + + rig_close(my_rig); /* close port */ + rig_cleanup(my_rig); /* if you care about memory */ + + printf("port %s closed ok \n", argv[2]); + + return 0; +} commit cca3891362a0efd56e47eaa10c00bf419bedd215 Author: Mike Black W9MDB <mdb...@ya...> Date: Sun Aug 20 16:03:25 2023 -0500 Change L METER to allow meter names in addition to numeric Change l METER to return meter number=name instead of just number Hopefully doesn't mess up anybody using this function via rigctl/rigctld uf they parsing the number correctly. It's easier for users with to use/see text names for both set/get https://github.com/Hamlib/Hamlib/issues/1369 diff --git a/NEWS b/NEWS index 2a6d62139..4e28851a7 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ Version 5.x -- future * Change FT1000MP Mark V model names to align with FT1000MP Version 4.6 + * rig set level METER can now take SWR,COMP,ALC,IC/ID,DB,PO,VDD,TEMP arguments to set which meter to display + * reg get level displays meter number=name now * Added parm BANDSELECT for Yaesu rigs 'p BANDSELECT' returns current band of VFOA 'P BANDSELECT BAND160M' example selects the 160M band diff --git a/doc/man1/rigctl.1 b/doc/man1/rigctl.1 index 584bc43c7..80728ac0c 100644 --- a/doc/man1/rigctl.1 +++ b/doc/man1/rigctl.1 @@ -985,6 +985,8 @@ Lookup - if level shows 0/0/0 then it's probably a lookup value SPECTRUM_MODE 0=None, 1=Center, 2=Fixed, 3=Center Scroll, 4=Fixed Scroll SPECTRUM_AVG rig specific +METER -- SWR,COMP,ALC,IC/ID,DB,PO,VDD,TEMP or can use the numbers above in Lookup l METER returns the meter number=name + Watts RFPOWER_METER_WATTS diff --git a/simulators/simic7300.c b/simulators/simic7300.c index 898475f24..86283a01c 100644 --- a/simulators/simic7300.c +++ b/simulators/simic7300.c @@ -198,19 +198,17 @@ void frameParse(int fd, unsigned char *frame, int len) break; case 0x0f: - if (frame[5] == 0) { split = 0; } - else if (frame[5] == 1) { split = 1; } - else { frame[6] = split; } - if (frame[5] == 0xfd) { printf("get split %d\n", split); - frame[7] = 0xfd; - n = write(fd, frame, 8); + frame[5] = split; + frame[6] = 0xfd; + n = write(fd, frame, 7); } else { printf("set split %d\n", 1); + split = frame[5]; frame[4] = 0xfb; frame[5] = 0xfd; n = write(fd, frame, 6); diff --git a/tests/Makefile.am b/tests/Makefile.am index 72717b30e..fb87a2918 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -14,7 +14,7 @@ endif DISTCLEANFILES = rigctl.log rigctl.sum testbcd.log testbcd.sum -bin_PROGRAMS = rigctl rigctld rigmem rigsmtr rigswr rotctl rotctld rigctlcom rigctltcp rigctlsync ampctl ampctld rigtestmcast rigtestmcastrx $(TESTLIBUSB) +bin_PROGRAMS = rigctl rigctld rigmem rigsmtr rigswr rotctl rotctld rigctlcom rigctltcp rigctlsync ampctl ampctld rigtestmcast rigtestmcastrx $(TESTLIBUSB) rigfreqwalk #check_PROGRAMS = dumpmem testrig testrigopen testrigcaps testtrn testbcd testfreq listrigs testloc rig_bench testcache cachetest cachetest2 testcookie testgrid testsecurity check_PROGRAMS = dumpmem testrig testrigopen testrigcaps testtrn testbcd testfreq listrigs testloc rig_bench testcache cachetest cachetest2 testcookie testgrid hamlibmodels testmW2power diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index ffcfe099c..dc322400a 100644 --- a/tests/rigctl_parse.c +++ b/tests/rigctl_parse.c @@ -3272,6 +3272,13 @@ declare_proto_rig(set_level) level = rig_parse_level(arg1); + if ((!strcmp(arg2, "?") || arg2[0]==0) && level == RIG_LEVEL_METER) + { + fprintf(fout, "COMP ALC SWR ID/IC VDD DB PO TEMP%c", resp_sep); + RETURNFUNC2(RIG_OK); + } + + // some Java apps send comma in international setups so substitute period char *p = strchr(arg2, ','); @@ -3288,6 +3295,7 @@ declare_proto_rig(set_level) RETURNFUNC2(-RIG_ENAVAIL); /* no such parameter */ } + switch (cfp->type) { case RIG_CONF_BUTTON: @@ -3315,6 +3323,23 @@ declare_proto_rig(set_level) RETURNFUNC2(rig_set_ext_level(rig, vfo, cfp->token, val)); } + int dummy; + if (level == RIG_LEVEL_METER && sscanf(arg2,"%d",&dummy)==0) + { + if (strcmp(arg2,"COMP")==0) arg2 = "2"; + else if (strcmp(arg2,"ALC")==0) arg2 = "4"; + else if (strcmp(arg2,"SWR")==0) arg2 = "1"; + else if (strcmp(arg2,"ID")==0 || strcmp(arg2,"IC")==0) arg2 = "8"; + else if (strcmp(arg2,"VDD")==0) arg2 = "64"; + else if (strcmp(arg2, "DB")==0) arg2 = "16"; + else if (strcmp(arg2, "PO")==0) arg2 = "32"; + else if (strcmp(arg2, "TEMP")==0) arg2 = "128"; + else + { + rig_debug(RIG_DEBUG_ERR, "%s: unknown meter=%s, only know COMP,ALC,SWR,ID/IC,VDD,DB,PO,TEMP\n", __func__, arg2); + RETURNFUNC2(-RIG_EINVAL); + } + } if (RIG_LEVEL_IS_FLOAT(level)) { CHKSCN1ARG(sscanf(arg2, "%f", &val.f)); @@ -3352,7 +3377,6 @@ declare_proto_rig(get_level) //fputc('\n', fout); RETURNFUNC2(RIG_OK); } - level = rig_parse_level(arg1); if (!rig_has_get_level(rig, level)) @@ -3416,6 +3440,26 @@ declare_proto_rig(get_level) { fprintf(fout, "%s: ", cmd->arg2); } + if (level == RIG_LEVEL_METER && interactive && prompt) + { + // we will show text answers as they make morse sense for rigtl + switch(val.i) + { + case RIG_METER_COMP: fprintf(fout, "%d=%s%c", val.i, "COMP", resp_sep);break; + case RIG_METER_ALC: fprintf(fout, "%d=%s%c", val.i, "ALC", resp_sep);break; + case RIG_METER_SWR: fprintf(fout, "%d=%s%c", val.i, "SWR", resp_sep);break; + case RIG_METER_IC: fprintf(fout, "%d=%s%c", val.i, "IC", resp_sep);break; + case RIG_METER_VDD: fprintf(fout, "%d=%s%c", val.i, "VDD", resp_sep);break; + case RIG_METER_DB: fprintf(fout, "%d=%s%c", val.i, "DB", resp_sep);break; + case RIG_METER_PO: fprintf(fout, "%d=%s%c", val.i, "PO", resp_sep);break; + case RIG_METER_TEMP: fprintf(fout, "%d=%s%c", val.i, "TEMP", resp_sep);break; + default: + rig_debug(RIG_DEBUG_ERR, "%s: unknown meter=%d, only know COMP,ALC,SWR,ID/IC,VDD,DB,PO,TEMP\n", __func__, val.i); + RETURNFUNC2(-RIG_EINVAL); + } + RETURNFUNC(RIG_OK); + } + if (RIG_LEVEL_IS_FLOAT(level)) { commit 1b0f0ec42201e418ebcdfa66ad0645ceed069348 Author: Mike Black W9MDB <mdb...@ya...> Date: Sat Aug 19 15:35:54 2023 -0500 Fix K3 stop_morse RPRT return https://github.com/Hamlib/Hamlib/issues/1365 diff --git a/rigs/kenwood/k3.c b/rigs/kenwood/k3.c index 9d391c148..46457e994 100644 --- a/rigs/kenwood/k3.c +++ b/rigs/kenwood/k3.c @@ -2911,6 +2911,7 @@ int k4_stop_voice_mem(RIG *rig, vfo_t vfo) int k3_stop_morse(RIG *rig, vfo_t vfo) { int retval; - retval = kenwood_transaction(rig, "KY;", NULL, 0); + char buf[32]; + retval = kenwood_transaction(rig, "KY;", buf, 4); return retval; } commit b40da0f6b0f07d19b79a0869d6fe522037dc3e5f Author: Mike Black W9MDB <mdb...@ya...> Date: Sat Aug 19 12:36:07 2023 -0500 Increase send_morse size to use maximum for rigs or 20 chars (if morse_qsize unknown) This will still allow for up to 1023 characater to queue up. No guarantees on which rigs allow for this queuing though. Kenwood rigs can at least find the buffer status to wait for room but not all rigs do. https://github.com/Hamlib/Hamlib/issues/1368 diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index 027bc92de..d49734608 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -2153,6 +2153,7 @@ struct rig_caps { int (*set_lock_mode)(RIG *rig, int mode); int (*get_lock_mode)(RIG *rig, int *mode); short timeout_retry; /*!< number of retries to make in case of read timeout errors, some serial interfaces may require this, 0 to use default value, -1 to disable */ + short morse_qsize; /* max length of morse */ // int (*bandwidth2rig)(RIG *rig, enum bandwidth_t bandwidth); // enum bandwidth_t (*rig2bandwidth)(RIG *rig, int rigbandwidth); }; diff --git a/rigs/kenwood/k3.c b/rigs/kenwood/k3.c index 6ad85abf8..9d391c148 100644 --- a/rigs/kenwood/k3.c +++ b/rigs/kenwood/k3.c @@ -342,6 +342,7 @@ const struct rig_caps k3_caps = .send_voice_mem = k3_send_voice_mem, .stop_voice_mem = k3_stop_voice_mem, .power2mW = k3_power2mW, + .morse_qsize = 24, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; @@ -497,6 +498,7 @@ const struct rig_caps k3s_caps = .send_voice_mem = k3_send_voice_mem, .stop_voice_mem = k3_stop_voice_mem, .power2mW = k3_power2mW, + .morse_qsize = 24, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; @@ -658,6 +660,7 @@ const struct rig_caps k4_caps = .send_voice_mem = k4_send_voice_mem, .stop_voice_mem = k4_stop_voice_mem, .power2mW = k3_power2mW, + .morse_qsize = 24, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; @@ -812,6 +815,7 @@ const struct rig_caps kx3_caps = .send_voice_mem = k3_send_voice_mem, .stop_voice_mem = k3_stop_voice_mem, .power2mW = k3_power2mW, + .morse_qsize = 24, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft1200.c b/rigs/yaesu/ft1200.c index 87e1f8c75..712e64aa2 100644 --- a/rigs/yaesu/ft1200.c +++ b/rigs/yaesu/ft1200.c @@ -147,7 +147,7 @@ const struct rig_caps ftdx1200_caps = RIG_MODEL(RIG_MODEL_FTDX1200), .model_name = "FTDX-1200", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".6", + .version = NEWCAT_VER ".7", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -328,5 +328,6 @@ const struct rig_caps ftdx1200_caps = .set_clock = newcat_set_clock, .get_clock = newcat_get_clock, .scan = newcat_scan, + .morse_qsize = 50, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft2000.c b/rigs/yaesu/ft2000.c index 0ebb5f94b..416b239b0 100644 --- a/rigs/yaesu/ft2000.c +++ b/rigs/yaesu/ft2000.c @@ -132,7 +132,7 @@ const struct rig_caps ft2000_caps = RIG_MODEL(RIG_MODEL_FT2000), .model_name = "FT-2000", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".4", + .version = NEWCAT_VER ".5", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -313,5 +313,6 @@ const struct rig_caps ft2000_caps = .send_morse = newcat_send_morse, .wait_morse = rig_wait_morse, .scan = newcat_scan, + .morse_qsize = 50, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft3000.c b/rigs/yaesu/ft3000.c index 20d3b7eaf..a51ae072e 100644 --- a/rigs/yaesu/ft3000.c +++ b/rigs/yaesu/ft3000.c @@ -242,7 +242,7 @@ const struct rig_caps ftdx3000_caps = RIG_MODEL(RIG_MODEL_FTDX3000), .model_name = "FTDX-3000", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".11", + .version = NEWCAT_VER ".12", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -419,6 +419,7 @@ const struct rig_caps ftdx3000_caps = .send_morse = newcat_send_morse, .wait_morse = rig_wait_morse, .scan = newcat_scan, + .morse_qsize = 50, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft450.c b/rigs/yaesu/ft450.c index e1e5d13a9..d0a7cbb34 100644 --- a/rigs/yaesu/ft450.c +++ b/rigs/yaesu/ft450.c @@ -207,6 +207,7 @@ const struct rig_caps ft450_caps = .send_morse = newcat_send_morse, .wait_morse = rig_wait_morse, .scan = newcat_scan, + .morse_qsize = 40, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft5000.c b/rigs/yaesu/ft5000.c index a15e8ab50..f1a06608f 100644 --- a/rigs/yaesu/ft5000.c +++ b/rigs/yaesu/ft5000.c @@ -138,7 +138,7 @@ const struct rig_caps ftdx5000_caps = RIG_MODEL(RIG_MODEL_FTDX5000), .model_name = "FTDX-5000", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".10", + .version = NEWCAT_VER ".11", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -315,5 +315,6 @@ const struct rig_caps ftdx5000_caps = .send_morse = newcat_send_morse, .wait_morse = rig_wait_morse, .scan = newcat_scan, + .morse_qsize = 50, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft710.c b/rigs/yaesu/ft710.c index ac0b425ec..792350806 100644 --- a/rigs/yaesu/ft710.c +++ b/rigs/yaesu/ft710.c @@ -119,7 +119,7 @@ const struct rig_caps ft710_caps = RIG_MODEL(RIG_MODEL_FT710), .model_name = "FT-710", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".6", + .version = NEWCAT_VER ".7", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -305,5 +305,6 @@ const struct rig_caps ft710_caps = .set_clock = newcat_set_clock, .get_clock = newcat_get_clock, .scan = newcat_scan, + .morse_qsize = 50, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft891.c b/rigs/yaesu/ft891.c index 817b0a8cc..9a2eabc99 100644 --- a/rigs/yaesu/ft891.c +++ b/rigs/yaesu/ft891.c @@ -130,7 +130,7 @@ const struct rig_caps ft891_caps = RIG_MODEL(RIG_MODEL_FT891), .model_name = "FT-891", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".8", + .version = NEWCAT_VER ".9", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -329,6 +329,7 @@ const struct rig_caps ft891_caps = .set_clock = newcat_set_clock, .get_clock = newcat_get_clock, .scan = newcat_scan, + .morse_qsize = 50, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft9000.c b/rigs/yaesu/ft9000.c index 795fa1b24..964bc38a6 100644 --- a/rigs/yaesu/ft9000.c +++ b/rigs/yaesu/ft9000.c @@ -46,7 +46,7 @@ const struct rig_caps ft9000_caps = RIG_MODEL(RIG_MODEL_FT9000), .model_name = "FTDX-9000", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".4", + .version = NEWCAT_VER ".5", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -214,6 +214,7 @@ const struct rig_caps ft9000_caps = .send_morse = newcat_send_morse, .wait_morse = rig_wait_morse, .scan = newcat_scan, + .morse_qsize = 50, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; @@ -222,7 +223,7 @@ const struct rig_caps ft9000Old_caps = RIG_MODEL(RIG_MODEL_FT9000OLD), .model_name = "FTDX-9000 Old", .mfg_name = "Yaesu", - .version = NEWCAT_VER ".4", + .version = NEWCAT_VER ".5", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -390,5 +391,6 @@ const struct rig_caps ft9000Old_caps = .send_morse = newcat_send_morse, .wait_morse = rig_wait_morse, .scan = newcat_scan, + .morse_qsize = 50, .hamlib_check_rig_caps = HAMLIB_CHECK_RIG_CAPS }; diff --git a/rigs/yaesu/ft950.c b/rigs/yaesu/ft950.c index d640bfe76..9802033c5 100644 --- a/rigs/yaesu/ft950.c +++ b/rigs/yaesu/ft950.c @@ -289,5 +289,6 @@ const struct rig_caps ft950_caps = .send_morse = newcat_send_morse, .wait_morse = rig_wait_morse, .scan = newcat_scan, + .morse_qsize = 50, ... [truncated message content] |