X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fhameg-hmo%2Fprotocol.c;h=28d8412d950d739c9da5591ace10739f46d13fb9;hb=fe227d17aeda0c460367883f57c3b683fe4798a6;hp=89825b7343592a6e1e7b1388ff5c4efbaac49c88;hpb=0a1f7b09b3fa4cc4da29c7acf53717e14b004b63;p=libsigrok.git diff --git a/src/hardware/hameg-hmo/protocol.c b/src/hardware/hameg-hmo/protocol.c index 89825b73..28d8412d 100644 --- a/src/hardware/hameg-hmo/protocol.c +++ b/src/hardware/hameg-hmo/protocol.c @@ -18,6 +18,8 @@ */ #include +#include +#include #include "scpi.h" #include "protocol.h" @@ -168,6 +170,8 @@ static const uint64_t hmo_vdivs[][2] = { { 2, 1 }, { 5, 1 }, { 10, 1 }, + { 20, 1 }, + { 50, 1 }, }; static const char *scope_analog_channel_names[] = { @@ -198,7 +202,9 @@ static const char *scope_digital_channel_names[] = { static const struct scope_config scope_models[] = { { - .name = {"HMO722", "HMO1022", "HMO1522", "HMO2022", NULL}, + /* HMO2522/3032/3042/3052 support 16 digital channels but they're not supported yet. */ + .name = {"HMO722", "HMO1022", "HMO1522", "HMO2022", "HMO2522", + "HMO3032", "HMO3042", "HMO3052", NULL}, .analog_channels = 2, .digital_channels = 8, .digital_pods = 1, @@ -228,7 +234,9 @@ static const struct scope_config scope_models[] = { .scpi_dialect = &hameg_scpi_dialect, }, { - .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", NULL}, + /* HMO2524/3034/3044/3054 support 16 digital channels but they're not supported yet. */ + .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", "HMO2524", + "HMO3034", "HMO3044", "HMO3054", NULL}, .analog_channels = 4, .digital_channels = 8, .digital_pods = 1, @@ -327,13 +335,75 @@ static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi, return SR_OK; } +/** + * This function takes a value of the form "2.000E-03", converts it to a + * significand / factor pair and returns the index of an array where + * a matching pair was found. + * + * It's a bit convoluted because of floating-point issues. The value "10.00E-09" + * is parsed by g_ascii_strtod() as 0.000000009999999939, for example. + * Therefore it's easier to break the number up into two strings and handle + * them separately. + * + * @param value The string to be parsed. + * @param array The array of s/f pairs. + * @param array_len The number of pairs in the array. + * @param result The index at which a matching pair was found. + * + * @return SR_ERR on any parsing error, SR_OK otherwise. + */ +static int array_float_get(gchar *value, const uint64_t array[][2], + int array_len, unsigned int *result) +{ + int i; + uint64_t f; + float s; + unsigned int s_int; + gchar ss[10], es[10]; + + memset(ss, 0, sizeof(ss)); + memset(es, 0, sizeof(es)); + + strncpy(ss, value, 5); + strncpy(es, &(value[6]), 3); + + if (sr_atof_ascii(ss, &s) != SR_OK) + return SR_ERR; + if (sr_atoi(es, &i) != SR_OK) + return SR_ERR; + + /* Transform e.g. 10^-03 to 1000 as the array stores the inverse. */ + f = pow(10, abs(i)); + + /* + * Adjust the significand/factor pair to make sure + * that f is a multiple of 1000. + */ + while ((int)fmod(log10(f), 3) > 0) { + s *= 10; + f *= 10; + } + + /* Truncate s to circumvent rounding errors. */ + s_int = (unsigned int)s; + + for (i = 0; i < array_len; i++) { + if ((s_int == array[i][0]) && (f == array[i][1])) { + *result = i; + return SR_OK; + } + } + + return SR_ERR; +} + static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi, const struct scope_config *config, struct scope_state *state) { unsigned int i, j; - float tmp_float; char command[MAX_COMMAND_SIZE]; + char *tmp_str; for (i = 0; i < config->analog_channels; i++) { g_snprintf(command, sizeof(command), @@ -348,20 +418,19 @@ static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi, (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_DIV], i + 1); - if (sr_scpi_get_float(scpi, command, &tmp_float) != SR_OK) + if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK) return SR_ERR; - for (j = 0; j < config->num_vdivs; j++) { - if (tmp_float == ((float) (*config->vdivs)[j][0] / - (*config->vdivs)[j][1])) { - state->analog_channels[i].vdiv = j; - break; - } - } - if (j == config->num_vdivs) { + + if (array_float_get(tmp_str, hmo_vdivs, ARRAY_SIZE(hmo_vdivs), + &j) != SR_OK) { + g_free(tmp_str); sr_err("Could not determine array index for vertical div scale."); return SR_ERR; } + g_free(tmp_str); + state->analog_channels[i].vdiv = j; + g_snprintf(command, sizeof(command), (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_OFFSET], i + 1);