From: Philipp Marek Date: Fri, 17 Nov 2017 09:29:24 +0000 (+0100) Subject: hantek-dso: dso2250: Initial support for the Hantek DSO 2250. X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=87f56d017858cfa2d8639f4f4683bb6bed24d695;p=libsigrok.git hantek-dso: dso2250: Initial support for the Hantek DSO 2250. Crashes after first acquiration, but at least it _does_ acquire data. --- diff --git a/src/hardware/hantek-dso/api.c b/src/hardware/hantek-dso/api.c index 01ef47f8..6994cbf6 100644 --- a/src/hardware/hantek-dso/api.c +++ b/src/hardware/hantek-dso/api.c @@ -819,6 +819,7 @@ static int handle_event(int fd, int revents, void *cb_data) /* No data yet. */ break; case CAPTURE_READY_8BIT: + case CAPTURE_READY2250: /* Remember where in the captured frame the trigger is. */ devc->trigger_offset = trigger_offset; diff --git a/src/hardware/hantek-dso/protocol.c b/src/hardware/hantek-dso/protocol.c index 644ac0d2..831e357f 100644 --- a/src/hardware/hantek-dso/protocol.c +++ b/src/hardware/hantek-dso/protocol.c @@ -241,6 +241,169 @@ static int get_channel_offsets(const struct sr_dev_inst *sdi) return SR_OK; } +/* See http://openhantek.sourceforge.net/doc/namespaceHantek.html#ac1cd181814cf3da74771c29800b39028 */ +static int dso2250_set_trigger_samplerate(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + struct sr_usb_dev_inst *usb; + int ret, tmp; + int base; + uint8_t cmdstring[12]; + + + devc = sdi->priv; + usb = sdi->conn; + + memset(cmdstring, 0, sizeof(cmdstring)); + /* Command */ + cmdstring[0] = CMD_2250_SET_TRIGGERSOURCE; + sr_dbg("Trigger source %s.", devc->triggersource); + if (!strcmp("CH2", devc->triggersource)) + tmp = 3; + else if (!strcmp("CH1", devc->triggersource)) + tmp = 2; + else if (!strcmp("EXT", devc->triggersource)) + tmp = 0; + else { + sr_err("Invalid trigger source: '%s'.", devc->triggersource); + return SR_ERR_ARG; + } + cmdstring[2] = tmp; + + + sr_dbg("Trigger slope: %d.", devc->triggerslope); + cmdstring[2] |= (devc->triggerslope == SLOPE_NEGATIVE ? 1 : 0) << 3; + + if (send_begin(sdi) != SR_OK) + return SR_ERR; + + if ((ret = libusb_bulk_transfer(usb->devhdl, DSO_EP_OUT, + cmdstring, 8, &tmp, 100)) != 0) { + sr_err("Failed to set trigger/samplerate: %s.", + libusb_error_name(ret)); + return SR_ERR; + } + + + /* Frame size */ + sr_dbg("Frame size: %d.", devc->framesize); + cmdstring[0] = CMD_2250_SET_RECORD_LENGTH; + cmdstring[2] = devc->framesize == FRAMESIZE_SMALL ? 0x01 : 0x02; + + if (send_begin(sdi) != SR_OK) + return SR_ERR; + + if ((ret = libusb_bulk_transfer(usb->devhdl, DSO_EP_OUT, + cmdstring, 4, &tmp, 100)) != 0) { + sr_err("Failed to set record length: %s.", + libusb_error_name(ret)); + return SR_ERR; + } + + + memset(cmdstring, 0, sizeof(cmdstring)); + cmdstring[0] = CMD_2250_SET_SAMPLERATE; + /* Timebase fast */ + sr_dbg("Time base index: %d.", devc->timebase); + base = 100e6; + if (devc->timebase < TIME_40us) { + if (devc->framesize != FRAMESIZE_SMALL) { + sr_err("Timebase < 40us only supported with 10K buffer."); + return SR_ERR_ARG; + } + + /* Fast mode on */ + base = 200e6; + cmdstring[2] |= 1; + } + + /* Downsampling on */ + cmdstring[2] |= 2; + /* Downsampler = 1comp((Base / Samplerate) - 2) + * Base == 100Msa resp. 200MSa + * + * Example for 500kSa/s: + * 100e6 / 500e3 => 200 + * 200 - 2 => 198 + * 1comp(198) => ff39 */ + + tmp = base * timebase_to_time(devc->timebase); + tmp = 200; + if (tmp < 0) + return SR_ERR_ARG; + tmp -= 2; + if (tmp < 0) + return SR_ERR_ARG; + tmp = ~tmp; + sr_dbg("sample rate value: 0x%x.", tmp & 0xffff); + cmdstring[4] = (tmp >> 0) & 0xff; + cmdstring[5] = (tmp >> 8) & 0xff; + + if (send_begin(sdi) != SR_OK) + return SR_ERR; + + if ((ret = libusb_bulk_transfer(usb->devhdl, DSO_EP_OUT, + cmdstring, 8, &tmp, 100)) != 0) { + sr_err("Failed to set sample rate: %s.", + libusb_error_name(ret)); + return SR_ERR; + } + sr_dbg("Sent CMD_2250_SET_SAMPLERATE."); + + + /* Enabled channels: 00=CH1 01=CH2 10=both */ + memset(cmdstring, 0, sizeof(cmdstring)); + cmdstring[0] = CMD_2250_SET_CHANNELS; + sr_dbg("Channels CH1=%d CH2=%d", devc->ch_enabled[0], devc->ch_enabled[1]); + cmdstring[2] = (devc->ch_enabled[0] ? 0 : 1) + (devc->ch_enabled[1] ? 2 : 0); + + if (send_begin(sdi) != SR_OK) + return SR_ERR; + + if ((ret = libusb_bulk_transfer(usb->devhdl, DSO_EP_OUT, + cmdstring, 4, &tmp, 100)) != 0) { + sr_err("Failed to set channels: %s.", + libusb_error_name(ret)); + return SR_ERR; + } + sr_dbg("Sent CMD_2250_SET_CHANNELS."); + + + + /* Trigger slope: 0=positive 1=negative */ + memset(cmdstring, 0, sizeof(cmdstring)); + cmdstring[0] = CMD_2250_SET_TRIGGERPOS_AND_BUFFER; + + /* TODO for big buffer */ + /* TODO */ + sr_dbg("Trigger position: %3.2f.", devc->triggerposition); +// tmp = 0x77fff + 0x8000 * devc->triggerposition; +// cmdstring[6] = tmp & 0xff; +// cmdstring[7] = (tmp >> 8) & 0xff; +// cmdstring[10] = (tmp >> 16) & 0xff; + + cmdstring[2]=0xff; + cmdstring[3]=0xff; + cmdstring[4]=0x07; + + cmdstring[6]=0xff; + cmdstring[7]=0xd7; + cmdstring[8]=0x07; + + if (send_begin(sdi) != SR_OK) + return SR_ERR; + + /* TODO: 12 bytes according to documentation? */ + if ((ret = libusb_bulk_transfer(usb->devhdl, DSO_EP_OUT, + cmdstring, 10, &tmp, 100)) != 0) { + sr_err("Failed to set trigger position: %s.", + libusb_error_name(ret)); + return SR_ERR; + } + + return SR_OK; +} + static int dso_set_trigger_samplerate(const struct sr_dev_inst *sdi) { struct dev_context *devc; @@ -252,9 +415,12 @@ static int dso_set_trigger_samplerate(const struct sr_dev_inst *sdi) uint16_t timebase_large[] = { 0xffff, 0x0000, 0xfffc, 0xfff7, 0xffe8, 0xffce, 0xff9d, 0xff07, 0xfe0d, 0xfc19, 0xf63d, 0xec79 }; + devc = sdi->priv; + if (devc->profile->fw_pid == 0x2250) + return dso2250_set_trigger_samplerate(sdi); + sr_dbg("Preparing CMD_SET_TRIGGER_SAMPLERATE."); - devc = sdi->priv; usb = sdi->conn; memset(cmdstring, 0, sizeof(cmdstring)); @@ -358,6 +524,7 @@ static int dso_set_trigger_samplerate(const struct sr_dev_inst *sdi) return SR_OK; } + static int dso_set_filters(const struct sr_dev_inst *sdi) { struct dev_context *devc; @@ -413,8 +580,13 @@ static int dso_set_voltage(const struct sr_dev_inst *sdi) memset(cmdstring, 0, sizeof(cmdstring)); cmdstring[0] = CMD_SET_VOLTAGE; - cmdstring[1] = 0x0f; - cmdstring[2] = 0x30; + + if (devc->profile->fw_pid == 0x2250) { + cmdstring[2] = 0x08; + } else { + cmdstring[1] = 0x0f; + cmdstring[2] = 0x30; + } /* CH1 volts/div is encoded in bits 0-1 */ sr_dbg("CH1 vdiv index: %d.", devc->voltage[0]); diff --git a/src/hardware/hantek-dso/protocol.h b/src/hardware/hantek-dso/protocol.h index 20aaebdc..71f62e7d 100644 --- a/src/hardware/hantek-dso/protocol.h +++ b/src/hardware/hantek-dso/protocol.h @@ -62,17 +62,25 @@ enum control_requests { }; enum dso_commands { - CMD_SET_FILTERS = 0, - CMD_SET_TRIGGER_SAMPLERATE, - CMD_FORCE_TRIGGER, - CMD_CAPTURE_START, - CMD_ENABLE_TRIGGER, - CMD_GET_CHANNELDATA, - CMD_GET_CAPTURESTATE, - CMD_SET_VOLTAGE, + CMD_SET_FILTERS = 0x0, + CMD_SET_TRIGGER_SAMPLERATE = 0x1, + CMD_FORCE_TRIGGER = 0x2, + CMD_CAPTURE_START = 0x3, + CMD_ENABLE_TRIGGER = 0x4, + CMD_GET_CHANNELDATA = 0x5, + CMD_GET_CAPTURESTATE = 0x6, + CMD_SET_VOLTAGE = 0x7, /* unused */ - CMD_SET_LOGICALDATA, - CMD_GET_LOGICALDATA, + CMD_SET_LOGICALDATA = 0x8, + CMD_GET_LOGICALDATA = 0x9, + CMD__UNUSED1 = 0xa, + /* For the following and other specials please see + * http://openhantek.sourceforge.net/doc/namespaceHantek.html#ac1cd181814cf3da74771c29800b39028 */ + CMD_2250_SET_CHANNELS = 0xb, + CMD_2250_SET_TRIGGERSOURCE = 0xc, + CMD_2250_SET_RECORD_LENGTH = 0xd, + CMD_2250_SET_SAMPLERATE = 0xe, + CMD_2250_SET_TRIGGERPOS_AND_BUFFER = 0xf, }; /* Must match the coupling table. */ @@ -130,6 +138,7 @@ enum capturestates { CAPTURE_EMPTY = 0, CAPTURE_FILLING = 1, CAPTURE_READY_8BIT = 2, + CAPTURE_READY2250 = 3, CAPTURE_READY_9BIT = 7, CAPTURE_TIMEOUT = 127, CAPTURE_UNKNOWN = 255,