/* * Hamlib Interface - toolbox * Copyright (c) 2000,2001 by Stephane Fillod and Frank Singleton * * $Id: misc.c,v 1.10 2001-12-16 11:24:17 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 #include #include /* Standard input/output definitions */ #include /* String function definitions */ #include /* UNIX standard function definitions */ #include /* File control definitions */ #include /* Error number definitions */ #include #include #include #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= ' ' && 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; }