2002-06-29 08:38:21 +00:00
|
|
|
/*
|
|
|
|
* ts2k_menu.c (C) Copyright 2002 by Dale E. Edmons. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* License: GNU
|
|
|
|
*/
|
|
|
|
|
2002-06-30 10:17:03 +00:00
|
|
|
/*
|
|
|
|
* status: Never been compiled!
|
|
|
|
*/
|
|
|
|
|
2002-06-29 08:38:21 +00:00
|
|
|
/*
|
|
|
|
* Functions to initialize, read, set, and list menus
|
|
|
|
* for the TS-2000. These functions will be added to
|
|
|
|
* src/rig.c as rig_*menu_*() as time permits.
|
|
|
|
*
|
|
|
|
* This is likely a can of worms nobody has wanted to
|
|
|
|
* deal with--until now. The ts2k is especially a
|
|
|
|
* pain as you'll soon seen (but cool nonetheless.)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <rig.h>
|
|
|
|
#include "ts2k.h"
|
|
|
|
#include "ts2k_menu.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the menu number(s) and terminate with ";" (not ';')
|
|
|
|
*/
|
|
|
|
int ts2k_set_menu_no(RIG *rig, ts2k_menu_t *menu, int main, int sub)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
menu->menu_no[0] = main;
|
|
|
|
menu->menu_no[1] = sub;
|
|
|
|
menu->menu_no[2] = menu->menu_no[3] = 0;
|
|
|
|
|
|
|
|
i = sprintf( &menu->cmd[0], "ex%03u%02u%01u%01u;", main, sub, 0, 0);
|
|
|
|
|
|
|
|
if(i != 10)
|
|
|
|
return -RIG_EINVAL;
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the menu number(s) from cmd[]
|
|
|
|
*/
|
|
|
|
int ts2k_get_menu_no(RIG *rig, ts2k_menu_t *menu, int *main, int *sub)
|
|
|
|
{
|
|
|
|
char tmp[30];
|
|
|
|
int m, s;
|
|
|
|
|
|
|
|
if(menu==NULL)
|
|
|
|
return -RIG_EINVAL;
|
|
|
|
|
|
|
|
m = int_n(tmp, &menu->cmd[2], 3);
|
|
|
|
s = int_n(tmp, &menu->cmd[7], 2);
|
|
|
|
|
|
|
|
menu->menu_no[0] = m;
|
|
|
|
menu->menu_no[1] = s;
|
|
|
|
menu->menu_no[2] = menu->menu_no[3] = 0;
|
|
|
|
|
|
|
|
if(main != NULL)
|
|
|
|
*main = m;
|
|
|
|
if(sub != NULL)
|
|
|
|
*sub = s;
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When called by ts2k_pm_init we read all of
|
|
|
|
* the rig's current menu options and set them
|
|
|
|
* in the current menu array. We don't do the
|
|
|
|
* memory allocation so you can init as many
|
|
|
|
* as you want. The reason for this is huge.
|
|
|
|
* First, after full reset the rig can access
|
|
|
|
* menuA or menuB and different values retained.
|
|
|
|
* Second, by sending "pm...;" we can select
|
|
|
|
* Programmable Memory 0-5, with 0 being the
|
|
|
|
* the default. Amazingly, each PM seems to
|
|
|
|
* have its own menuA and menuB. Thus, all
|
|
|
|
* told, we have up to twelve distinct menus
|
|
|
|
* each with (potentially) unique values. We
|
|
|
|
* do the allocation in the PM routines and
|
|
|
|
* leave this one much simpler and just call
|
|
|
|
* it up to twelve times with uniq ts2k_menu_t
|
|
|
|
* pointers. Third, the user may wish to use
|
|
|
|
* this to obtain a private copy for local use
|
|
|
|
* and only has to call this routine to make
|
|
|
|
* sure its current. (A ts2k_pm_t should be
|
|
|
|
* allocated as well!)
|
|
|
|
*/
|
|
|
|
int ts2k_menu_init(RIG *rig, ts2k_menu_t *menu[])
|
|
|
|
{
|
|
|
|
int retval, i;
|
|
|
|
ts2k_menu_t *m, *mref;
|
|
|
|
|
|
|
|
if(menu == NULL || menu == ts2k_menus) {
|
|
|
|
rig_debug(rig, __FUNCTION__": invalid menu pointer\n");
|
|
|
|
return -RIG_EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// One set of defaults has been globally defined (mref)
|
|
|
|
for(i=0, i<(sizeof(menu)/sizeof(ts2k_menu_t)); i++) {
|
|
|
|
m = menu[i];
|
|
|
|
mref = ts2k_menus[i];
|
|
|
|
retval = ts2k_set_menu_no(rig, m, mref->menu[0], mref->menu[1]);
|
|
|
|
if(retval != RIG_OK)
|
|
|
|
return retval;
|
|
|
|
retval = ts2k_get_menu(rig, m);
|
|
|
|
if(retval != RIG_OK)
|
|
|
|
return retval;
|
|
|
|
// FIXME: set some debug traces here?
|
|
|
|
}
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* read the rig and get the parameters for menu[n].
|
|
|
|
* convert them to a ts2k_menu_t, and eventually to
|
|
|
|
* a rig_menu_t. I do a lot of checking to ensure
|
|
|
|
* nothing breaks (hi!).
|
|
|
|
*/
|
|
|
|
int ts2k_get_menu(RIG *rig, ts2k_menu_t *menu, )
|
|
|
|
{
|
|
|
|
int retval, i, j, k, acklen;
|
|
|
|
char ack[30];
|
|
|
|
|
|
|
|
if(menu == NULL)
|
|
|
|
return -RIG_EINVAL;
|
|
|
|
else if( (toupper(menu->cmd[0]) != 'E')
|
|
|
|
|| (toupper(menu->cmd[1]) != 'X') )
|
|
|
|
return -RIG_EINVAL;
|
|
|
|
else if(menu->cmd[9] != ';')
|
|
|
|
retval = -RIG_EINVAL;
|
|
|
|
|
|
|
|
retval = ts2k_transaction(rig, menu->cmd, 10, ack, &acklen);
|
|
|
|
if(retval != RIG_OK)
|
|
|
|
return retval;
|
|
|
|
|
|
|
|
strncpy(menu->cmd, ack, 30);
|
|
|
|
retval = ts2k_menu_parse(rig, menu);
|
|
|
|
if(retval != RIG_OK)
|
|
|
|
return retval;
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Here, I expect everything to be setup for me.
|
|
|
|
* All we do is determe the value and param_txt
|
|
|
|
* for the menu item we are given.
|
|
|
|
*
|
|
|
|
* status: real ugly!
|
|
|
|
*/
|
|
|
|
int ts2k_menu_parse(RIG *rig, ts2k_menu_t *menu)
|
|
|
|
{
|
|
|
|
ts2k_menu_t *mref, *m;
|
|
|
|
char *vptr;
|
|
|
|
int on_off[] = { 01, 03, 04, 05, 07, 09, 17, 18, 23, 25, 26,
|
|
|
|
27, 30, 34, 35, 36, 37, 43, 44, 52, 53, 63, 54, 55,
|
|
|
|
-1},
|
|
|
|
zero2nine = {
|
|
|
|
|
|
|
|
m = menu; // to lazy to spell menu-> all the time
|
|
|
|
|
|
|
|
if(m->cmd[0] == '\0' || m->cmd[1] == '\0')
|
|
|
|
return -RIG_EINVAL; // Caller has blown it!
|
|
|
|
|
|
|
|
// find matching refence menu
|
|
|
|
i=0;
|
|
|
|
do {
|
|
|
|
mref = ts2k_menus[i];
|
|
|
|
if(mref == NULL) // Either Caller or I blew it!
|
|
|
|
return -RIG_EINTERNAL;
|
|
|
|
if(mref->menu_no[i] == NULL)
|
|
|
|
return -RIG_EINVAL; // It has to match one!
|
|
|
|
if(menu == ts2k_menus[i]) // Nobody changes our REF!
|
|
|
|
return -RIG_EINTERNAL;
|
|
|
|
|
|
|
|
if(mref->menu[0] == m->menu[0])
|
|
|
|
&& mref->menu[1] == m->menu[1]
|
|
|
|
&& mref->menu[2] == m->menu[2]
|
|
|
|
/*&& mref->menu[3] == m->menu[3]*/) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (++i)
|
|
|
|
|
|
|
|
/* Match the main menu and only look for sub-menus later */
|
|
|
|
|
|
|
|
// check for menus that are simple on/off first
|
|
|
|
// FIXME: this isn't fast, it just eliminates alot of cases!
|
|
|
|
for(i=0; on_off == -1; i++) {
|
|
|
|
if(m->menu[0] == m->menu[0]) {
|
|
|
|
m->val = m->cmd[9] - '0';
|
|
|
|
m->param_txt = (m->val == 1)? m_on : m_off;
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use mref to do all we can
|
|
|
|
retval = -RIG_EINTERNAL;
|
|
|
|
for(i=0; mref->param_txt != NULL; i++) {
|
|
|
|
if(retval == RIG_OK) {
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
switch( mref->param_txt[i] ) {
|
|
|
|
case m_tbd: // menu item under development!
|
|
|
|
m->param_txt = m_tbd;
|
|
|
|
vptr = malloc( 17 );
|
|
|
|
if(vptr == NULL)
|
|
|
|
return -RIG_NOMEM;
|
|
|
|
|
|
|
|
for(j=0; vptr[i] != ';' && i<17; i++) {
|
|
|
|
vptr[i] == m->cmd[i];
|
|
|
|
}
|
|
|
|
vptr[i] = '\0';
|
|
|
|
return -RIG_NIMPL;
|
|
|
|
|
|
|
|
case m_off:
|
|
|
|
if(m->cmd[9] == '0') {
|
|
|
|
m->param_txt = mref->param_txt[i];
|
|
|
|
m->val = 0;
|
|
|
|
retval = RIG_OK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case m_num:
|
|
|
|
default:
|
|
|
|
return -RIG_NIMPL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch( m->menu[0] ) {
|
|
|
|
|
|
|
|
case 00:
|
|
|
|
case 00:
|
|
|
|
case 00:
|
|
|
|
case 00:
|
|
|
|
case 00:
|
|
|
|
case 00:
|
|
|
|
case 00:
|
|
|
|
case 00:
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -RIG_EINTERNAL; // I'm requiring 100% match
|
|
|
|
}
|
|
|
|
|
|
|
|
return RIG_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// End of ts2k_menu.c
|