X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fhameg-hmo%2Fprotocol.c;h=28d8412d950d739c9da5591ace10739f46d13fb9;hb=fe227d17aeda0c460367883f57c3b683fe4798a6;hp=b865d4a516e1a72e302ce75c12af98452a23d696;hpb=5a1afc0907abfee5848484f944789213d6be9752;p=libsigrok.git diff --git a/src/hardware/hameg-hmo/protocol.c b/src/hardware/hameg-hmo/protocol.c index b865d4a5..28d8412d 100644 --- a/src/hardware/hameg-hmo/protocol.c +++ b/src/hardware/hameg-hmo/protocol.c @@ -17,6 +17,9 @@ * along with this program. If not, see . */ +#include +#include +#include #include "scpi.h" #include "protocol.h" @@ -167,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[] = { @@ -197,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, @@ -227,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, @@ -264,7 +273,7 @@ static void scope_state_dump(const struct scope_config *config, unsigned int i; char *tmp; - for (i = 0; i < config->analog_channels; ++i) { + for (i = 0; i < config->analog_channels; i++) { tmp = sr_voltage_string((*config->vdivs)[state->analog_channels[i].vdiv][0], (*config->vdivs)[state->analog_channels[i].vdiv][1]); sr_info("State of analog channel %d -> %s : %s (coupling) %s (vdiv) %2.2e (offset)", @@ -273,12 +282,12 @@ static void scope_state_dump(const struct scope_config *config, tmp, state->analog_channels[i].vertical_offset); } - for (i = 0; i < config->digital_channels; ++i) { + for (i = 0; i < config->digital_channels; i++) { sr_info("State of digital channel %d -> %s", i, state->digital_channels[i] ? "On" : "Off"); } - for (i = 0; i < config->digital_pods; ++i) { + for (i = 0; i < config->digital_pods; i++) { sr_info("State of digital POD %d -> %s", i, state->digital_pods[i] ? "On" : "Off"); } @@ -309,7 +318,7 @@ static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi, return SR_ERR; } - for (i = 0; (*array)[i]; ++i) { + for (i = 0; (*array)[i]; i++) { if (!g_strcmp0(tmp, (*array)[i])) { *result = i; g_free(tmp); @@ -326,15 +335,77 @@ 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) { + for (i = 0; i < config->analog_channels; i++) { g_snprintf(command, sizeof(command), (*config->scpi_dialect)[SCPI_CMD_GET_ANALOG_CHAN_STATE], i + 1); @@ -347,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); @@ -388,7 +458,7 @@ static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi, unsigned int i; char command[MAX_COMMAND_SIZE]; - for (i = 0; i < config->digital_channels; ++i) { + for (i = 0; i < config->digital_channels; i++) { g_snprintf(command, sizeof(command), (*config->scpi_dialect)[SCPI_CMD_GET_DIG_CHAN_STATE], i); @@ -398,7 +468,7 @@ static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi, return SR_ERR; } - for (i = 0; i < config->digital_pods; ++i) { + for (i = 0; i < config->digital_pods; i++) { g_snprintf(command, sizeof(command), (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_STATE], i + 1); @@ -429,7 +499,7 @@ SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi) state = devc->model_state; channel_found = FALSE; - for (i = 0; i < config->analog_channels; ++i) { + for (i = 0; i < config->analog_channels; i++) { if (state->analog_channels[i].state) { g_snprintf(chan_name, sizeof(chan_name), "CHAN%d", i + 1); g_snprintf(tmp_str, sizeof(tmp_str), @@ -613,7 +683,7 @@ SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi) } /* Add digital channel groups. */ - for (i = 0; i < scope_models[model_index].digital_pods; ++i) { + for (i = 0; i < scope_models[model_index].digital_pods; i++) { g_snprintf(tmp, 25, "POD%d", i); devc->digital_groups[i] = g_malloc0(sizeof(struct sr_channel_group)); @@ -648,7 +718,7 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) struct dev_context *devc; struct sr_datafeed_packet packet; GArray *data; - struct sr_datafeed_analog analog; + struct sr_datafeed_analog_old analog; struct sr_datafeed_logic logic; (void)fd; @@ -684,7 +754,7 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = 0; - packet.type = SR_DF_ANALOG; + packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; sr_session_send(cb_data, &packet); g_slist_free(analog.channels);