diff --git a/hardware/cem-dt-885x/api.c b/hardware/cem-dt-885x/api.c index 64055914..fb309fe2 100644 --- a/hardware/cem-dt-885x/api.c +++ b/hardware/cem-dt-885x/api.c @@ -37,6 +37,7 @@ static const int32_t hwcaps[] = { SR_CONF_SPL_WEIGHT_TIME, SR_CONF_HOLD_MAX, SR_CONF_HOLD_MIN, + SR_CONF_SPL_MEASUREMENT_RANGE, }; static const char *weight_freq[] = { @@ -49,6 +50,13 @@ static const char *weight_time[] = { "S", }; +static const uint64_t meas_ranges[][2] = { + { 30, 130 }, + { 30, 80 }, + { 50, 100 }, + { 80, 130 }, +}; + SR_PRIV struct sr_dev_driver cem_dt_885x_driver_info; static struct sr_dev_driver *di = &cem_dt_885x_driver_info; @@ -102,6 +110,7 @@ static GSList *scan(GSList *options) } devc->cur_mqflags = 0; devc->recording = -1; + devc->cur_meas_range = 0; if (!(sdi->conn = sr_serial_dev_inst_new(conn, SERIALCOMM))) return NULL; @@ -173,6 +182,8 @@ static int cleanup(void) static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi) { struct dev_context *devc; + GVariant *range[2]; + uint64_t low, high; int tmp, ret; if (!sdi) @@ -214,6 +225,13 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi) if ((ret = cem_dt_885x_holdmode_get(sdi, &tmp)) == SR_OK) *data = g_variant_new_boolean(tmp == SR_MQFLAG_MIN); break; + case SR_CONF_SPL_MEASUREMENT_RANGE: + if ((ret = cem_dt_885x_meas_range_get(sdi, &low, &high)) == SR_OK) { + range[0] = g_variant_new_uint64(low); + range[1] = g_variant_new_uint64(high); + *data = g_variant_new_tuple(range, 2); + } + break; default: return SR_ERR_NA; } @@ -224,7 +242,8 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi) static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi) { struct dev_context *devc; - uint64_t tmp_u64; + uint64_t tmp_u64, low, high; + unsigned int i; int tmp, ret; const char *tmp_str; @@ -276,6 +295,16 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi) tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MIN : 0; ret = cem_dt_885x_holdmode_set(sdi, tmp); break; + case SR_CONF_SPL_MEASUREMENT_RANGE: + g_variant_get(data, "(tt)", &low, &high); + ret = SR_ERR_ARG; + for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) { + if (meas_ranges[i][0] == low && meas_ranges[i][1] == high) { + ret = cem_dt_885x_meas_range_set(sdi, low, high); + break; + } + } + break; default: ret = SR_ERR_NA; } @@ -285,6 +314,9 @@ static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi) static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi) { + GVariant *tuple, *range[2]; + GVariantBuilder gvb; + unsigned int i; int ret; (void)sdi; @@ -305,6 +337,16 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi) case SR_CONF_SPL_WEIGHT_TIME: *data = g_variant_new_strv(weight_time, ARRAY_SIZE(weight_time)); break; + case SR_CONF_SPL_MEASUREMENT_RANGE: + g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); + for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) { + range[0] = g_variant_new_uint64(meas_ranges[i][0]); + range[1] = g_variant_new_uint64(meas_ranges[i][1]); + tuple = g_variant_new_tuple(range, 2); + g_variant_builder_add_value(&gvb, tuple); + } + *data = g_variant_builder_end(&gvb); + break; default: return SR_ERR_NA; } diff --git a/hardware/cem-dt-885x/protocol.c b/hardware/cem-dt-885x/protocol.c index 33fe1405..3ae43a70 100644 --- a/hardware/cem-dt-885x/protocol.c +++ b/hardware/cem-dt-885x/protocol.c @@ -152,6 +152,12 @@ static void process_mset(const struct sr_dev_inst *sdi) case TOKEN_RECORDING_OFF: devc->recording = FALSE; break; + case TOKEN_MEAS_RANGE_30_80: + case TOKEN_MEAS_RANGE_30_130: + case TOKEN_MEAS_RANGE_50_100: + case TOKEN_MEAS_RANGE_80_130: + devc->cur_meas_range = devc->token; + break; case TOKEN_TIME: case TOKEN_STORE_OK: case TOKEN_STORE_FULL: @@ -160,10 +166,6 @@ static void process_mset(const struct sr_dev_inst *sdi) case TOKEN_MEAS_RANGE_OK: case TOKEN_MEAS_RANGE_OVER: case TOKEN_MEAS_RANGE_UNDER: - case TOKEN_MEAS_RANGE_30_80: - case TOKEN_MEAS_RANGE_30_130: - case TOKEN_MEAS_RANGE_50_100: - case TOKEN_MEAS_RANGE_80_130: /* Not useful, or not expressable in sigrok. */ break; } @@ -594,3 +596,92 @@ SR_PRIV int cem_dt_885x_holdmode_set(const struct sr_dev_inst *sdi, int holdmode return ret; } + +SR_PRIV int cem_dt_885x_meas_range_get(const struct sr_dev_inst *sdi, + uint64_t *low, uint64_t *high) +{ + struct dev_context *devc; + char tokens[5]; + + devc = sdi->priv; + if (devc->cur_meas_range == 0) { + tokens[0] = TOKEN_MEAS_RANGE_30_130; + tokens[1] = TOKEN_MEAS_RANGE_30_80; + tokens[2] = TOKEN_MEAS_RANGE_50_100; + tokens[3] = TOKEN_MEAS_RANGE_80_130; + tokens[4] = -1; + if (wait_for_token(sdi, tokens, 0) != SR_OK) + return SR_ERR; + devc->cur_meas_range = devc->token; + } + + switch (devc->cur_meas_range) { + case TOKEN_MEAS_RANGE_30_130: + *low = 30; + *high = 130; + break; + case TOKEN_MEAS_RANGE_30_80: + *low = 30; + *high = 80; + break; + case TOKEN_MEAS_RANGE_50_100: + *low = 50; + *high = 100; + break; + case TOKEN_MEAS_RANGE_80_130: + *low = 80; + *high = 130; + break; + default: + return SR_ERR; + } + + return SR_OK; +} + +SR_PRIV int cem_dt_885x_meas_range_set(const struct sr_dev_inst *sdi, + uint64_t low, uint64_t high) +{ + struct dev_context *devc; + int ret; + char token, tokens[6]; + + devc = sdi->priv; + if (low == 30 && high == 130) + token = TOKEN_MEAS_RANGE_30_130; + else if (low == 30 && high == 80) + token = TOKEN_MEAS_RANGE_30_80; + else if (low == 50 && high == 100) + token = TOKEN_MEAS_RANGE_50_100; + else if (low == 80 && high == 130) + token = TOKEN_MEAS_RANGE_80_130; + else + return SR_ERR; + + sr_dbg("want 0x%.2x", token); + /* The toggle below needs the desired state in first position. */ + tokens[0] = token; + tokens[1] = TOKEN_MEAS_RANGE_30_130; + tokens[2] = TOKEN_MEAS_RANGE_30_80; + tokens[3] = TOKEN_MEAS_RANGE_50_100; + tokens[4] = TOKEN_MEAS_RANGE_80_130; + tokens[5] = -1; + + if (devc->cur_meas_range == 0) { + /* 110ms should be enough for two of these announcements */ + if (wait_for_token(sdi, tokens, 110) != SR_OK) + return SR_ERR; + devc->cur_meas_range = devc->token; + } + + if (devc->cur_meas_range == token) + /* Already set to this range. */ + return SR_OK; + + /* For measurement range, it works best to ignore announcements of the + * current setting and keep resending the toggle quickly. */ + tokens[1] = -1; + ret = cem_dt_885x_toggle(sdi, CMD_TOGGLE_MEAS_RANGE, tokens, 11); + + return ret; +} diff --git a/hardware/cem-dt-885x/protocol.h b/hardware/cem-dt-885x/protocol.h index a7d6203b..59106086 100644 --- a/hardware/cem-dt-885x/protocol.h +++ b/hardware/cem-dt-885x/protocol.h @@ -71,6 +71,7 @@ enum { CMD_TOGGLE_WEIGHT_FREQ = 0x99, CMD_TOGGLE_WEIGHT_TIME = 0x77, CMD_TOGGLE_HOLD_MAX_MIN = 0x11, + CMD_TOGGLE_MEAS_RANGE = 0x88, }; /** Private, per-device-instance driver context. */ @@ -78,6 +79,7 @@ struct dev_context { /* Device state */ uint64_t cur_mqflags; int recording; + int cur_meas_range; /* Acquisition settings */ uint64_t limit_samples; @@ -115,5 +117,9 @@ SR_PRIV int cem_dt_885x_weight_time_set(const struct sr_dev_inst *sdi, int timew SR_PRIV int cem_dt_885x_holdmode_get(const struct sr_dev_inst *sdi, gboolean *holdmode); SR_PRIV int cem_dt_885x_holdmode_set(const struct sr_dev_inst *sdi, int holdmode); +SR_PRIV int cem_dt_885x_meas_range_get(const struct sr_dev_inst *sdi, + uint64_t *low, uint64_t *high); +SR_PRIV int cem_dt_885x_meas_range_set(const struct sr_dev_inst *sdi, + uint64_t low, uint64_t high); #endif