/* * Hamlib Interface - toolbox * Copyright (c) 2000-2003 by Stephane Fillod and Frank Singleton * * $Id: misc.c,v 1.27 2003-08-17 22:39:07 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 order to align right ASCII dump column */ if ((i / DUMP_HEX_WIDTH) > 0) { int j; for (j = i % DUMP_HEX_WIDTH; j < DUMP_HEX_WIDTH; j++) rig_debug(RIG_DEBUG_TRACE," "); } 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, unsigned bcd_len) { int i; unsigned char a; /* '450'/4-> 5,0;0,4 */ /* '450'/3-> 5,0;x,4 */ 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[], unsigned 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, unsigned bcd_len) { int i; unsigned char a; /* '450'/4 -> 0,4;5,0 */ /* '450'/3 -> 4,5;0,x */ if (bcd_len&1) { bcd_data[bcd_len/2] &= 0x0f; bcd_data[bcd_len/2] |= (freq%10)<<4; /* NB: low nibble is left uncleared */ freq /= 10; } for (i=(bcd_len/2)-1; i >= 0; i--) { a = freq%10; freq /= 10; a |= (freq%10)<<4; freq /= 10; bcd_data[i] = a; } return bcd_data; } /* * Same as from_bcd, but in Big Endian mode */ unsigned long long from_bcd_be(const unsigned char bcd_data[], unsigned bcd_len) { int i; freq_t f = 0; for (i=0; i < bcd_len/2; i++) { f *= 10; f += bcd_data[i]>>4; f *= 10; f += bcd_data[i] & 0x0f; } if (bcd_len&1) { f *= 10; f += bcd_data[bcd_len/2]>>4; } 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); } } #ifndef llabs #define llabs(a) ((a)<0?-(a):(a)) #endif /* * rig_freq_snprintf? * pretty print frequencies * str must be long enough. max can be as long as 17 chars */ int sprintf_freq(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 *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"; } return NULL; } const char *strstatus(enum rig_status_e status) { switch (status) { case RIG_STATUS_ALPHA: return "Alpha"; case RIG_STATUS_UNTESTED: return "Untested"; case RIG_STATUS_BETA: return "Beta"; case RIG_STATUS_STABLE: return "Stable"; case RIG_STATUS_BUGGY: return "Buggy"; case RIG_STATUS_NEW: return "New"; } return ""; } int sprintf_mode(char *str, rmode_t mode) { int i, len=0; *str = '\0'; if (mode == RIG_MODE_NONE) return 0; for (i = 0; i < 30; i++) { const char *ms = strrmode(mode & (1UL<