From: Toshiaki Yoshida Date: Mon, 5 Nov 2012 07:06:14 +0000 (+0900) Subject: zeroplus-logic-cube: Fix samplerate and trigger X-Git-Tag: dsupstream~587 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=0ab0cb942f59e2232921c10d79ed43cad6cf3153;p=libsigrok.git zeroplus-logic-cube: Fix samplerate and trigger - Default to 1MHz. The default sample rate is the lowest frequency (100Hz), but it takes a very long time until 128K memory is full. - Fix the 1MHz setting. - Use samplerate list. - Fix 10MHz frequency. - Fix trigger. - Change the size of memory according to the number of samples. - Add pre-trigger (capture ratio) setting. - Fix the first acquisition after power on. --- diff --git a/hardware/zeroplus-logic-cube/analyzer.c b/hardware/zeroplus-logic-cube/analyzer.c index 4f86aa50..6f3e6cf9 100644 --- a/hardware/zeroplus-logic-cube/analyzer.c +++ b/hardware/zeroplus-logic-cube/analyzer.c @@ -110,11 +110,11 @@ static int g_trigger_count = 1; static int g_filter_status[8] = { 0 }; static int g_filter_enable = 0; -static int g_freq_value = 100; +static int g_freq_value = 1; static int g_freq_scale = FREQ_SCALE_MHZ; -static int g_memory_size = MEMORY_SIZE_512K; -static int g_ramsize_triggerbar_addr = 0x80000 >> 2; -static int g_triggerbar_addr = 0x3fe; +static int g_memory_size = MEMORY_SIZE_8K; +static int g_ramsize_triggerbar_addr = 2 * 1024; +static int g_triggerbar_addr = 0; static int g_compression = COMPRESSION_NONE; /* Maybe unk specifies an "endpoint" or "register" of sorts. */ @@ -125,6 +125,7 @@ static int analyzer_write_status(libusb_device_handle *devh, unsigned char unk, return gl_reg_write(devh, START_STATUS, unk << 6 | flags); } +#if 0 static int __analyzer_set_freq(libusb_device_handle *devh, int freq, int scale) { int reg0 = 0, divisor = 0, reg2 = 0; @@ -261,6 +262,80 @@ static int __analyzer_set_freq(libusb_device_handle *devh, int freq, int scale) return 0; } +#endif + +/* + * It seems that ... + * FREQUENCT_REG0 - division factor (?) + * FREQUENCT_REG1 - multiplication factor (?) + * FREQUENCT_REG4 - clock selection (?) + * + * clock selection + * 0 10MHz 16 1MHz 32 100kHz 48 10kHz 64 1kHz + * 1 5MHz 17 500kHz 33 50kHz 49 5kHz 65 500Hz + * 2 2.5MHz . . 50 2.5kHz 66 250Hz + * . . . . 67 125Hz + * . . . . 68 62.5Hz + */ +static int __analyzer_set_freq(libusb_device_handle *devh, int freq, int scale) +{ + struct freq_factor { + int freq; + int scale; + int sel; + int div; + int mul; + }; + + static const struct freq_factor f[] = { + { 200, FREQ_SCALE_MHZ, 0, 1, 20 }, + { 150, FREQ_SCALE_MHZ, 0, 1, 15 }, + { 100, FREQ_SCALE_MHZ, 0, 1, 10 }, + { 80, FREQ_SCALE_MHZ, 0, 2, 16 }, + { 50, FREQ_SCALE_MHZ, 0, 2, 10 }, + { 25, FREQ_SCALE_MHZ, 1, 5, 25 }, + { 10, FREQ_SCALE_MHZ, 1, 5, 10 }, + { 1, FREQ_SCALE_MHZ, 16, 5, 5 }, + { 800, FREQ_SCALE_KHZ, 17, 5, 8 }, + { 400, FREQ_SCALE_KHZ, 32, 5, 20 }, + { 200, FREQ_SCALE_KHZ, 32, 5, 10 }, + { 100, FREQ_SCALE_KHZ, 32, 5, 5 }, + { 50, FREQ_SCALE_KHZ, 33, 5, 5 }, + { 25, FREQ_SCALE_KHZ, 49, 5, 25 }, + { 5, FREQ_SCALE_KHZ, 50, 5, 10 }, + { 1, FREQ_SCALE_KHZ, 64, 5, 5 }, + { 500, FREQ_SCALE_HZ, 64, 10, 5 }, + { 100, FREQ_SCALE_HZ, 68, 5, 8 }, + { 0, 0, 0, 0, 0 } + }; + + int i; + + for (i = 0; f[i].freq; i++) { + if (scale == f[i].scale && freq == f[i].freq) + break; + } + if (!f[i].freq) + return -1; + + sr_dbg("zp: Setting samplerate regs (freq=%d, scale=%d): " + "reg0: %d, reg1: %d, reg2: %d, reg3: %d.", + freq, scale, f[i].div, f[i].mul, 0x02, f[i].sel); + + if (gl_reg_write(devh, FREQUENCY_REG0, f[i].div) < 0) + return -1; + + if (gl_reg_write(devh, FREQUENCY_REG1, f[i].mul) < 0) + return -1; + + if (gl_reg_write(devh, FREQUENCY_REG2, 0x02) < 0) + return -1; + + if (gl_reg_write(devh, FREQUENCY_REG4, f[i].sel) < 0) + return -1; + + return 0; +} static void __analyzer_set_ramsize_trigger_address(libusb_device_handle *devh, unsigned int address) @@ -399,7 +474,10 @@ SR_PRIV void analyzer_configure(libusb_device_handle *devh) __analyzer_set_triggerbar_address(devh, g_triggerbar_addr); /* Set_Dont_Care_TriggerBar */ - gl_reg_write(devh, DONT_CARE_TRIGGERBAR, 0x01); + if (g_triggerbar_addr) + gl_reg_write(devh, DONT_CARE_TRIGGERBAR, 0x00); + else + gl_reg_write(devh, DONT_CARE_TRIGGERBAR, 0x01); /* Enable_Status */ analyzer_set_filter(devh); @@ -413,44 +491,26 @@ SR_PRIV void analyzer_configure(libusb_device_handle *devh) SR_PRIV void analyzer_add_trigger(int channel, int type) { - int i; - - if ((channel & 0xf) >= 8) - return; - - if (type == TRIGGER_HIGH || type == TRIGGER_LOW) { - if (channel & CHANNEL_A) - i = 0; - else if (channel & CHANNEL_B) - i = 2; - else if (channel & CHANNEL_C) - i = 4; - else if (channel & CHANNEL_D) - i = 6; - else - return; - if ((channel & 0xf) >= 4) { - i++; - channel -= 4; - } - g_trigger_status[i] |= - 1 << ((2 * channel) + (type == TRIGGER_LOW ? 1 : 0)); - } else { - if (type == TRIGGER_POSEDGE) - g_trigger_status[8] = 0x40; - else if (type == TRIGGER_NEGEDGE) - g_trigger_status[8] = 0x80; - else - g_trigger_status[8] = 0xc0; - - /* FIXME: Just guessed the index; need to verify. */ - if (channel & CHANNEL_B) - g_trigger_status[8] += 8; - else if (channel & CHANNEL_C) - g_trigger_status[8] += 16; - else if (channel & CHANNEL_D) - g_trigger_status[8] += 24; - g_trigger_status[8] += channel % 8; + switch (type) { + case TRIGGER_HIGH: + g_trigger_status[channel / 4] |= 1 << (channel % 4 * 2); + break; + case TRIGGER_LOW: + g_trigger_status[channel / 4] |= 2 << (channel % 4 * 2); + break; +#if 0 + case TRIGGER_POSEDGE: + g_trigger_status[8] = 0x40 | channel; + break; + case TRIGGER_NEGEDGE: + g_trigger_status[8] = 0x80 | channel; + break; + case TRIGGER_ANYEDGE: + g_trigger_status[8] = 0xc0 | channel; + break; +#endif + default: + break; } } @@ -511,6 +571,11 @@ SR_PRIV void analyzer_set_triggerbar_address(unsigned int address) g_triggerbar_addr = address; } +SR_PRIV unsigned int analyzer_read_status(libusb_device_handle *devh) +{ + return gl_reg_read(devh, DEV_STATUS); +} + SR_PRIV unsigned int analyzer_read_id(libusb_device_handle *devh) { return gl_reg_read(devh, DEV_ID1) << 8 | gl_reg_read(devh, DEV_ID0); diff --git a/hardware/zeroplus-logic-cube/analyzer.h b/hardware/zeroplus-logic-cube/analyzer.h index d427c436..6fad571a 100644 --- a/hardware/zeroplus-logic-cube/analyzer.h +++ b/hardware/zeroplus-logic-cube/analyzer.h @@ -85,6 +85,7 @@ SR_PRIV void analyzer_add_trigger(int channel, int type); SR_PRIV void analyzer_set_trigger_count(int count); SR_PRIV void analyzer_add_filter(int channel, int type); +SR_PRIV unsigned int analyzer_read_status(libusb_device_handle *devh); SR_PRIV unsigned int analyzer_read_id(libusb_device_handle *devh); SR_PRIV unsigned int analyzer_get_stop_address(libusb_device_handle *devh); SR_PRIV unsigned int analyzer_get_now_address(libusb_device_handle *devh); diff --git a/hardware/zeroplus-logic-cube/zeroplus.c b/hardware/zeroplus-logic-cube/zeroplus.c index f1b6431b..f292ba56 100644 --- a/hardware/zeroplus-logic-cube/zeroplus.c +++ b/hardware/zeroplus-logic-cube/zeroplus.c @@ -42,6 +42,8 @@ #define PACKET_SIZE 2048 /* ?? */ +//#define ZP_EXPERIMENTAL + typedef struct { unsigned short vid; unsigned short pid; @@ -149,20 +151,22 @@ static const struct sr_samplerates samplerates = { /* Private, per-device-instance driver context. */ struct dev_context { uint64_t cur_samplerate; + uint64_t max_samplerate; uint64_t limit_samples; int num_channels; /* TODO: This isn't initialized before it's needed :( */ - uint64_t memory_size; - uint8_t probe_mask; - uint8_t trigger_mask[NUM_TRIGGER_STAGES]; - uint8_t trigger_value[NUM_TRIGGER_STAGES]; + int memory_size; + unsigned int max_memory_size; + //uint8_t probe_mask; + //uint8_t trigger_mask[NUM_TRIGGER_STAGES]; + //uint8_t trigger_value[NUM_TRIGGER_STAGES]; // uint8_t trigger_buffer[NUM_TRIGGER_STAGES]; + int trigger; + unsigned int capture_ratio; /* TODO: this belongs in the device instance */ struct sr_usb_dev_inst *usb; }; -static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, - const void *value); static int hw_dev_close(struct sr_dev_inst *sdi); static unsigned int get_memory_size(int type) @@ -179,6 +183,7 @@ static unsigned int get_memory_size(int type) return 0; } +#if 0 static int configure_probes(const struct sr_dev_inst *sdi) { struct dev_context *devc; @@ -219,6 +224,53 @@ static int configure_probes(const struct sr_dev_inst *sdi) return SR_OK; } +#endif + +static int configure_probes(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + const GSList *l; + const struct sr_probe *probe; + char *tc; + int type; + + /* Note: sdi and sdi->priv are non-NULL, the caller checked this. */ + devc = sdi->priv; + + for (l = sdi->probes; l; l = l->next) { + probe = (struct sr_probe *)l->data; + if (probe->enabled == FALSE) + continue; + + if ((tc = probe->trigger)) { + switch (*tc) { + case '1': + type = TRIGGER_HIGH; + break; + case '0': + type = TRIGGER_LOW; + break; +#if 0 + case 'r': + type = TRIGGER_POSEDGE; + break; + case 'f': + type = TRIGGER_NEGEDGE; + break; + case 'c': + type = TRIGGER_ANYEDGE; + break; +#endif + default: + return SR_ERR; + } + analyzer_add_trigger(probe->index, type); + devc->trigger = 1; + } + } + + return SR_OK; +} static int clear_instances(void) { @@ -325,7 +377,15 @@ static GSList *hw_scan(GSList *options) } sdi->priv = devc; devc->num_channels = prof->channels; - devc->memory_size = prof->sample_depth * 1024; +#ifdef ZP_EXPERIMENTAL + devc->max_memory_size = 128 * 1024; + devc->max_samplerate = 200; +#else + devc->max_memory_size = prof->sample_depth * 1024; + devc->max_samplerate = prof->max_sampling_freq; +#endif + devc->max_samplerate *= SR_MHZ(1); + devc->memory_size = MEMORY_SIZE_8K; // memset(devc->trigger_buffer, 0, NUM_TRIGGER_STAGES); /* Fill in probelist according to this device's profile. */ @@ -418,16 +478,18 @@ static int hw_dev_open(struct sr_dev_inst *sdi) return SR_ERR; } + /* Set default configuration after power on */ + if (analyzer_read_status(devc->usb->devhdl) == 0) + analyzer_configure(devc->usb->devhdl); + analyzer_reset(devc->usb->devhdl); analyzer_initialize(devc->usb->devhdl); - analyzer_set_memory_size(MEMORY_SIZE_512K); + //analyzer_set_memory_size(MEMORY_SIZE_512K); // analyzer_set_freq(g_freq, g_freq_scale); analyzer_set_trigger_count(1); // analyzer_set_ramsize_trigger_address((((100 - g_pre_trigger) // * get_memory_size(g_memory_size)) / 100) >> 2); - analyzer_set_ramsize_trigger_address( - (100 * get_memory_size(MEMORY_SIZE_512K) / 100) >> 2); #if 0 if (g_double_mode == 1) @@ -439,10 +501,9 @@ static int hw_dev_open(struct sr_dev_inst *sdi) analyzer_set_compression(COMPRESSION_NONE); if (devc->cur_samplerate == 0) { - /* Samplerate hasn't been set. Default to the slowest one. */ - if (hw_dev_config_set(sdi, SR_HWCAP_SAMPLERATE, - &samplerates.list[0]) == SR_ERR) - return SR_ERR; + /* Samplerate hasn't been set. Default to 1MHz. */ + analyzer_set_freq(1, FREQ_SCALE_MHZ); + devc->cur_samplerate = SR_MHZ(1); } return SR_OK; @@ -533,25 +594,23 @@ static int hw_info_get(int info_id, const void **data, return SR_OK; } -static int set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) +static int set_samplerate(struct dev_context *devc, uint64_t samplerate) { - struct dev_context *devc; - - if (!sdi) { - sr_err("zp: %s: sdi was NULL", __func__); - return SR_ERR_ARG; - } + int i; - if (!(devc = sdi->priv)) { - sr_err("zp: %s: sdi->priv was NULL", __func__); + for (i = 0; supported_samplerates[i]; i++) + if (samplerate == supported_samplerates[i]) + break; + if (!supported_samplerates[i] || samplerate > devc->max_samplerate) { + sr_err("zp: %s: unsupported samplerate", __func__); return SR_ERR_ARG; } sr_info("zp: Setting samplerate to %" PRIu64 "Hz.", samplerate); - if (samplerate > SR_MHZ(1)) + if (samplerate >= SR_MHZ(1)) analyzer_set_freq(samplerate / SR_MHZ(1), FREQ_SCALE_MHZ); - else if (samplerate > SR_KHZ(1)) + else if (samplerate >= SR_KHZ(1)) analyzer_set_freq(samplerate / SR_KHZ(1), FREQ_SCALE_KHZ); else analyzer_set_freq(samplerate, FREQ_SCALE_HZ); @@ -561,11 +620,52 @@ static int set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate) return SR_OK; } +static int set_limit_samples(struct dev_context *devc, uint64_t samples) +{ + devc->limit_samples = samples; + + if (samples <= 2 * 1024) + devc->memory_size = MEMORY_SIZE_8K; + else if (samples <= 16 * 1024) + devc->memory_size = MEMORY_SIZE_64K; + else if (samples <= 32 * 1024 || + devc->max_memory_size <= 32 * 1024) + devc->memory_size = MEMORY_SIZE_128K; + else + devc->memory_size = MEMORY_SIZE_512K; + + sr_info("zp: Setting memory size to %dK.", + get_memory_size(devc->memory_size) / 1024); + + analyzer_set_memory_size(devc->memory_size); + + return SR_OK; +} + +static int set_capture_ratio(struct dev_context *devc, uint64_t ratio) +{ + if (ratio > 100) { + sr_err("zp: %s: invalid capture ratio", __func__); + return SR_ERR_ARG; + } + + devc->capture_ratio = ratio; + + sr_info("zp: Setting capture ratio to %d%%.", devc->capture_ratio); + + return SR_OK; +} + static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, - const void *value) + const void *value) { struct dev_context *devc; + if (!sdi) { + sr_err("zp: %s: sdi was NULL", __func__); + return SR_ERR_ARG; + } + if (!(devc = sdi->priv)) { sr_err("zp: %s: sdi->priv was NULL", __func__); return SR_ERR_ARG; @@ -573,15 +673,45 @@ static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, switch (hwcap) { case SR_HWCAP_SAMPLERATE: - return set_samplerate(sdi, *(const uint64_t *)value); + return set_samplerate(devc, *(const uint64_t *)value); case SR_HWCAP_LIMIT_SAMPLES: - devc->limit_samples = *(const uint64_t *)value; - return SR_OK; + return set_limit_samples(devc, *(const uint64_t *)value); + case SR_HWCAP_CAPTURE_RATIO: + return set_capture_ratio(devc, *(const uint64_t *)value); default: return SR_ERR; } } +static void set_triggerbar(struct dev_context *devc) +{ + unsigned int ramsize; + unsigned int n; + unsigned int triggerbar; + + ramsize = get_memory_size(devc->memory_size) / 4; + if (devc->trigger) { + n = ramsize; + if (devc->max_memory_size < n) + n = devc->max_memory_size; + if (devc->limit_samples < n) + n = devc->limit_samples; + n = n * devc->capture_ratio / 100; + if (n > ramsize - 8) + triggerbar = ramsize - 8; + else + triggerbar = n; + } else { + triggerbar = 0; + } + analyzer_set_triggerbar_address(triggerbar); + analyzer_set_ramsize_trigger_address(ramsize - triggerbar); + + sr_dbg("zp: triggerbar_address = %d(0x%x)", triggerbar, triggerbar); + sr_dbg("zp: ramsize_triggerbar_address = %d(0x%x)", + ramsize - triggerbar, ramsize - triggerbar); +} + static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { @@ -589,9 +719,10 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, struct sr_datafeed_logic logic; struct sr_datafeed_header header; struct sr_datafeed_meta_logic meta; - uint64_t samples_read; + //uint64_t samples_read; int res; unsigned int packet_num; + unsigned int n; unsigned char *buf; struct dev_context *devc; @@ -605,6 +736,8 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, return SR_ERR; } + set_triggerbar(devc); + /* push configured settings to device */ analyzer_configure(devc->usb->devhdl); @@ -637,13 +770,15 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, return SR_ERR_MALLOC; } - samples_read = 0; + //samples_read = 0; analyzer_read_start(devc->usb->devhdl); /* Send the incoming transfer to the session bus. */ - for (packet_num = 0; packet_num < (devc->memory_size * 4 / PACKET_SIZE); - packet_num++) { + n = get_memory_size(devc->memory_size); + if (devc->max_memory_size * 4 < n) + n = devc->max_memory_size * 4; + for (packet_num = 0; packet_num < n / PACKET_SIZE; packet_num++) { res = analyzer_read_data(devc->usb->devhdl, buf, PACKET_SIZE); - sr_info("zp: Tried to read %llx bytes, actually read %x bytes", + sr_info("zp: Tried to read %d bytes, actually read %d bytes", PACKET_SIZE, res); packet.type = SR_DF_LOGIC; @@ -652,7 +787,7 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, logic.unitsize = 4; logic.data = buf; sr_session_send(cb_data, &packet); - samples_read += res / 4; + //samples_read += res / 4; } analyzer_read_stop(devc->usb->devhdl); g_free(buf);