Thread: [Hamlib-developer] Icom transceive feature and poll
Library to control radio transceivers and receivers
Brought to you by:
n0nb
|
From: Chuck H. <n2...@am...> - 2002-02-27 10:38:55
|
When working on my software, I wanted to use the "transceive function" (have
radio send a ci-v frame when the dial is changed) so I could tell if someone
was turning the dial on the radio.
(One of the modes I wanted to support was the ability to have the user tune
the radio with the dial, stop when the user hears something interesting, and
then do doppler updates after that point (sort of like InstantTune))
I also was writing this as a network daemon using a poll loop and I didn't want
to use signals. I couldn't find any documentation for doing this. So after
looking through testtrn.c, and some of the other routines I came up with
something like this:
When opening the rig, set up callback for freq event:
rig->callbacks.freq_event = process_freq_event;
Add rig rig->state.rigport.fd to my list of fd's to poll.
And when I see input on that fd, I call:
void check_rig_for_input(int xkey,RIG *rig)
{
if(!rig)
return;
/*
* Do not disturb, the backend is currently receiving data
*/
if (rig->state.hold_decode)
return;
if (rig->caps->decode_event)
rig->caps->decode_event(rig);
}
int process_freq_event(RIG *xrig, vfo_t xvfo, freq_t xfreq)
{
int slot;
char message_buf[1024];
printf("Rig %p changed freq to %l Hz\n",xrig,xfreq);
...
return(0);
}
This seemed to work reasonably well, but it seemed to have a few problems:
a. It seems to me to be not as clean as it could be.
b. I'm not sure how I would handle multiple radios on the same serial/ci-v bus.
c. I'm not sure if I'm using routines that I'm not supposed be using.
d. I'm not sure if there is anywhere I can store any user data so I don't have
to do a search to find which rig this came from.
Either the ability to set something that comes back as an additional
argument to the callback routine, or a user_data pointer in RIG.
e. I'm not a big fan of callbacks (they tend to cause large numbers of global
variables) but I'll live with them if need be.
e. There doesn't seem to be any docs for it.
Since in both network (poll) based programming and gtk (callback if input
available on fd) could use an api to be able to poll the radio I was wondering
if there was a plan?
Also was wondering if someone had played with multiple radios on a CI-V bus.
Just looking at the design of the transceive feature, it looks like if you
turn it on on a radio, it wants to both send and receive the frames and
because of this if you have two radios that can tune the same frequency, then
it automatically sets the second radio to the same frequency as the first. It
looks like an interesting misfeature that you can't separately turn on and off
the send and receive parts.
Also just wondering what I want to do with radios that don't support this
feature. It looks like you would have to poll the radio every so often to
see if the frequency has changed. I was just wondering if hamlib should worry
about that, or leave that up to the calling software.
BTW When doing this, it seems that occasionally it seems that hamlib gets
confused and doesn't send out all the updates. (it seems to keep calling
the icom_decode routine but doesn't always call the callback routine. I haven't
had a chance to track this down further. I don't know if this is caused by a
collision, something getting in the wrong state, or something else.
|
|
From: Stephane F. <f4...@fr...> - 2002-02-27 23:13:03
|
On Wed, Feb 27, 2002, Chuck Hemker wrote:
> (One of the modes I wanted to support was the ability to have the user tune
> the radio with the dial, stop when the user hears something interesting, and
> then do doppler updates after that point (sort of like InstantTune))
Should be possible with Hamlib and a yet to be written user application.
> I also was writing this as a network daemon using a poll loop and I didn't want
> to use signals. I couldn't find any documentation for doing this. So after
> looking through testtrn.c, and some of the other routines I came up with
> something like this:
Do you have any reason for not using signals? Hamlib is using SIGIO, for
asynchronous event notification. Fortunately, there's no need for the user
application to know anything about signals. The freq_event just get called
when the event arrives.
> When opening the rig, set up callback for freq event:
>
> rig->callbacks.freq_event = process_freq_event;
>
> Add rig rig->state.rigport.fd to my list of fd's to poll.
>
> And when I see input on that fd, I call:
>
> void check_rig_for_input(int xkey,RIG *rig)
> {
> if(!rig)
> return;
> /*
> * Do not disturb, the backend is currently receiving data
> */
> if (rig->state.hold_decode)
> return;
>
> if (rig->caps->decode_event)
> rig->caps->decode_event(rig);
> }
Please, don't use decode_event() and state.hold_decode. These are internal
to Hamlib, and such implementation may change without notice. The
freq_event won't.
> int process_freq_event(RIG *xrig, vfo_t xvfo, freq_t xfreq)
> {
> int slot;
> char message_buf[1024];
>
> printf("Rig %p changed freq to %l Hz\n",xrig,xfreq);
>
> ...
>
> return(0);
> }
>
> This seemed to work reasonably well, but it seemed to have a few problems:
> a. It seems to me to be not as clean as it could be.
check_rig_for_input is unnecessary.
> b. I'm not sure how I would handle multiple radios on the same serial/ci-v bus.
The low-level CI-V code is not very robust. It may work. But I have only
one IC-706 to test with. This code has to be rewritten most likely.
> c. I'm not sure if I'm using routines that I'm not supposed be using.
I've create new calls for installing call backs: rig_set_freq_callback.
See testtrn for an example. To do InstantTune, you may replace the
sleep() by your doppler compensation code, and doing rig_set_freq() only
if freq_event has not been called for xx seconds (i.e. the user is not
tuning with the VFO dial any more)
> d. I'm not sure if there is anywhere I can store any user data so I don't have
> to do a search to find which rig this came from.
> Either the ability to set something that comes back as an additional
> argument to the callback routine, or a user_data pointer in RIG.
The freq_event callback already has the rig handle as a parameter, so you
can do rig_set_freq within the callback (even though it's not
recommanded to do it synchronously).
However, you're damn right, there's missing a private data pointer.
Okay, this is fixed and commited (not tested though).
Let me know if it looks better this way.
> e. I'm not a big fan of callbacks (they tend to cause large numbers of global
> variables) but I'll live with them if need be.
There's no need of global variables if you have a private data pointer.
BTW, do you know any better replacement for callback routines?
> e. There doesn't seem to be any docs for it.
Hmmm, at least there's some code :-) Yeah, I know, documentation is
sparse. To be honest, the design of Hamlib is not complete. See the
private data pointer that was missing. The event notification was more an
alpha state of a proof-of-concept. Now if you're interrested in, I can
help you implement it to a more usable state.
Patchs are welcome too :)
> Since in both network (poll) based programming and gtk (callback if input
> available on fd) could use an api to be able to poll the radio I was wondering
> if there was a plan?
Do you mean we need something like rig_get_fd() ?
Might be a good idea. This may be tricky since asynchronous event
notification get mixed with regular protocol answers.
rig_get_dcd_fd may be useful too.
> Also was wondering if someone had played with multiple radios on a CI-V bus.
> Just looking at the design of the transceive feature, it looks like if you
> turn it on on a radio, it wants to both send and receive the frames and
> because of this if you have two radios that can tune the same frequency, then
> it automatically sets the second radio to the same frequency as the first. It
> looks like an interesting misfeature that you can't separately turn on and off
> the send and receive parts.
Too bad there's not an option on the rig to select the destination
address: either 0x00 (i.e. broadcast) or 0xe0 (the controller = the PC).
And there's not easy way to do it using diodes and transistors.
The only solution I can see would involve a PIC.
> Also just wondering what I want to do with radios that don't support this
> feature. It looks like you would have to poll the radio every so often to
> see if the frequency has changed. I was just wondering if hamlib should worry
> about that, or leave that up to the calling software.
That's the reason why there's a RIG_TRN_POLL define in rig.h. However,
this feature is not implemented yet.
> BTW When doing this, it seems that occasionally it seems that hamlib gets
> confused and doesn't send out all the updates. (it seems to keep calling
> the icom_decode routine but doesn't always call the callback routine. I haven't
> had a chance to track this down further. I don't know if this is caused by a
> collision, something getting in the wrong state, or something else.
The code is not robust at all, is not asynch safe, and it can even work.
Some traces would help to debug the problem you're reporting, or maybe
just a closer look at the source code.
Cheers,
Stephane
|