2
0
forked from Ivasoft/DSView

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

This commit is contained in:
DreamSourceLab
2020-01-10 22:43:30 +08:00
parent 235a863b3a
commit a5f47b42c1
25 changed files with 1268 additions and 400 deletions

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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 (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->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 (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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -1074,11 +1074,10 @@ static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_data)
return SR_OK;
}
static int hw_dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg, int begin, int end)
static int hw_dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg)
{
(void)prg;
(void)begin;
(void)end;
if (sdi) {
struct demo_context *const devc = sdi->priv;
*status = devc->mstatus;

View File

@@ -425,8 +425,7 @@ SR_API const struct sr_config_info *sr_config_info_get(int key)
* as an indication that it's not applicable.
*/
SR_API int sr_status_get(const struct sr_dev_inst *sdi,
struct sr_status *status,
gboolean prg, int begin, int end)
struct sr_status *status, gboolean prg)
{
int ret;
@@ -435,7 +434,7 @@ SR_API int sr_status_get(const struct sr_dev_inst *sdi,
else if (!sdi->driver->dev_status_get)
ret = SR_ERR_ARG;
else
ret = sdi->driver->dev_status_get(sdi, status, prg, begin, end);
ret = sdi->driver->dev_status_get(sdi, status, prg);
return ret;
}

View File

@@ -126,6 +126,8 @@ enum {
#define DS_CONF_DSO_VDIVS 10
#define DS_MAX_TRIG_PERCENT 90
#define SAMPLES_ALIGN 1023ULL
/*
* Oscilloscope
*/
@@ -647,6 +649,16 @@ struct sr_channel {
int8_t comb_diff_top;
int8_t comb_diff_bom;
int8_t comb_comp;
uint16_t digi_fgain;
double cali_fgain0;
double cali_fgain1;
double cali_fgain2;
double cali_fgain3;
double cali_comb_fgain0;
double cali_comb_fgain1;
double cali_comb_fgain2;
double cali_comb_fgain3;
gboolean map_default;
const char *map_unit;
@@ -680,17 +692,6 @@ struct sr_config_info {
char *description;
};
enum {
SR_STATUS_TRIG_BEGIN = 0,
SR_STATUS_TRIG_END = 4,
SR_STATUS_CH0_BEGIN = 5,
SR_STATUS_CH0_END = 14,
SR_STATUS_CH1_BEGIN = 15,
SR_STATUS_CH1_END = 24,
SR_STATUS_ZERO_BEGIN = 128,
SR_STATUS_ZERO_END = 135,
};
struct sr_status {
uint8_t trig_hit;
uint8_t captured_cnt3;
@@ -722,6 +723,9 @@ struct sr_status {
uint32_t ch0_cyc_flen;
uint64_t ch0_acc_square;
uint32_t ch0_acc_mean;
uint32_t ch0_acc_mean_p1;
uint32_t ch0_acc_mean_p2;
uint32_t ch0_acc_mean_p3;
uint8_t ch1_max;
uint8_t ch1_min;
@@ -737,6 +741,9 @@ struct sr_status {
uint32_t ch1_cyc_flen;
uint64_t ch1_acc_square;
uint32_t ch1_acc_mean;
uint32_t ch1_acc_mean_p1;
uint32_t ch1_acc_mean_p2;
uint32_t ch1_acc_mean_p3;
};
enum {
@@ -877,6 +884,8 @@ enum {
SR_CONF_ZERO_SET,
SR_CONF_ZERO_LOAD,
SR_CONF_ZERO_DEFAULT,
SR_CONF_ZERO_COMB_FGAIN,
SR_CONF_ZERO_COMB,
SR_CONF_VOCM,
SR_CONF_CALI,
@@ -1199,8 +1208,7 @@ struct sr_dev_driver {
int (*dev_open) (struct sr_dev_inst *sdi);
int (*dev_close) (struct sr_dev_inst *sdi);
int (*dev_status_get) (const struct sr_dev_inst *sdi,
struct sr_status *status,
gboolean prg, int begin, int end);
struct sr_status *status, gboolean prg);
int (*dev_acquisition_start) (struct sr_dev_inst *sdi,
void *cb_data);
int (*dev_acquisition_stop) (const struct sr_dev_inst *sdi,

View File

@@ -78,7 +78,7 @@ SR_API int sr_config_list(const struct sr_dev_driver *driver,
int key, GVariant **data);
SR_API const struct sr_config_info *sr_config_info_get(int key);
SR_API const struct sr_config_info *sr_config_info_name_get(const char *optname);
SR_API int sr_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg, int begin, int end);
SR_API int sr_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg);
SR_API struct sr_config *sr_config_new(int key, GVariant *data);
SR_API void sr_config_free(struct sr_config *src);

View File

@@ -867,11 +867,9 @@ static int config_list(int key, GVariant **data,
return SR_OK;
}
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)
{
(void)prg;
(void)begin;
(void)end;
struct session_vdev *vdev;