diff --git a/libsigrok4DSL/hardware/demo.c b/libsigrok4DSL/hardware/demo.c new file mode 100644 index 00000000..6aac7ee3 --- /dev/null +++ b/libsigrok4DSL/hardware/demo.c @@ -0,0 +1,2718 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2010 Uwe Hermann + * Copyright (C) 2011 Olivier Fauchon + * Copyright (C) 2012 Alexandru Gagniuc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "demo.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef _WIN32 +#include +#include +#define pipe(fds) _pipe(fds, 4096, _O_BINARY) +#endif + +#include "../../log.h" + +/* Message logging helpers with subsystem-specific prefix string. */ + +#undef LOG_PREFIX +#define LOG_PREFIX "demo: " + +/* The size of chunks to send through the session bus. */ +/* TODO: Should be configurable. */ +#define BUFSIZE 512*1024 +#define DSO_BUFSIZE 10*1024 + +static struct DEMO_channels logic_channel_modes[] = { + {DEMO_LOGIC125x16, LOGIC, SR_CHANNEL_LOGIC, 16, 1, SR_MHZ(1), SR_Mn(1), + SR_KHZ(10), SR_MHZ(125), "Use 16 Channels (Max 125MHz)"}, + {DEMO_LOGIC250x12, LOGIC, SR_CHANNEL_LOGIC, 12, 1, SR_MHZ(1), SR_Mn(1), + SR_KHZ(10), SR_MHZ(250), "Use 12 Channels (Max 250MHz)"}, + {DEMO_LOGIC500x6, LOGIC, SR_CHANNEL_LOGIC, 6, 1, SR_MHZ(1), SR_Mn(1), + SR_KHZ(10), SR_MHZ(500), "Use 6 Channels (Max 500MHz)"}, + {DEMO_LOGIC1000x3, LOGIC, SR_CHANNEL_LOGIC, 3, 1, SR_MHZ(1), SR_Mn(1), + SR_KHZ(10), SR_GHZ(1), "Use 3 Channels (Max 1GHz)"}, +}; + +static struct sr_list_item logic_channel_mode_list[ARRAY_SIZE(logic_channel_modes)+1]; + +static struct DEMO_channels channel_modes[] = { + // LA Stream + {DEMO_LOGIC100x16, LOGIC, SR_CHANNEL_LOGIC, 16, 1, SR_MHZ(1), SR_Mn(1), + SR_KHZ(10), SR_GHZ(1), "Use 16 Channels (Max 20MHz)"}, + + // DAQ + {DEMO_ANALOG10x2, ANALOG, SR_CHANNEL_ANALOG, 2, 8, SR_MHZ(1), SR_Mn(1), + SR_HZ(10), SR_MHZ(10), "Use Channels 0~1 (Max 10MHz)"}, + + // OSC + {DEMO_DSO200x2, DSO, SR_CHANNEL_DSO, 2, 8, SR_MHZ(100), SR_Kn(10), + SR_HZ(100), SR_MHZ(200), "Use Channels 0~1 (Max 200MHz)"}, +}; + + +/* Private, per-device-instance driver context. */ +/* TODO: struct context as with the other drivers. */ + +/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */ +SR_PRIV struct sr_dev_driver demo_driver_info; +static struct sr_dev_driver *di = &demo_driver_info; + +extern struct ds_trigger *trigger; + +static int logic_adjust_probe(struct sr_dev_inst *sdi, int num_probes) +{ + uint16_t j; + struct sr_channel *probe; + struct DSL_context *devc = sdi->priv; + GSList *l; + + assert(num_probes > 0); + + j = g_slist_length(sdi->channels); + while(j < num_probes) { + if (!(probe = sr_channel_new(j, SR_CHANNEL_LOGIC, + TRUE, probe_names[j]))) + return SR_ERR; + sdi->channels = g_slist_append(sdi->channels, probe); + j++; + } + + while(j > num_probes) { + sdi->channels = g_slist_delete_link(sdi->channels, g_slist_last(sdi->channels)); + j--; + } + + for(l = sdi->channels; l; l = l->next) { + probe = (struct sr_channel *)l->data; + probe->enabled = TRUE; + probe->type = SR_CHANNEL_LOGIC; + } + return SR_OK; +} + +static void logic_adjust_samplerate(struct session_vdev * vdev) +{ + vdev->samplerates_max_index = ARRAY_SIZE(samplerates) - 1; + while (samplerates[vdev->samplerates_max_index] > + logic_channel_modes[logic_index].max_samplerate) + vdev->samplerates_max_index--; + + vdev->samplerates_min_index = 0; + while (samplerates[vdev->samplerates_min_index] < + logic_channel_modes[logic_index].min_samplerate) + vdev->samplerates_min_index++; + + assert(vdev->samplerates_max_index >= vdev->samplerates_min_index); + + if (vdev->samplerate > samplerates[vdev->samplerates_max_index]) + vdev->samplerate = samplerates[vdev->samplerates_max_index]; + + if (vdev->samplerate < samplerates[vdev->samplerates_min_index]) + vdev->samplerate = samplerates[vdev->samplerates_min_index]; +} + + +static void init_analog_random_data(struct session_vdev * vdev) +{ + if(vdev->analog_buf != NULL) + { + g_safe_free(vdev->analog_buf); + vdev->analog_buf = NULL; + } + + vdev->analog_buf = g_try_malloc0(DSO_BUF_LEN); + if (vdev->analog_buf == NULL) + { + sr_err("%s: vdev->analog_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + for(int i = 0;i < DSO_BUF_LEN ;i++) + { + if(i % 2 == 0) + *(uint8_t*)(vdev->analog_buf + i) = ANALOG_RANDOM_DATA; + else + *(uint8_t*)(vdev->analog_buf + i) = *(uint8_t*)(vdev->analog_buf + i -1); + } + vdev->analog_buf_len = DSO_BUF_LEN; +} + +static void delay_time() +{ + gdouble packet_elapsed = g_timer_elapsed(packet_interval, NULL); + gdouble waittime = packet_time - packet_elapsed; + if(waittime > 0) + { + g_usleep(SR_MS(waittime)); + } +} + +static void get_last_packet_len(struct sr_datafeed_logic *logic,const struct session_vdev * vdev) +{ + assert(vdev); + int last_packet_len = post_data_len - (logic->length / enabled_probe_num); + last_packet_len = (vdev->total_samples/8) - last_packet_len; + logic->length = last_packet_len * enabled_probe_num; + post_data_len = vdev->total_samples/8; +} + +static void reset_enabled_probe_num(struct sr_dev_inst *sdi) +{ + struct sr_channel *probe; + enabled_probe_num = 0; + for(GSList *l = sdi->channels; l; l = l->next) + { + probe = (struct sr_channel *)l->data; + if(probe->enabled) + { + enabled_probe_num++; + } + } +} + +static void init_pattern_mode_list() +{ + int i; + if(pattern_logic_count != 1) + { + for(i = 1 ;i < pattern_logic_count ; i++) + { + if(pattern_strings_logic[i] != NULL) + { + g_safe_free(pattern_strings_logic[i]); + pattern_strings_logic[i] =NULL; + } + } + } + if(pattern_dso_count != 1) + { + for(i = 1 ;i < pattern_dso_count ; i++) + { + if(pattern_strings_dso[i] != NULL) + { + g_safe_free(pattern_strings_dso[i]); + pattern_strings_dso[i] =NULL; + } + } + } + if(pattern_analog_count != 1) + { + for(i = 1 ;i < pattern_analog_count ; i++) + { + if(pattern_strings_analog[i] != NULL) + { + g_safe_free(pattern_strings_analog[i]); + pattern_strings_analog[i] =NULL; + } + } + } +} + +static int get_pattern_mode_index_by_string(uint8_t device_mode , const char* str) +{ + int index = PATTERN_INVALID, + i = PATTERN_RANDOM; + if (device_mode == LOGIC) + { + while (pattern_strings_logic[i] != NULL) + { + if(!strcmp(str,pattern_strings_logic[i])) + { + index = i; + break; + } + else + i++; + } + } + else if (device_mode == DSO) + { + while (pattern_strings_dso[i] != NULL) + { + if(!strcmp(str,pattern_strings_dso[i])) + { + index = i; + break; + } + else + i++; + } + } + else + { + while (pattern_strings_analog[i] != NULL) + { + if(!strcmp(str,pattern_strings_analog[i])) + { + index = i; + break; + } + else + i++; + } + } + + if(index == PATTERN_INVALID) + index = PATTERN_RANDOM; + return index; +} + +static void get_pattern_mode_from_file(uint8_t device_mode) +{ + const gchar * filename = NULL; + char dir_str[500]; + int index = 1; + + strcpy(dir_str,DS_RES_PATH); + strcat(dir_str,"../"); + strcat(dir_str,"demo/"); + + if(device_mode == LOGIC) + strcat(dir_str,"logic/"); + else if(device_mode == DSO) + strcat(dir_str,"dso/"); + else if(device_mode == ANALOG) + strcat(dir_str,"analog/"); + + GDir *dir = NULL; + dir = g_dir_open(dir_str,0,NULL); + if(dir == NULL) + { + return 0; + } + + while ((filename = g_dir_read_name(dir)) != NULL) + { + if (FALSE == g_file_test(filename,G_FILE_TEST_IS_DIR)) + { + if(strstr(filename,".demo") != NULL) + { + char *tmp_file_name = g_try_malloc0(strlen(filename)-strlen(".demo")+1); + snprintf(tmp_file_name, strlen(filename)-strlen(".demo")+1 , "%s", filename); + if(device_mode == LOGIC) + pattern_strings_logic[index] = tmp_file_name; + else if(device_mode == DSO) + pattern_strings_dso[index] = tmp_file_name; + else if(device_mode == ANALOG) + pattern_strings_analog[index] = tmp_file_name; + if(index < 99) + index++; + } + } + } + + g_dir_close(dir); + + if(device_mode == LOGIC) + pattern_logic_count = index; + else if(device_mode == DSO) + pattern_dso_count = index; + else if(device_mode == ANALOG) + pattern_analog_count = index; + + return 0; +} + +static void scan_dsl_file(struct sr_dev_inst *sdi) +{ + init_pattern_mode_list(); + + get_pattern_mode_from_file(LOGIC); + get_pattern_mode_from_file(DSO); + get_pattern_mode_from_file(ANALOG); + + if(PATTERN_RANDOM mode = LOGIC; + reset_dsl_path(sdi,LOGIC,PATTERN_DEFAULT); + } + else + { + sample_generator = PATTERN_RANDOM; + sdi->mode = LOGIC; + reset_dsl_path(sdi,LOGIC,PATTERN_RANDOM); + } +} + +static int reset_dsl_path(struct sr_dev_inst *sdi,uint8_t device_mode ,uint8_t pattern_mode) +{ + unzFile archive = NULL; + if(sdi->path != NULL) + g_safe_free(sdi->path); + + char *str = g_try_malloc0(500); + strcpy(str,DS_RES_PATH); + strcat(str,"../"); + strcat(str,"demo/"); + + if (pattern_mode != PATTERN_RANDOM) + { + switch (device_mode) + { + case LOGIC: + if(NULL != pattern_strings_logic[pattern_mode]) + { + strcat(str,"logic/"); + strcat(str,pattern_strings_logic[pattern_mode]); + } + break; + case DSO: + if(NULL != pattern_strings_dso[pattern_mode]) + { + strcat(str,"dso/"); + strcat(str,pattern_strings_dso[pattern_mode]); + } + break; + case ANALOG: + if(NULL != pattern_strings_analog[pattern_mode]) + { + strcat(str,"analog/"); + strcat(str,pattern_strings_analog[pattern_mode]); + } + break; + default: + break; + } + strcat(str,".demo"); + } + + if(pattern_mode != PATTERN_RANDOM) + { + archive = unzOpen64(str); + if (NULL != archive){ + sdi->path = str; + return SR_OK; + } + else{ + g_safe_free(str); + sdi->path = g_strdup(""); + return SR_ERR; + } + + } + else{ + g_safe_free(str); + sdi->path = g_strdup(""); + return SR_OK; + } +} + +static void adjust_samplerate(struct sr_dev_inst *sdi) +{ + if(sdi->mode == LOGIC && sample_generator > PATTERN_RANDOM) + { + return; + } + + struct session_vdev *vdev = sdi->priv; + int cur_mode = -1; + if(sdi->mode == LOGIC) + cur_mode = 0; + else if(sdi->mode == DSO) + cur_mode = 2; + else if(sdi->mode == ANALOG) + cur_mode = 1; + + if(cur_mode == -1) + return; + + vdev->samplerates_max_index = ARRAY_SIZE(samplerates) - 1; + while (samplerates[vdev->samplerates_max_index] > + channel_modes[cur_mode].max_samplerate) + vdev->samplerates_max_index--; + + vdev->samplerates_min_index = 0; + while (samplerates[vdev->samplerates_min_index] < + channel_modes[cur_mode].min_samplerate) + vdev->samplerates_min_index++; + + assert(vdev->samplerates_max_index >= vdev->samplerates_min_index); + + if (vdev->samplerate > samplerates[vdev->samplerates_max_index]) + vdev->samplerate = samplerates[vdev->samplerates_max_index]; + + if (vdev->samplerate < samplerates[vdev->samplerates_min_index]) + vdev->samplerate = samplerates[vdev->samplerates_min_index]; + +} + +static void init_random_data(struct session_vdev * vdev,struct sr_dev_inst *sdi) +{ + int cur_probe = 0; + int probe_count[LOGIC_MAX_PROBE_NUM] = {0}; + uint8_t probe_status[LOGIC_MAX_PROBE_NUM] = {LOGIC_HIGH_LEVEL}; + + memset(probe_status,LOGIC_HIGH_LEVEL,16); + memset(vdev->logic_buf,0,LOGIC_BUF_LEN); + + for(int i = 0 ;i < enabled_probe_num;i++) + { + probe_count[i] = rand()%SR_KB(5); + } + + for(int i = 0 ; i < vdev->logic_buf_len ;i++) + { + if(i % 8 == 0 && i != 0) + { + cur_probe++; + if(cur_probe >enabled_probe_num-1) + cur_probe = 0; + } + if(probe_count[cur_probe]> 0) + { + memset(vdev->logic_buf+i,probe_status[cur_probe],1); + probe_count[cur_probe] -= 1; + } + else + { + if(probe_status[cur_probe] == LOGIC_HIGH_LEVEL) + probe_status[cur_probe] = LOGIC_LOW_LEVEL; + else + probe_status[cur_probe] = LOGIC_HIGH_LEVEL; + probe_count[cur_probe] = rand()%SR_KB(5); + memset(vdev->logic_buf+i,probe_status[cur_probe],1); + probe_count[cur_probe] -= 1; + } + } + return 0; +} + + +static int hw_init(struct sr_context *sr_ctx) +{ + return std_hw_init(sr_ctx, di, LOG_PREFIX); +} + +static GSList *hw_scan(GSList *options) +{ + struct sr_dev_inst *sdi; + struct session_vdev *vdev; + GSList *devices; + char str[500]; + + (void)options; + devices = NULL; + + sr_info("%s", "Scan demo device."); + + vdev = g_try_malloc0(sizeof(struct session_vdev)); + if (vdev == NULL) + { + sr_err("%s: sdi->priv malloc failed", __func__); + return devices; + } + + sdi = sr_dev_inst_new(LOGIC, SR_ST_INACTIVE, + supported_Demo[0].vendor, + supported_Demo[0].model, + supported_Demo[0].model_version); + if (!sdi) { + g_safe_free(vdev); + sr_err("Device instance creation failed."); + return NULL; + } + sdi->priv = vdev; + sdi->driver = di; + sdi->dev_type = DEV_TYPE_DEMO; + + vdev->is_loop = 0; + + devices = g_slist_append(devices, sdi); + + return devices; +} + +static const GSList *hw_dev_mode_list(const struct sr_dev_inst *sdi) +{ + // struct demo_context *devc; + GSList *l = NULL; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sr_mode_list); i++) { + // if (devc->profile->dev_caps.mode_caps & (1 << i)) + if (supported_Demo[0].dev_caps.mode_caps & (1 << i)) + l = g_slist_append(l, &sr_mode_list[i]); + } + + return l; +} + +static int hw_dev_open(struct sr_dev_inst *sdi) +{ + int ret; + assert(sdi); + assert(sdi->priv); + + if (sdi->status == SR_ST_ACTIVE){ + return SR_OK; + } + + scan_dsl_file(sdi); + struct session_vdev* vdev = sdi->priv; + + vdev->trig_pos = 0; + vdev->trig_time = 0; + vdev->cur_block = 0; + vdev->cur_channel = 0; + vdev->cur_probes = 0; + vdev->num_blocks = 0; + if(sdi->mode == LOGIC) + { + vdev->unit_bits = 1; + } + else + { + vdev->unit_bits = 8; + } + + vdev->ref_min = 1; + vdev->ref_max = 255; + + vdev->timebase = SR_NS(500); + vdev->max_timebase = MAX_TIMEBASE; + vdev->min_timebase = MIN_TIMEBASE; + + vdev->mstatus.measure_valid = TRUE; + vdev->archive = NULL; + vdev->capfile = 0; + vdev->packet_buffer = NULL; + vdev->logic_buf = NULL; + sdi->status = SR_ST_ACTIVE; + + if(vdev->logic_buf != NULL) + { + g_safe_free(vdev->logic_buf); + } + vdev->logic_buf = g_try_malloc0(LOGIC_BUF_LEN); + if(vdev->logic_buf == NULL) + { + sr_err("%s: vdev->logic_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + + if(vdev->dso_buf != NULL) + { + g_safe_free(vdev->dso_buf); + } + vdev->dso_buf = g_try_malloc0(DSO_PACKET_LEN); + if(vdev->dso_buf == NULL) + { + sr_err("%s: vdev->dso_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + + + vdev->logic_buf_len = LOGIC_BUF_LEN; + + packet_interval = g_timer_new(); + run_time = g_timer_new(); + + ret = load_virtual_device_session(sdi); + if (ret != SR_OK) + { + sr_err("%s", "Error!Load session file failed."); + return ret; + } + + return SR_OK; +} + +static int hw_dev_close(struct sr_dev_inst *sdi) +{ + struct session_vdev *vdev; + int i; + struct session_packet_buffer *pack_buf; + + if (sdi && sdi->priv) + { + vdev = sdi->priv; + + if (vdev->packet_buffer != NULL){ + pack_buf = vdev->packet_buffer; + + g_safe_free(pack_buf->post_buf); + + for (i = 0; i < SESSION_MAX_CHANNEL_COUNT; i++){ + if (pack_buf->block_bufs[i] != NULL){ + g_safe_free(pack_buf->block_bufs[i]); + pack_buf->block_bufs[i] = NULL; + } + else{ + break; + } + } + } + + g_safe_free(vdev->packet_buffer); + g_safe_free(vdev->logic_buf); + g_safe_free(vdev->analog_buf); + g_safe_free(sdi->path); + g_safe_free(packet_interval); + g_safe_free(run_time); + + sdi->status = SR_ST_INACTIVE; + return SR_OK; + } + + return SR_ERR_CALL_STATUS; +} + +static int dev_destroy(struct sr_dev_inst *sdi) +{ + assert(sdi); + hw_dev_close(sdi); + sr_dev_inst_free(sdi); +} + +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) +{ + (void)cg; + + assert(sdi); + assert(sdi->priv); + + struct session_vdev *vdev = sdi->priv; + + switch (id) + { + case SR_CONF_SAMPLERATE: + *data = g_variant_new_uint64(vdev->samplerate); + break; + case SR_CONF_LIMIT_SAMPLES: + *data = g_variant_new_uint64(vdev->total_samples); + break; + case SR_CONF_DEVICE_MODE: + *data = g_variant_new_int16(sdi->mode); + break; + case SR_CONF_DEMO_CHANGE: + *data = g_variant_new_boolean(is_change); + break; + case SR_CONF_INSTANT: + *data = g_variant_new_boolean(instant); + break; + case SR_CONF_PATTERN_MODE: + if(sdi->mode == LOGIC) + *data = g_variant_new_string(pattern_strings_logic[sample_generator]); + else if(sdi->mode == DSO) + *data = g_variant_new_string(pattern_strings_dso[sample_generator]); + else + *data = g_variant_new_string(pattern_strings_analog[sample_generator]); + break; + case SR_CONF_MAX_HEIGHT: + *data = g_variant_new_string(maxHeights[vdev->max_height]); + break; + case SR_CONF_MAX_HEIGHT_VALUE: + *data = g_variant_new_byte(vdev->max_height); + break; + case SR_CONF_PROBE_OFFSET: + if (ch) + *data = g_variant_new_uint16(ch->offset); + break; + case SR_CONF_PROBE_HW_OFFSET: + if (ch) + *data = g_variant_new_uint16(ch->hw_offset); + break; + case SR_CONF_PROBE_VDIV: + if (ch) + *data = g_variant_new_uint64(ch->vdiv); + break; + case SR_CONF_PROBE_FACTOR: + if (ch) + *data = g_variant_new_uint64(ch->vfactor); + break; + case SR_CONF_TIMEBASE: + *data = g_variant_new_uint64(vdev->timebase); + break; + case SR_CONF_MAX_TIMEBASE: + *data = g_variant_new_uint64(MAX_TIMEBASE); + break; + case SR_CONF_MIN_TIMEBASE: + *data = g_variant_new_uint64(MIN_TIMEBASE); + break; + case SR_CONF_PROBE_COUPLING: + if (ch) + *data = g_variant_new_byte(ch->coupling); + break; + case SR_CONF_TRIGGER_VALUE: + if (ch) + *data = g_variant_new_byte(ch->trig_value); + break; + case SR_CONF_PROBE_EN: + if (ch) + *data = g_variant_new_boolean(ch->enabled); + break; + case SR_CONF_MAX_DSO_SAMPLERATE: + *data = g_variant_new_uint64(SR_MHZ(200)); + break; + case SR_CONF_MAX_DSO_SAMPLELIMITS: + *data = g_variant_new_uint64(SR_Kn(20)); + break; + case SR_CONF_HW_DEPTH: + switch (sdi->mode) + { + case LOGIC: + if(sample_generator == PATTERN_RANDOM) + *data = g_variant_new_uint64(LOGIC_HW_DEPTH); + else + *data = g_variant_new_uint64(vdev->total_samples); + break; + case DSO: + *data = g_variant_new_uint64(vdev->total_samples); + break; + case ANALOG: + *data = g_variant_new_uint64(ANALOG_HW_DEPTH); + break; + default: + break; + } + break; + case SR_CONF_UNIT_BITS: + *data = g_variant_new_byte(vdev->unit_bits); + break; + case SR_CONF_PROBE_MAP_DEFAULT: + if (!sdi || !ch) + return SR_ERR; + *data = g_variant_new_boolean(ch->map_default); + break; + case SR_CONF_PROBE_MAP_UNIT: + if (!sdi || !ch) + return SR_ERR; + *data = g_variant_new_string(ch->map_unit); + break; + case SR_CONF_PROBE_MAP_MIN: + if (!sdi || !ch) + return SR_ERR; + *data = g_variant_new_double(ch->map_min); + break; + case SR_CONF_PROBE_MAP_MAX: + if (!sdi || !ch) + return SR_ERR; + *data = g_variant_new_double(ch->map_max); + break; + case SR_CONF_VLD_CH_NUM: + *data = g_variant_new_int16(vdev->num_probes); + break; + case SR_CONF_HAVE_ZERO: + *data = g_variant_new_boolean(FALSE); + break; + case SR_CONF_LOAD_DECODER: + *data = g_variant_new_boolean(sample_generator != PATTERN_RANDOM); + break; + case SR_CONF_REF_MIN: + *data = g_variant_new_uint32(vdev->ref_min); + break; + case SR_CONF_REF_MAX: + *data = g_variant_new_uint32(vdev->ref_max); + break; + case SR_CONF_CHANNEL_MODE: + *data = g_variant_new_int16(ch_mode); + break; + default: + return SR_ERR_NA; + } + + return SR_OK; +} + +static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, + struct sr_channel *ch, + struct sr_channel_group *cg) +{ + (void)cg; + + struct session_vdev *vdev; + const char *stropt; + unsigned int i; + int nv; + + assert(sdi); + assert(sdi->priv); + + vdev = sdi->priv; + + switch (id) + { + case SR_CONF_SAMPLERATE: + vdev->samplerate = g_variant_get_uint64(data); + sr_dbg("Setting samplerate to %llu.", vdev->samplerate); + break; + case SR_CONF_LIMIT_SAMPLES: + vdev->total_samples = g_variant_get_uint64(data); + sr_dbg("Setting limit samples to %llu.", vdev->total_samples); + break; + case SR_CONF_LIMIT_MSEC: + break; + case SR_CONF_DEVICE_MODE: + sdi->mode = g_variant_get_int16(data); + switch (sdi->mode) + { + case LOGIC: + if(SR_OK == reset_dsl_path(sdi,sdi->mode ,PATTERN_DEFAULT)) + { + sample_generator = PATTERN_DEFAULT; + } + else + { + sample_generator = PATTERN_RANDOM; + } + break; + case DSO: + reset_dsl_path(sdi,sdi->mode ,PATTERN_RANDOM); + sample_generator = PATTERN_RANDOM; + break; + case ANALOG: + reset_dsl_path(sdi,sdi->mode ,PATTERN_RANDOM); + sample_generator = PATTERN_RANDOM; + break; + default: + break; + } + load_virtual_device_session(sdi); + break; + case SR_CONF_PATTERN_MODE: + stropt = g_variant_get_string(data, NULL); + sample_generator = get_pattern_mode_index_by_string(sdi->mode , stropt); + if(SR_OK != reset_dsl_path(sdi,sdi->mode,sample_generator)) + { + sample_generator = PATTERN_RANDOM; + } + sr_dbg("%s: setting pattern to %d", + __func__, sample_generator); + break; + + case SR_CONF_MAX_HEIGHT: + stropt = g_variant_get_string(data, NULL); + for (i = 0; i < ARRAY_SIZE(maxHeights); i++) + { + if (!strcmp(stropt, maxHeights[i])) + { + vdev->max_height = i; + break; + } + } + sr_dbg("%s: setting Signal Max Height to %d", + __func__, vdev->max_height); + break; + case SR_CONF_PROBE_EN: + ch->enabled = g_variant_get_boolean(data); + break; + case SR_CONF_PROBE_VDIV: + ch->vdiv = g_variant_get_uint64(data); + if(sdi->mode == DSO) + { + if(vdev->packet_buffer) + { + vdev->packet_buffer->post_len = 0; + vdev->packet_buffer->block_read_positions[0] = 0; + vdev->packet_buffer->block_read_positions[1] = 0; + vdev->packet_buffer->block_chan_read_pos = 0; + } + vdiv_change = TRUE; + } + break; + case SR_CONF_PROBE_FACTOR: + ch->vfactor = g_variant_get_uint64(data); + break; + case SR_CONF_PROBE_OFFSET: + ch->offset = g_variant_get_uint16(data); + if(sdi->mode == DSO && ch->vdiv <= SR_mV(200)) + { + ch->hw_offset = ch->offset; + offset_change = TRUE; + } + else{ + if(ch->coupling == 0) + { + ch->hw_offset = 178; + } + else + { + ch->hw_offset = 128; + } + } + break; + case SR_CONF_PROBE_HW_OFFSET: + ch->hw_offset = g_variant_get_uint16(data); + break; + case SR_CONF_TIMEBASE: + vdev->timebase = g_variant_get_uint64(data); + if(sdi->mode == DSO) + { + g_timer_start(run_time); + timebase_change = TRUE; + } + sr_dbg("Setting timebase to %llu.", vdev->timebase); + break; + case SR_CONF_PROBE_COUPLING: + if(sdi->mode != LOGIC) + { + if(sdi->mode == DSO && ch->vdiv <= SR_mV(200)) + { + ch->coupling = g_variant_get_byte(data); + ch->hw_offset = ch->offset; + } + else + { + ch->coupling = g_variant_get_byte(data); + if(ch->coupling == 0) + { + ch->hw_offset = 178; + } + else + { + ch->hw_offset = 128; + } + + } + } + break; + case SR_CONF_TRIGGER_SOURCE: + break; + case SR_CONF_TRIGGER_SLOPE: + break; + case SR_CONF_TRIGGER_VALUE: + ch->trig_value = g_variant_get_byte(data); + break; + case SR_CONF_PROBE_MAP_DEFAULT: + ch->map_default = g_variant_get_boolean(data); + if (ch->map_default) { + ch->map_unit = probeMapUnits[0]; + ch->map_min = -(ch->vdiv * ch->vfactor * DS_CONF_DSO_VDIVS / 2000.0); + ch->map_max = ch->vdiv * ch->vfactor * DS_CONF_DSO_VDIVS / 2000.0; + } + break; + case SR_CONF_PROBE_MAP_UNIT: + ch->map_unit = g_variant_get_string(data, NULL); + break; + case SR_CONF_PROBE_MAP_MIN: + ch->map_min = g_variant_get_double(data); + break; + case SR_CONF_PROBE_MAP_MAX: + ch->map_max = g_variant_get_double(data); + if(sdi->mode == ANALOG) + break; + case SR_CONF_NUM_BLOCKS: + vdev->num_blocks = g_variant_get_uint64(data); + sr_dbg("Setting block number to %llu.", vdev->num_blocks); + break; + case SR_CONF_CAPTURE_NUM_PROBES: + vdev->num_probes = g_variant_get_uint64(data); + break; + case SR_CONF_INSTANT: + instant = g_variant_get_boolean(data); + break; + case SR_CONF_DEMO_CHANGE: + is_change = g_variant_get_boolean(data); + break; + case SR_CONF_DEMO_INIT: + load_virtual_device_session(sdi); + break; + case SR_CONF_LOOP_MODE: + vdev->is_loop = g_variant_get_boolean(data); + sr_info("Set demo loop mode:%d", vdev->is_loop); + break; + case SR_CONF_CHANNEL_MODE: + nv = g_variant_get_int16(data); + if(sdi->mode == LOGIC && sample_generator == PATTERN_RANDOM) + { + for(i = 0 ; i < ARRAY_SIZE(logic_channel_modes);i++) + { + if(logic_channel_modes[i].id == nv) + { + logic_index = i; + ch_mode = nv; + logic_adjust_probe(sdi,logic_channel_modes[i].num); + logic_adjust_samplerate(vdev); + break; + } + } + + } + break; + default: + sr_err("Unknown capability: %d.", id); + return SR_ERR_NA; + } + + return SR_OK; + +} + +static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) +{ + (void)cg; + + GVariant *gvar; + GVariantBuilder gvb; + + (void)sdi; + struct session_vdev *vdev = sdi->priv; + + switch (key) + { + case SR_CONF_DEVICE_OPTIONS: + *data = g_variant_new_from_data(G_VARIANT_TYPE("ai"), + hwoptions, ARRAY_SIZE(hwoptions) * sizeof(int32_t), TRUE, NULL, NULL); + break; + case SR_CONF_DEVICE_SESSIONS: + *data = g_variant_new_from_data(G_VARIANT_TYPE("ai"), + sessions, ARRAY_SIZE(sessions) * sizeof(int32_t), TRUE, NULL, NULL); + break; + case SR_CONF_SAMPLERATE: + g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); + if(sdi->mode == LOGIC && sample_generator != PATTERN_RANDOM) + { + gvar = g_variant_new_from_data(G_VARIANT_TYPE("at"), + samplerates_file, ARRAY_SIZE(samplerates_file) * sizeof(uint64_t), TRUE, NULL, NULL); + } + else + { + gvar = g_variant_new_from_data(G_VARIANT_TYPE("at"), + samplerates + vdev->samplerates_min_index , (vdev->samplerates_max_index - vdev->samplerates_min_index + 1) * sizeof(uint64_t), TRUE, NULL, NULL); + } + g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); + *data = g_variant_builder_end(&gvb); + break; + case SR_CONF_PATTERN_MODE: + if(sdi->mode == LOGIC) + { + *data = g_variant_new_strv(pattern_strings_logic, pattern_logic_count); + } + else if (sdi->mode == DSO) + { + *data = g_variant_new_strv(pattern_strings_dso, pattern_dso_count); + } + else + { + *data = g_variant_new_strv(pattern_strings_analog, pattern_analog_count); + } + break; + case SR_CONF_MAX_HEIGHT: + *data = g_variant_new_strv(maxHeights, ARRAY_SIZE(maxHeights)); + break; + case SR_CONF_PROBE_CONFIGS: + *data = g_variant_new_from_data(G_VARIANT_TYPE("ai"), + probeOptions, ARRAY_SIZE(probeOptions) * sizeof(int32_t), TRUE, NULL, NULL); + break; + case SR_CONF_PROBE_VDIV: + g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); + gvar = g_variant_new_from_data(G_VARIANT_TYPE("at"), + vdivs10to2000, (ARRAY_SIZE(vdivs10to2000)-1) * sizeof(uint64_t), TRUE, NULL, NULL); + g_variant_builder_add(&gvb, "{sv}", "vdivs", gvar); + *data = g_variant_builder_end(&gvb); + break; + case SR_CONF_PROBE_COUPLING: + g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); + gvar = g_variant_new_from_data(G_VARIANT_TYPE("ay"), + probeCoupling, ARRAY_SIZE(probeCoupling)*sizeof(uint8_t), TRUE, NULL, NULL); + g_variant_builder_add(&gvb, "{sv}", "coupling", gvar); + *data = g_variant_builder_end(&gvb); + break; + case SR_CONF_PROBE_MAP_UNIT: + *data = g_variant_new_strv(probeMapUnits, ARRAY_SIZE(probeMapUnits)); + break; + case SR_CONF_CHANNEL_MODE: + if(sdi->mode == LOGIC&& sample_generator == PATTERN_RANDOM) + { + for(int i = 0;ipriv); + + + vdev = sdi->priv; + vdev->enabled_probes = 0; + packet.status = SR_PKT_OK; + + vdev->cur_block = 0; + vdev->cur_channel = 0; + + if(sample_generator != PATTERN_RANDOM) + { + if (vdev->archive != NULL) + { + sr_err("history archive is not closed."); + } + + sr_dbg("Opening archive file %s", sdi->path); + + vdev->archive = unzOpen64(sdi->path); + + if (NULL == vdev->archive) + { + sr_err("Failed to open session file '%s': " + "zip error %d\n", + sdi->path, ret); + return SR_ERR; + } + } + + if (sdi->mode == LOGIC) + vdev->cur_channel = 0; + else + vdev->cur_channel = vdev->num_probes - 1; + + for (l = sdi->channels; l; l = l->next) + { + probe = l->data; + if (probe->enabled) + vdev->enabled_probes++; + } + + /* Send header packet to the session bus. */ + std_session_send_df_header(sdi, LOG_PREFIX); + + /* Send trigger packet to the session bus */ + if (vdev->trig_pos != 0) + { + struct ds_trigger_pos session_trigger; + if (sdi->mode == DSO) + session_trigger.real_pos = vdev->trig_pos * vdev->enabled_probes / vdev->num_probes; + else + session_trigger.real_pos = vdev->trig_pos; + packet.type = SR_DF_TRIGGER; + packet.payload = &session_trigger; + ds_data_forward(sdi, &packet); + } + + + if(sdi->mode == LOGIC) + { + reset_enabled_probe_num(sdi); + post_data_len = 0; + packet_len = LOGIC_PACKET_LEN(vdev->samplerate); + packet_time = LOGIC_PACKET_TIME(LOGIC_PACKET_NUM_PER_SEC); + if(packet_len < LOGIC_MIN_PACKET_LEN) + { + packet_len = LOGIC_MIN_PACKET_LEN; + packet_time = LOGIC_MIN_PACKET_TIME(vdev->samplerate); + } + + if(sample_generator == PATTERN_RANDOM) + { + logic_total_packet_num = (vdev->total_samples/8/packet_len) + 1; + logci_cur_packet_num = 1; + logic_data_status = LOGIC_FULL; + init_random_data(vdev,sdi); + g_timer_start(run_time); + sr_session_source_add(-1, 0, 0, receive_data_logic, sdi); + } + else + { + sr_session_source_add(-1, 0, 0, receive_data_logic_decoder, sdi); + } + } + else if(sdi->mode == DSO) + { + vdiv_change = TRUE; + if(instant){ + post_data_len = 0; + + gdouble total_time = vdev->timebase /(gdouble)SR_SEC(1)*(gdouble)10; + uint64_t post_data_per_sec = DSO_PACKET_LEN/total_time; + packet_len = 2; + uint64_t packet_num = post_data_per_sec/packet_len; + packet_time = SEC/(gdouble)packet_num; + } + else{ + packet_time = DSO_PACKET_TIME; + } + + load_data = TRUE; + + g_timer_start(run_time); + + sr_session_source_add(-1, 0, 0, receive_data_dso, sdi); + } + else if(sdi->mode == ANALOG) + { + load_data = TRUE; + packet_len = ANALOG_PACKET_LEN(vdev->samplerate); + + if(packet_len < ANALOG_MIN_PACKET_LEN) + { + packet_len = ANALOG_MIN_PACKET_LEN; + packet_time = ANALOG_PACKET_TIME(ANALOG_MIN_PACKET_NUM(vdev->samplerate)); + } + else + { + if (packet_len % ANALOG_PACKET_ALIGN != 0) + { + packet_len += 1; + } + packet_time = ANALOG_PACKET_TIME(ANALOG_PACKET_NUM_PER_SEC); + } + if(sample_generator == PATTERN_RANDOM) + init_analog_random_data(vdev); + + vdev->analog_read_pos = 0; + + sr_session_source_add(-1, 0, 0, receive_data_analog, sdi); + } + + return SR_OK; +} + +static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_data) +{ + struct session_vdev *vdev = sdi->priv; + struct sr_datafeed_packet packet; + packet.status = SR_PKT_OK; + + if(sdi->mode != LOGIC) + { + packet.type = SR_DF_END; + ds_data_forward(sdi, &packet); + close_archive(vdev); + } + + return SR_OK; +} + +static int hw_dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg) +{ + (void)prg; + + struct session_vdev *vdev; + + if (sdi) + { + vdev = sdi->priv; + *status = vdev->mstatus; + return SR_OK; + } + else + { + return SR_ERR; + } +} + +static int receive_data_logic(int fd, int revents, const struct sr_dev_inst *sdi) +{ + assert(sdi); + assert(sdi->priv); + + (void)fd; + (void)revents; + + struct session_vdev *vdev = sdi->priv; + struct sr_datafeed_packet packet; + struct sr_datafeed_logic logic; + + int bToEnd; + int chan_num; + + bToEnd = 0; + + vdev = sdi->priv; + + chan_num = enabled_probe_num; + + if (chan_num < 1){ + sr_err("%s: channel count < 1.", __func__); + return SR_ERR_ARG; + } + if (chan_num > SESSION_MAX_CHANNEL_COUNT){ + sr_err("%s: channel count is to big.", __func__); + return SR_ERR_ARG; + } + + g_timer_start(packet_interval); + + if(!vdev->is_loop){ + if(post_data_len >= vdev->total_samples/8){ + bToEnd = 1; + } + } + + if(!bToEnd) + { + packet.status = SR_PKT_OK; + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.format = LA_CROSS_DATA; + logic.index = 0; + logic.order = 0; + logic.length = chan_num * packet_len; + + void *logic_buf = g_try_malloc0(chan_num * packet_len); + if(logic_buf == NULL) + { + sr_err("%s: logic buf malloc error", __func__); + return SR_ERR_MALLOC; + } + + if(!vdev->is_loop) + { + post_data_len += logic.length / enabled_probe_num; + if(post_data_len >= vdev->total_samples/8) + { + get_last_packet_len(&logic,vdev); + } + } + + if(vdev->samplerate >=SR_MHZ(100) && logic_data_status!= LOGIC_FULL) + { + memset(logic_buf,0,chan_num * packet_len); + if(logic_data_status == LOGIC_EMPTY_END) + logic_data_status = LOGIC_FULL; + else + logic_data_status++; + } + else + { + uint64_t random = vdev->logic_buf_len - logic.length; + random = rand() % random; + int index = enabled_probe_num * 8; + random = floor(random/index)*index; + memcpy(logic_buf,vdev->logic_buf + random,logic.length); + logic.data = logic_buf; + if(vdev->samplerate >=SR_MHZ(100)) + logic_data_status++; + } + + gdouble ideal_time = vdev->total_samples/(gdouble)vdev->samplerate; + ideal_time = ideal_time/(gdouble)logic_total_packet_num*logci_cur_packet_num; + gdouble packet_elapsed = g_timer_elapsed(run_time, NULL); + gdouble waittime = ideal_time - packet_elapsed; + if(waittime > 0) + { + g_usleep(SR_MS(waittime)); + } + + ds_data_forward(sdi, &packet); + g_safe_free(logic_buf); + } + + if (bToEnd || revents == -1) + { + packet.type = SR_DF_END; + ds_data_forward(sdi, &packet); + sr_session_source_remove(-1); + } + + return TRUE; +} + +static int receive_data_logic_decoder(int fd, int revents, const struct sr_dev_inst *sdi) +{ + struct session_vdev *vdev = NULL; + struct sr_datafeed_packet packet; + struct sr_datafeed_logic logic; + struct sr_datafeed_dso dso; + + int ret; + char file_name[32]; + int channel; + int ch_index, malloc_chan_index; + struct session_packet_buffer *pack_buffer; + unz_file_info64 fileInfo; + char szFilePath[15]; + int bToEnd; + int read_chan_index; + int chan_num; + uint8_t *p_wr; + uint8_t *p_rd; + int byte_align; + int dir_index; + int bCheckFile; + const int file_max_channel_count = 128; + + assert(sdi); + assert(sdi->priv); + + (void)fd; + (void)revents; + + sr_detail("Feed chunk."); + + ret = 0; + bToEnd = 0; + packet.status = SR_PKT_OK; + + vdev = sdi->priv; + + assert(vdev->unit_bits > 0); + assert(vdev->archive); + + chan_num = enabled_probe_num; + byte_align = sdi->mode == LOGIC ? 8 : 1; + + if (chan_num < 1){ + sr_err("%s: channel count < 1.", __func__); + return SR_ERR_ARG; + } + if (chan_num > SESSION_MAX_CHANNEL_COUNT){ + sr_err("%s: channel count is to big.", __func__); + return SR_ERR_ARG; + } + + g_timer_start(packet_interval); + + // Make buffer + if (vdev->packet_buffer == NULL){ + vdev->cur_block = 0; + + vdev->packet_buffer = g_try_malloc0(sizeof(struct session_packet_buffer)); + if (vdev->packet_buffer == NULL){ + sr_err("%s: vdev->packet_buffer malloc failed", __func__); + return SR_ERR_MALLOC; + } + + for (ch_index = 0; ch_index <= chan_num; ch_index++){ + vdev->packet_buffer->block_bufs[ch_index] = NULL; + vdev->packet_buffer->block_read_positions[ch_index] = 0; + } + + vdev->packet_buffer->post_buf_len = chan_num * packet_len; + + vdev->packet_buffer->post_buf = g_try_malloc0(vdev->packet_buffer->post_buf_len + 1); + if (vdev->packet_buffer->post_buf == NULL){ + sr_err("%s: vdev->packet_buffer->post_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + + pack_buffer = vdev->packet_buffer; + pack_buffer->post_len; + pack_buffer->block_buf_len = 0; + pack_buffer->block_data_len = 0; + pack_buffer->block_chan_read_pos = 0; + + max_probe_num = chan_num; + } + pack_buffer = vdev->packet_buffer; + + if(chan_num != max_probe_num) + { + for(ch_index = 0 ;ch_index < chan_num; ch_index++) + { + if(pack_buffer->block_bufs[ch_index] != NULL) + { + g_safe_free(pack_buffer->block_bufs[ch_index]); + } + pack_buffer->block_bufs[ch_index] = NULL; + pack_buffer->block_read_positions[ch_index] = 0; + } + pack_buffer->block_buf_len = 0; + pack_buffer->block_data_len = 0; + pack_buffer->block_chan_read_pos = 0; + max_probe_num = chan_num; + } + + if(pack_buffer->post_buf_len != chan_num * packet_len) + { + pack_buffer->post_buf_len = chan_num * packet_len; + if(pack_buffer->post_buf != NULL) + { + g_safe_free(pack_buffer->post_buf); + } + + pack_buffer->post_buf = g_try_malloc0(pack_buffer->post_buf_len); + if (pack_buffer->post_buf == NULL) + { + sr_err("%s: pack_buffer->post_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + + pack_buffer->post_len = 0; + } + + // Make packet. + read_chan_index = 0; + dir_index = 0; + + while (pack_buffer->post_len < pack_buffer->post_buf_len) + { + if (pack_buffer->block_chan_read_pos >= pack_buffer->block_data_len) + { + if(vdev->cur_block >= vdev->num_blocks){ + bToEnd = 1; + break; + } + + for (ch_index = 0; ch_index < chan_num; ch_index++) + { + bCheckFile = 0; + + while (1) + { + snprintf(file_name, sizeof(file_name)-1, "L-%d/%d", dir_index++, vdev->cur_block); + + if (unzLocateFile(vdev->archive, file_name, 0) == UNZ_OK){ + bCheckFile = 1; + break; + } + else if (dir_index > file_max_channel_count){ + break; + } + } + + if (!bCheckFile) + { + sr_err("can't locate zip inner file:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + + if (unzGetCurrentFileInfo64(vdev->archive, &fileInfo, szFilePath, + sizeof(szFilePath), NULL, 0, NULL, 0) != UNZ_OK) + { + sr_err("%s: unzGetCurrentFileInfo64 error.", __func__); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + + if (ch_index == 0){ + pack_buffer->block_data_len = fileInfo.uncompressed_size; + + if (pack_buffer->block_data_len > pack_buffer->block_buf_len) + { + for (malloc_chan_index = 0; malloc_chan_index < chan_num; malloc_chan_index++){ + // Release the old buffer. + if (pack_buffer->block_bufs[malloc_chan_index] != NULL){ + g_safe_free(pack_buffer->block_bufs[malloc_chan_index]); + pack_buffer->block_bufs[malloc_chan_index] = NULL; + } + + pack_buffer->block_bufs[malloc_chan_index] = g_try_malloc0(pack_buffer->block_data_len + 1); + if (pack_buffer->block_bufs[malloc_chan_index] == NULL){ + sr_err("%s: block buffer malloc failed", __func__); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + pack_buffer->block_buf_len = pack_buffer->block_data_len; + } + } + } + else + { + if (pack_buffer->block_data_len != fileInfo.uncompressed_size){ + sr_err("The block size is not coincident:%s", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + } + + // Read the data to buffer. + if (unzOpenCurrentFile(vdev->archive) != UNZ_OK) + { + sr_err("can't open zip inner file:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + + ret = unzReadCurrentFile(vdev->archive, pack_buffer->block_bufs[ch_index], pack_buffer->block_data_len); + if (-1 == ret) + { + sr_err("read zip inner file error:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + unzCloseCurrentFile(vdev->archive); + pack_buffer->block_read_positions[ch_index] = 0; // Reset the read position. + } + vdev->cur_block++; + pack_buffer->block_chan_read_pos = 0; + } + + p_wr = (uint8_t*)pack_buffer->post_buf + pack_buffer->post_len; + p_rd = (uint8_t*)pack_buffer->block_bufs[read_chan_index] + pack_buffer->block_read_positions[read_chan_index]; + *p_wr = *p_rd; + + pack_buffer->post_len++; + pack_buffer->block_read_positions[read_chan_index]++; + + if (pack_buffer->block_read_positions[read_chan_index] % byte_align == 0 + || pack_buffer->block_read_positions[read_chan_index] == pack_buffer->block_data_len) + { + read_chan_index++; + + if (pack_buffer->block_read_positions[read_chan_index] == pack_buffer->block_data_len){ + sr_info("Block read end."); + if (vdev->cur_block < vdev->num_blocks){ + sr_err("%s", "The block data is not align."); + break; + } + } + + // Each channel's data is ready. + if (read_chan_index == chan_num){ + read_chan_index = 0; + pack_buffer->block_chan_read_pos += byte_align; + } + } + } + + if (pack_buffer->post_len >= byte_align * chan_num) + { + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.format = LA_CROSS_DATA; + logic.index = 0; + logic.order = 0; + logic.length = pack_buffer->post_len; + logic.data = pack_buffer->post_buf; + + delay_time(); + ds_data_forward(sdi, &packet); + + pack_buffer->post_len = 0; + } + + if (bToEnd || revents == -1) + { + packet.type = SR_DF_END; + ds_data_forward(sdi, &packet); + sr_session_source_remove(-1); + close_archive(vdev); + } + + return TRUE; +} + +int get_bit(uint64_t timebase) +{ + if(timebase < SR_MS(1) && timebase >= SR_US(20)) + return SR_MS(1)/timebase*2; + else if(timebase < SR_MS(200) && timebase >= SR_MS(1)) + return SR_MS(200)/timebase*2; + else if(timebase <= SR_SEC(10) && timebase > SR_MS(200)) + return SR_SEC(40)/timebase*2; + else + return 200; +} + +static int receive_data_dso(int fd, int revents, const struct sr_dev_inst *sdi) +{ + struct session_vdev *vdev = NULL; + struct sr_datafeed_packet packet; + struct sr_datafeed_dso dso; + struct sr_channel *probe; + + int ret; + char file_name[32]; + int ch_index, malloc_chan_index; + struct session_packet_buffer *pack_buffer; + unz_file_info64 fileInfo; + char szFilePath[15]; + int bToEnd; + int read_chan_index; + int chan_num; + uint8_t *p_wr; + uint8_t *p_rd; + int byte_align; + int dir_index; + int bCheckFile; + const int file_max_channel_count = 128; + + uint16_t tem; + uint8_t val = 0; + uint64_t vdiv; + + assert(sdi); + assert(sdi->priv); + + (void)fd; + (void)revents; + + sr_detail("Feed chunk."); + + ret = 0; + bToEnd = 0; + packet.status = SR_PKT_OK; + + vdev = sdi->priv; + + assert(vdev->unit_bits > 0); + if(sample_generator != PATTERN_RANDOM) + { + assert(vdev->archive); + } + + chan_num = vdev->num_probes; + byte_align = sdi->mode == LOGIC ? 8 : 1; + + if (chan_num < 1){ + sr_err("%s: channel count < 1.", __func__); + return SR_ERR_ARG; + } + if (chan_num > SESSION_MAX_CHANNEL_COUNT){ + sr_err("%s: channel count is to big.", __func__); + return SR_ERR_ARG; + } + + // Make buffer + if (vdev->packet_buffer == NULL){ + vdev->cur_block = 0; + + vdev->packet_buffer = g_try_malloc0(sizeof(struct session_packet_buffer)); + if (vdev->packet_buffer == NULL){ + sr_err("%s: vdev->packet_buffer malloc failed", __func__); + return SR_ERR_MALLOC; + } + + for (ch_index = 0; ch_index <= chan_num; ch_index++){ + vdev->packet_buffer->block_bufs[ch_index] = NULL; + vdev->packet_buffer->block_read_positions[ch_index] = 0; + } + + vdev->packet_buffer->post_buf_len = chan_num * 10000; + + vdev->packet_buffer->post_buf = g_try_malloc0(vdev->packet_buffer->post_buf_len); + if (vdev->packet_buffer->post_buf == NULL){ + sr_err("%s: vdev->packet_buffer->post_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + + pack_buffer = vdev->packet_buffer; + pack_buffer->post_len; + pack_buffer->block_buf_len = 0; + pack_buffer->block_data_len = 0; + pack_buffer->block_chan_read_pos = 0; + } + pack_buffer = vdev->packet_buffer; + if(pack_buffer->post_buf_len != chan_num * 10000) + { + vdev->packet_buffer->post_buf_len = chan_num * 10000; + if(pack_buffer->post_buf != NULL) + { + g_safe_free(pack_buffer->post_buf); + } + pack_buffer->post_buf = g_try_malloc0(pack_buffer->post_buf_len); + if (pack_buffer->post_buf == NULL) + { + sr_err("%s: pack_buffer->post_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + + pack_buffer->post_len = 0; + } + + if(chan_num != max_probe_num) + { + for(ch_index = 0 ;ch_index < chan_num; ch_index++) + { + if(pack_buffer->block_bufs[ch_index] != NULL) + { + g_safe_free(pack_buffer->block_bufs[ch_index]); + } + pack_buffer->block_bufs[ch_index] = NULL; + pack_buffer->block_read_positions[ch_index] = 0; + } + pack_buffer->block_buf_len = 0; + pack_buffer->block_data_len = 0; + pack_buffer->block_chan_read_pos = 0; + max_probe_num = chan_num; + } + + // Make packet. + read_chan_index = 0; + dir_index = 0; + + if(vdiv_change || timebase_change ||offset_change) + { + if(sample_generator == PATTERN_RANDOM) + { + for(int i = 0 ; i < pack_buffer->post_buf_len ;i++) + { + if(i % 2 == 0) + *(uint8_t*)(pack_buffer->post_buf + i) = DSO_RANDOM_DATA; + else + *(uint8_t*)(pack_buffer->post_buf + i) = *(uint8_t*)(pack_buffer->post_buf + i -1); + } + pack_buffer->post_len = pack_buffer->post_buf_len; + } + else + { + if(load_data) + { + pack_buffer->post_len = 0; + while (pack_buffer->post_len < pack_buffer->post_buf_len) + { + if (pack_buffer->block_chan_read_pos >= pack_buffer->block_data_len) + { + if (vdev->cur_block >= vdev->num_blocks){ + vdev->cur_block = 0; + } + + for (ch_index = 0; ch_index < chan_num; ch_index++) + { + bCheckFile = 0; + + while (1) + { + if (sdi->mode == LOGIC) + snprintf(file_name, sizeof(file_name)-1, "L-%d/%d", dir_index++, vdev->cur_block); + else if (sdi->mode == DSO) + snprintf(file_name, sizeof(file_name)-1, "O-%d/0", dir_index++); + + if (unzLocateFile(vdev->archive, file_name, 0) == UNZ_OK){ + bCheckFile = 1; + break; + } + else if (dir_index > file_max_channel_count){ + break; + } + } + + if (!bCheckFile) + { + sr_err("cant't locate zip inner file:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + + if (unzGetCurrentFileInfo64(vdev->archive, &fileInfo, szFilePath, + sizeof(szFilePath), NULL, 0, NULL, 0) != UNZ_OK) + { + sr_err("%s: unzGetCurrentFileInfo64 error.", __func__); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + + if (ch_index == 0){ + pack_buffer->block_data_len = fileInfo.uncompressed_size; + + if (pack_buffer->block_data_len > pack_buffer->block_buf_len) + { + for (malloc_chan_index = 0; malloc_chan_index < chan_num; malloc_chan_index++){ + // Release the old buffer. + if (pack_buffer->block_bufs[malloc_chan_index] != NULL){ + g_safe_free(pack_buffer->block_bufs[malloc_chan_index]); + pack_buffer->block_bufs[malloc_chan_index] = NULL; + } + + pack_buffer->block_bufs[malloc_chan_index] = g_try_malloc0(pack_buffer->block_data_len + 1); + if (pack_buffer->block_bufs[malloc_chan_index] == NULL){ + sr_err("%s: block buffer malloc failed", __func__); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + pack_buffer->block_buf_len = pack_buffer->block_data_len; + } + } + } + else + { + if (pack_buffer->block_data_len != fileInfo.uncompressed_size){ + sr_err("The block size is not coincident:%s", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + } + + // Read the data to buffer. + if (unzOpenCurrentFile(vdev->archive) != UNZ_OK) + { + sr_err("cant't open zip inner file:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + + ret = unzReadCurrentFile(vdev->archive, pack_buffer->block_bufs[ch_index], pack_buffer->block_data_len); + if (-1 == ret) + { + sr_err("read zip inner file error:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + unzCloseCurrentFile(vdev->archive); + pack_buffer->block_read_positions[ch_index] = 0; // Reset the read position. + } + vdev->cur_block++; + pack_buffer->block_chan_read_pos = 0; + } + + p_wr = (uint8_t*)pack_buffer->post_buf + pack_buffer->post_len; + p_rd = (uint8_t*)pack_buffer->block_bufs[read_chan_index] + pack_buffer->block_read_positions[read_chan_index]; + *p_wr = *p_rd; + + pack_buffer->post_len++; + pack_buffer->block_read_positions[read_chan_index]++; + + if (pack_buffer->block_read_positions[read_chan_index] % byte_align == 0 + || pack_buffer->block_read_positions[read_chan_index] == pack_buffer->block_data_len) + { + read_chan_index++; + + if (pack_buffer->block_read_positions[read_chan_index] == pack_buffer->block_data_len){ + sr_info("Block read end."); + if (vdev->cur_block < vdev->num_blocks){ + sr_err("%s", "The block data is not align."); + break; + } + } + + // Each channel's data is ready. + if (read_chan_index == chan_num){ + read_chan_index = 0; + pack_buffer->block_chan_read_pos += byte_align; + } + } + } + memcpy(vdev->dso_buf,pack_buffer->post_buf,DSO_PACKET_LEN); + load_data = FALSE; + } + else{ + memcpy(pack_buffer->post_buf,vdev->dso_buf,DSO_PACKET_LEN); + pack_buffer->post_buf_len = DSO_PACKET_LEN; + } + + } + + if(timebase_change || vdiv_change || offset_change) + { + int index; + int bit = get_bit(vdev->timebase); + + if(sample_generator!= PATTERN_RANDOM) + { + void* tmp_buf = g_try_malloc0(bit); + if(tmp_buf == NULL) + { + sr_err("%s: tmp_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + for(int i = 0 ; i < bit ; i++) + { + if(i%2 == 0) + { + if(bit == 10) + index = i * 16; + else + index = i * 100 / (bit / 2); + } + else + { + + if(bit == 10) + index = (i-1) * 16 + 1; + else + index = (i-1) * 100 / (bit / 2) + 1; + } + *((uint8_t*)tmp_buf+ i) = *((uint8_t*)pack_buffer->post_buf + index + 30); + } + + for(int i = 0 ; i < DSO_PACKET_LEN/bit ; i++) + { + memcpy(pack_buffer->post_buf+i*bit,tmp_buf,bit); + } + + g_safe_free(tmp_buf); + } + + uint16_t offset; + uint16_t high_gate,low_gate; + for(int i = 0 ; i < pack_buffer->post_buf_len; i++) + { + if(i % 2 == 0) + probe = g_slist_nth(sdi->channels, 0)->data; + else + probe = g_slist_nth(sdi->channels, 1)->data; + if(!probe->enabled){ + if(i % 2 == 0) + probe = g_slist_nth(sdi->channels, 1)->data; + else + probe = g_slist_nth(sdi->channels, 0)->data; + } + vdiv = probe->vdiv; + offset = probe->offset; + + uint8_t temp_val = *((uint8_t*)pack_buffer->post_buf + i); + + if(vdiv > SR_mV(200)) + { + if(temp_val > DSO_MID_VAL) + { + val = temp_val - DSO_MID_VAL; + tem = val * DSO_DEFAULT_VDIV / vdiv; + temp_val = DSO_MID_VAL + tem; + } + else if(temp_val < DSO_MID_VAL) + { + val = DSO_MID_VAL - temp_val; + tem = val * DSO_DEFAULT_VDIV / vdiv; + temp_val = DSO_MID_VAL - tem; + } + *((uint8_t*)pack_buffer->post_buf + i) = temp_val; + } + else{ + if(temp_val > DSO_MID_VAL) + { + val = temp_val - DSO_MID_VAL; + tem = (uint16_t)val * (uint16_t)DSO_DEFAULT_VDIV/(uint16_t)vdiv; + tem = DSO_EXPAND_MID_VAL(SR_mV(200)/vdiv) + tem; + } + else if(temp_val < DSO_MID_VAL) + { + val = DSO_MID_VAL - temp_val; + tem = (uint16_t)val * (uint16_t)DSO_DEFAULT_VDIV/(uint16_t)vdiv; + tem = DSO_EXPAND_MID_VAL(SR_mV(200)/vdiv) - tem; + } + else{ + tem = DSO_EXPAND_MID_VAL(SR_mV(200)/vdiv); + } + + high_gate = DSO_EXPAND_MID_VAL(SR_mV(200)/vdiv); + high_gate -= probe->offset; + low_gate = high_gate + DSO_LIMIT; + if(tem <=high_gate) + tem = DSO_MAX_VAL; + else if(tem >=low_gate) + tem = DSO_MIN_VAL; + else + tem-= high_gate; + *((uint8_t*)pack_buffer->post_buf + i) = (uint8_t)tem; + } + } + + offset_change = FALSE; + timebase_change = FALSE; + vdiv_change = FALSE; + } + } + + gdouble total_time = vdev->timebase /(gdouble)SR_SEC(1)*(gdouble)10; + gdouble total_time_elapsed = g_timer_elapsed(run_time, NULL); + + if(!instant) + { + if (total_time_elapsed < total_time) + { + gdouble percent = total_time_elapsed / total_time; + int buf_len = percent* DSO_PACKET_LEN; + if(buf_len %2 != 0) + buf_len +=1; + pack_buffer->post_len = buf_len; + } + else + { + uint8_t top0; + uint8_t top1; + if(sample_generator == PATTERN_RANDOM) + { + top0 = *((uint8_t*)pack_buffer->post_buf + pack_buffer->post_buf_len -2); + top1 = *((uint8_t*)pack_buffer->post_buf + pack_buffer->post_buf_len -1); + } + else + { + top0 = *((uint8_t*)pack_buffer->post_buf + get_bit(vdev->timebase) -2); + top1 = *((uint8_t*)pack_buffer->post_buf + get_bit(vdev->timebase) -1); + } + + for(int i = pack_buffer->post_len -1; i > 1; i -= 2){ + *((uint8_t*)pack_buffer->post_buf + i) = *((uint8_t*)pack_buffer->post_buf + i - 2); + } + + for(int i = pack_buffer->post_len -2; i > 0; i -= 2){ + *((uint8_t*)pack_buffer->post_buf + i) = *((uint8_t*)pack_buffer->post_buf + i - 2); + } + + *(uint8_t*)pack_buffer->post_buf = top0; + *((uint8_t*)pack_buffer->post_buf + 1)= top1; + pack_buffer->post_len = DSO_PACKET_LEN; + } + + } + else + { + if(DSO_PACKET_LEN >post_data_len) + { + pack_buffer->post_len = packet_len; + post_data_len += packet_len; + } + else + { + bToEnd = 1; + instant = FALSE; + } + } + + if (pack_buffer->post_len >= byte_align * chan_num && !bToEnd) + { + packet.type = SR_DF_DSO; + packet.payload = &dso; + dso.probes = sdi->channels; + dso.mq = SR_MQ_VOLTAGE; + dso.unit = SR_UNIT_VOLT; + dso.mqflags = SR_MQFLAG_AC; + dso.num_samples = pack_buffer->post_len / chan_num; + if (instant) + dso.data = pack_buffer->post_buf+post_data_len; + else + dso.data = pack_buffer->post_buf; + + delay_time(); + g_timer_start(packet_interval); + // Send data back. + ds_data_forward(sdi, &packet); + } + + if (bToEnd || revents == -1) + { + packet.type = SR_DF_END; + ds_data_forward(sdi, &packet); + sr_session_source_remove(-1); + } + + return TRUE; +} + + +static int receive_data_analog(int fd, int revents, const struct sr_dev_inst *sdi) +{ + struct session_vdev *vdev = sdi->priv; + struct sr_datafeed_packet packet; + struct sr_datafeed_analog analog; + struct sr_channel *probe = NULL; + + char file_name[32]; + int ret; + + assert(sdi); + assert(sdi->priv); + + (void)fd; + (void)revents; + + sr_detail("Feed chunk."); + + packet.status = SR_PKT_OK; + + assert(vdev->unit_bits > 0); + + g_timer_start(packet_interval); + + if(load_data) + { + if(sample_generator != PATTERN_RANDOM) + { + vdev->analog_buf_len = 0; + + void* analog_data = g_try_malloc0(ANALOG_DATA_LEN_PER_CYCLE); + if(analog_data == NULL) + { + sr_err("%s:analog_data malloc failed",__func__); + return SR_ERR_MALLOC; + } + + snprintf(file_name, sizeof(file_name)-1, "%s-%d/%d", "A", + 0, 0); + + if (unzLocateFile(vdev->archive, file_name, 0) != UNZ_OK) + { + sr_err("can't locate zip inner file:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + if (unzOpenCurrentFile(vdev->archive) != UNZ_OK) + { + sr_err("can't open zip inner file:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + + ret = unzReadCurrentFile(vdev->archive, analog_data, ANALOG_DATA_LEN_PER_CYCLE); + if (-1 == ret) + { + sr_err("read zip inner file error:\"%s\"", file_name); + send_error_packet(sdi, vdev, &packet); + return FALSE; + } + + uint64_t total_buf_len = ANALOG_CYCLE_RATIO * vdev->total_samples * ANALOG_PROBE_NUM; + if(total_buf_len % ANALOG_DATA_LEN_PER_CYCLE != 0) + { + total_buf_len = total_buf_len / ANALOG_DATA_LEN_PER_CYCLE * ANALOG_DATA_LEN_PER_CYCLE; + } + + if(vdev->analog_buf != NULL) + { + g_safe_free(vdev->analog_buf); + vdev->analog_buf = NULL; + } + vdev->analog_buf = (g_try_malloc0(total_buf_len)); + if (vdev->analog_buf == NULL) + { + sr_err("%s: vdev->analog_buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + vdev->analog_buf_len = total_buf_len; + uint64_t per_block_after_expend = total_buf_len / ANALOG_DATA_LEN_PER_CYCLE; + + probe = g_slist_nth(sdi->channels, 0)->data; + uint64_t p0_vdiv = probe->vdiv; + probe = g_slist_nth(sdi->channels, 1)->data; + uint64_t p1_vdiv = probe->vdiv; + uint64_t vdiv; + uint8_t val = 0; + uint16_t tem; + uint64_t cur_l = 0; + for(int i = 0 ; i < ANALOG_DATA_LEN_PER_CYCLE;i++) + { + if(i % 2 == 0) + vdiv = p0_vdiv; + else + vdiv = p1_vdiv; + tem = 0; + + uint8_t temp_value = *((uint8_t*)analog_data + i); + + if(temp_value > ANALOG_MID_VAL){ + val = temp_value - ANALOG_MID_VAL; + tem = val * ANALOG_DEFAULT_VDIV / vdiv; + if(tem >= ANALOG_MID_VAL) + temp_value = ANALOG_MIN_VAL; + else + temp_value = ANALOG_MID_VAL + tem; + } + else if(temp_value < ANALOG_MID_VAL) + { + val = ANALOG_MID_VAL - temp_value; + tem = val * ANALOG_DEFAULT_VDIV / vdiv; + + if(tem >= ANALOG_MID_VAL) + temp_value = ANALOG_MAX_VAL; + else + temp_value = ANALOG_MID_VAL - tem; + } + + for(int j = 0 ; j analog_buf + cur_l,temp_value,1); + } + } + g_safe_free(analog_data); + } + load_data = FALSE; + } + + void* buf = g_try_malloc0(packet_len); + if(buf == NULL) + { + sr_err("%s: buf malloc failed", __func__); + return SR_ERR_MALLOC; + } + if(vdev->analog_read_pos + packet_len >= vdev->analog_buf_len - 1 ) + { + uint64_t back_len = vdev->analog_buf_len - vdev->analog_read_pos; + for (int i = 0; i < back_len; i++) + { + uint8_t temp_val = *((uint8_t*)vdev->analog_buf + vdev->analog_read_pos + i); + memset(buf + i,temp_val,1); + } + + uint64_t front_len = packet_len - back_len; + for (int i = 0; i < front_len; i++) + { + uint8_t temp_val = *((uint8_t*)vdev->analog_buf + i); + memset(buf + back_len + i,temp_val,1); + } + vdev->analog_read_pos = front_len; + } + else + { + memcpy(buf,vdev->analog_buf + vdev->analog_read_pos,packet_len); + vdev->analog_read_pos += packet_len; + } + + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + analog.probes = sdi->channels; + analog.num_samples = packet_len / vdev->num_probes; + analog.unit_bits = vdev->unit_bits; + analog.mq = SR_MQ_VOLTAGE; + analog.unit = SR_UNIT_VOLT; + analog.mqflags = SR_MQFLAG_AC; + analog.data = buf; + + delay_time(); + ds_data_forward(sdi, &packet); + g_safe_free(buf); + + return TRUE; +} + +static void send_error_packet(const struct sr_dev_inst *cb_sdi, struct session_vdev *vdev, struct sr_datafeed_packet *packet) +{ + packet->type = SR_DF_END; + packet->status = SR_PKT_SOURCE_ERROR; + ds_data_forward(cb_sdi, packet); + sr_session_source_remove(-1); + close_archive(vdev); +} + + +static int close_archive(struct session_vdev *vdev) +{ + if(sample_generator != PATTERN_RANDOM) + { + assert(vdev->archive); + + // close current inner file + if (vdev->capfile) + { + unzCloseCurrentFile(vdev->archive); + vdev->capfile = 0; + } + + int ret = unzClose(vdev->archive); + if (ret != UNZ_OK) + { + sr_err("close zip archive error!"); + } + + vdev->archive = NULL; + } + + return SR_OK; +} + +static int load_virtual_device_session(struct sr_dev_inst *sdi) +{ + GKeyFile *kf; + unzFile archive = NULL; + char szFilePath[15]; + unz_file_info64 fileInfo; + + struct sr_channel *probe; + int devcnt, i, j; + uint64_t tmp_u64, total_probes, enabled_probes; + char **sections, **keys, *metafile, *val,*probe_name; + int mode = LOGIC; + int channel_type = SR_CHANNEL_LOGIC; + int version = 1; + + struct session_vdev * vdev = sdi->priv; + + assert(sdi); + if (sample_generator != PATTERN_RANDOM) + { + assert(sdi->path); + } + + switch (sdi->mode) + { + case LOGIC: + if(sample_generator != PATTERN_RANDOM){ + archive = unzOpen64(sdi->path); + if (NULL == archive) + { + sr_err("%s: Load zip file error.", __func__); + return SR_ERR; + } + if (unzLocateFile(archive, "header", 0) != UNZ_OK) + { + unzClose(archive); + sr_err("%s: unzLocateFile error.", __func__); + return SR_ERR; + } + if (unzGetCurrentFileInfo64(archive, &fileInfo, szFilePath, + sizeof(szFilePath), NULL, 0, NULL, 0) != UNZ_OK) + { + unzClose(archive); + sr_err("%s: unzGetCurrentFileInfo64 error.", __func__); + return SR_ERR; + } + if (unzOpenCurrentFile(archive) != UNZ_OK) + { + sr_err("%s: Cant't open zip inner file.", __func__); + unzClose(archive); + return SR_ERR; + } + + if (!(metafile = g_try_malloc(fileInfo.uncompressed_size))) + { + sr_err("%s: metafile malloc failed", __func__); + return SR_ERR_MALLOC; + } + + unzReadCurrentFile(archive, metafile, fileInfo.uncompressed_size); + unzCloseCurrentFile(archive); + + if (unzClose(archive) != UNZ_OK) + { + sr_err("%s: Close zip archive error.", __func__); + return SR_ERR; + } + archive = NULL; + + kf = g_key_file_new(); + if (!g_key_file_load_from_data(kf, metafile, fileInfo.uncompressed_size, 0, NULL)) + { + sr_err("Failed to parse metadata."); + return SR_ERR; + } + + devcnt = 0; + sections = g_key_file_get_groups(kf, NULL); + + for (i = 0; sections[i]; i++) + { + if (!strcmp(sections[i], "version")) + { + keys = g_key_file_get_keys(kf, sections[i], NULL, NULL); + for (j = 0; keys[j]; j++) + { + val = g_key_file_get_string(kf, sections[i], keys[j], NULL); + if (!strcmp(keys[j], "version")) + { + version = strtoull(val, NULL, 10); + sr_info("The 'header' file format version:%d", version); + } + } + } + + if (!strncmp(sections[i], "header", 6)) + { + enabled_probes = total_probes = 0; + keys = g_key_file_get_keys(kf, sections[i], NULL, NULL); + + for (j = 0; keys[j]; j++) + { + val = g_key_file_get_string(kf, sections[i], keys[j], NULL); + + if (!strcmp(keys[j], "device mode")) + { + mode = strtoull(val, NULL, 10); + } + else if (!strcmp(keys[j], "samplerate")) + { + sr_parse_sizestring(val, &tmp_u64); + vdev->samplerate = tmp_u64; + if(sdi->mode == LOGIC && sample_generator >PATTERN_RANDOM) + { + samplerates_file[0] = vdev->samplerate; + } + } + else if (!strcmp(keys[j], "total samples")) + { + tmp_u64 = strtoull(val, NULL, 10); + vdev->total_samples = tmp_u64; + if(sdi->mode == LOGIC && sample_generator >PATTERN_RANDOM) + { + samplecounts_file[0] = vdev->total_samples; + } + } + else if (!strcmp(keys[j], "total blocks")) + { + tmp_u64 = strtoull(val, NULL, 10); + vdev->num_blocks = tmp_u64; + } + else if (!strcmp(keys[j], "total probes")) + { + sr_dev_probes_free(sdi); + total_probes = strtoull(val, NULL, 10); + vdev->num_probes = total_probes; + } + else if (!strncmp(keys[j], "probe", 5)) + { + enabled_probes++; + tmp_u64 = strtoul(keys[j] + 5, NULL, 10); + channel_type = (mode == DSO) ? SR_CHANNEL_DSO : (mode == ANALOG) ? SR_CHANNEL_ANALOG + : SR_CHANNEL_LOGIC; + if (!(probe = sr_channel_new(tmp_u64, channel_type, TRUE, val))) + { + sr_err("%s: create channel failed", __func__); + sr_dev_inst_free(sdi); + return SR_ERR; + } + + sdi->channels = g_slist_append(sdi->channels, probe); + } + } + adjust_samplerate(sdi); + g_strfreev(keys); + } + devcnt++; + } + + g_strfreev(sections); + g_key_file_free(kf); + g_safe_free(metafile); + } + else + { + vdev->samplerate = LOGIC_DEFAULT_SAMPLERATE; + vdev->total_samples = LOGIC_DEFAULT_TOTAL_SAMPLES; + vdev->num_probes = LOGIC_DEFAULT_NUM_PROBE; + sr_dev_probes_free(sdi); + + for (int i = 0; i < LOGIC_DEFAULT_NUM_PROBE; i++) + { + probe_name = probe_names[i]; + if (!(probe = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, probe_name))) + { + sr_err("%s: create channel failed", __func__); + sr_dev_inst_free(sdi); + return SR_ERR; + } + sdi->channels = g_slist_append(sdi->channels, probe); + } + //updata + ch_mode = DEMO_LOGIC125x16; + logic_index = LOGIC125x16; + logic_adjust_samplerate(sdi->priv); + } + break; + case DSO: + vdev->samplerate = DSO_DEFAULT_SAMPLERATE; + vdev->total_samples = DSO_DEFAULT_TOTAL_SAMPLES; + vdev->num_probes = DSO_DEFAULT_NUM_PROBE; + vdev->num_blocks = DSO_DEFAULT_NUM_BLOCK; + sr_dev_probes_free(sdi); + + for (int i = 0; i < DSO_DEFAULT_NUM_PROBE; i++) + { + probe_name = probe_names[i]; + if (!(probe = sr_channel_new(i, SR_CHANNEL_DSO, TRUE, probe_name))) + { + sr_err("%s: create channel failed", __func__); + sr_dev_inst_free(sdi); + return SR_ERR; + } + probe->enabled = DSO_DEFAULT_ENABLE; + probe->coupling = DSO_DEFAULT_COUPLING; + probe->vdiv = DSO_DEFAULT_VIDV; + probe->vfactor = DSO_DEFAULT_VFACOTR; + probe->hw_offset = DSO_DEFAULT_HW_OFFSET; + probe->offset = DSO_DEFAULT_OFFSET; + probe->trig_value = DSO_DEFAULT_TRIG_VAL; + sdi->channels = g_slist_append(sdi->channels, probe); + } + adjust_samplerate(sdi); + break; + case ANALOG: + vdev->samplerate = ANALOG_DEFAULT_SAMPLERATE; + vdev->total_samples = ANALOG_DEFAULT_TOTAL_SAMPLES; + vdev->num_probes = ANALOG_DEFAULT_NUM_PROBE; + vdev->num_blocks = ANALOG_DEFAULT_NUM_BLOCK; + sr_dev_probes_free(sdi); + + for (int i = 0; i < ANALOG_DEFAULT_NUM_PROBE; i++) + { + probe_name = probe_names[i]; + if (!(probe = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE, probe_name))) + { + sr_err("%s: create channel failed", __func__); + sr_dev_inst_free(sdi); + return SR_ERR; + } + probe->bits = ANALOG_DEFAULT_BIT; + probe->enabled = ANALOG_DEFAULT_ENABLE; + probe->coupling = ANALOG_DEFAULT_COUPLING; + probe->vdiv = ANALOG_DEFAULT_VIDV; + probe->vfactor = ANALOG_DEFAULT_VFACOTR; + probe->hw_offset = ANALOG_DEFAULT_HW_OFFSET; + probe->offset = ANALOG_DEFAULT_OFFSET; + probe->trig_value = ANALOG_DEFAULT_TRIG_VAL; + probe->map_default = ANALOG_DEFAULT_MAP_DEFAULT; + probe->map_unit = ANALOG_DEFAULT_MAP_UNIT; + probe->map_min = ANALOG_DEFAULT_MAP_MIN; + probe->map_max = ANALOG_DEFAULT_MAP_MAX; + + sdi->channels = g_slist_append(sdi->channels, probe); + } + adjust_samplerate(sdi); + break; + default: + break; + } + return SR_OK; +} + + +SR_PRIV struct sr_dev_driver demo_driver_info = { + .name = "virtual-demo", + .longname = "Demo driver and pattern generator", + .api_version = 1, + .driver_type = DRIVER_TYPE_DEMO, + .init = hw_init, + .cleanup = NULL, + .scan = hw_scan, + .dev_mode_list = hw_dev_mode_list, + .config_get = config_get, + .config_set = config_set, + .config_list = config_list, + .dev_open = hw_dev_open, + .dev_close = hw_dev_close, + .dev_destroy = dev_destroy, + .dev_status_get = hw_dev_status_get, + .dev_acquisition_start = hw_dev_acquisition_start, + .dev_acquisition_stop = hw_dev_acquisition_stop, + .priv = NULL, +}; diff --git a/libsigrok4DSL/hardware/demo.h b/libsigrok4DSL/hardware/demo.h new file mode 100644 index 00000000..3aead6f4 --- /dev/null +++ b/libsigrok4DSL/hardware/demo.h @@ -0,0 +1,619 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2013 Bert Vermeulen + * Copyright (C) 2013 DreamSourceLab + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef LIBDSL_HARDWARE_DEMO_H +#define LIBDSL_HARDWARE_DEMO_H + +#include +#include "../../libsigrok-internal.h" +#include + +enum DEMO_PATTERN { + PATTERN_INVALID = -1, + PATTERN_RANDOM = 0, + PATTERN_DEFAULT = 1, +}; + +enum DEMO_LOGIC_CHANNEL_ID { + DEMO_LOGIC125x16 = 16, + DEMO_LOGIC250x12 = 17, + DEMO_LOGIC500x6 = 18, + DEMO_LOGIC1000x3 = 19, +}; + +enum DEMO_CHANNEL_ID { + DEMO_LOGIC100x16 = 0, + DEMO_ANALOG10x2 = 1 , + DEMO_DSO200x2 = 2, +}; + +enum DEMO_LOGIC_CHANNEL_INDEX { + LOGIC125x16 = 0, + LOGIC250x12 = 1, + LOGIC500x6 = 2, + LOGIC1000x3 = 3, +}; + +static char *pattern_strings_logic[100] = {"random"}; +static char *pattern_strings_dso[100] = {"random"}; +static char *pattern_strings_analog[100] = {"random"}; +static int pattern_logic_count = 1; +static int pattern_dso_count= 1; +static int pattern_analog_count= 1; + +static uint64_t samplerates_file[1]; +static uint64_t samplecounts_file[1]; +static GTimer *packet_interval = NULL; +static GTimer *run_time = NULL; +static gboolean load_data = TRUE; +static gboolean is_change = FALSE; +static int enabled_probe_num; +static uint64_t packet_len; +static gdouble packet_time; +static uint64_t post_data_len; +extern char DS_RES_PATH[500]; +static gboolean vdiv_change; +static gboolean timebase_change; +static gboolean offset_change; +static gboolean instant = FALSE; +static int max_probe_num = 0; +extern char DS_RES_PATH[500]; +uint8_t sample_generator; +static int64_t analog_count = 0; +static uint64_t total_num = 0; +static uint64_t logci_cur_packet_num = 0; +static uint64_t logic_total_packet_num = 0; +static uint8_t logic_data_status = 0; + +static enum DEMO_LOGIC_CHANNEL_ID ch_mode = DEMO_LOGIC125x16; +static enum DEMO_LOGIC_CHANNEL_INDEX logic_index = LOGIC125x16; + +struct session_packet_buffer; + +static const uint64_t vdivs10to2000[] = { + SR_mV(10), + SR_mV(20), + SR_mV(50), + SR_mV(100), + SR_mV(200), + SR_mV(500), + SR_V(1), + SR_V(2), + 0, +}; + +struct session_vdev +{ + int version; + unzFile archive; // zip document + int capfile; // current inner file open status + + uint16_t samplerates_min_index; + uint16_t samplerates_max_index; + + void *logic_buf; + uint64_t logic_buf_len; + + void *dso_buf; + + void *analog_buf; + uint64_t analog_buf_len; + uint64_t analog_read_pos; + + int cur_channel; + int cur_block; + int num_blocks; + uint64_t samplerate; + uint64_t total_samples; + int64_t trig_time; + uint64_t trig_pos; + int cur_probes; + int num_probes; + int enabled_probes; + uint64_t timebase; + uint64_t max_timebase; + uint64_t min_timebase; + uint8_t unit_bits; + uint32_t ref_min; + uint32_t ref_max; + uint8_t max_height; + struct sr_status mstatus; + struct session_packet_buffer *packet_buffer; + + int is_loop; +}; + +#define SESSION_MAX_CHANNEL_COUNT 512 + +struct session_packet_buffer +{ + void *post_buf; + uint64_t post_buf_len; + uint64_t post_len; + + uint64_t block_buf_len; + uint64_t block_chan_read_pos; + uint64_t block_data_len; + void *block_bufs[SESSION_MAX_CHANNEL_COUNT]; + uint64_t block_read_positions[SESSION_MAX_CHANNEL_COUNT]; +}; + +struct DEMO_caps { + uint64_t mode_caps; + uint64_t feature_caps; + uint64_t channels; + uint64_t hw_depth; + uint64_t dso_depth; + uint8_t intest_channel; + const uint64_t *vdivs; + uint8_t vga_id; + uint16_t default_channelmode; + int default_pattern; /**enum DEMO_PATTERN type*/ + uint64_t default_timebase; +}; + +struct DEMO_profile { + const char *vendor; + const char *model; + const char *model_version; + + struct DEMO_caps dev_caps; +}; + + + +struct DEMO_channels { + enum DEMO_CHANNEL_ID id; + enum OPERATION_MODE mode; + enum CHANNEL_TYPE type; + + uint16_t num; + uint8_t unit_bits; + uint64_t default_samplerate; + uint64_t default_samplelimit; + uint64_t min_samplerate; + uint64_t max_samplerate; + + const char *descr; +}; + +struct demo_context { + const struct DEMO_profile *profile; + + int pipe_fds[2]; + GIOChannel *channel; + uint64_t cur_samplerate; + uint64_t limit_samples; + uint64_t limit_samples_show; + uint64_t limit_msec; + uint8_t sample_generator; + uint64_t samples_counter; + void *cb_data; + int64_t starttime; + int stop; + uint64_t timebase; + enum DEMO_CHANNEL_ID ch_mode; + uint16_t samplerates_min_index; + uint16_t samplerates_max_index; + gboolean instant; + uint8_t max_height; + uint64_t samples_not_sent; + + uint16_t *buf; + uint64_t pre_index; + struct sr_status mstatus; + + int trigger_stage; + uint16_t trigger_mask; + uint16_t trigger_value; + uint16_t trigger_edge; + uint8_t trigger_slope; + uint8_t trigger_source; +}; + +static const uint64_t samplerates[] = { + SR_HZ(10), + SR_HZ(20), + SR_HZ(50), + SR_HZ(100), + SR_HZ(200), + SR_HZ(500), + SR_KHZ(1), + SR_KHZ(2), + SR_KHZ(5), + SR_KHZ(10), + SR_KHZ(20), + SR_KHZ(40), + SR_KHZ(50), + SR_KHZ(100), + SR_KHZ(200), + SR_KHZ(400), + SR_KHZ(500), + SR_MHZ(1), + SR_MHZ(2), + SR_MHZ(4), + SR_MHZ(5), + SR_MHZ(10), + SR_MHZ(20), + SR_MHZ(25), + SR_MHZ(40), + SR_MHZ(50), + SR_MHZ(100), + SR_MHZ(125), + SR_MHZ(250), + SR_MHZ(400), + SR_MHZ(500), + SR_MHZ(800), + SR_GHZ(1), + SR_GHZ(2), + SR_GHZ(5), + SR_GHZ(10), +}; + +/* hardware Capabilities */ +#define CAPS_MODE_LOGIC (1 << 0) +#define CAPS_MODE_ANALOG (1 << 1) +#define CAPS_MODE_DSO (1 << 2) + +#define CAPS_FEATURE_NONE 0 +// zero calibration ability +#define CAPS_FEATURE_ZERO (1 << 4) +/* end */ + +#define DEFAULT_LOGIC_FILE "protocol" + +#define SEC 1 +#define LOGIC_POST_DATA_PER_SECOND(n) ((n)/(8)) +#define LOGIC_PACKET_NUM_PER_SEC (gdouble)1000 +#define LOGIC_PACKET_TIME(n) (gdouble)((SEC)/(n)) +#define LOGIC_PACKET_LEN(n) (ceil((LOGIC_POST_DATA_PER_SECOND(n))/(LOGIC_PACKET_NUM_PER_SEC)/(8))*(8)) +#define LOGIC_MIN_PACKET_LEN 8 +#define LOGIC_MIN_PACKET_NUM(n) (LOGIC_POST_DATA_PER_SECOND(n))/(LOGIC_MIN_PACKET_LEN) +#define LOGIC_MIN_PACKET_TIME(n) ((SEC)/(gdouble)(LOGIC_MIN_PACKET_NUM(n))) +#define LOGIC_MAX_PACKET_LEN 62504 +#define LOGIC_MAX_PACKET_NUM(n) (LOGIC_POST_DATA_PER_SECOND(n))/(LOGIC_MAX_PACKET_LEN) +#define LOGIC_MAX_PACKET_TIME(n) ((SEC)/(gdouble)(LOGIC_MAX_PACKET_NUM(n))) + +#define LOGIC_BUF_LEN SR_MB(2) + +#define LOGIC_EMPTY_END 9 +#define LOGIC_FULL 0 + + +#define DSO_PACKET_NUM_PER_SEC (gdouble)200 +#define DSO_PACKET_TIME ((SEC)/(DSO_PACKET_NUM_PER_SEC)) +#define DSO_PACKET_LEN 20000 +#define DSO_RANDOM_DATA rand()%120 +68 +#define DSO_BUF_LEN SR_MB(1) + +#define ANALOG_PROBE_NUM 2 +#define ANALOG_PACKET_NUM_PER_SEC 200 +#define ANALOG_POST_DATA_PER_SECOND(n) ((n)*(ANALOG_PROBE_NUM)) +#define ANALOG_PACKET_LEN(n) ((ANALOG_POST_DATA_PER_SECOND(n))/(ANALOG_PACKET_NUM_PER_SEC)) +#define ANALOG_PACKET_TIME(n) (gdouble)((SEC)/(gdouble)(n)) +#define ANALOG_MIN_PACKET_LEN 2 +#define ANALOG_MIN_PACKET_NUM(n) ((ANALOG_POST_DATA_PER_SECOND(n))/(ANALOG_MIN_PACKET_LEN)) +#define ANALOG_PACKET_ALIGN 2 + +#define LOGIC_HW_DEPTH (SR_GHZ(16)) + + +#define LOGIC_MAX_PROBE_NUM 16 +#define LOGIC_HIGH_LEVEL 255 +#define LOGIC_LOW_LEVEL 0 + + +#define DSO_DEFAULT_VDIV 1000 +#define DSO_MID_VAL 128 +#define DSO_MAX_VAL 0 +#define DSO_MIN_VAL 255 + +#define DSO_EXPAND_MID_VAL(i) ((i)*(uint16_t)(256)) +#define DSO_LIMIT 255 + + +#define ANALOG_HW_DEPTH (SR_MHZ(12.5)) +#define ANALOG_DEFAULT_VDIV 1000 +#define ANALOG_MID_VAL 128 +#define ANALOG_MAX_VAL 0 +#define ANALOG_MIN_VAL 255 + +#define ANALOG_CYCLE_RATIO ((gdouble)(103) / (gdouble)(2048)) +#define ANALOG_DATA_LEN_PER_CYCLE 206 +#define ANALOG_RANDOM_DATA rand()%120 +68 +#define ANALOG_PROBE_NUM 2 + +#define ANALOG_RETE(n) ((n/SR_HZ(10))) + +//defult value +#define LOGIC_DEFAULT_SAMPLERATE SR_MHZ(1) +#define LOGIC_DEFAULT_TOTAL_SAMPLES SR_MHZ(1) +#define LOGIC_DEFAULT_NUM_PROBE 16 + +#define DSO_DEFAULT_SAMPLERATE SR_MHZ(100) +#define DSO_DEFAULT_TOTAL_SAMPLES SR_KHZ(10) +#define DSO_DEFAULT_NUM_PROBE 2 +#define DSO_DEFAULT_NUM_BLOCK 1 +#define DSO_DEFAULT_ENABLE TRUE +#define DSO_DEFAULT_COUPLING 1 +#define DSO_DEFAULT_VIDV SR_V(1) +#define DSO_DEFAULT_VFACOTR SR_V(1) +#define DSO_DEFAULT_HW_OFFSET 128 +#define DSO_DEFAULT_OFFSET 128 +#define DSO_DEFAULT_TRIG_VAL 0.5 + +#define ANALOG_DEFAULT_SAMPLERATE SR_MHZ(1) +#define ANALOG_DEFAULT_TOTAL_SAMPLES SR_MHZ(1) +#define ANALOG_DEFAULT_NUM_PROBE 2 +#define ANALOG_DEFAULT_NUM_BLOCK 1 +#define ANALOG_DEFAULT_BIT 8 +#define ANALOG_DEFAULT_ENABLE TRUE +#define ANALOG_DEFAULT_COUPLING 1 +#define ANALOG_DEFAULT_VIDV SR_V(1) +#define ANALOG_DEFAULT_VFACOTR SR_mV(1) +#define ANALOG_DEFAULT_HW_OFFSET 128 +#define ANALOG_DEFAULT_OFFSET 128 +#define ANALOG_DEFAULT_TRIG_VAL 128 +#define ANALOG_DEFAULT_MAP_DEFAULT TRUE +#define ANALOG_DEFAULT_MAP_UNIT "V" +#define ANALOG_DEFAULT_MAP_MIN (gdouble)-5 +#define ANALOG_DEFAULT_MAP_MAX (gdouble)+5 + + + +static const char *maxHeights[] = { + "1X", + "2X", + "3X", + "4X", + "5X", +}; + +/* We name the probes 0-7 on our demo driver. */ +static const char *probe_names[] = { + "0", "1", "2", "3", + "4", "5", "6", "7", + "8", "9", "10", "11", + "12", "13", "14", "15", + NULL, +}; + +static const char *probeMapUnits[] = { + "V", + "A", + "°C", + "°F", + "g", + "m", + "m/s", +}; + +static const int hwoptions[] = { + SR_CONF_PATTERN_MODE, + SR_CONF_MAX_HEIGHT, +}; + +static const int32_t sessions[] = { + SR_CONF_SAMPLERATE, + SR_CONF_LIMIT_SAMPLES, + SR_CONF_PATTERN_MODE, + SR_CONF_MAX_HEIGHT, +}; + +static const int32_t probeOptions[] = { + SR_CONF_PROBE_COUPLING, + SR_CONF_PROBE_VDIV, + SR_CONF_PROBE_MAP_DEFAULT, + SR_CONF_PROBE_MAP_UNIT, + SR_CONF_PROBE_MAP_MIN, + SR_CONF_PROBE_MAP_MAX, +}; + +static const int32_t probeSessions[] = { + SR_CONF_PROBE_COUPLING, + SR_CONF_PROBE_VDIV, + SR_CONF_PROBE_MAP_DEFAULT, + SR_CONF_PROBE_MAP_UNIT, + SR_CONF_PROBE_MAP_MIN, + SR_CONF_PROBE_MAP_MAX, +}; + +static const uint8_t probeCoupling[] = { + SR_DC_COUPLING, + SR_AC_COUPLING, +}; + +static const gboolean default_ms_en[] = { + FALSE, /* DSO_MS_BEGIN */ + TRUE, /* DSO_MS_FREQ */ + FALSE, /* DSO_MS_PERD */ + TRUE, /* DSO_MS_VMAX */ + TRUE, /* DSO_MS_VMIN */ + FALSE, /* DSO_MS_VRMS */ + FALSE, /* DSO_MS_VMEA */ + FALSE, /* DSO_MS_VP2P */ +}; + +static const struct DEMO_profile supported_Demo[] = { + /* + * Demo + */ + {"DreamSourceLab", "Demo Device", NULL, + {CAPS_MODE_LOGIC | CAPS_MODE_ANALOG | CAPS_MODE_DSO, + CAPS_FEATURE_NONE, + (1 << DEMO_LOGIC100x16) | + (1 << DEMO_ANALOG10x2) | + (1 << DEMO_DSO200x2), + SR_Mn(100), + SR_Kn(20), + 0, + vdivs10to2000, + 0, + DEMO_LOGIC100x16, + PATTERN_RANDOM, + SR_NS(500)} + }, + + { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} +}; + +static const int const_dc = 1.95 / 10 * 255; +static const int sinx[] = { + 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 18, 20, 21, 23, 24, 26, 27, 28, + 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 41, 42, 43, 44, 45, 45, 46, 47, 47, + 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 48, 48, + 47, 47, 46, 46, 45, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 31, 30, + 29, 28, 26, 25, 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, 9, 7, 6, 4, 2, 1, + -1, -2, -4, -6, -7, -9, -10, -12, -13, -15, -16, -18, -19, -21, -22, -24, -25, -26, -28, -29, +-30, -31, -33, -34, -35, -36, -37, -38, -39, -40, -41, -42, -43, -44, -44, -45, -46, -46, -47, -47, +-48, -48, -49, -49, -49, -50, -50, -50, -50, -50, -50, -50, -50, -50, -49, -49, -49, -49, -48, -48, +-47, -47, -46, -45, -45, -44, -43, -42, -41, -41, -40, -39, -38, -37, -35, -34, -33, -32, -31, -30, +-28, -27, -26, -24, -23, -21, -20, -18, -17, -16, -14, -12, -11, -9, -8, -6, -5, -3, -2, 0, +}; + +static const int sqrx[] = { + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, +-50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, +-50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, +-50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, +-50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, +-50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, +}; + +static const int trix[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, +-20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -32, -33, -34, -35, -36, -37, -38, -39, +-40, -41, -42, -43, -44, -45, -46, -47, -48, -49, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, +-40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, +-20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, +}; + +static const int sawx[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, + 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, + 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, + 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 50, +-50, -49, -48, -48, -47, -47, -46, -46, -45, -45, -44, -44, -43, -43, -42, -42, -41, -41, -40, -40, +-39, -39, -38, -38, -37, -37, -36, -36, -35, -35, -34, -34, -33, -33, -32, -32, -31, -31, -30, -30, +-29, -29, -28, -28, -27, -27, -26, -26, -25, -25, -24, -24, -23, -23, -22, -22, -21, -21, -20, -20, +-19, -19, -18, -18, -17, -17, -16, -16, -15, -15, -14, -14, -13, -13, -12, -12, -11, -11, -10, -10, + -9, -9, -8, -8, -7, -7, -6, -6, -5, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, +}; + +static const int ranx[] = { + -4, 47, -49, -1, -3, 6, -29, 26, 1, 14, -39, -38, 36, 17, 26, -37, -2, 27, -20, -15, +-49, -46, 36, 16, 29, 23, -30, -3, 28, -2, -6, 46, 43, 50, -42, 30, 48, -50, -38, -30, + 7, -36, -20, -24, -10, -34, -24, 3, -48, 46, -11, 22, 19, 28, 39, -49, -31, 34, 2, -29, + 9, 35, 8, 10, 38, 30, 17, 48, -3, -6, -28, 46, -19, 18, -43, -9, -31, -32, -41, 16, +-10, 46, -4, 4, -32, -43, -45, -39, -33, 28, 24, -17, -43, 42, -7, 36, -44, -5, 9, 39, + 17, -40, 12, 16, -42, -1, 2, -9, 50, -8, 27, 27, 14, 8, -18, 12, -8, 26, -8, 12, +-35, 49, 35, 2, -26, -24, -31, 33, 15, -47, 34, 46, -1, -12, 14, 32, -25, -31, -35, -18, +-48, -21, -5, 1, -27, -14, 12, 49, -11, 33, 31, 35, -36, 19, 20, 44, 29, -48, 14, -43, + 1, 30, -12, 44, 20, 49, 29, -43, 42, 30, -34, 24, 20, -40, 33, -12, 13, -45, 45, -24, +-41, 36, -8, 46, 47, -34, 28, -39, 7, -32, 38, -27, 28, -3, -8, 43, -37, -24, 6, 3, +}; + +static int get_logic_probe_type_index_by_probe_type(int probe_type); + +static int logic_adjust_probe(struct sr_dev_inst *sdi, int num_probes); + +static void logic_adjust_samplerate(struct session_vdev * vdev); + +static void init_analog_random_data(struct session_vdev * vdev); + +static void delay_time(); + +static void get_last_packet_len(struct sr_datafeed_logic *logic,const struct session_vdev * vdev); + +static void reset_enabled_probe_num(struct sr_dev_inst *sdi); + +static void init_pattern_mode_list(); + +static int get_bit(uint64_t timebase); + +static int get_pattern_mode_index_by_string(uint8_t device_mode , const char* str); + +static void get_pattern_mode_from_file(uint8_t device_mode); + +static void scan_dsl_file(struct sr_dev_inst *sdi); + +static int reset_dsl_path(struct sr_dev_inst *sdi,uint8_t device_mode ,uint8_t pattern_mode); + +static void adjust_samplerate(struct sr_dev_inst *sdi); + +static void init_random_data(struct session_vdev * vdev,struct sr_dev_inst *sdi); + +static int hw_init(struct sr_context *sr_ctx); + +static GSList *hw_scan(GSList *options); + +static const GSList *hw_dev_mode_list(const struct sr_dev_inst *sdi); + +static int hw_dev_open(struct sr_dev_inst *sdi); + +static int hw_dev_close(struct sr_dev_inst *sdi); + +static int dev_destroy(struct sr_dev_inst *sdi); + + +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); + +static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, + struct sr_channel *ch, + struct sr_channel_group *cg); + +static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg); + +static int hw_dev_acquisition_start(struct sr_dev_inst *sdi, + void *cb_data); + +static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi, void *cb_data); + +static int hw_dev_status_get(const struct sr_dev_inst *sdi, struct sr_status *status, gboolean prg); + +static int load_virtual_device_session(struct sr_dev_inst *sdi); + +static int receive_data_logic(int fd, int revents, const struct sr_dev_inst *sdi); + +static int receive_data_logic_decoder(int fd, int revents, const struct sr_dev_inst *sdi); + +static int receive_data_dso(int fd, int revents, const struct sr_dev_inst *sdi); + +static int receive_data_analog(int fd, int revents, const struct sr_dev_inst *sdi); + +static void send_error_packet(const struct sr_dev_inst *cb_sdi, struct session_vdev *vdev, struct sr_datafeed_packet *packet); + +static int close_archive(struct session_vdev *vdev); + + +#endif diff --git a/libsigrok4DSL/hardware/demo/demo.c b/libsigrok4DSL/hardware/demo/demo.c index 1218b51e..d999be8c 100644 --- a/libsigrok4DSL/hardware/demo/demo.c +++ b/libsigrok4DSL/hardware/demo/demo.c @@ -1059,6 +1059,7 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, break; } } + } break; default: @@ -1255,7 +1256,11 @@ static int hw_dev_acquisition_start(struct sr_dev_inst *sdi, if(sample_generator == PATTERN_RANDOM) { + logic_total_packet_num = (vdev->total_samples/8/packet_len); + logci_cur_packet_num = 1; + logic_data_status = LOGIC_FULL; init_random_data(vdev,sdi); + g_timer_start(run_time); sr_session_source_add(-1, 0, 0, receive_data_logic, sdi); } else @@ -1396,21 +1401,55 @@ static int receive_data_logic(int fd, int revents, const struct sr_dev_inst *sdi logic.order = 0; logic.length = chan_num * packet_len; - if(!vdev->is_loop){ + void *logic_buf = g_try_malloc0(chan_num * packet_len); + if(logic_buf == NULL) + { + sr_err("%s: logic buf malloc error", __func__); + return SR_ERR_MALLOC; + } + + if(!vdev->is_loop) + { post_data_len += logic.length / enabled_probe_num; - if(post_data_len >= vdev->total_samples/8){ + if(post_data_len >= vdev->total_samples/8) + { get_last_packet_len(&logic,vdev); } } - - uint64_t random = vdev->logic_buf_len - logic.length; - random = rand() % random; - int index = enabled_probe_num * 8; - random = floor(random/index)*index; - logic.data = vdev->logic_buf + random; + if(vdev->samplerate >=LOGIC_EMPTY_FREQ && logic_data_status!= LOGIC_FULL) + { + memset(logic_buf,0,chan_num * packet_len); + if(logic_data_status == LOGIC_EMPTY_END) + logic_data_status = LOGIC_FULL; + else + logic_data_status++; + } + else + { + uint64_t random = vdev->logic_buf_len - logic.length; + random = rand() % random; + int index = enabled_probe_num * 8; + random = floor(random/index)*index; + memcpy(logic_buf,vdev->logic_buf + random,logic.length); + logic.data = logic_buf; + if(vdev->samplerate >=SR_MHZ(100)) + logic_data_status++; + } + + gdouble ideal_time = vdev->total_samples/(gdouble)vdev->samplerate; + ideal_time = ideal_time/(gdouble)logic_total_packet_num*(gdouble)logci_cur_packet_num; + gdouble packet_elapsed = g_timer_elapsed(run_time, NULL); + gdouble waittime = ideal_time - packet_elapsed; + logci_cur_packet_num++; + if(waittime > 0) + { + g_usleep(SR_MS(waittime)); + } ds_data_forward(sdi, &packet); - delay_time(); + + + g_safe_free(logic_buf); } if (bToEnd || revents == -1) @@ -1720,7 +1759,6 @@ static int receive_data_dso(int fd, int revents, const struct sr_dev_inst *sdi) int ret; char file_name[32]; - int channel; int ch_index, malloc_chan_index; struct session_packet_buffer *pack_buffer; unz_file_info64 fileInfo; diff --git a/libsigrok4DSL/hardware/demo/demo.h b/libsigrok4DSL/hardware/demo/demo.h index 17553697..2fcdf4ee 100644 --- a/libsigrok4DSL/hardware/demo/demo.h +++ b/libsigrok4DSL/hardware/demo/demo.h @@ -78,6 +78,9 @@ extern char DS_RES_PATH[500]; uint8_t sample_generator; static int64_t analog_count = 0; static uint64_t total_num = 0; +static uint64_t logci_cur_packet_num = 0; +static uint64_t logic_total_packet_num = 0; +static uint8_t logic_data_status = 0; static enum DEMO_LOGIC_CHANNEL_ID ch_mode = DEMO_LOGIC125x16; static enum DEMO_LOGIC_CHANNEL_INDEX logic_index = LOGIC125x16; @@ -278,7 +281,7 @@ static const uint64_t samplerates[] = { #define SEC 1 #define LOGIC_POST_DATA_PER_SECOND(n) ((n)/(8)) -#define LOGIC_PACKET_NUM_PER_SEC (gdouble)200 +#define LOGIC_PACKET_NUM_PER_SEC (gdouble)1000 #define LOGIC_PACKET_TIME(n) (gdouble)((SEC)/(n)) #define LOGIC_PACKET_LEN(n) (ceil((LOGIC_POST_DATA_PER_SECOND(n))/(LOGIC_PACKET_NUM_PER_SEC)/(8))*(8)) #define LOGIC_MIN_PACKET_LEN 8 @@ -288,7 +291,11 @@ static const uint64_t samplerates[] = { #define LOGIC_MAX_PACKET_NUM(n) (LOGIC_POST_DATA_PER_SECOND(n))/(LOGIC_MAX_PACKET_LEN) #define LOGIC_MAX_PACKET_TIME(n) ((SEC)/(gdouble)(LOGIC_MAX_PACKET_NUM(n))) -#define LOGIC_BUF_LEN SR_MB(10) +#define LOGIC_BUF_LEN SR_MB(2) + +#define LOGIC_EMPTY_FREQ SR_MHZ(100) +#define LOGIC_EMPTY_END 9 +#define LOGIC_FULL 0 #define DSO_PACKET_NUM_PER_SEC (gdouble)200 @@ -306,7 +313,7 @@ static const uint64_t samplerates[] = { #define ANALOG_MIN_PACKET_NUM(n) ((ANALOG_POST_DATA_PER_SECOND(n))/(ANALOG_MIN_PACKET_LEN)) #define ANALOG_PACKET_ALIGN 2 -#define LOGIC_HW_DEPTH (SR_GHZ(1)) +#define LOGIC_HW_DEPTH (SR_GHZ(16)) #define LOGIC_MAX_PROBE_NUM 16