Commit a5f47b42 authored by DreamSourceLab's avatar DreamSourceLab
Browse files

Add new products support (DSLogicU3Pro16/DSLogicU3Pro32/DSCopeU2B100/DSCopeU3P100)

parent 235a863b
......@@ -170,8 +170,34 @@ void WaitingDialog::changeText()
{
tips->setText(tr("Waiting"));
index = 0;
GVariant* gvar;
bool comb_comp_en = false;
bool zero_fgain = false;
GVariant* gvar = _dev_inst->get_config(NULL, NULL, _key);
gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_PROBE_COMB_COMP_EN);
if (gvar != NULL) {
comb_comp_en = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
if (comb_comp_en) {
gvar = _dev_inst->get_config(NULL, NULL, SR_CONF_ZERO_COMB_FGAIN);
if (gvar != NULL) {
zero_fgain = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
if (zero_fgain) {
boost::shared_ptr<view::DsoSignal> dsoSig;
BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals())
{
if ((dsoSig = dynamic_pointer_cast<view::DsoSignal>(s)))
dsoSig->set_enable(dsoSig->get_index() == 0);
}
boost::this_thread::sleep(boost::posix_time::millisec(100));
_dev_inst->set_config(NULL, NULL, SR_CONF_ZERO_COMB, g_variant_new_boolean(true));
}
}
}
}
gvar = _dev_inst->get_config(NULL, NULL, _key);
if (gvar != NULL) {
bool zero = g_variant_get_boolean(gvar);
g_variant_unref(gvar);
......
......@@ -505,7 +505,7 @@ bool SigSession::get_capture_status(bool &triggered, int &progress)
{
uint64_t sample_limits = cur_samplelimits();
sr_status status;
if (sr_status_get(_dev_inst->dev_inst(), &status, true, SR_STATUS_TRIG_BEGIN, SR_STATUS_TRIG_END) == SR_OK){
if (sr_status_get(_dev_inst->dev_inst(), &status, true) == SR_OK){
triggered = status.trig_hit & 0x01;
uint64_t captured_cnt = status.trig_hit >> 2;
captured_cnt = ((uint64_t)status.captured_cnt0 +
......
......@@ -460,7 +460,7 @@ QString StoreSession::meta_gen(boost::shared_ptr<data::Snapshot> snapshot)
fprintf(meta, " vFactor%d = %" PRIu64 "\n", probecnt, probe->vfactor);
fprintf(meta, " vOffset%d = %d\n", probecnt, probe->hw_offset);
fprintf(meta, " vTrig%d = %d\n", probecnt, probe->trig_value);
if (sr_status_get(sdi, &status, false, 0, 0) == SR_OK) {
if (sr_status_get(sdi, &status, false) == SR_OK) {
if (probe->index == 0) {
fprintf(meta, " period%d = %" PRIu32 "\n", probecnt, status.ch0_cyc_tlen);
fprintf(meta, " pcnt%d = %" PRIu32 "\n", probecnt, status.ch0_cyc_cnt);
......
......@@ -804,7 +804,7 @@ void SamplingBar::commit_settings()
g_variant_new_uint64(sample_rate));
if (dev_inst->dev_inst()->mode != DSO) {
const uint64_t sample_count = ((uint64_t)ceil(sample_duration / SR_SEC(1) *
sample_rate) + 1023ULL) & ~1023ULL;
sample_rate) + SAMPLES_ALIGN) & ~SAMPLES_ALIGN;
if (sample_count != dev_inst->get_sample_limit())
dev_inst->set_config(NULL, NULL,
SR_CONF_LIMIT_SAMPLES,
......
......@@ -892,7 +892,7 @@ void DsoSignal::paint_mid(QPainter &p, int left, int right, QColor fore, QColor
}
sr_status status;
if (sr_status_get(_dev_inst->dev_inst(), &status, false, 0, 0) == SR_OK) {
if (sr_status_get(_dev_inst->dev_inst(), &status, false) == SR_OK) {
_mValid = true;
if (status.measure_valid) {
_min = (index == 0) ? status.ch0_min : status.ch1_min;
......
File added
File added
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
File added
File added
......@@ -137,6 +137,14 @@ struct cmd_zero_info {
uint8_t trans0;
uint8_t trans1;
uint8_t comb_comp;
uint8_t fgain0_code;
uint8_t fgain1_code;
uint8_t fgain2_code;
uint8_t fgain3_code;
uint8_t comb_fgain0_code;
uint8_t comb_fgain1_code;
uint8_t comb_fgain2_code;
uint8_t comb_fgain3_code;
};
struct cmd_vga_info {
......
......@@ -159,6 +159,9 @@ static struct DSL_context *DSCope_dev_new(const struct DSL_profile *prof)
devc->trigger_hpos = 0x0;
devc->trigger_hrate = 0;
devc->zero = FALSE;
devc->zero_branch = FALSE;
devc->zero_comb_fgain = FALSE;
devc->zero_comb = FALSE;
devc->tune = FALSE;
devc->data_lock = FALSE;
devc->cali = FALSE;
......@@ -195,6 +198,7 @@ static GSList *scan(GSList *options)
libusb_device **devlist;
int devcnt, ret, i, j;
const char *conn;
enum libusb_speed usb_speed;
drvc = di->priv;
......@@ -236,10 +240,16 @@ static GSList *scan(GSList *options)
continue;
}
usb_speed = libusb_get_device_speed( devlist[i]);
if ((usb_speed != LIBUSB_SPEED_HIGH) &&
(usb_speed != LIBUSB_SPEED_SUPER))
continue;
prof = NULL;
for (j = 0; supported_DSCope[j].vid; j++) {
if (des.idVendor == supported_DSCope[j].vid &&
des.idProduct == supported_DSCope[j].pid) {
des.idProduct == supported_DSCope[j].pid &&
usb_speed == supported_DSCope[j].usb_speed) {
prof = &supported_DSCope[j];
}
}
......@@ -343,8 +353,9 @@ static uint64_t dso_offset(const struct sr_dev_inst *sdi, const struct sr_channe
struct DSL_context *devc = sdi->priv;
const double offset_mid = (1 << (ch->bits - 1));
const double offset_max = ((1 << ch->bits) - 1.0);
const uint64_t offset = devc->zero ? ch->zero_offset : ch->hw_offset;
double comb_off = 2.0 / (pow(10, 24.0*ch->comb_comp/20/4096) - 1);
const uint64_t offset = devc->zero ? ch->zero_offset : ch->offset;
double comb_off = (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511) ? 0.57 / (pow(10, 24.0*ch->comb_comp/20/4096) - 1) :
2.0 / (pow(10, 24.0*ch->comb_comp/20/4096) - 1);
// const double comb_compensate = ((devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511) &&
// (dsl_en_ch_num(sdi) == 1))? (offset - offset_mid) / comb_off : 0;
const double comb_compensate = ((ch->comb_comp != 0) && (dsl_en_ch_num(sdi) == 1)) ? (offset - offset_mid) / comb_off : 0;
......@@ -385,9 +396,8 @@ static uint64_t dso_cmd_gen(const struct sr_dev_inst *sdi, struct sr_channel* ch
switch (id) {
case SR_CONF_PROBE_EN:
case SR_CONF_PROBE_COUPLING:
if (devc->zero || sdi->mode == ANALOG || dsl_en_ch_num(sdi) == 2) {
if (sdi->mode == ANALOG || dsl_en_ch_num(sdi) == 2) {
cmd += 0x0E00;
//cmd += 0x000;
} else if (dsl_en_ch_num(sdi) == 1) {
if (((ch->index == 0) && ch->enabled) || ((ch->index == 1) && !ch->enabled))
cmd += 0x1600;
......@@ -418,7 +428,6 @@ static uint64_t dso_cmd_gen(const struct sr_dev_inst *sdi, struct sr_channel* ch
case SR_CONF_PROBE_OFFSET:
cmd += 0x10;
cmd += ch->index << ch_bit;
ch->hw_offset = ch->offset;
offset = dso_offset(sdi, ch);
cmd += (offset << 8);
break;
......@@ -429,7 +438,7 @@ static uint64_t dso_cmd_gen(const struct sr_dev_inst *sdi, struct sr_channel* ch
break;
case SR_CONF_HORIZ_TRIGGERPOS:
cmd += 0x20;
cmd += devc->trigger_hpos << 8;
cmd += ((uint64_t)devc->trigger_hpos << 8);
break;
case SR_CONF_TRIGGER_SLOPE:
cmd += 0x28;
......@@ -539,6 +548,8 @@ static gboolean dso_load_eep(struct sr_dev_inst *sdi, struct sr_channel *probe,
zero_info.zero_addr = dst_addr;
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_SEEP)
real_zero_addr = zero_info.zero_addr;
else if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_FLASH)
real_zero_addr = probe->index * DSO_ZERO_PAGE;
else
real_zero_addr = (zero_big_addr << 8) + zero_info.zero_addr;
if ((ret = dsl_rd_nvm(sdi, (unsigned char *)&zero_info, real_zero_addr, sizeof(struct cmd_zero_info))) != SR_OK) {
......@@ -555,6 +566,16 @@ static gboolean dso_load_eep(struct sr_dev_inst *sdi, struct sr_channel *probe,
probe->comb_diff_bom = *(preoff_ptr + 2*i + 1);
probe->vpos_trans = *(preoff_ptr + 2*i + 2) + (*(preoff_ptr + 2*i + 3) << 8);
probe->comb_comp = *(preoff_ptr + 2*i + 4);
probe->digi_fgain = *(preoff_ptr + 2*i + 5) + (*(preoff_ptr + 2*i + 6) << 8);
probe->cali_fgain0 = dsl_adc_code2fgain(*(preoff_ptr + 2*i + 7));
probe->cali_fgain1 = dsl_adc_code2fgain(*(preoff_ptr + 2*i + 8));
probe->cali_fgain2 = dsl_adc_code2fgain(*(preoff_ptr + 2*i + 9));
probe->cali_fgain3 = dsl_adc_code2fgain(*(preoff_ptr + 2*i + 10));
probe->cali_comb_fgain0 = dsl_adc_code2fgain(*(preoff_ptr + 2*i + 11));
probe->cali_comb_fgain1 = dsl_adc_code2fgain(*(preoff_ptr + 2*i + 12));
probe->cali_comb_fgain2 = dsl_adc_code2fgain(*(preoff_ptr + 2*i + 13));
probe->cali_comb_fgain3 = dsl_adc_code2fgain(*(preoff_ptr + 2*i + 14));
if (!fpga_done) {
const double slope = (probe->comb_diff_bom - probe->comb_diff_top)/(2.0*255.0);
for (i = 0; i < 256; i++) {
......@@ -575,6 +596,8 @@ static gboolean dso_load_eep(struct sr_dev_inst *sdi, struct sr_channel *probe,
vga_info.vga_addr = dst_addr + sizeof(struct cmd_zero_info);
if (devc ->profile->dev_caps.feature_caps & CAPS_FEATURE_SEEP)
real_zero_addr = vga_info.vga_addr;
else if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_FLASH)
real_zero_addr = probe->index * DSO_ZERO_PAGE + 1;
else
real_zero_addr = (zero_big_addr << 8) + vga_info.vga_addr;
if ((ret = dsl_rd_nvm(sdi, (unsigned char *)&vga_info, real_zero_addr, sizeof(struct cmd_vga_info))) != SR_OK) {
......@@ -594,6 +617,396 @@ static gboolean dso_load_eep(struct sr_dev_inst *sdi, struct sr_channel *probe,
return TRUE;
}
static int dso_zero(const struct sr_dev_inst *sdi, gboolean reset)
{
struct DSL_context *devc = sdi->priv;
GSList *l;
int ret = SR_OK;
struct sr_usb_dev_inst *usb;
struct libusb_device_handle *hdl;
struct ctl_wr_cmd wr_cmd;
static uint64_t vdiv_back[2] = {0, 0};
struct sr_channel *probe0 = NULL, *probe1 = NULL;
uint16_t offset_top;
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511)
offset_top = 15;
else
offset_top = 20;
const uint16_t offset_bom = ((1 << channel_modes[devc->ch_mode].unit_bits) - 1) - offset_top;
const uint16_t offset_mid = (1 << (channel_modes[devc->ch_mode].unit_bits - 1));
const uint16_t max_trans = ((1 << 10) - 1);
#ifdef _WIN32
const int zero_interval = (devc->profile->usb_speed == LIBUSB_SPEED_SUPER) ? 10 : 4;
#else
const int zero_interval = 50;
#endif
const double margin_pass = 0.3;
int end_cnt = 0;
const int branch_done_cnt = (devc->profile->usb_speed == LIBUSB_SPEED_SUPER) ? 10 : 2;
static gboolean warm_done = FALSE;
static gboolean trans_fix_done = FALSE;
static gboolean mid_zero_done = FALSE;
static double margin[2];
//static double offset[2];
double acc_mean = 0;
double acc_mean0 = 0;
double acc_mean1 = 0;
double acc_skew[8];
double acc_max_skew;
if (reset) {
warm_done = FALSE;
trans_fix_done = FALSE;
mid_zero_done = FALSE;
vdiv_back[0] = 0;
vdiv_back[1] = 0;
return SR_OK;
}
if (!devc->mstatus_valid)
return SR_ERR_ARG;
usb = sdi->conn;
hdl = usb->devhdl;
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
if (probe->index == 0)
probe0 = probe;
if (probe->index == 1)
probe1 = probe;
if (vdiv_back[probe->index] == 0)
vdiv_back[probe->index] = probe->vdiv;
}
if (!trans_fix_done && devc->zero_stage == 0) {
ret = SR_OK;
if (!warm_done) {
if (devc->zero_pcnt == 0*zero_interval) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
for (int i = 0; (probe->vga_ptr+i)->key; i++)
probe->vdiv = (probe->vga_ptr+i)->key;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_VDIV));
probe->zero_offset = offset_mid;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
}
}
if (!(devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511) ||
(devc->zero_pcnt == 1*zero_interval)) {
warm_done = TRUE;
devc->zero_pcnt = 0*zero_interval-1;
}
} else if (!(devc->profile->dev_caps.feature_caps & CAPS_FEATURE_PREOFF)) {
if (devc->zero_pcnt == 0*zero_interval) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
}
}
if (devc->zero_pcnt == 1*zero_interval) {
margin[0] = (devc->mstatus.ch0_acc_mean * 1.0 / devc->limit_samples);
margin[1] = (devc->mstatus.ch1_acc_mean * 1.0 / devc->limit_samples);
// if (margin[0] >= value_max || margin[1] >= value_max)
// ret = SR_ERR;
}
if (devc->zero_pcnt == 1*zero_interval+1) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->zero_offset = offset_top;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
}
}
if (devc->zero_pcnt == 2*zero_interval) {
double top0 = (devc->mstatus.ch0_acc_mean * 1.0 / devc->limit_samples);
double top1 = (devc->mstatus.ch1_acc_mean * 1.0 / devc->limit_samples);
// if (top0 <= value_min || top1 <= value_min) {
// ret = SR_ERR;
//} else {
margin[0] -= top0;
margin[1] -= top1;
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
margin[probe->index] -= (offset_bom - offset_top);
if (fabs(margin[probe->index]) > margin_pass) {
margin[probe->index] = margin[probe->index] > 0 ? ceil(margin[probe->index]) : floor(margin[probe->index]);
probe->vpos_trans = min(probe->vpos_trans - margin[probe->index], max_trans);
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
} else {
margin[probe->index] = 0;
}
}
trans_fix_done = (margin[0] == 0) && (margin[1] == 0);
devc->zero_pcnt = trans_fix_done ? 0*zero_interval : 0*zero_interval-1;
//}
}
} else {
trans_fix_done = TRUE;
}
if (!trans_fix_done && ret == SR_OK)
devc->zero_pcnt++;
} else if (!mid_zero_done) {
if (devc->zero_pcnt == 0) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->vdiv = (probe->vga_ptr+devc->zero_stage)->key;
if (probe->vdiv == 0) {
probe->vdiv = (probe->vga_ptr+devc->zero_stage-1)->key;
mid_zero_done = TRUE;
break;
}
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_VDIV));
probe->zero_offset = offset_mid;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
// must after offset setting
probe->vdiv = vdiv_back[probe->index];
}
}
if (devc->zero_pcnt == zero_interval) {
margin[0] = offset_mid - (devc->mstatus.ch0_acc_mean * 1.0 / devc->limit_samples);
margin[1] = offset_mid - (devc->mstatus.ch1_acc_mean * 1.0 / devc->limit_samples);
if (fabs(margin[0]) < margin_pass && fabs(margin[1]) < margin_pass) {
devc->zero_stage++;
} else {
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_PREOFF) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
double trans_coarse = ((probe->vga_ptr+devc->zero_stage)->key < 500) ? (probe->vpos_trans >> 8)/DSCOPE_TRANS_CMULTI : (probe->vpos_trans >> 8);
double trans_fine = ((probe->vga_ptr+devc->zero_stage)->key < 500) ? (probe->vpos_trans & 0x00ff) / 1000.0 : (probe->vpos_trans & 0x00ff) / DSCOPE_TRANS_FMULTI;
double voltage_margin = margin[probe->index] * (probe->vga_ptr+devc->zero_stage)->key * 10 / 255.0;
uint16_t last_preoff = (probe->vga_ptr+devc->zero_stage)->preoff;
int preoff_coarse = floor(voltage_margin / trans_coarse + 0.5);
int preoff_fine = floor(-(voltage_margin - preoff_coarse*trans_coarse)/trans_fine + 0.5);
preoff_coarse = (last_preoff >> 10) + preoff_coarse;
preoff_fine = (last_preoff&0x03ff) + preoff_fine;
(probe->vga_ptr+devc->zero_stage)->preoff = (preoff_coarse << 10) + preoff_fine;
}
} else {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
(probe->vga_ptr+devc->zero_stage)->preoff += margin[probe->index] > 0 ? ceil(margin[probe->index]) : floor(margin[probe->index]);
}
}
}
devc->zero_pcnt = 0;
} else if (!mid_zero_done) {
devc->zero_pcnt++;
}
} else {
ret = SR_OK;
end_cnt = 0*zero_interval + 1;
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511) {
if (!devc->zero_comb_fgain) {
if (devc->zero_pcnt == 0*zero_interval+1) {
devc->zero_branch = TRUE;
probe0->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
probe1->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe1, SR_CONF_PROBE_OFFSET));
dsl_probe_cali_fgain(devc, probe0, 1, FALSE, TRUE);
dsl_probe_cali_fgain(devc, probe1, 1, FALSE, TRUE);
dsl_config_adc_fgain(sdi, 0, probe0->cali_fgain0, probe0->cali_fgain1);
dsl_config_adc_fgain(sdi, 1, probe0->cali_fgain2, probe0->cali_fgain3);
dsl_config_adc_fgain(sdi, 2, probe1->cali_fgain0, probe1->cali_fgain1);
dsl_config_adc_fgain(sdi, 3, probe1->cali_fgain2, probe1->cali_fgain3);
acc_mean0 = 0;
acc_mean1 = 0;
} else if (devc->zero_pcnt == branch_done_cnt*zero_interval) {
acc_mean0 = (devc->mstatus.ch0_acc_mean + devc->mstatus.ch0_acc_mean_p1 +
devc->mstatus.ch0_acc_mean_p2 + devc->mstatus.ch0_acc_mean_p3) / 4.0;
acc_mean1 = (devc->mstatus.ch1_acc_mean + devc->mstatus.ch1_acc_mean_p1 +
devc->mstatus.ch1_acc_mean_p2 + devc->mstatus.ch1_acc_mean_p3) / 4.0;
acc_skew[0] = devc->mstatus.ch0_acc_mean / acc_mean0 - 1;
acc_skew[1] = devc->mstatus.ch0_acc_mean_p1 / acc_mean0 - 1;
acc_skew[2] = devc->mstatus.ch0_acc_mean_p2 / acc_mean0 - 1;
acc_skew[3] = devc->mstatus.ch0_acc_mean_p3 / acc_mean0 - 1;
acc_skew[4] = devc->mstatus.ch1_acc_mean / acc_mean1 - 1;
acc_skew[5] = devc->mstatus.ch1_acc_mean_p1 / acc_mean1 - 1;
acc_skew[6] = devc->mstatus.ch1_acc_mean_p2 / acc_mean1 - 1;
acc_skew[7] = devc->mstatus.ch1_acc_mean_p3 / acc_mean1 - 1;
acc_max_skew = fabs(acc_skew[0]);
for (int i=1; i <8; i++)
acc_max_skew = max(acc_max_skew, fabs(acc_skew[i]));
if ((acc_max_skew > MAX_ACC_VARIANCE) && (dsl_probe_fgain_inrange(probe0, FALSE, acc_skew) ||
dsl_probe_fgain_inrange(probe1, FALSE, acc_skew))) {
devc->zero_pcnt = 0*zero_interval+1;
dsl_probe_cali_fgain(devc, probe0, acc_mean0, FALSE, FALSE);
dsl_probe_cali_fgain(devc, probe1, acc_mean1, FALSE, FALSE);
dsl_config_adc_fgain(sdi, 0, probe0->cali_fgain0, probe0->cali_fgain1);
dsl_config_adc_fgain(sdi, 1, probe0->cali_fgain2, probe0->cali_fgain3);
dsl_config_adc_fgain(sdi, 2, probe1->cali_fgain0, probe1->cali_fgain1);
dsl_config_adc_fgain(sdi, 3, probe1->cali_fgain2, probe1->cali_fgain3);
} else {
if (acc_max_skew <= MAX_ACC_VARIANCE) {
devc->zero_comb_fgain = TRUE;
devc->zero_pcnt = 0*zero_interval;
} else {
devc->zero_pcnt = 0*zero_interval;
dsl_skew_fpga_fgain(sdi, FALSE, acc_skew);
}
}
}
}
if (devc->zero_comb_fgain) {
if (devc->zero_pcnt == 0*zero_interval+1) {
probe0->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
probe1->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe1, SR_CONF_PROBE_OFFSET));
acc_mean = 0;
devc->zero_comb = FALSE;
dsl_probe_cali_fgain(devc, probe0, 1, TRUE, TRUE);
dsl_probe_cali_fgain(devc, probe1, 1, TRUE, TRUE);
dsl_config_adc_fgain(sdi, 0, probe0->cali_comb_fgain0, probe0->cali_comb_fgain1);
dsl_config_adc_fgain(sdi, 1, probe0->cali_comb_fgain2, probe0->cali_comb_fgain3);
dsl_config_adc_fgain(sdi, 2, probe1->cali_comb_fgain0, probe1->cali_comb_fgain1);
dsl_config_adc_fgain(sdi, 3, probe1->cali_comb_fgain2, probe1->cali_comb_fgain3);
} else if (devc->zero_pcnt == 1*zero_interval) {
if (!devc->zero_comb)
devc->zero_pcnt = 0*zero_interval+1;
} else if (devc->zero_pcnt == branch_done_cnt*zero_interval) {
acc_mean = (devc->mstatus.ch0_acc_mean + devc->mstatus.ch0_acc_mean_p1 +
devc->mstatus.ch0_acc_mean_p2 + devc->mstatus.ch0_acc_mean_p3 +
devc->mstatus.ch1_acc_mean + devc->mstatus.ch1_acc_mean_p1 +
devc->mstatus.ch1_acc_mean_p2 + devc->mstatus.ch1_acc_mean_p3) / 8.0;
acc_skew[0] = devc->mstatus.ch0_acc_mean / acc_mean - 1;
acc_skew[1] = devc->mstatus.ch0_acc_mean_p1 / acc_mean - 1;
acc_skew[2] = devc->mstatus.ch0_acc_mean_p2 / acc_mean - 1;
acc_skew[3] = devc->mstatus.ch0_acc_mean_p3 / acc_mean - 1;
acc_skew[4] = devc->mstatus.ch1_acc_mean / acc_mean - 1;
acc_skew[5] = devc->mstatus.ch1_acc_mean_p1 / acc_mean - 1;
acc_skew[6] = devc->mstatus.ch1_acc_mean_p2 / acc_mean - 1;
acc_skew[7] = devc->mstatus.ch1_acc_mean_p3 / acc_mean - 1;
acc_max_skew = fabs(acc_skew[0]);
for (int i=1; i <8; i++)
acc_max_skew = max(acc_max_skew, fabs(acc_skew[i]));
if ((acc_max_skew > MAX_ACC_VARIANCE) && (dsl_probe_fgain_inrange(probe0, TRUE, acc_skew) ||
dsl_probe_fgain_inrange(probe1, TRUE, acc_skew))) {
devc->zero_pcnt = 0*zero_interval+1;
dsl_probe_cali_fgain(devc, probe0, acc_mean, TRUE, FALSE);
dsl_probe_cali_fgain(devc, probe1, acc_mean, TRUE, FALSE);
dsl_config_adc_fgain(sdi, 0, probe0->cali_comb_fgain0, probe0->cali_comb_fgain1);
dsl_config_adc_fgain(sdi, 1, probe0->cali_comb_fgain2, probe0->cali_comb_fgain3);
dsl_config_adc_fgain(sdi, 2, probe1->cali_comb_fgain0, probe1->cali_comb_fgain1);
dsl_config_adc_fgain(sdi, 3, probe1->cali_comb_fgain2, probe1->cali_comb_fgain3);
} else {
if (acc_max_skew <= MAX_ACC_VARIANCE) {
devc->zero_comb_fgain = FALSE;
devc->zero_branch = FALSE;
} else {
devc->zero_pcnt = 0*zero_interval;
dsl_skew_fpga_fgain(sdi, TRUE, acc_skew);
}
}
}
}
end_cnt = branch_done_cnt*zero_interval + 1;
} else {
if (devc->zero_pcnt == 0*zero_interval+1) {
ret = dsl_wr_reg(sdi, COMB_ADDR+6, 0b1101);
wr_cmd.header.dest = DSL_CTL_DSO_EN1;
wr_cmd.data[0] = (uint8_t)~bmCH_CH1;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
probe0->zero_offset = offset_top;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
} else if (devc->zero_pcnt == 1*zero_interval) {
probe0->comb_diff_top = ((devc->mstatus.ch0_acc_mean * 2.0 - devc->mstatus.ch1_acc_mean * 2.0) / devc->limit_samples);
probe0->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
} else if (devc->zero_pcnt == 2*zero_interval) {
probe0->comb_diff_bom = ((devc->mstatus.ch0_acc_mean * 2.0 - devc->mstatus.ch1_acc_mean * 2.0) / devc->limit_samples);
}
if (devc->zero_pcnt == 2*zero_interval+1) {
ret = dsl_wr_reg(sdi, COMB_ADDR+6, 0b1110);
wr_cmd.header.dest = DSL_CTL_DSO_EN1;
wr_cmd.data[0] = bmCH_CH1;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
wr_cmd.header.dest = DSL_CTL_DSO_EN0;
wr_cmd.data[0] = (uint8_t)~bmCH_CH0;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
probe1->zero_offset = offset_top;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe1, SR_CONF_PROBE_OFFSET));
} else if (devc->zero_pcnt == 3*zero_interval) {
probe1->comb_diff_top = ((devc->mstatus.ch1_acc_mean * 2.0 - devc->mstatus.ch0_acc_mean * 2.0) / devc->limit_samples);
probe1->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe1, SR_CONF_PROBE_OFFSET));
} else if (devc->zero_pcnt == 4*zero_interval) {
probe1->comb_diff_bom = ((devc->mstatus.ch1_acc_mean * 2.0 - devc->mstatus.ch0_acc_mean * 2.0) / devc->limit_samples);
}
end_cnt = 4*zero_interval+1;
}
if (ret == SR_OK)
devc->zero_pcnt++;
if (devc->zero_pcnt == end_cnt) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->vdiv = vdiv_back[probe->index];
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_VDIV));
// vgain tunning
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_AUTO_VGAIN) {
if (probe->vga_ptr != NULL) {
for (uint16_t i = 0; devc->profile->dev_caps.vdivs[i]; i++) {
for (uint16_t j = 0; j < ARRAY_SIZE(vga_defaults); j++) {
if (vga_defaults[j].id == devc->profile->dev_caps.vga_id &&
vga_defaults[j].key == devc->profile->dev_caps.vdivs[i]) {
const int64_t vgain_delta = probe->vpos_trans > devc->profile->dev_caps.default_pwmtrans ?
((int64_t)(probe->vpos_trans - devc->profile->dev_caps.default_pwmtrans) << 8) :
(((int64_t)(probe->vpos_trans - devc->profile->dev_caps.default_pwmtrans) << 7) & 0xFFFFFF00);
(probe->vga_ptr+i)->vgain = vga_defaults[j].vgain + vgain_delta;
break;
}
}
}
}
}
}
ret = dsl_wr_reg(sdi, COMB_ADDR+6, 0b0011);
wr_cmd.header.dest = DSL_CTL_DSO_EN0;
wr_cmd.data[0] = bmCH_CH0;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
wr_cmd.header.dest = DSL_CTL_DSO_EN1;
wr_cmd.data[0] = bmCH_CH1;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
devc->zero = FALSE;
warm_done = FALSE;
trans_fix_done = FALSE;
mid_zero_done = FALSE;
vdiv_back[0] = 0;
vdiv_back[1] = 0;
dso_init(sdi);
}
}
return ret;
}
static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
const struct sr_channel *ch,
const struct sr_channel_group *cg)
......@@ -651,9 +1064,9 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
*data = g_variant_new_uint64(dso_vga(ch)>>8);
break;
case SR_CONF_PROBE_COMB_COMP_EN:
if (!sdi || !ch)
if (!sdi)
return SR_ERR;
*data = g_variant_new_boolean(devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511);
*data = g_variant_new_boolean((devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511) != 0);
break;
case SR_CONF_PROBE_COMB_COMP:
if (!sdi || !ch)
......@@ -1065,6 +1478,8 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
}
}
}
} else {
dso_zero(sdi, TRUE);
}
} else if (id == SR_CONF_ZERO_DEFAULT) {
unsigned int i, j;
......@@ -1072,6 +1487,15 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->vpos_trans = devc->profile->dev_caps.default_pwmtrans;
probe->comb_comp = devc->profile->dev_caps.default_comb_comp;
probe->digi_fgain = 0;
probe->cali_fgain0 = 1;
probe->cali_fgain1 = 1;
probe->cali_fgain2 = 1;
probe->cali_fgain3 = 1;
probe->cali_comb_fgain0 = 1;
probe->cali_comb_fgain1 = 1;
probe->cali_comb_fgain2 = 1;
probe->cali_comb_fgain3 = 1;
if (probe->vga_ptr != NULL) {
for (i = 0; devc->profile->dev_caps.vdivs[i]; i++) {
for (j = 0; j < ARRAY_SIZE(vga_defaults); j++) {
......@@ -1120,6 +1544,16 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
*(preoff_ptr+2*i+2) = (probe->vpos_trans&0x00FF);
*(preoff_ptr+2*i+3) = (probe->vpos_trans>>8);
*(preoff_ptr+2*i+4) = probe->comb_comp;
*(preoff_ptr+2*i+5) = (probe->digi_fgain&0x00FF);
*(preoff_ptr+2*i+6) = (probe->digi_fgain>>8);
*(preoff_ptr+2*i+7) = dsl_adc_fgain2code(probe->cali_fgain0);
*(preoff_ptr+2*i+8) = dsl_adc_fgain2code(probe->cali_fgain1);
*(preoff_ptr+2*i+9) = dsl_adc_fgain2code(probe->cali_fgain2);
*(preoff_ptr+2*i+10) = dsl_adc_fgain2code(probe->cali_fgain3);
*(preoff_ptr+2*i+11) = dsl_adc_fgain2code(probe->cali_comb_fgain0);
*(preoff_ptr+2*i+12) = dsl_adc_fgain2code(probe->cali_comb_fgain1);
*(preoff_ptr+2*i+13) = dsl_adc_fgain2code(probe->cali_comb_fgain2);
*(preoff_ptr+2*i+14) = dsl_adc_fgain2code(probe->cali_comb_fgain3);
vga_info.vga_addr = zero_info.zero_addr + sizeof(struct cmd_zero_info);
uint16_t *vgain_ptr = &vga_info.vga0;
......@@ -1130,6 +1564,8 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
if (ret == SR_OK) {
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_SEEP)
real_zero_addr = zero_info.zero_addr;
else if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_FLASH)
real_zero_addr = probe->index * DSO_ZERO_PAGE;
else
real_zero_addr = (zero_big_addr << 8) + zero_info.zero_addr;
ret = dsl_wr_nvm(sdi, (unsigned char *)&zero_info, real_zero_addr, sizeof(struct cmd_zero_info));
......@@ -1137,6 +1573,8 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
if (ret == SR_OK) {
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_SEEP)
real_zero_addr = vga_info.vga_addr;
else if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_FLASH)
real_zero_addr = probe->index * DSO_ZERO_PAGE + 1;
else
real_zero_addr = (zero_big_addr << 8) + vga_info.vga_addr;
ret = dsl_wr_nvm(sdi, (unsigned char *)&vga_info, real_zero_addr, sizeof(struct cmd_vga_info));
......@@ -1260,269 +1698,6 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
return SR_OK;
}
static int dso_zero(const struct sr_dev_inst *sdi)
{
struct DSL_context *devc = sdi->priv;
GSList *l;
int ret;
struct sr_usb_dev_inst *usb;
struct libusb_device_handle *hdl;
struct ctl_wr_cmd wr_cmd;
static uint64_t vdiv_back[2];
struct sr_channel *probe0 = NULL, *probe1 = NULL;
const uint16_t offset_top = 20;
const uint16_t offset_bom = ((1 << channel_modes[devc->ch_mode].unit_bits) - 1) - offset_top;
const uint16_t offset_mid = (1 << (channel_modes[devc->ch_mode].unit_bits - 1));
const uint16_t max_trans = ((1 << 10) - 1);
const uint8_t value_min = 0;
const uint8_t value_max = (1 << channel_modes[devc->ch_mode].unit_bits) - 1;
const int zero_interval = 10;
const double margin_pass = 0.3;
int end_cnt = 0;
static gboolean trans_fix_done = FALSE;
static gboolean mid_zero_done = FALSE;
static double margin[2];
//static double offset[2];
usb = sdi->conn;
hdl = usb->devhdl;
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
if (probe->index == 0)
probe0 = probe;
if (probe->index == 1)
probe1 = probe;
vdiv_back[probe->index] = probe->vdiv;
}
if (!trans_fix_done && devc->zero_stage == 0) {
ret = SR_OK;
if (!(devc->profile->dev_caps.feature_caps & CAPS_FEATURE_PREOFF)) {
if (devc->zero_pcnt == 0*zero_interval) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
}
}
if (devc->zero_pcnt == 1*zero_interval) {
margin[0] = (devc->mstatus.ch0_acc_mean * 1.0 / devc->limit_samples);
margin[1] = (devc->mstatus.ch1_acc_mean * 1.0 / devc->limit_samples);
if (margin[0] >= value_max || margin[1] >= value_max)
ret = SR_ERR;
}
if (devc->zero_pcnt == 1*zero_interval+1) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->zero_offset = offset_top;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
}
}
if (devc->zero_pcnt == 2*zero_interval) {
double top0 = (devc->mstatus.ch0_acc_mean * 1.0 / devc->limit_samples);
double top1 = (devc->mstatus.ch1_acc_mean * 1.0 / devc->limit_samples);
if (top0 <= value_min || top1 <= value_min) {
ret = SR_ERR;
} else {
margin[0] -= top0;
margin[1] -= top1;
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
margin[probe->index] -= (offset_bom - offset_top);
if (fabs(margin[probe->index]) > margin_pass) {
margin[probe->index] = margin[probe->index] > 0 ? ceil(margin[probe->index]) : floor(margin[probe->index]);
probe->vpos_trans = min(probe->vpos_trans - margin[probe->index], max_trans);
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
} else {
margin[probe->index] = 0;
}
}
trans_fix_done = (margin[0] == 0) && (margin[1] == 0);
devc->zero_pcnt = trans_fix_done ? 0*zero_interval : 0*zero_interval-1;
}
}
} else {
trans_fix_done = TRUE;
}
if (!trans_fix_done && ret == SR_OK)
devc->zero_pcnt++;
} else if (!mid_zero_done) {
if (devc->zero_pcnt == 0) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->vdiv = (probe->vga_ptr+devc->zero_stage)->key;
if (probe->vdiv == 0) {
probe->vdiv = vdiv_back[probe->index];
mid_zero_done = TRUE;
break;
}
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_VDIV));
probe->zero_offset = offset_mid;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
// must after offset setting
probe->vdiv = vdiv_back[probe->index];
}
}
if (devc->zero_pcnt == zero_interval) {
margin[0] = offset_mid - (devc->mstatus.ch0_acc_mean * 1.0 / devc->limit_samples);
margin[1] = offset_mid - (devc->mstatus.ch1_acc_mean * 1.0 / devc->limit_samples);
if (fabs(margin[0]) < margin_pass && fabs(margin[1]) < margin_pass) {
devc->zero_stage++;
} else {
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_PREOFF) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
double trans_coarse = ((probe->vga_ptr+devc->zero_stage)->key < 500) ? (probe->vpos_trans >> 8)/DSCOPE_TRANS_CMULTI : (probe->vpos_trans >> 8);
double trans_fine = ((probe->vga_ptr+devc->zero_stage)->key < 500) ? (probe->vpos_trans & 0x00ff) / 1000.0 : (probe->vpos_trans & 0x00ff) / DSCOPE_TRANS_FMULTI;
double voltage_margin = margin[probe->index] * (probe->vga_ptr+devc->zero_stage)->key * 10 / 255.0;
uint16_t last_preoff = (probe->vga_ptr+devc->zero_stage)->preoff;
int preoff_coarse = floor(voltage_margin / trans_coarse + 0.5);
int preoff_fine = floor(-(voltage_margin - preoff_coarse*trans_coarse)/trans_fine + 0.5);
preoff_coarse = (last_preoff >> 10) + preoff_coarse;
preoff_fine = (last_preoff&0x03ff) + preoff_fine;
(probe->vga_ptr+devc->zero_stage)->preoff = (preoff_coarse << 10) + preoff_fine;
}
} else {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
(probe->vga_ptr+devc->zero_stage)->preoff += margin[probe->index] > 0 ? ceil(margin[probe->index]) : floor(margin[probe->index]);
}
}
}
devc->zero_pcnt = 0;
} else if (!mid_zero_done) {
devc->zero_pcnt++;
}
} else {
ret = SR_OK;
end_cnt = 0*zero_interval + 1;
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511) {
// if (devc->zero_pcnt == 0*zero_interval+1) {
// for(l = sdi->channels; l; l = l->next) {
// struct sr_channel *probe = (struct sr_channel *)l->data;
// probe->zero_offset = offset_bom;
// ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
// }
// }
// if (devc->zero_pcnt == 1*zero_interval) {
// offset[0] = (devc->mstatus.ch0_acc_mean * 1.0 / devc->limit_samples);
// offset[1] = (devc->mstatus.ch1_acc_mean * 1.0 / devc->limit_samples);
// if (margin[0] >= value_max || margin[1] >= value_max)
// ret = SR_ERR;
// }
// if (devc->zero_pcnt == 1*zero_interval+1) {
// dsl_config_adc(sdi, adc_single_ch0);
// probe0->enabled = TRUE;
// probe1->enabled = FALSE;
// probe0->zero_offset = offset_bom;
// ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
// }
// if (devc->zero_pcnt == 2*zero_interval) {
// margin[0] = offset[0] - (devc->mstatus.ch0_acc_mean * 1.0 / devc->limit_samples);
// if (fabs(margin[0]) > margin_pass) {
// probe0->comb_comp -= margin[0] > 0 ? ceil(margin[0]) : floor(margin[0]);
// ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
// devc->zero_pcnt = 1*zero_interval+1;
// }
// }
// if (devc->zero_pcnt == 2*zero_interval+1) {
// dsl_config_adc(sdi, adc_single_ch3);
// probe0->enabled = FALSE;
// probe1->enabled = TRUE;
// probe1->zero_offset = offset_bom;
// ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe1, SR_CONF_PROBE_OFFSET));
// }
// if (devc->zero_pcnt == 3*zero_interval) {
// margin[1] = offset[1] - (devc->mstatus.ch1_acc_mean * 1.0 / devc->limit_samples);
// if (fabs(margin[1]) > margin_pass) {
// probe1->comb_comp -= margin[1] > 0 ? ceil(margin[1]) : floor(margin[1]);
// ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe1, SR_CONF_PROBE_OFFSET));
// devc->zero_pcnt = 2*zero_interval+1;
// }
// }
// end_cnt = 3*zero_interval + 1;
} else {
if (devc->zero_pcnt == 0*zero_interval+1) {
ret = dsl_wr_reg(sdi, COMB_ADDR+6, 0b1101);
wr_cmd.header.dest = DSL_CTL_DSO_EN1;
wr_cmd.data[0] = (uint8_t)~bmCH_CH1;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
probe0->zero_offset = offset_top;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
} else if (devc->zero_pcnt == 1*zero_interval) {
probe0->comb_diff_top = ((devc->mstatus.ch0_acc_mean * 2.0 - devc->mstatus.ch1_acc_mean * 2.0) / devc->limit_samples);
probe0->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe0, SR_CONF_PROBE_OFFSET));
} else if (devc->zero_pcnt == 2*zero_interval) {
probe0->comb_diff_bom = ((devc->mstatus.ch0_acc_mean * 2.0 - devc->mstatus.ch1_acc_mean * 2.0) / devc->limit_samples);
}
if (devc->zero_pcnt == 2*zero_interval+1) {
ret = dsl_wr_reg(sdi, COMB_ADDR+6, 0b1110);
wr_cmd.header.dest = DSL_CTL_DSO_EN1;
wr_cmd.data[0] = bmCH_CH1;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
wr_cmd.header.dest = DSL_CTL_DSO_EN0;
wr_cmd.data[0] = (uint8_t)~bmCH_CH0;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
probe1->zero_offset = offset_top;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe1, SR_CONF_PROBE_OFFSET));
} else if (devc->zero_pcnt == 3*zero_interval) {
probe1->comb_diff_top = ((devc->mstatus.ch1_acc_mean * 2.0 - devc->mstatus.ch0_acc_mean * 2.0) / devc->limit_samples);
probe1->zero_offset = offset_bom;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe1, SR_CONF_PROBE_OFFSET));
} else if (devc->zero_pcnt == 4*zero_interval) {
probe1->comb_diff_bom = ((devc->mstatus.ch1_acc_mean * 2.0 - devc->mstatus.ch0_acc_mean * 2.0) / devc->limit_samples);
}
end_cnt = 4*zero_interval+1;
}
if (ret == SR_OK)
devc->zero_pcnt++;
if (devc->zero_pcnt == end_cnt) {
for(l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->vdiv = vdiv_back[probe->index];
// if (!(devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511))
// probe->comb_comp = ((1 << channel_modes[devc->ch_mode].unit_bits) - 1) * 0.7 * 2 /
// min(abs(probe->comb_diff_top), abs(probe->comb_diff_bom));
}
ret = dsl_wr_reg(sdi, COMB_ADDR+6, 0b0011);
wr_cmd.header.dest = DSL_CTL_DSO_EN0;
wr_cmd.data[0] = bmCH_CH0;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
wr_cmd.header.dest = DSL_CTL_DSO_EN1;
wr_cmd.data[0] = bmCH_CH1;
wr_cmd.header.size = 1;
ret = command_ctl_wr(hdl, wr_cmd);
devc->zero = FALSE;
trans_fix_done = FALSE;
mid_zero_done = FALSE;
dso_init(sdi);
}
}
return ret;
}
static int dso_tune(const struct sr_dev_inst *sdi)
{
struct DSL_context *devc = sdi->priv;
......@@ -1631,6 +1806,7 @@ static int dev_open(struct sr_dev_inst *sdi)
static int dev_close(struct sr_dev_inst *sdi)
{
int ret;
dso_zero(sdi, TRUE);
ret = dsl_dev_close(sdi);
return ret;
}
......@@ -1667,23 +1843,45 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi)
struct timeval tv;
struct drv_context *drvc;
struct DSL_context *devc;
struct ctl_rd_cmd rd_cmd;
struct sr_usb_dev_inst *usb;
int ret;
(void)fd;
(void)revents;
drvc = di->priv;
devc = sdi->priv;
usb = sdi->conn;
tv.tv_sec = tv.tv_usec = 0;
libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &tv, &completed);
if (devc->trf_completed)
devc->empty_poll_count = 0;
else
devc->empty_poll_count++;
if (devc->zero && devc->trf_completed) {
dso_zero(sdi);
dso_zero(sdi, FALSE);
}
if (devc->tune && devc->trf_completed) {
dso_tune(sdi);
}
// progress check
if ((devc->empty_poll_count > MAX_EMPTY_POLL) && (devc->status == DSL_START)) {
devc->mstatus.captured_cnt0 = 0;
rd_cmd.header.dest = DSL_CTL_I2C_STATUS;
rd_cmd.header.offset = 0;
rd_cmd.header.size = 4;
rd_cmd.data = (unsigned char*)&devc->mstatus;
if ((ret = command_ctl_rd(usb->devhdl, rd_cmd)) != SR_OK)
sr_err("Failed to get progress infos.");
devc->empty_poll_count = 0;
}
if (devc->status == DSL_FINISH) {
remove_sources(devc);
}
......@@ -1716,12 +1914,18 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data)
devc->cb_data = sdi;
devc->num_samples = 0;
devc->empty_transfer_count = 0;
devc->empty_poll_count = 0;
devc->status = DSL_INIT;
devc->num_transfers = 0;
devc->submitted_transfers = 0;
devc->actual_samples = (devc->limit_samples + 1023ULL) & ~1023ULL;
devc->actual_samples = (devc->limit_samples + SAMPLES_ALIGN) & ~SAMPLES_ALIGN;
devc->abort = FALSE;
devc->mstatus_valid = FALSE;
devc->mstatus.captured_cnt0 = 0;
devc->mstatus.captured_cnt1 = 0;
devc->mstatus.captured_cnt2 = 0;
devc->mstatus.captured_cnt3 = 0;
devc->mstatus.trig_hit = 0;
devc->overflow = FALSE;
devc->instant_tail_bytes = dsl_header_size(devc);
......@@ -1745,19 +1949,27 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data)
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_HMCAD1511) {
if (dsl_en_ch_num(sdi) == 2) {
dsl_config_adc(sdi, adc_dual_ch03);
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
dsl_config_adc_fgain(sdi, probe->index*2 + 0, probe->cali_fgain0, probe->cali_fgain1);
dsl_config_adc_fgain(sdi, probe->index*2 + 1, probe->cali_fgain2, probe->cali_fgain3);
}
} else if (dsl_en_ch_num(sdi) == 1) {
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
if (probe->enabled && probe->index == 0) {
dsl_config_adc(sdi, adc_single_ch0);
break;
} else if (probe->enabled && probe->index == 1) {
dsl_config_adc(sdi, adc_single_ch3);
break;
}
}
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
dsl_config_adc_fgain(sdi, probe->index*2 + 0, probe->cali_comb_fgain0, probe->cali_comb_fgain1);
dsl_config_adc_fgain(sdi, probe->index*2 + 1, probe->cali_comb_fgain2, probe->cali_comb_fgain3);
}
}
//dsl_config_adc(sdi, adc_power_up);
dsl_config_fpga_fgain(sdi);
}
if ((ret = dsl_fpga_arm(sdi)) != SR_OK) {
sr_err("%s: Arm FPGA failed!", __func__);
......@@ -1771,12 +1983,14 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data)
return ret;
}
devc->zero_stage = 0;
devc->zero_comb_fgain = FALSE;
devc->zero_branch = FALSE;
}
/*
* settings must be updated before acquisition
*/
if (sdi->mode == DSO) {
if (sdi->mode != LOGIC) {
devc->trigger_hpos = devc->trigger_hrate * dsl_en_ch_num(sdi) * devc->limit_samples / 200.0;
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, NULL, SR_CONF_HORIZ_TRIGGERPOS));
if (ret != SR_OK)
......@@ -1790,6 +2004,7 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data)
ret = dsl_wr_dso(sdi, dso_cmd_gen(sdi, probe, SR_CONF_PROBE_OFFSET));
if (ret != SR_OK)
sr_err("%s: Set OFFSET of channel %d command failed!", __func__, probe->index);
probe->hw_offset = probe->offset;
}
}
......@@ -1839,9 +2054,9 @@ static int dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_data)
return ret;
}
static int dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg, int begin, int end)
static int dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg)
{
int ret = dsl_dev_status_get(sdi, status, prg, begin, end);
int ret = dsl_dev_status_get(sdi, status, prg);
return ret;
}
......
......@@ -86,12 +86,20 @@ SR_PRIV void dsl_probe_init(struct sr_dev_inst *sdi)
probe->bits = channel_modes[devc->ch_mode].unit_bits;
probe->vdiv = 1000;
probe->vfactor = 1;
probe->cali_fgain0 = 1;
probe->cali_fgain1 = 1;
probe->cali_fgain2 = 1;
probe->cali_fgain3 = 1;
probe->cali_comb_fgain0 = 1;
probe->cali_comb_fgain1 = 1;
probe->cali_comb_fgain2 = 1;
probe->cali_comb_fgain3 = 1;
probe->offset = (1 << (probe->bits - 1));
probe->hw_offset = (1 << (probe->bits - 1));
probe->coupling = SR_DC_COUPLING;
probe->trig_value = (1 << (probe->bits - 1));
probe->vpos_trans = devc->profile->dev_caps.default_pwmtrans;
probe->comb_comp = devc->profile->dev_caps.default_comb_comp;
probe->digi_fgain = 0;
probe->map_default = TRUE;
probe->map_unit = probeMapUnits[0];
......@@ -421,7 +429,7 @@ SR_PRIV uint64_t dsl_channel_depth(const struct sr_dev_inst *sdi)
{
struct DSL_context *devc = sdi->priv;
int ch_num = dsl_en_ch_num(sdi);
return devc->profile->dev_caps.hw_depth / (ch_num ? ch_num : 1);
return (devc->profile->dev_caps.hw_depth / (ch_num ? ch_num : 1)) & ~SAMPLES_ALIGN;
}
SR_PRIV int dsl_wr_reg(const struct sr_dev_inst *sdi, uint8_t addr, uint8_t value)
......@@ -675,6 +683,282 @@ SR_PRIV int dsl_config_adc(const struct sr_dev_inst *sdi, const struct DSL_adc_c
return SR_OK;
}
SR_PRIV double dsl_adc_code2fgain(uint8_t code)
{
double xcode = code & 0x40 ? -(~code & 0x3F) : code & 0x3F;
return (1 + xcode / (1 << 13));
}
SR_PRIV uint8_t dsl_adc_fgain2code(double gain)
{
int xratio = (gain - 1) * (1 << 13);
uint8_t code = xratio > 63 ? 63 :
xratio > 0 ? xratio :
xratio < -63 ? 64 : ~(-xratio) & 0x7F;
return code;
}
SR_PRIV int dsl_config_adc_fgain(const struct sr_dev_inst *sdi, uint8_t branch, double gain0, double gain1)
{
dsl_wr_reg(sdi, ADCC_ADDR, 0x00);
dsl_wr_reg(sdi, ADCC_ADDR, dsl_adc_fgain2code(gain0));
dsl_wr_reg(sdi, ADCC_ADDR, dsl_adc_fgain2code(gain1));
dsl_wr_reg(sdi, ADCC_ADDR, 0x34 + branch);
return SR_OK;
}
SR_PRIV int dsl_config_fpga_fgain(const struct sr_dev_inst *sdi)
{
GSList *l;
int ret = SR_OK;
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
if (probe->index == 0) {
ret = dsl_wr_reg(sdi, ADCC_ADDR+3, (probe->digi_fgain & 0x00FF));
ret = dsl_wr_reg(sdi, ADCC_ADDR+4, (probe->digi_fgain >> 8));
} else if (probe->index == 1) {
ret = dsl_wr_reg(sdi, ADCC_ADDR+5, (probe->digi_fgain & 0x00FF));
ret = dsl_wr_reg(sdi, ADCC_ADDR+6, (probe->digi_fgain >>8));
}
}
return ret;
}
SR_PRIV int dsl_skew_fpga_fgain(const struct sr_dev_inst *sdi, gboolean comb, double skew[])
{
uint8_t fgain_up = 0;
uint8_t fgain_dn = 0;
GSList *l;
gboolean tmp;
int ret;
for (int i = 0; i <= 7; i++) {
tmp = (-skew[i] > 1.6*MAX_ACC_VARIANCE);
fgain_up += (tmp << i);
}
if (comb) {
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
if (probe->index == 0) {
probe->digi_fgain |= (probe->digi_fgain & 0xFF00) + fgain_up;
fgain_up = (probe->digi_fgain & 0x00FF);
break;
}
}
ret = dsl_wr_reg(sdi, ADCC_ADDR+3, fgain_up);
} else {
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
if (probe->index == 0) {
probe->digi_fgain |= (fgain_up << 8) + (probe->digi_fgain & 0x00FF);
fgain_up = (probe->digi_fgain>>8);
break;
}
}
ret = dsl_wr_reg(sdi, ADCC_ADDR+4, fgain_up);
}
for (int i = 0; i <= 7; i++) {
tmp = (skew[i] > 1.6*MAX_ACC_VARIANCE);
fgain_dn += (tmp << i);
}
if (comb) {
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
if (probe->index == 1) {
probe->digi_fgain |= (probe->digi_fgain & 0xFF00) + fgain_dn;
fgain_dn = (probe->digi_fgain & 0x00FF);
break;
}
}
ret = dsl_wr_reg(sdi, ADCC_ADDR+5, fgain_dn);
} else {
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
if (probe->index == 1) {
probe->digi_fgain |= (fgain_dn << 8) + (probe->digi_fgain & 0x00FF);
fgain_dn = (probe->digi_fgain>>8);
break;
}
}
ret = dsl_wr_reg(sdi, ADCC_ADDR+6, fgain_dn);
}
return ret;
}
SR_PRIV int dsl_probe_cali_fgain(struct DSL_context *devc, struct sr_channel *probe, double mean, gboolean comb, gboolean reset)
{
const double UPGAIN = 1.0077;
const double DNGAIN = 0.9923;
const double MDGAIN = 1;
const double ignore_ratio = 2.0;
const double ratio = 2.0;
double drift;
if (reset) {
if (comb) {
probe->cali_comb_fgain0 = MDGAIN;
probe->cali_comb_fgain1 = MDGAIN;
probe->cali_comb_fgain2 = MDGAIN;
probe->cali_comb_fgain3 = MDGAIN;
} else {
probe->cali_fgain0 = MDGAIN;
probe->cali_fgain1 = MDGAIN;
probe->cali_fgain2 = MDGAIN;
probe->cali_fgain3 = MDGAIN;
}
} else {
if (comb) {
/*
* not consist with hmcad1511 datasheet
*
* byte order | acc_mean | single channel branch (datasheet)
* 0 ch0_acc_mean 1 (0->cali_comb_fgain0)
* 1 ch1_acc_mean 6 (1->cali_comb_fgain1)
* 2 ch0_acc_mean_p1 2 (0->cali_comb_fgain1)
* 3 ch1_acc_mean_p1 5 (1->cali_comb_fgain0)
* 4 ch0_acc_mean_p2 8 (1->cali_comb_fgain3)
* 5 ch1_acc_mean_p2 3 (0->cali_comb_fgain2)
* 6 ch0_acc_mean_p3 7 (1->cali_comb_fgain2)
* 7 ch1_acc_mean_p3 4 (0->cali_comb_fgain3)
*/
if (probe->index == 0) {
drift = (devc->mstatus.ch0_acc_mean / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_comb_fgain0 /= (1 + drift);
drift = (devc->mstatus.ch0_acc_mean_p1 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_comb_fgain1 /= (1 + drift);
drift = (devc->mstatus.ch1_acc_mean_p2 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_comb_fgain2 /= (1 + drift);
drift = (devc->mstatus.ch1_acc_mean_p3 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_comb_fgain3 /= (1 + drift);
} else {
drift = (devc->mstatus.ch1_acc_mean_p1 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_comb_fgain0 /= (1 + drift);
drift = (devc->mstatus.ch1_acc_mean / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_comb_fgain1 /= (1 + drift);
drift = (devc->mstatus.ch0_acc_mean_p3 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_comb_fgain2 /= (1 + drift);
drift = (devc->mstatus.ch0_acc_mean_p2 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_comb_fgain3 /= (1 + drift);
}
probe->cali_comb_fgain0 = max(min(probe->cali_comb_fgain0, UPGAIN), DNGAIN);
probe->cali_comb_fgain1 = max(min(probe->cali_comb_fgain1, UPGAIN), DNGAIN);
probe->cali_comb_fgain2 = max(min(probe->cali_comb_fgain2, UPGAIN), DNGAIN);
probe->cali_comb_fgain3 = max(min(probe->cali_comb_fgain3, UPGAIN), DNGAIN);
} else {
/*
* byte order | acc_mean | dual channel branch
* 0 ch0_acc_mean 1 (0->cali_fgain0)
* 1 ch0_acc_mean_p1 3 (0->cali_fgain2)
* 2 ch0_acc_mean_p2 2 (0->cali_fgain1)
* 3 ch0_acc_mean_p3 4 (0->cali_fgain3)
* 4 ch1_acc_mean 5 (1->cali_fgain0)
* 5 ch1_acc_mean_p1 7 (1->cali_fgain2)
* 6 ch1_acc_mean_p2 6 (1->cali_fgain1)
* 7 ch1_acc_mean_p3 8 (1->cali_fgain3)
*/
if (probe->index == 0) {
drift = (devc->mstatus.ch0_acc_mean / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_fgain0 /= (1 + drift);
drift = (devc->mstatus.ch0_acc_mean_p2 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_fgain1 /= (1 + drift);
drift = (devc->mstatus.ch0_acc_mean_p1 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_fgain2 /= (1 + drift);
drift = (devc->mstatus.ch0_acc_mean_p3 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_fgain3 /= (1 + drift);
} else {
drift = (devc->mstatus.ch1_acc_mean / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_fgain0 /= (1 + drift);
drift = (devc->mstatus.ch1_acc_mean_p2 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_fgain1 /= (1 + drift);
drift = (devc->mstatus.ch1_acc_mean_p1 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_fgain2 /= (1 + drift);
drift = (devc->mstatus.ch1_acc_mean_p3 / mean - 1) / ratio;
if (fabs(drift) > MAX_ACC_VARIANCE / ignore_ratio)
probe->cali_fgain3 /= (1 + drift);
}
probe->cali_fgain0 = max(min(probe->cali_fgain0, UPGAIN), DNGAIN);
probe->cali_fgain1 = max(min(probe->cali_fgain1, UPGAIN), DNGAIN);
probe->cali_fgain2 = max(min(probe->cali_fgain2, UPGAIN), DNGAIN);
probe->cali_fgain3 = max(min(probe->cali_fgain3, UPGAIN), DNGAIN);
}
}
return SR_OK;
}
SR_PRIV gboolean dsl_probe_fgain_inrange(struct sr_channel *probe, gboolean comb, double skew[])
{
const double UPGAIN = 1.0077;
const double DNGAIN = 0.9923;
if (comb) {
if (probe->index == 0) {
if (fabs(skew[0]) > MAX_ACC_VARIANCE && probe->cali_comb_fgain0 > DNGAIN && probe->cali_comb_fgain0 < UPGAIN)
return TRUE;
if (fabs(skew[1]) > MAX_ACC_VARIANCE && probe->cali_comb_fgain1 > DNGAIN && probe->cali_comb_fgain1 < UPGAIN)
return TRUE;
if (fabs(skew[6]) > MAX_ACC_VARIANCE && probe->cali_comb_fgain2 > DNGAIN && probe->cali_comb_fgain2 < UPGAIN)
return TRUE;
if (fabs(skew[7]) > MAX_ACC_VARIANCE && probe->cali_comb_fgain3 > DNGAIN && probe->cali_comb_fgain3 < UPGAIN)
return TRUE;
} else {
if (fabs(skew[5]) > MAX_ACC_VARIANCE && probe->cali_comb_fgain0 > DNGAIN && probe->cali_comb_fgain0 < UPGAIN)
return TRUE;
if (fabs(skew[4]) > MAX_ACC_VARIANCE && probe->cali_comb_fgain1 > DNGAIN && probe->cali_comb_fgain1 < UPGAIN)
return TRUE;
if (fabs(skew[3]) > MAX_ACC_VARIANCE && probe->cali_comb_fgain2 > DNGAIN && probe->cali_comb_fgain2 < UPGAIN)
return TRUE;
if (fabs(skew[2]) > MAX_ACC_VARIANCE && probe->cali_comb_fgain3 > DNGAIN && probe->cali_comb_fgain3 < UPGAIN)
return TRUE;
}
} else {
if (probe->index == 0) {
if (fabs(skew[0]) > MAX_ACC_VARIANCE && probe->cali_fgain0 > DNGAIN && probe->cali_fgain0 < UPGAIN)
return TRUE;
if (fabs(skew[2]) > MAX_ACC_VARIANCE && probe->cali_fgain1 > DNGAIN && probe->cali_fgain1 < UPGAIN)
return TRUE;
if (fabs(skew[1]) > MAX_ACC_VARIANCE && probe->cali_fgain2 > DNGAIN && probe->cali_fgain2 < UPGAIN)
return TRUE;
if (fabs(skew[3]) > MAX_ACC_VARIANCE && probe->cali_fgain3 > DNGAIN && probe->cali_fgain3 < UPGAIN)
return TRUE;
} else {
if (fabs(skew[4]) > MAX_ACC_VARIANCE && probe->cali_fgain0 > DNGAIN && probe->cali_fgain0 < UPGAIN)
return TRUE;
if (fabs(skew[6]) > MAX_ACC_VARIANCE && probe->cali_fgain1 > DNGAIN && probe->cali_fgain1 < UPGAIN)
return TRUE;
if (fabs(skew[5]) > MAX_ACC_VARIANCE && probe->cali_fgain2 > DNGAIN && probe->cali_fgain2 < UPGAIN)
return TRUE;
if (fabs(skew[7]) > MAX_ACC_VARIANCE && probe->cali_fgain3 > DNGAIN && probe->cali_fgain3 < UPGAIN)
return TRUE;
}
}
return FALSE;
}
SR_PRIV int dsl_rd_probe(const struct sr_dev_inst *sdi, unsigned char *ctx, uint16_t addr, uint8_t len)
{
struct sr_usb_dev_inst *usb;
......@@ -802,6 +1086,13 @@ SR_PRIV int dsl_fpga_arm(const struct sr_dev_inst *sdi)
setting.ch_en_h += probe->enabled << (probe->index - 16);
}
// digital fgain
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
setting.fgain = probe->digi_fgain;
break;
}
// trigger advanced configuration
if (trigger->trigger_mode == SIMPLE_TRIGGER) {
qutr_trig = !(devc->profile->dev_caps.feature_caps & CAPS_FEATURE_USB30) && (setting.mode & (1 << QUAR_MODE_BIT));
......@@ -1156,7 +1447,7 @@ SR_PRIV int dsl_config_get(int id, GVariant **data, const struct sr_dev_inst *sd
case SR_CONF_USB30_SUPPORT:
if (!sdi)
return SR_ERR;
*data = g_variant_new_boolean(devc->profile->dev_caps.feature_caps & CAPS_FEATURE_USB30);
*data = g_variant_new_boolean((devc->profile->dev_caps.feature_caps & CAPS_FEATURE_USB30) != 0);
break;
case SR_CONF_LIMIT_SAMPLES:
if (!sdi)
......@@ -1171,7 +1462,10 @@ SR_PRIV int dsl_config_get(int id, GVariant **data, const struct sr_dev_inst *sd
case SR_CONF_RLE_SUPPORT:
if (!sdi)
return SR_ERR;
*data = g_variant_new_boolean(devc->rle_support);
if ((devc->test_mode != SR_TEST_NONE))
*data = g_variant_new_boolean(FALSE);
else
*data = g_variant_new_boolean(devc->rle_support);
break;
case SR_CONF_CLOCK_TYPE:
if (!sdi)
......@@ -1280,7 +1574,7 @@ SR_PRIV int dsl_config_get(int id, GVariant **data, const struct sr_dev_inst *sd
case SR_CONF_HAVE_ZERO:
if (!sdi)
return SR_ERR;
*data = g_variant_new_boolean(devc->profile->dev_caps.feature_caps & CAPS_FEATURE_ZERO);
*data = g_variant_new_boolean((devc->profile->dev_caps.feature_caps & CAPS_FEATURE_ZERO) != 0);
break;
case SR_CONF_ZERO:
if (!sdi)
......@@ -1290,6 +1584,11 @@ SR_PRIV int dsl_config_get(int id, GVariant **data, const struct sr_dev_inst *sd
else
*data = g_variant_new_boolean(FALSE);
break;
case SR_CONF_ZERO_COMB_FGAIN:
if (!sdi)
return SR_ERR;
*data = g_variant_new_boolean(devc->zero_comb_fgain);
break;
case SR_CONF_ROLL:
if (!sdi)
return SR_ERR;
......@@ -1362,6 +1661,8 @@ SR_PRIV int dsl_config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
if (id == SR_CONF_LANGUAGE) {
devc->language = g_variant_get_int16(data);
} else if (id == SR_CONF_ZERO_COMB) {
devc->zero_comb = g_variant_get_boolean(data);
} else if (id == SR_CONF_PROBE_MAP_DEFAULT) {
ch->map_default = g_variant_get_boolean(data);
if (ch->map_default) {
......@@ -1579,24 +1880,14 @@ SR_PRIV int dsl_dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_dat
return SR_OK;
}
SR_PRIV int dsl_dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg, int begin, int end)
SR_PRIV int dsl_dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg)
{
int ret = SR_ERR;
struct ctl_rd_cmd rd_cmd;
if (sdi) {
struct DSL_context *devc;
struct sr_usb_dev_inst *usb;
devc = sdi->priv;
usb = sdi->conn;
if (prg && (devc->status == DSL_START)) {
rd_cmd.header.dest = DSL_CTL_I2C_STATUS;
rd_cmd.header.offset = begin;
rd_cmd.header.size = end - begin + 1;
rd_cmd.data = (unsigned char*)status;
ret = command_ctl_rd(usb->devhdl, rd_cmd);
} else if (devc->mstatus_valid) {
if (prg || devc->mstatus_valid) {
*status = devc->mstatus;
ret = SR_OK;
}
......@@ -1630,7 +1921,7 @@ static unsigned int to_bytes_per_ms(struct DSL_context *devc)
if (devc->cur_samplerate > SR_MHZ(100))
return SR_MHZ(100) / 1000.0 * dsl_en_ch_num(sdi);
else
return ceil(devc->cur_samplerate / 1000.0 * dsl_en_ch_num(sdi));
return ceil(max(devc->cur_samplerate, channel_modes[devc->ch_mode].hw_min_samplerate) / 1000.0 * dsl_en_ch_num(sdi));
}
}
......@@ -1638,7 +1929,7 @@ SR_PRIV int dsl_header_size(const struct DSL_context *devc)
{
int size;
if (devc->profile->usb_speed == LIBUSB_SPEED_SUPER)
if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_USB30)
size = SR_KB(1);
else
size = SR_B(512);
......@@ -1660,7 +1951,11 @@ static size_t get_buffer_size(const struct sr_dev_inst *sdi)
} else {
s = (devc->stream) ? get_single_buffer_time(devc) * to_bytes_per_ms(devc) : 1024*1024;
}
return (s + 511ULL) & ~511ULL;
if (devc->profile->usb_speed == LIBUSB_SPEED_SUPER)
return (s + 1023ULL) & ~1023ULL;
else
return (s + 511ULL) & ~511ULL;
}
static unsigned int get_number_of_transfers(const struct sr_dev_inst *sdi)
......@@ -1673,7 +1968,8 @@ static unsigned int get_number_of_transfers(const struct sr_dev_inst *sdi)
/* Total buffer size should be able to hold about 100ms of data. */
n = (devc->stream) ? ceil(get_total_buffer_time(devc) * 1.0f * to_bytes_per_ms(devc) / get_buffer_size(sdi)) : 1;
#else
n = (devc->stream) ? ceil(get_total_buffer_time(devc) * 1.0f * to_bytes_per_ms(devc) / get_buffer_size(sdi)) : 4;
n = (devc->stream) ? ceil(get_total_buffer_time(devc) * 1.0f * to_bytes_per_ms(devc) / get_buffer_size(sdi)) :
(devc->profile->usb_speed == LIBUSB_SPEED_SUPER) ? 16 : 4;
#endif
if (n > NUM_SIMUL_TRANSFERS)
......@@ -1695,7 +1991,7 @@ SR_PRIV unsigned int dsl_get_timeout(const struct sr_dev_inst *sdi)
if (devc->stream)
return timeout + timeout / 4; /* Leave a headroom of 25% percent. */
else
return 1000;
return 20;
}
static void finish_acquisition(struct DSL_context *devc)
......@@ -1756,6 +2052,7 @@ static void get_measure(const struct sr_dev_inst *sdi, uint8_t *buf, uint32_t of
{
uint64_t u64_tmp;
struct DSL_context *devc = sdi->priv;
GSList *l;
devc->mstatus.pkt_id = *((const uint16_t*)buf + offset);
devc->mstatus.vlen = *((const uint32_t*)buf + offset/2 + 2/2) & 0x0fffffff;
......@@ -1779,8 +2076,11 @@ static void get_measure(const struct sr_dev_inst *sdi, uint8_t *buf, uint32_t of
devc->mstatus.ch0_low_level = *((const uint8_t*)buf + offset*2 + 43*2+1);
devc->mstatus.ch0_cyc_rlen = *((const uint32_t*)buf + offset/2 + 44/2);
devc->mstatus.ch0_cyc_flen = *((const uint32_t*)buf + offset/2 + 46/2);
devc->mstatus.ch0_acc_square = *((const uint64_t*)buf + offset/4 + 48/4);
devc->mstatus.ch0_acc_square = *((const uint64_t*)buf + offset/4 + 48/4) & 0x0000FFFFFFFFFFFF;
devc->mstatus.ch0_acc_mean = *((const uint32_t*)buf + offset/2 + 52/2);
devc->mstatus.ch0_acc_mean_p1 = *((const uint32_t*)buf + offset/2 + 54/2);
devc->mstatus.ch0_acc_mean_p2 = *((const uint32_t*)buf + offset/2 + 56/2);
devc->mstatus.ch0_acc_mean_p3 = *((const uint32_t*)buf + offset/2 + 58/2);
devc->mstatus.ch1_max = *((const uint8_t*)buf + offset*2 + 65*2);
devc->mstatus.ch1_min = *((const uint8_t*)buf + offset*2 + 65*2+1);
......@@ -1794,16 +2094,46 @@ static void get_measure(const struct sr_dev_inst *sdi, uint8_t *buf, uint32_t of
devc->mstatus.ch1_low_level = *((const uint8_t*)buf + offset*2 + 75*2+1);
devc->mstatus.ch1_cyc_rlen = *((const uint32_t*)buf + offset/2 + 76/2);
devc->mstatus.ch1_cyc_flen = *((const uint32_t*)buf + offset/2 + 78/2);
devc->mstatus.ch1_acc_square = *((const uint64_t*)buf + offset/4 + 80/4);
devc->mstatus.ch1_acc_square = *((const uint64_t*)buf + offset/4 + 80/4) & 0x0000FFFFFFFFFFFF;
devc->mstatus.ch1_acc_mean = *((const uint32_t*)buf + offset/2 + 84/2);
devc->mstatus.ch1_acc_mean_p1 = *((const uint32_t*)buf + offset/2 + 86/2);
devc->mstatus.ch1_acc_mean_p2 = *((const uint32_t*)buf + offset/2 + 88/2);
devc->mstatus.ch1_acc_mean_p3 = *((const uint32_t*)buf + offset/2 + 90/2);
if (!devc->zero_branch) {
devc->mstatus.ch0_acc_mean += devc->mstatus.ch0_acc_mean_p1;
devc->mstatus.ch0_acc_mean += devc->mstatus.ch0_acc_mean_p2;
devc->mstatus.ch0_acc_mean += devc->mstatus.ch0_acc_mean_p3;
devc->mstatus.ch1_acc_mean += devc->mstatus.ch1_acc_mean_p1;
devc->mstatus.ch1_acc_mean += devc->mstatus.ch1_acc_mean_p2;
devc->mstatus.ch1_acc_mean += devc->mstatus.ch1_acc_mean_p3;
if (1 == dsl_en_ch_num(sdi)) {
u64_tmp = devc->mstatus.ch0_acc_square + devc->mstatus.ch1_acc_square;
devc->mstatus.ch0_acc_square = u64_tmp;
devc->mstatus.ch1_acc_square = u64_tmp;
u64_tmp = devc->mstatus.ch0_acc_mean + devc->mstatus.ch1_acc_mean;
devc->mstatus.ch0_acc_mean = u64_tmp;
devc->mstatus.ch1_acc_mean = u64_tmp;
}
}
devc->mstatus_valid = FALSE;
const uint32_t divider = devc->zero ? 0x1 : (uint32_t)ceil(channel_modes[devc->ch_mode].max_samplerate * 1.0 / devc->cur_samplerate / dsl_en_ch_num(sdi));
if (devc->instant) {
devc->mstatus_valid = (devc->mstatus.pkt_id == DSO_PKTID);
} else if (devc->mstatus.pkt_id == DSO_PKTID &&
devc->mstatus.sample_divider == divider &&
devc->mstatus.vlen != 0) {
devc->mstatus_valid = TRUE;
}
if (1 == dsl_en_ch_num(sdi)) {
u64_tmp = devc->mstatus.ch0_acc_square + devc->mstatus.ch1_acc_square;
devc->mstatus.ch0_acc_square = u64_tmp;
devc->mstatus.ch1_acc_square = u64_tmp;
u64_tmp = devc->mstatus.ch0_acc_mean + devc->mstatus.ch1_acc_mean;
devc->mstatus.ch0_acc_mean = u64_tmp;
devc->mstatus.ch0_acc_mean = u64_tmp;
if (devc->mstatus_valid) {
for (l = sdi->channels; l; l = l->next) {
struct sr_channel *probe = (struct sr_channel *)l->data;
probe->hw_offset = *((const uint8_t*)buf + offset*2 + (51 + 32*probe->index)*2);
}
}
}
......@@ -1856,16 +2186,13 @@ static void receive_transfer(struct libusb_transfer *transfer)
get_measure(sdi, cur_buf, offset);
} else {
devc->mstatus.vlen = get_buffer_size(sdi) / channel_modes[devc->ch_mode].num;
devc->mstatus.trig_offset = 0;
devc->mstatus.sample_divider_tog = FALSE;
devc->mstatus_valid = TRUE;
}
const uint32_t divider = devc->zero ? 0x1 : (uint32_t)ceil(channel_modes[devc->ch_mode].max_samplerate * 1.0 / devc->cur_samplerate / dsl_en_ch_num(sdi));
if ((devc->mstatus.pkt_id == DSO_PKTID &&
devc->mstatus.sample_divider == divider &&
devc->mstatus.vlen != 0 &&
devc->mstatus.vlen <= (uint32_t)(transfer->actual_length - dsl_header_size(devc)) / 2) ||
devc->instant) {
if (devc->mstatus_valid) {
devc->roll = (devc->mstatus.stream_mode != 0);
devc->mstatus_valid = devc->instant ? FALSE : TRUE;
packet.type = SR_DF_DSO;
packet.payload = &dso;
dso.probes = sdi->channels;
......@@ -1876,11 +2203,11 @@ static void receive_transfer(struct libusb_transfer *transfer)
dso.mqflags = SR_MQFLAG_AC;
dso.samplerate_tog = (devc->mstatus.sample_divider_tog != 0);
dso.trig_flag = (devc->mstatus.trig_flag != 0);
dso.data = cur_buf;
dso.trig_ch = devc->mstatus.trig_ch;
dso.data = cur_buf + (devc->zero ? 0 : 2*devc->mstatus.trig_offset);
} else {
packet.type = SR_DF_DSO;
packet.status = SR_PKT_DATA_ERROR;
devc->mstatus_valid = FALSE;
}
} else if (sdi->mode == ANALOG) {
packet.type = SR_DF_ANALOG;
......@@ -1902,14 +2229,8 @@ static void receive_transfer(struct libusb_transfer *transfer)
logic.length = min(logic.length, remain_length);
/* send data to session bus */
if (!devc->overflow) {
if (packet.status == SR_PKT_OK)
sr_session_send(sdi, &packet);
} else {
packet.type = SR_DF_OVERFLOW;
packet.payload = NULL;
if (packet.status == SR_PKT_OK)
sr_session_send(sdi, &packet);
}
}
devc->num_samples += cur_sample_count;
......@@ -1925,8 +2246,6 @@ static void receive_transfer(struct libusb_transfer *transfer)
if (over_bytes >= devc->instant_tail_bytes) {
const uint32_t offset = (transfer->actual_length - over_bytes) / 2;
get_measure(sdi, cur_buf, offset);
if (devc->mstatus.pkt_id == DSO_PKTID)
devc->mstatus_valid = TRUE;
devc->status = DSL_STOP;
} else {
......@@ -1968,7 +2287,7 @@ static void receive_header(struct libusb_transfer *transfer)
devc->stream ||
remain_cnt < devc->limit_samples) {
if (sdi->mode == LOGIC && (!devc->stream || (devc->status == DSL_ABORT))) {
devc->actual_samples = devc->limit_samples - remain_cnt;
devc->actual_samples = (devc->limit_samples - remain_cnt) & ~SAMPLES_ALIGN;
devc->actual_bytes = devc->actual_samples / DSLOGIC_ATOMIC_SAMPLES * dsl_en_ch_num(sdi) * DSLOGIC_ATOMIC_SIZE;
devc->actual_samples = devc->actual_bytes / dsl_en_ch_num(sdi) * 8;
}
......
......@@ -54,6 +54,7 @@
#define USB_CONFIGURATION 1
#define NUM_TRIGGER_STAGES 16
#define NUM_SIMUL_TRANSFERS 64
#define MAX_EMPTY_POLL 16
#define DSL_REQUIRED_VERSION_MAJOR 2
#define DSL_REQUIRED_VERSION_MINOR 0
......@@ -132,6 +133,11 @@
#define TRIG_CHECKID 0x55555555
#define DSO_PKTID 0xa500
/*
* zero configuration
*/
#define DSO_ZERO_PAGE 8
#define MAX_ACC_VARIANCE 0.0005
/*
* for DSCope device
* trans: x << 8 + y
......@@ -341,14 +347,14 @@ static const struct DSL_vga vga_defaults[] = {
{3, 1000, 0x57200, 45, 1024-920-45},
{3, 2000, 0x2DD00, 45, 1024-920-45},
{4, 10, 0x1C6C00, 45, 1024-945-45},
{4, 20, 0x19E000, 45, 1024-945-45},
{4, 50, 0x16A800, 45, 1024-945-45},
{4, 100, 0x142800, 45, 1024-945-45},
{4, 200, 0xC7F00, 45, 1024-945-45},
{4, 500, 0x94000, 45, 1024-945-45},
{4, 1000, 0x6CF00, 45, 1024-945-45},
{4, 2000, 0x44F00, 45, 1024-945-45},
{4, 10, 0x1C6C00, 60, 1024-900-60},
{4, 20, 0x19E000, 60, 1024-900-60},
{4, 50, 0x16A800, 60, 1024-900-60},
{4, 100, 0x142800, 60, 1024-900-60},
{4, 200, 0xC7F00, 60, 1024-900-60},
{4, 500, 0x94000, 60, 1024-900-60},
{4, 1000, 0x6CF00, 60, 1024-900-60},
{4, 2000, 0x44F00, 60, 1024-900-60},
{0, 0, 0, 0, 0}
};
......@@ -358,19 +364,36 @@ enum CHANNEL_ID {
DSL_STREAM25x12,
DSL_STREAM50x6,
DSL_STREAM100x3,
DSL_STREAM100x16,
DSL_STREAM125x16,
DSL_STREAM20x16_3DN2,
DSL_STREAM25x12_3DN2,
DSL_STREAM50x6_3DN2,
DSL_STREAM100x3_3DN2,
DSL_STREAM10x32_32_3DN2,
DSL_STREAM20x16_32_3DN2,
DSL_STREAM25x12_32_3DN2,
DSL_STREAM50x6_32_3DN2,
DSL_STREAM100x3_32_3DN2,
DSL_STREAM50x32,
DSL_STREAM100x30,
DSL_STREAM250x12,
DSL_STREAM125x16_16,
DSL_STREAM250x12_16,
DSL_STREAM500x6,
DSL_STREAM1000x3,
DSL_BUFFER100x16,
DSL_BUFFER200x8,
DSL_BUFFER400x4,
DSL_BUFFER250x32,
DSL_BUFFER500x16,
DSL_BUFFER1000x8,
DSL_ANALOG10x2,
DSL_ANALOG10x2_500,
DSL_DSO200x2,
DSL_DSO1000x2,
......@@ -403,15 +426,40 @@ static const struct DSL_channels channel_modes[] = {
SR_KHZ(10), SR_MHZ(100), 1, "Use 6 Channels (Max 50MHz)", "使用6个通道(最大采样率 50MHz)"},
{DSL_STREAM100x3, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 3, 1, SR_KHZ(10), SR_MHZ(100),
SR_KHZ(10), SR_MHZ(100), 1, "Use 3 Channels (Max 100MHz)", "使用3个通道(最大采样率 100MHz)"},
{DSL_STREAM100x16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(10), SR_MHZ(100),
SR_KHZ(10), SR_MHZ(500), 5, "Use 16 Channels (Max 100MHz)", "使用16个通道(最大采样率 100MHz)"},
{DSL_STREAM125x16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(10), SR_MHZ(125),
{DSL_STREAM20x16_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(10), SR_MHZ(20),
SR_KHZ(10), SR_MHZ(500), 5, "Use 16 Channels (Max 20MHz)", "使用16个通道(最大采样率 20MHz)"},
{DSL_STREAM25x12_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_KHZ(10), SR_MHZ(25),
SR_KHZ(10), SR_MHZ(500), 5, "Use 12 Channels (Max 25MHz)", "使用12个通道(最大采样率 25MHz)"},
{DSL_STREAM50x6_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 6, 1, SR_KHZ(10), SR_MHZ(50),
SR_KHZ(10), SR_MHZ(500), 5, "Use 6 Channels (Max 50MHz)", "使用6个通道(最大采样率 50MHz)"},
{DSL_STREAM100x3_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 3, 1, SR_KHZ(10), SR_MHZ(100),
SR_KHZ(10), SR_MHZ(500), 5, "Use 3 Channels (Max 100MHz)", "使用3个通道(最大采样率 100MHz)"},
{DSL_STREAM10x32_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 32, 1, SR_KHZ(10), SR_MHZ(10),
SR_KHZ(10), SR_MHZ(500), 5, "Use 32 Channels (Max 10MHz)", "使用32个通道(最大采样率 10MHz)"},
{DSL_STREAM20x16_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 16, 1, SR_KHZ(10), SR_MHZ(20),
SR_KHZ(10), SR_MHZ(500), 5, "Use 16 Channels (Max 20MHz)", "使用16个通道(最大采样率 20MHz)"},
{DSL_STREAM25x12_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 12, 1, SR_KHZ(10), SR_MHZ(25),
SR_KHZ(10), SR_MHZ(500), 5, "Use 12 Channels (Max 25MHz)", "使用12个通道(最大采样率 25MHz)"},
{DSL_STREAM50x6_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 6, 1, SR_KHZ(10), SR_MHZ(50),
SR_KHZ(10), SR_MHZ(500), 5, "Use 6 Channels (Max 50MHz)", "使用6个通道(最大采样率 50MHz)"},
{DSL_STREAM100x3_32_3DN2, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 3, 1, SR_KHZ(10), SR_MHZ(100),
SR_KHZ(10), SR_MHZ(500), 5, "Use 3 Channels (Max 100MHz)", "使用3个通道(最大采样率 100MHz)"},
{DSL_STREAM50x32, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 32, 1, SR_KHZ(10), SR_MHZ(50),
SR_KHZ(10), SR_MHZ(500), 5, "Use 32 Channels (Max 50MHz)", "使用32个通道(最大采样率 50MHz)"},
{DSL_STREAM100x30, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 30, 1, SR_KHZ(10), SR_MHZ(100),
SR_KHZ(10), SR_MHZ(500), 5, "Use 30 Channels (Max 100MHz)", "使用30个通道(最大采样率 100MHz)"},
{DSL_STREAM250x12, LOGIC, SR_CHANNEL_LOGIC, TRUE, 32, 12, 1, SR_KHZ(10), SR_MHZ(250),
SR_KHZ(10), SR_MHZ(500), 5, "Use 12 Channels (Max 250MHz)", "使用12个通道(最大采样率 250MHz)"},
{DSL_STREAM125x16_16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 16, 1, SR_KHZ(10), SR_MHZ(125),
SR_KHZ(10), SR_MHZ(500), 5, "Use 16 Channels (Max 125MHz)", "使用16个通道(最大采样率 125MHz)"},
{DSL_STREAM250x12, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_KHZ(10), SR_MHZ(250),
{DSL_STREAM250x12_16, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 12, 1, SR_KHZ(10), SR_MHZ(250),
SR_KHZ(10), SR_MHZ(500), 5, "Use 12 Channels (Max 250MHz)", "使用12个通道(最大采样率 250MHz)"},
{DSL_STREAM500x6, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 6, 1, SR_KHZ(10), SR_MHZ(500),
SR_KHZ(10), SR_MHZ(500), 5, "Use 6 Channels (Max 500MHz)", "使用6个通道(最大采样率 500MHz)"},
{DSL_STREAM1000x3, LOGIC, SR_CHANNEL_LOGIC, TRUE, 16, 3, 1, SR_KHZ(10), SR_GHZ(1),
{DSL_STREAM1000x3, LOGIC, SR_CHANNEL_LOGIC, TRUE, 8, 3, 1, SR_KHZ(10), SR_GHZ(1),
SR_KHZ(10), SR_MHZ(500), 5, "Use 3 Channels (Max 1GHz)", "使用3个通道(最大采样率 1GHz)"},
// LA Buffer
......@@ -421,6 +469,9 @@ static const struct DSL_channels channel_modes[] = {
SR_KHZ(10), SR_MHZ(100), 1, "Use Channels 0~7 (Max 200MHz)", "使用通道 0~7 (最大采样率 200MHz)"},
{DSL_BUFFER400x4, LOGIC, SR_CHANNEL_LOGIC, FALSE, 4, 4, 1, SR_KHZ(10), SR_MHZ(400),
SR_KHZ(10), SR_MHZ(100), 1, "Use Channels 0~3 (Max 400MHz)", "使用通道 0~3 (最大采样率 400MHz)"},
{DSL_BUFFER250x32, LOGIC, SR_CHANNEL_LOGIC, FALSE, 32, 32, 1, SR_KHZ(10), SR_MHZ(250),
SR_KHZ(10), SR_MHZ(500), 5, "Use Channels 0~31 (Max 250MHz)", "使用通道 0~31 (最大采样率 250MHz)"},
{DSL_BUFFER500x16, LOGIC, SR_CHANNEL_LOGIC, FALSE, 16, 16, 1, SR_KHZ(10), SR_MHZ(500),
SR_KHZ(10), SR_MHZ(500), 5, "Use Channels 0~15 (Max 500MHz)", "使用通道 0~15 (最大采样率 500MHz)"},
{DSL_BUFFER1000x8, LOGIC, SR_CHANNEL_LOGIC, FALSE, 8, 8, 1, SR_KHZ(10), SR_GHZ(1),
......@@ -429,12 +480,14 @@ static const struct DSL_channels channel_modes[] = {
// DAQ
{DSL_ANALOG10x2, ANALOG, SR_CHANNEL_ANALOG, TRUE, 2, 2, 8, SR_HZ(10), SR_MHZ(10),
SR_KHZ(10), SR_MHZ(100), 1, "Use Channels 0~1 (Max 10MHz)", "使用通道 0~1 (最大采样率 10MHz)"},
{DSL_ANALOG10x2_500, ANALOG, SR_CHANNEL_ANALOG, TRUE, 2, 2, 8, SR_HZ(10), SR_MHZ(10),
SR_KHZ(10), SR_MHZ(500), 1, "Use Channels 0~1 (Max 10MHz)", "使用通道 0~1 (最大采样率 10MHz)"},
// OSC
{DSL_DSO200x2, DSO, SR_CHANNEL_DSO, FALSE, 2, 2, 8, SR_KHZ(10), SR_MHZ(200),
SR_KHZ(10), SR_MHZ(100), 1, "Use Channels 0~1 (Max 200MHz)", "使用通道 0~1 (最大采样率 200MHz)"},
{DSL_DSO1000x2, DSO, SR_CHANNEL_DSO, FALSE, 2, 2, 8, SR_KHZ(10), SR_GHZ(1),
SR_KHZ(10), SR_MHZ(100), 1, "Use Channels 0~1 (Max 1GHz)", "使用通道 0~1 (最大采样率 1GHz)"}
SR_KHZ(10), SR_MHZ(500), 1, "Use Channels 0~1 (Max 1GHz)", "使用通道 0~1 (最大采样率 1GHz)"}
};
static const struct DSL_profile supported_DSLogic[] = {
......@@ -578,6 +631,114 @@ static const struct DSL_profile supported_DSLogic[] = {
SR_MHZ(400)}
},
{0x2A0E, 0x002A, LIBUSB_SPEED_HIGH, "DreamSourceLab", "DSLogic U3Pro16", NULL,
"DSLogicU3Pro16.fw",
"DSLogicU3Pro16.bin",
"DSLogicU3Pro16.bin",
{CAPS_MODE_LOGIC,
CAPS_FEATURE_VTH | CAPS_FEATURE_BUF | CAPS_FEATURE_USB30 | CAPS_FEATURE_ADF4360,
(1 << DSL_STREAM20x16_3DN2) | (1 << DSL_STREAM25x12_3DN2) | (1 << DSL_STREAM50x6_3DN2) | (1 << DSL_STREAM100x3_3DN2) |
(1 << DSL_BUFFER500x16) | (1 << DSL_BUFFER1000x8),
16,
SR_GB(2),
0,
DSL_BUFFER500x16,
0,
samplerates1000,
0,
DSL_STREAM20x16_3DN2,
SR_MHZ(1),
SR_Mn(1),
0,
0,
0,
0,
0,
SR_MHZ(500),
SR_GHZ(1)}
},
{0x2A0E, 0x002A, LIBUSB_SPEED_SUPER, "DreamSourceLab", "DSLogic U3Pro16", NULL,
"DSLogicU3Pro16.fw",
"DSLogicU3Pro16.bin",
"DSLogicU3Pro16.bin",
{CAPS_MODE_LOGIC,
CAPS_FEATURE_VTH | CAPS_FEATURE_BUF | CAPS_FEATURE_USB30 | CAPS_FEATURE_ADF4360,
(1 << DSL_STREAM125x16_16) | (1 << DSL_STREAM250x12_16) | (1 << DSL_STREAM500x6) | (1 << DSL_STREAM1000x3) |
(1 << DSL_BUFFER500x16) | (1 << DSL_BUFFER1000x8),
16,
SR_GB(2),
0,
DSL_BUFFER500x16,
0,
samplerates1000,
0,
DSL_STREAM125x16_16,
SR_MHZ(1),
SR_Mn(1),
0,
0,
0,
0,
0,
SR_MHZ(500),
SR_GHZ(1)}
},
{0x2A0E, 0x002C, LIBUSB_SPEED_HIGH, "DreamSourceLab", "DSLogic U3Pro32", NULL,
"DSLogicU3Pro32.fw",
"DSLogicU3Pro32.bin",
"DSLogicU3Pro32.bin",
{CAPS_MODE_LOGIC,
CAPS_FEATURE_VTH | CAPS_FEATURE_BUF | CAPS_FEATURE_USB30 | CAPS_FEATURE_ADF4360 | CAPS_FEATURE_LA_CH32,
(1 << DSL_STREAM10x32_32_3DN2) | (1 << DSL_STREAM20x16_32_3DN2) | (1 << DSL_STREAM25x12_32_3DN2) | (1 << DSL_STREAM50x6_32_3DN2) | (1 << DSL_STREAM100x3_32_3DN2) |
(1 << DSL_BUFFER500x16) | (1 << DSL_BUFFER1000x8),
32,
SR_GB(2),
0,
DSL_BUFFER250x32,
0,
samplerates1000,
0,
DSL_STREAM10x32_32_3DN2,
SR_MHZ(1),
SR_Mn(1),
0,
0,
0,
0,
0,
SR_MHZ(500),
SR_GHZ(1)}
},
{0x2A0E, 0x002C, LIBUSB_SPEED_SUPER, "DreamSourceLab", "DSLogic U3Pro32", NULL,
"DSLogicU3Pro32.fw",
"DSLogicU3Pro32.bin",
"DSLogicU3Pro32.bin",
{CAPS_MODE_LOGIC,
CAPS_FEATURE_VTH | CAPS_FEATURE_BUF | CAPS_FEATURE_USB30 | CAPS_FEATURE_ADF4360 | CAPS_FEATURE_LA_CH32,
(1 << DSL_STREAM50x32) | (1 << DSL_STREAM100x30) | (1 << DSL_STREAM250x12) | (1 << DSL_STREAM500x6) | (1 << DSL_STREAM1000x3) |
(1 << DSL_BUFFER250x32) | (1 << DSL_BUFFER500x16) | (1 << DSL_BUFFER1000x8),
32,
SR_GB(2),
0,
DSL_BUFFER250x32,
0,
samplerates1000,
0,
DSL_STREAM50x32,
SR_MHZ(1),
SR_Mn(1),
0,
0,
0,
0,
0,
SR_MHZ(500),
SR_GHZ(1)}
},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
};
......@@ -753,7 +914,7 @@ static const struct DSL_profile supported_DSCope[] = {
"DSCopeU2B20.bin",
"DSCopeU2B20.bin",
{CAPS_MODE_ANALOG | CAPS_MODE_DSO,
CAPS_FEATURE_ZERO,
CAPS_FEATURE_ZERO | CAPS_FEATURE_AUTO_VGAIN,
(1 << DSL_ANALOG10x2) |
(1 << DSL_DSO200x2),
2,
......@@ -766,8 +927,8 @@ static const struct DSL_profile supported_DSCope[] = {
DSL_DSO200x2,
SR_MHZ(100),
SR_Kn(10),
945,
1024-945,
930,
1024-930,
10,
245,
22,
......@@ -780,7 +941,7 @@ static const struct DSL_profile supported_DSCope[] = {
"DSCopeU2P20.bin",
"DSCopeU2P20.bin",
{CAPS_MODE_ANALOG | CAPS_MODE_DSO,
CAPS_FEATURE_ZERO | CAPS_FEATURE_BUF | CAPS_FEATURE_POGOPIN,
CAPS_FEATURE_ZERO | CAPS_FEATURE_BUF | CAPS_FEATURE_POGOPIN | CAPS_FEATURE_AUTO_VGAIN,
(1 << DSL_ANALOG10x2) |
(1 << DSL_DSO200x2),
2,
......@@ -793,8 +954,8 @@ static const struct DSL_profile supported_DSCope[] = {
DSL_DSO200x2,
SR_MHZ(100),
SR_Mn(1),
945,
1024-945,
930,
1024-930,
10,
245,
22,
......@@ -802,6 +963,86 @@ static const struct DSL_profile supported_DSCope[] = {
SR_HZ(0)}
},
{0x2A0E, 0x0028, LIBUSB_SPEED_HIGH, "DreamSourceLab", "DSCope U2B100", NULL,
"DSCopeU2B100.fw",
"DSCopeU2B100.bin",
"DSCopeU2B100.bin",
{CAPS_MODE_ANALOG | CAPS_MODE_DSO,
CAPS_FEATURE_ZERO | CAPS_FEATURE_HMCAD1511 | CAPS_FEATURE_20M,
(1 << DSL_ANALOG10x2_500) |
(1 << DSL_DSO1000x2),
2,
SR_KB(256),
SR_Kn(20),
0,
vdivs10to2000,
samplerates1000,
4,
DSL_DSO1000x2,
SR_MHZ(500),
SR_Kn(10),
850,
1024-850,
10,
245,
80,
SR_HZ(0),
SR_HZ(0)}
},
{0x2A0E, 0x002B, LIBUSB_SPEED_HIGH, "DreamSourceLab", "DSCope U3P100", NULL,
"DSCopeU3P100.fw",
"DSCopeU3P100.bin",
"DSCopeU3P100.bin",
{CAPS_MODE_ANALOG | CAPS_MODE_DSO,
CAPS_FEATURE_ZERO | CAPS_FEATURE_FLASH | CAPS_FEATURE_USB30 | CAPS_FEATURE_HMCAD1511 | CAPS_FEATURE_20M,
(1 << DSL_ANALOG10x2_500) |
(1 << DSL_DSO1000x2),
2,
SR_GB(2),
SR_Mn(2),
0,
vdivs10to2000,
samplerates1000,
4,
DSL_DSO1000x2,
SR_MHZ(500),
SR_Mn(1),
900,
1024-900,
10,
245,
60,
SR_HZ(0),
SR_HZ(0)}
},
{0x2A0E, 0x002B, LIBUSB_SPEED_SUPER, "DreamSourceLab", "DSCope U3P100", NULL,
"DSCopeU3P100.fw",
"DSCopeU3P100.bin",
"DSCopeU3P100.bin",
{CAPS_MODE_ANALOG | CAPS_MODE_DSO,
CAPS_FEATURE_ZERO | CAPS_FEATURE_FLASH | CAPS_FEATURE_USB30 | CAPS_FEATURE_HMCAD1511 | CAPS_FEATURE_20M,
(1 << DSL_ANALOG10x2_500) |
(1 << DSL_DSO1000x2),
2,
SR_GB(2),
SR_Mn(2),
0,
vdivs10to2000,
samplerates1000,
4,
DSL_DSO1000x2,
SR_MHZ(500),
SR_Mn(1),
900,
1024-900,
10,
245,
60,
SR_HZ(0),
SR_HZ(0)}
},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
};
......@@ -880,6 +1121,9 @@ struct DSL_context {
int16_t tune_index;
int zero_stage;
int zero_pcnt;
gboolean zero_branch;
gboolean zero_comb_fgain;
gboolean zero_comb;
int tune_stage;
int tune_pcnt;
struct sr_channel *tune_probe;
......@@ -908,6 +1152,7 @@ struct DSL_context {
gboolean abort;
gboolean overflow;
int bw_limit;
int empty_poll_count;
int language;
};
......@@ -1085,6 +1330,13 @@ SR_PRIV int dsl_rd_nvm(const struct sr_dev_inst *sdi, unsigned char *ctx, uint16
SR_PRIV int dsl_rd_probe(const struct sr_dev_inst *sdi, unsigned char *ctx, uint16_t addr, uint8_t len);
SR_PRIV int dsl_config_adc(const struct sr_dev_inst *sdi, const struct DSL_adc_config *config);
SR_PRIV double dsl_adc_code2fgain(uint8_t code);
SR_PRIV uint8_t dsl_adc_fgain2code(double gain);
SR_PRIV int dsl_config_adc_fgain(const struct sr_dev_inst *sdi, uint8_t branch, double gain0, double gain1);
SR_PRIV int dsl_config_fpga_fgain(const struct sr_dev_inst *sdi);
SR_PRIV int dsl_skew_fpga_fgain(const struct sr_dev_inst *sdi, gboolean comb, double skew[]);
SR_PRIV int dsl_probe_cali_fgain(struct DSL_context *devc, struct sr_channel *probe, double mean, gboolean comb, gboolean reset);
SR_PRIV gboolean dsl_probe_fgain_inrange(struct sr_channel *probe, gboolean comb, double skew[]);
SR_PRIV int dsl_fpga_arm(const struct sr_dev_inst *sdi);
SR_PRIV int dsl_fpga_config(struct libusb_device_handle *hdl, const char *filename);
......@@ -1101,7 +1353,7 @@ SR_PRIV int dsl_config_list(int key, GVariant **data, const struct sr_dev_inst *
SR_PRIV int dsl_dev_open(struct sr_dev_driver *di, struct sr_dev_inst *sdi, gboolean *fpga_done);
SR_PRIV int dsl_dev_close(struct sr_dev_inst *sdi);
SR_PRIV int dsl_dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_data);
SR_PRIV int dsl_dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg, int begin, int end);
SR_PRIV int dsl_dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg);
SR_PRIV unsigned int dsl_get_timeout(const struct sr_dev_inst *sdi);
SR_PRIV int dsl_start_transfers(const struct sr_dev_inst *sdi);
......
......@@ -228,6 +228,9 @@ static struct DSL_context *DSLogic_dev_new(const struct DSL_profile *prof)
devc->trigger_hrate = 0;
devc->trigger_holdoff = 0;
devc->zero = FALSE;
devc->zero_branch = FALSE;
devc->zero_comb_fgain = FALSE;
devc->zero_comb = FALSE;
devc->status = DSL_FINISH;
devc->mstatus_valid = FALSE;
......@@ -932,7 +935,7 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
dsl_adjust_samplerate(devc);
if (devc->op_mode == OP_INTEST) {
devc->cur_samplerate = devc->stream ? channel_modes[devc->ch_mode].max_samplerate / 10 :
channel_modes[devc->ch_mode].max_samplerate;
SR_MHZ(100);
devc->limit_samples = devc->stream ? devc->cur_samplerate * 3 :
devc->profile->dev_caps.hw_depth / dsl_en_ch_num(sdi);
}
......@@ -1042,10 +1045,6 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi,
ch->offset = g_variant_get_uint16(data);
sr_dbg("%s: setting OFFSET of channel %d to %d", __func__,
ch->index, ch->offset);
} else if (id == SR_CONF_PROBE_HW_OFFSET) {
ch->hw_offset = g_variant_get_uint16(data);
sr_dbg("%s: setting OFFSET of channel %d to %d", __func__,
ch->index, ch->offset);
} else if (id == SR_CONF_TRIGGER_SOURCE) {
devc->trigger_source = g_variant_get_byte(data);
if (sdi->mode == DSO) {
......@@ -1119,12 +1118,12 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
for (i = 0; i < ARRAY_SIZE(channel_modes); i++) {
if (channel_modes[i].stream == devc->stream &&
devc->profile->dev_caps.channels & (1 << i)) {
if (devc->test_mode != SR_TEST_NONE && devc->profile->dev_caps.intest_channel != channel_modes[i].id)
continue;
if (devc->language == LANGUAGE_CN)
g_variant_builder_add(&gvb, "s", channel_modes[i].descr_cn);
else
g_variant_builder_add(&gvb, "s", channel_modes[i].descr);
if (devc->test_mode != SR_TEST_NONE)
break;
}
}
*data = g_variant_builder_end(&gvb);
......@@ -1197,6 +1196,17 @@ static void remove_sources(struct DSL_context *devc)
g_free(devc->usbfd);
}
static void report_overflow(struct DSL_context *devc)
{
struct sr_datafeed_packet packet;
struct sr_dev_inst *sdi = devc->cb_data;
packet.status = SR_PKT_OK;
packet.type = SR_DF_OVERFLOW;
packet.payload = NULL;
sr_session_send(sdi, &packet);
}
static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi)
{
int completed = 0;
......@@ -1218,16 +1228,44 @@ static int receive_data(int fd, int revents, const struct sr_dev_inst *sdi)
tv.tv_sec = tv.tv_usec = 0;
libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &tv, &completed);
// overflow check
if (devc->stream && devc->trf_completed) {
rd_cmd.header.dest = DSL_CTL_HW_STATUS;
rd_cmd.header.size = 1;
hw_info = 0;
rd_cmd.data = &hw_info;
if (devc->trf_completed)
devc->empty_poll_count = 0;
else
devc->empty_poll_count++;
// --
// progress check
// must before overflow check (1ch@10K)
// --
if ((devc->empty_poll_count > MAX_EMPTY_POLL) && (devc->status == DSL_START)) {
devc->mstatus.captured_cnt0 = 0;
rd_cmd.header.dest = DSL_CTL_I2C_STATUS;
rd_cmd.header.offset = 0;
rd_cmd.header.size = 4;
rd_cmd.data = (unsigned char*)&devc->mstatus;
if ((ret = command_ctl_rd(usb->devhdl, rd_cmd)) != SR_OK)
sr_err("Failed to get hardware infos.");
else
devc->overflow = (hw_info & bmSYS_OVERFLOW) != 0;
sr_err("Failed to get progress infos.");
devc->empty_poll_count = 0;
}
// overflow check
if (devc->stream) {
if (devc->empty_poll_count > MAX_EMPTY_POLL) {
rd_cmd.header.dest = DSL_CTL_HW_STATUS;
rd_cmd.header.size = 1;
hw_info = 0;
rd_cmd.data = &hw_info;
if ((ret = command_ctl_rd(usb->devhdl, rd_cmd)) != SR_OK)
sr_err("Failed to get hardware infos.");
else
devc->overflow = (hw_info & bmSYS_OVERFLOW) != 0;
if (devc->overflow)
report_overflow(devc);
devc->empty_poll_count = 0;
}
}
if (devc->status == DSL_FINISH) {
......@@ -1263,13 +1301,19 @@ static int dev_acquisition_start(struct sr_dev_inst *sdi, void *cb_data)
devc->num_samples = 0;
devc->num_bytes = 0;
devc->empty_transfer_count = 0;
devc->empty_poll_count = 0;
devc->status = DSL_INIT;
devc->num_transfers = 0;
devc->submitted_transfers = 0;
devc->actual_samples = (devc->limit_samples + 1023ULL) & ~1023ULL;
devc->actual_samples = (devc->limit_samples + SAMPLES_ALIGN) & ~SAMPLES_ALIGN;
devc->actual_bytes = devc->actual_samples / DSLOGIC_ATOMIC_SAMPLES * dsl_en_ch_num(sdi) * DSLOGIC_ATOMIC_SIZE;
devc->abort = FALSE;
devc->mstatus_valid = FALSE;
devc->mstatus.captured_cnt0 = 0;
devc->mstatus.captured_cnt1 = 0;
devc->mstatus.captured_cnt2 = 0;
devc->mstatus.captured_cnt3 = 0;
devc->mstatus.trig_hit = 0;
devc->overflow = FALSE;
/* Configures devc->trigger_* and devc->sample_wide */
......@@ -1346,9 +1390,9 @@ static int dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_data)
return ret;
}
static int dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg, int begin, int end)
static int dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg)
{
int ret = dsl_dev_status_get(sdi, status, prg, begin, end);
int ret = dsl_dev_status_get(sdi, status, prg);
return ret;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment