Hamlib/src/misc.c

378 wiersze
8.3 KiB
C
Czysty Zwykły widok Historia

/*
* Hamlib Interface - toolbox
* Copyright (c) 2000,2001 by Stephane Fillod and Frank Singleton
*
* $Id: misc.c,v 1.11 2001-12-20 07:48:38 fillods Exp $
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <sys/types.h>
#include <unistd.h>
#include <hamlib/rig.h>
#include "misc.h"
static int rig_debug_level = RIG_DEBUG_TRACE;
/*
* Do a hex dump of the unsigned char array.
*/
#define DUMP_HEX_WIDTH 16
void dump_hex(const unsigned char ptr[], size_t size)
{
int i;
char buf[DUMP_HEX_WIDTH+1];
if (!rig_need_debug(RIG_DEBUG_TRACE))
return;
buf[DUMP_HEX_WIDTH] = '\0';
for(i=0; i<size; i++) {
if (i % DUMP_HEX_WIDTH == 0)
rig_debug(RIG_DEBUG_TRACE,"%.4x\t",i);
rig_debug(RIG_DEBUG_TRACE," %.2x", ptr[i]);
if (ptr[i] >= ' ' && ptr[i] < 0x7f)
buf[i%DUMP_HEX_WIDTH] = ptr[i];
else
buf[i%DUMP_HEX_WIDTH] = '.';
if (i % DUMP_HEX_WIDTH == DUMP_HEX_WIDTH-1)
rig_debug(RIG_DEBUG_TRACE,"\t%s\n",buf);
}
/*
* add some spaces in this case in order to align right ASCII dump column
*/
if (i % DUMP_HEX_WIDTH != DUMP_HEX_WIDTH-1) {
buf[i % DUMP_HEX_WIDTH] = '\0';
rig_debug(RIG_DEBUG_TRACE,"\t%s\n",buf);
}
}
/*
* Convert a long long (eg. frequency in Hz) to 4-bit BCD digits,
* packed two digits per octet, in little-endian order.
* bcd_len is the number of BCD digits, usually 10 or 8 in 1-Hz units,
* and 6 digits in 100-Hz units for Tx offset data.
*
* Hope the compiler will do a good job optimizing it (esp. w/ the 64bit freq)
*/
unsigned char *
to_bcd(unsigned char bcd_data[], unsigned long long freq, int bcd_len)
{
int i;
unsigned char a;
/* '450'-> 0,5;4,0 */
for (i=0; i < bcd_len/2; i++) {
a = freq%10;
freq /= 10;
a |= (freq%10)<<4;
freq /= 10;
bcd_data[i] = a;
}
if (bcd_len&1) {
bcd_data[i] &= 0xf0;
bcd_data[i] |= freq%10; /* NB: high nibble is left uncleared */
}
return bcd_data;
}
/*
* Convert BCD digits to a long long (eg. frequency in Hz)
* bcd_len is the number of BCD digits.
*
* Hope the compiler will do a good job optimizing it (esp. w/ the 64bit freq)
*/
unsigned long long from_bcd(const unsigned char bcd_data[], int bcd_len)
{
int i;
freq_t f = 0;
if (bcd_len&1)
f = bcd_data[bcd_len/2] & 0x0f;
for (i=(bcd_len/2)-1; i >= 0; i--) {
f *= 10;
f += bcd_data[i]>>4;
f *= 10;
f += bcd_data[i] & 0x0f;
}
return f;
}
/*
* Same as to_bcd, but in Big Endian mode
*/
unsigned char *
to_bcd_be(unsigned char bcd_data[], unsigned long long freq, int bcd_len)
{
int i;
unsigned char a;
/* '450'-> 0,4;5,0 */
for (i=(bcd_len/2)-1; i >= 0; i--) {
a = freq%10;
freq /= 10;
a |= (freq%10)<<4;
freq /= 10;
bcd_data[i] = a;
}
if (bcd_len&1) {
bcd_data[0] &= 0xf0;
bcd_data[0] |= freq%10; /* NB: high nibble is left uncleared */
}
return bcd_data;
}
/*
* Same as from_bcd, but in Big Endian mode
*/
unsigned long long from_bcd_be(const unsigned char bcd_data[], int bcd_len)
{
int i;
freq_t f = 0;
if (bcd_len&1)
f = bcd_data[0] & 0x0f;
for (i=bcd_len&1; i < (bcd_len+1)/2; i++) {
f *= 10;
f += bcd_data[i]>>4;
f *= 10;
f += bcd_data[i] & 0x0f;
}
return f;
}
/*
* rig_set_debug
* Change the current debug level
*/
void rig_set_debug(enum rig_debug_level_e debug_level)
{
rig_debug_level = debug_level;
}
/*
* rig_need_debug
* Usefull for dump_hex, etc.
*/
int rig_need_debug(enum rig_debug_level_e debug_level)
{
return (debug_level <= rig_debug_level);
}
/*
* rig_debug
* Debugging messages are done through stderr
* TODO: add syslog support if needed
*/
void rig_debug(enum rig_debug_level_e debug_level, const char *fmt, ...)
{
va_list ap;
if (debug_level <= rig_debug_level) {
va_start(ap, fmt);
/*
* Who cares about return code?
*/
vfprintf (stderr, fmt, ap);
va_end(ap);
}
}
#define llabs(a) ((a)<0?-(a):(a))
/*
* rig_freq_snprintf
* pretty print frequencies
* str must be long enough. max can be as long as 17 chars
*/
int freq_sprintf(char *str, freq_t freq)
{
double f;
char *hz;
if (llabs(freq) >= GHz(1)) {
hz = "GHz";
f = (double)freq/GHz(1);
} else if (llabs(freq) >= MHz(1)) {
hz = "MHz";
f = (double)freq/MHz(1);
} else if (llabs(freq) >= kHz(1)) {
hz = "kHz";
f = (double)freq/kHz(1);
} else {
hz = "Hz";
f = (double)freq;
}
return sprintf (str, "%g%s", f, hz);
}
const char * strmode(rmode_t mode)
{
switch (mode) {
case RIG_MODE_AM: return "AM";
case RIG_MODE_CW: return "CW";
case RIG_MODE_USB: return "USB";
case RIG_MODE_LSB: return "LSB";
case RIG_MODE_RTTY: return "RTTY";
case RIG_MODE_FM: return "FM";
case RIG_MODE_WFM: return "WFM";
case RIG_MODE_NONE: return "None";
default:
}
return NULL;
}
const char *strvfo(vfo_t vfo)
{
switch (vfo) {
case RIG_VFO_A:
return "VFOA";
case RIG_VFO_B:
return "VFOB";
case RIG_VFO_C:
return "VFOC";
case RIG_VFO_CURR:
return "currVFO";
case RIG_VFO_ALL:
return "VFOall";
case RIG_VFO_MEM:
return "MEM";
case RIG_VFO_VFO:
return "VFO";
case RIG_VFO_MAIN:
return "Main";
case RIG_VFO_SUB:
return "Sub";
}
return NULL;
}
const char *strfunc(setting_t func)
{
switch (func) {
case RIG_FUNC_FAGC: return "FAGC";
case RIG_FUNC_NB: return "NB";
case RIG_FUNC_COMP: return "COMP";
case RIG_FUNC_VOX: return "VOX";
case RIG_FUNC_TONE: return "TONE";
case RIG_FUNC_TSQL: return "TSQL";
case RIG_FUNC_SBKIN: return "SBKIN";
case RIG_FUNC_FBKIN: return "FBKIN";
case RIG_FUNC_ANF: return "ANF";
case RIG_FUNC_NR: return "NR";
case RIG_FUNC_AIP: return "AIP";
case RIG_FUNC_APF: return "APF";
case RIG_FUNC_MON: return "MON";
case RIG_FUNC_MN: return "MN";
case RIG_FUNC_RNF: return "RNF";
case RIG_FUNC_NONE: return "None";
default:
}
return NULL;
}
const char *strlevel(setting_t level)
{
switch (level) {
case RIG_LEVEL_PREAMP: return "PREAMP";
case RIG_LEVEL_ATT: return "ATT";
case RIG_LEVEL_AF: return "AF";
case RIG_LEVEL_RF: return "RF";
case RIG_LEVEL_SQL: return "SQL";
case RIG_LEVEL_IF: return "IF";
case RIG_LEVEL_APF: return "APF";
case RIG_LEVEL_NR: return "NR";
case RIG_LEVEL_PBT_IN: return "PBT_IN";
case RIG_LEVEL_PBT_OUT: return "PBT_OUT";
case RIG_LEVEL_CWPITCH: return "CWPITCH";
case RIG_LEVEL_RFPOWER: return "RFPOWER";
case RIG_LEVEL_MICGAIN: return "MICGAIN";
case RIG_LEVEL_KEYSPD: return "KEYSPD";
case RIG_LEVEL_NOTCHF: return "NOTCHF";
case RIG_LEVEL_COMP: return "COMP";
case RIG_LEVEL_AGC: return "AGC";
case RIG_LEVEL_BKINDL: return "BKINDL";
case RIG_LEVEL_BALANCE: return "BALANCE";
case RIG_LEVEL_SWR: return "SWR";
case RIG_LEVEL_ALC: return "ALC";
case RIG_LEVEL_SQLSTAT: return "SQLSTAT";
case RIG_LEVEL_STRENGTH: return "STRENGTH";
case RIG_LEVEL_NONE: return "None";
default:
}
return NULL;
}
const char *strparm(setting_t parm)
{
switch (parm) {
case RIG_PARM_ANN: return "ANN";
case RIG_PARM_APO: return "APO";
case RIG_PARM_BACKLIGHT: return "BACKLIGHT";
case RIG_PARM_BEEP: return "BEEP";
case RIG_PARM_TIME: return "TIME";
case RIG_PARM_BAT: return "BAT";
case RIG_PARM_NONE: return "None";
default:
}
return NULL;
}
const char *strptrshift(rptr_shift_t shift)
{
switch (shift) {
case RIG_RPT_SHIFT_MINUS: return "+";
case RIG_RPT_SHIFT_PLUS: return "-";
case RIG_RPT_SHIFT_NONE: return "None";
default:
}
return NULL;
}