/** * Convert a "natural" string representation of a size value to uint64_t. * * E.g. a value of "3k" or "3 K" would be converted to 3000, a value * of "15M" would be converted to 15000000. * * Value representations other than decimal (such as hex or octal) are not * supported. Only 'k' (kilo), 'm' (mega), 'g' (giga) suffixes are supported. * Spaces (but not other whitespace) between value and suffix are allowed. * * @param sizestring A string containing a (decimal) size value. * @param size Pointer to uint64_t which will contain the string's size value. * * @return SR_OK upon success, SR_ERR upon errors. * * @since 0.1.0 */ SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size) { uint64_t multiplier; int done; double frac_part; char *s; *size = strtoull(sizestring, &s, 10); multiplier = 0; frac_part = 0; done = FALSE; while (s && *s && multiplier == 0 && !done) { switch (*s) { case ' ': break; case '.': frac_part = g_ascii_strtod(s, &s); break; case 'k': case 'K': multiplier = SR_KHZ(1); break; case 'm': case 'M': multiplier = SR_MHZ(1); break; case 'g': case 'G': multiplier = SR_GHZ(1); break; case 't': case 'T': multiplier = SR_GHZ(1000); break; case 'p': case 'P': multiplier = SR_GHZ(1000 * 1000); break; case 'e': case 'E': multiplier = SR_GHZ(1000 * 1000 * 1000); break; default: done = TRUE; s--; } s++; } if (multiplier > 0) { *size *= multiplier; *size += frac_part * multiplier; } else { *size += frac_part; } if (s && *s && g_ascii_strcasecmp(s, "Hz")) return SR_ERR; return SR_OK; }
/** * Convert a numeric value value to its "natural" string representation * in SI units. * * E.g. a value of 3000000, with units set to "W", would be converted * to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW". * * @param x The value to convert. * @param unit The unit to append to the string, or NULL if the string * has no units. * * @return A newly allocated string representation of the samplerate value, * or NULL upon errors. The caller is responsible to g_free() the * memory. * * @since 0.2.0 */ SR_API char *sr_si_string_u64(uint64_t x, const char *unit) { uint8_t i; uint64_t quot, divisor[] = { SR_HZ(1), SR_KHZ(1), SR_MHZ(1), SR_GHZ(1), SR_GHZ(1000), SR_GHZ(1000 * 1000), SR_GHZ(1000 * 1000 * 1000), }; const char *p, prefix[] = "\0kMGTPE"; char fmt[16], fract[20] = "", *f; if (!unit) unit = ""; for (i = 0; (quot = x / divisor[i]) >= 1000; i++); if (i) { sprintf(fmt, ".%%0%d"PRIu64, i * 3); f = fract + sprintf(fract, fmt, x % divisor[i]) - 1; while (f >= fract && strchr("0.", *f)) *f-- = 0; } p = prefix + i; return g_strdup_printf("%" PRIu64 "%s %.1s%s", quot, fract, p, unit); }
/** * Convert a numeric frequency value to the "natural" string representation * of its period. * * E.g. a value of 3000000 would be converted to "3 us", 20000 to "50 ms". * * @param frequency The frequency in Hz. * * @return A newly allocated string representation of the frequency value, * or NULL upon errors. The caller is responsible to g_free() the * memory. * * @since 0.1.0 */ SR_API char *sr_period_string(uint64_t frequency) { char *o; int r; /* Allocate enough for a uint64_t as string + " ms". */ o = g_malloc0(30 + 1); if (frequency >= SR_GHZ(1)) r = snprintf(o, 30, "%" PRIu64 " ns", frequency / 1000000000); else if (frequency >= SR_MHZ(1)) r = snprintf(o, 30, "%" PRIu64 " us", frequency / 1000000); else if (frequency >= SR_KHZ(1)) r = snprintf(o, 30, "%" PRIu64 " ms", frequency / 1000); else r = snprintf(o, 30, "%" PRIu64 " s", frequency); if (r < 0) { /* Something went wrong... */ g_free(o); return NULL; } return o; }
/** * Convert a numeric period value to the "natural" string representation * of its period value. * * The period is specified as a rational number's numerator and denominator. * * E.g. a pair of (1, 5) would be converted to "200 ms", (10, 100) to "100 ms". * * @param v_p The period numerator. * @param v_q The period denominator. * * @return A newly allocated string representation of the period value, * or NULL upon errors. The caller is responsible to g_free() the * memory. * * @since 0.5.0 */ SR_API char *sr_period_string(uint64_t v_p, uint64_t v_q) { double freq, v; int prec; freq = 1 / ((double)v_p / v_q); if (freq > SR_GHZ(1)) { v = (double)v_p / v_q * 1000000000000.0; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f ps", prec, v); } else if (freq > SR_MHZ(1)) { v = (double)v_p / v_q * 1000000000.0; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f ns", prec, v); } else if (freq > SR_KHZ(1)) { v = (double)v_p / v_q * 1000000.0; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f us", prec, v); } else if (freq > 1) { v = (double)v_p / v_q * 1000.0; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f ms", prec, v); } else { v = (double)v_p / v_q; prec = ((v - (uint64_t)v) < FLT_MIN) ? 0 : 3; return g_strdup_printf("%.*f s", prec, v); } }
/** * Convert a numeric value value to its "natural" string representation. * in SI units * * E.g. a value of 3000000, with units set to "W", would be converted * to "3 MW", 20000 to "20 kW", 31500 would become "31.5 kW". * * @param x The value to convert. * @param unit The unit to append to the string, or NULL if the string * has no units. * * @return A g_try_malloc()ed string representation of the samplerate value, * or NULL upon errors. The caller is responsible to g_free() the * memory. */ SR_API char *sr_si_string_u64(uint64_t x, const char *unit) { if (unit == NULL) unit = ""; if ((x >= SR_GHZ(1)) && (x % SR_GHZ(1) == 0)) { return g_strdup_printf("%" PRIu64 " G%s", x / SR_GHZ(1), unit); } else if ((x >= SR_GHZ(1)) && (x % SR_GHZ(1) != 0)) { return g_strdup_printf("%" PRIu64 ".%" PRIu64 " G%s", x / SR_GHZ(1), x % SR_GHZ(1), unit); } else if ((x >= SR_MHZ(1)) && (x % SR_MHZ(1) == 0)) { return g_strdup_printf("%" PRIu64 " M%s", x / SR_MHZ(1), unit); } else if ((x >= SR_MHZ(1)) && (x % SR_MHZ(1) != 0)) { return g_strdup_printf("%" PRIu64 ".%" PRIu64 " M%s", x / SR_MHZ(1), x % SR_MHZ(1), unit); } else if ((x >= SR_KHZ(1)) && (x % SR_KHZ(1) == 0)) { return g_strdup_printf("%" PRIu64 " k%s", x / SR_KHZ(1), unit); } else if ((x >= SR_KHZ(1)) && (x % SR_KHZ(1) != 0)) { return g_strdup_printf("%" PRIu64 ".%" PRIu64 " K%s", x / SR_KHZ(1), x % SR_KHZ(1), unit); } else { return g_strdup_printf("%" PRIu64 " %s", x, unit); } sr_err("%s: Error creating SI units string.", __func__); return NULL; }
/** * Convert a "natural" string representation of a size value to uint64_t. * * E.g. a value of "3k" or "3 K" would be converted to 3000, a value * of "15M" would be converted to 15000000. * * Value representations other than decimal (such as hex or octal) are not * supported. Only 'k' (kilo), 'm' (mega), 'g' (giga) suffixes are supported. * Spaces (but not other whitespace) between value and suffix are allowed. * * @param sizestring A string containing a (decimal) size value. * @param size Pointer to uint64_t which will contain the string's size value. * * @return SR_OK upon success, SR_ERR upon errors. */ SR_API int sr_parse_sizestring(const char *sizestring, uint64_t *size) { int multiplier, done; char *s; *size = strtoull(sizestring, &s, 10); multiplier = 0; done = FALSE; while (s && *s && multiplier == 0 && !done) { switch (*s) { case ' ': break; case 'k': case 'K': multiplier = SR_KHZ(1); break; case 'm': case 'M': multiplier = SR_MHZ(1); break; case 'g': case 'G': multiplier = SR_GHZ(1); break; default: done = TRUE; s--; } s++; } if (multiplier > 0) *size *= multiplier; if (*s && strcasecmp(s, "Hz")) return SR_ERR; return SR_OK; }
static const int devopts[] = { SR_CONF_LOGIC_ANALYZER, SR_CONF_DEMO_DEV, SR_CONF_SAMPLERATE, SR_CONF_LIMIT_SAMPLES, SR_CONF_LIMIT_MSEC, }; static const int devopts_cg[] = { SR_CONF_PATTERN_MODE, }; static const uint64_t samplerates[] = { SR_HZ(1), SR_GHZ(1), SR_HZ(1), }; static uint8_t pattern_sigrok[] = { 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00, 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00, 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00, 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; SR_PRIV struct sr_dev_driver demo_driver_info;
END_TEST START_TEST(test_ghz) { /* Note: Numbers > 2^32 need a ULL suffix. */ test_samplerate(1000000000, "1 GHz"); test_samplerate(5000000000ULL, "5 GHz"); test_samplerate(72000000000ULL, "72 GHz"); test_samplerate(388000000000ULL, "388 GHz"); test_samplerate(4417594444ULL, "4.417594444 GHz"); test_samplerate(44175944444ULL, "44.175944444 GHz"); test_samplerate(441759444441ULL, "441.759444441 GHz"); test_samplerate(441759000001ULL, "441.759000001 GHz"); test_samplerate(441050000000ULL, "441.05 GHz"); test_samplerate(441000000005ULL, "441.000000005 GHz"); test_samplerate(441500000000ULL, "441.5 GHz"); /* Again, but now using SR_GHZ(). */ test_samplerate(SR_GHZ(1), "1 GHz"); test_samplerate(SR_GHZ(5), "5 GHz"); test_samplerate(SR_GHZ(72), "72 GHz"); test_samplerate(SR_GHZ(388), "388 GHz"); test_samplerate(SR_GHZ(4.417594444), "4.417594444 GHz"); test_samplerate(SR_GHZ(44.175944444), "44.175944444 GHz"); test_samplerate(SR_GHZ(441.759444441), "441.759444441 GHz"); test_samplerate(SR_GHZ(441.759000001), "441.759000001 GHz"); test_samplerate(SR_GHZ(441.050000000), "441.05 GHz"); test_samplerate(SR_GHZ(441.000000005), "441.000000005 GHz"); test_samplerate(SR_GHZ(441.500000000), "441.5 GHz"); /* Now check the biggest-possible samplerate (2^64 Hz). */ // test_samplerate(18446744073709551615ULL, "18446744073.709551615 GHz"); // test_samplerate(SR_GHZ(18446744073ULL), "18446744073 GHz"); }