]> sigrok.org Git - libsigrok.git/blame - hardware/asix-sigma/asix-sigma.c
Sigma: Use software trigger to pinpoint exact sample.
[libsigrok.git] / hardware / asix-sigma / asix-sigma.c
CommitLineData
28a35d8a
HE
1/*
2 * This file is part of the sigrok project.
3 *
911f1834
UH
4 * Copyright (C) 2010 Håvard Espeland <gus@ping.uio.no>,
5 * Copyright (C) 2010 Martin Stensgård <mastensg@ping.uio.no>
6 * Copyright (C) 2010 Carl Henrik Lunde <chlunde@ping.uio.no>
28a35d8a
HE
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
911f1834
UH
22/*
23 * ASIX Sigma Logic Analyzer Driver
24 */
25
28a35d8a
HE
26#include <ftdi.h>
27#include <string.h>
28#include <zlib.h>
fefa1800 29#include <sigrok.h>
28a35d8a
HE
30#include "asix-sigma.h"
31
32#define USB_VENDOR 0xa600
33#define USB_PRODUCT 0xa000
34#define USB_DESCRIPTION "ASIX SIGMA"
35#define USB_VENDOR_NAME "ASIX"
36#define USB_MODEL_NAME "SIGMA"
37#define USB_MODEL_VERSION ""
ee492173 38#define TRIGGER_TYPES "rf10"
28a35d8a
HE
39
40static GSList *device_instances = NULL;
41
42// XXX These should be per device
43static struct ftdi_context ftdic;
f78898e9 44static uint64_t cur_samplerate = 0;
28a35d8a
HE
45static uint32_t limit_msec = 0;
46static struct timeval start_tv;
f6564c8d 47static int cur_firmware = -1;
f78898e9
HE
48static int num_probes = 0;
49static int samples_per_event = 0;
57bbf56b 50static int capture_ratio = 50;
c53d793f 51static struct sigma_trigger trigger;
6aac7737 52static struct sigma_state sigma;
ee492173 53
28a35d8a 54static uint64_t supported_samplerates[] = {
ed09fd07 55 KHZ(200),
edca2c5c 56 KHZ(250),
ed09fd07 57 KHZ(500),
edca2c5c 58 MHZ(1),
ed09fd07 59 MHZ(5),
edca2c5c
HE
60 MHZ(10),
61 MHZ(25),
e8397563
HE
62 MHZ(50),
63 MHZ(100),
28a35d8a
HE
64 MHZ(200),
65 0,
66};
67
68static struct samplerates samplerates = {
ed09fd07 69 KHZ(200),
28a35d8a
HE
70 MHZ(200),
71 0,
72 supported_samplerates,
73};
74
75static int capabilities[] = {
76 HWCAP_LOGIC_ANALYZER,
77 HWCAP_SAMPLERATE,
57bbf56b
HE
78 HWCAP_CAPTURE_RATIO,
79 HWCAP_PROBECONFIG,
28a35d8a 80
28a35d8a
HE
81 HWCAP_LIMIT_MSEC,
82 0,
83};
84
fefa1800
UH
85/* Force the FPGA to reboot. */
86static uint8_t suicide[] = {
87 0x84, 0x84, 0x88, 0x84, 0x88, 0x84, 0x88, 0x84,
88};
89
90/* Prepare to upload firmware (FPGA specific). */
91static uint8_t init[] = {
92 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
93};
94
95/* Initialize the logic analyzer mode. */
96static uint8_t logic_mode_start[] = {
97 0x00, 0x40, 0x0f, 0x25, 0x35, 0x40,
98 0x2a, 0x3a, 0x40, 0x03, 0x20, 0x38,
99};
100
eec5275e 101static const char *firmware_files[] = {
a8116d76
HE
102 "asix-sigma-50.fw", /* 50 MHz, supports 8 bit fractions */
103 "asix-sigma-100.fw", /* 100 MHz */
104 "asix-sigma-200.fw", /* 200 MHz */
ed09fd07 105 "asix-sigma-50sync.fw", /* Synchronous clock from pin */
a8116d76 106 "asix-sigma-phasor.fw", /* Frequency counter */
f6564c8d
HE
107};
108
6aac7737
HE
109static void hw_stop_acquisition(int device_index, gpointer session_device_id);
110
9ddb2a12 111static int sigma_read(void *buf, size_t size)
28a35d8a
HE
112{
113 int ret;
fefa1800
UH
114
115 ret = ftdi_read_data(&ftdic, (unsigned char *)buf, size);
28a35d8a
HE
116 if (ret < 0) {
117 g_warning("ftdi_read_data failed: %s",
fefa1800 118 ftdi_get_error_string(&ftdic));
28a35d8a
HE
119 }
120
121 return ret;
122}
123
fefa1800 124static int sigma_write(void *buf, size_t size)
28a35d8a
HE
125{
126 int ret;
fefa1800
UH
127
128 ret = ftdi_write_data(&ftdic, (unsigned char *)buf, size);
28a35d8a
HE
129 if (ret < 0) {
130 g_warning("ftdi_write_data failed: %s",
fefa1800
UH
131 ftdi_get_error_string(&ftdic));
132 } else if ((size_t) ret != size) {
28a35d8a
HE
133 g_warning("ftdi_write_data did not complete write\n");
134 }
135
136 return ret;
137}
138
139static int sigma_write_register(uint8_t reg, uint8_t *data, size_t len)
140{
141 size_t i;
142 uint8_t buf[len + 2];
143 int idx = 0;
144
145 buf[idx++] = REG_ADDR_LOW | (reg & 0xf);
146 buf[idx++] = REG_ADDR_HIGH | (reg >> 4);
147
fefa1800 148 for (i = 0; i < len; ++i) {
28a35d8a
HE
149 buf[idx++] = REG_DATA_LOW | (data[i] & 0xf);
150 buf[idx++] = REG_DATA_HIGH_WRITE | (data[i] >> 4);
151 }
152
153 return sigma_write(buf, idx);
154}
155
156static int sigma_set_register(uint8_t reg, uint8_t value)
157{
158 return sigma_write_register(reg, &value, 1);
159}
160
161static int sigma_read_register(uint8_t reg, uint8_t *data, size_t len)
162{
163 uint8_t buf[3];
fefa1800 164
28a35d8a
HE
165 buf[0] = REG_ADDR_LOW | (reg & 0xf);
166 buf[1] = REG_ADDR_HIGH | (reg >> 4);
28a35d8a
HE
167 buf[2] = REG_READ_ADDR;
168
169 sigma_write(buf, sizeof(buf));
170
171 return sigma_read(data, len);
172}
173
174static uint8_t sigma_get_register(uint8_t reg)
175{
176 uint8_t value;
fefa1800 177
28a35d8a
HE
178 if (1 != sigma_read_register(reg, &value, 1)) {
179 g_warning("Sigma_get_register: 1 byte expected");
180 return 0;
181 }
182
183 return value;
184}
185
186static int sigma_read_pos(uint32_t *stoppos, uint32_t *triggerpos)
187{
188 uint8_t buf[] = {
189 REG_ADDR_LOW | READ_TRIGGER_POS_LOW,
190
191 REG_READ_ADDR | NEXT_REG,
192 REG_READ_ADDR | NEXT_REG,
193 REG_READ_ADDR | NEXT_REG,
194 REG_READ_ADDR | NEXT_REG,
195 REG_READ_ADDR | NEXT_REG,
196 REG_READ_ADDR | NEXT_REG,
197 };
28a35d8a
HE
198 uint8_t result[6];
199
200 sigma_write(buf, sizeof(buf));
201
202 sigma_read(result, sizeof(result));
203
204 *triggerpos = result[0] | (result[1] << 8) | (result[2] << 16);
205 *stoppos = result[3] | (result[4] << 8) | (result[5] << 16);
206
57bbf56b
HE
207 /* Not really sure why this must be done, but according to spec. */
208 if ((--*stoppos & 0x1ff) == 0x1ff)
209 stoppos -= 64;
210
211 if ((*--triggerpos & 0x1ff) == 0x1ff)
212 triggerpos -= 64;
213
28a35d8a
HE
214 return 1;
215}
216
217static int sigma_read_dram(uint16_t startchunk, size_t numchunks, uint8_t *data)
218{
219 size_t i;
220 uint8_t buf[4096];
221 int idx = 0;
222
fefa1800 223 /* Send the startchunk. Index start with 1. */
28a35d8a
HE
224 buf[0] = startchunk >> 8;
225 buf[1] = startchunk & 0xff;
226 sigma_write_register(WRITE_MEMROW, buf, 2);
227
fefa1800 228 /* Read the DRAM. */
28a35d8a
HE
229 buf[idx++] = REG_DRAM_BLOCK;
230 buf[idx++] = REG_DRAM_WAIT_ACK;
231
232 for (i = 0; i < numchunks; ++i) {
fefa1800
UH
233 /* Alternate bit to copy from DRAM to cache. */
234 if (i != (numchunks - 1))
235 buf[idx++] = REG_DRAM_BLOCK | (((i + 1) % 2) << 4);
28a35d8a
HE
236
237 buf[idx++] = REG_DRAM_BLOCK_DATA | ((i % 2) << 4);
238
fefa1800 239 if (i != (numchunks - 1))
28a35d8a
HE
240 buf[idx++] = REG_DRAM_WAIT_ACK;
241 }
242
243 sigma_write(buf, idx);
244
245 return sigma_read(data, numchunks * CHUNK_SIZE);
246}
247
4ae1f451 248/* Upload trigger look-up tables to Sigma. */
ee492173
HE
249static int sigma_write_trigger_lut(struct triggerlut *lut)
250{
251 int i;
252 uint8_t tmp[2];
253 uint16_t bit;
254
255 /* Transpose the table and send to Sigma. */
256 for (i = 0; i < 16; ++i) {
257 bit = 1 << i;
258
259 tmp[0] = tmp[1] = 0;
260
261 if (lut->m2d[0] & bit)
262 tmp[0] |= 0x01;
263 if (lut->m2d[1] & bit)
264 tmp[0] |= 0x02;
265 if (lut->m2d[2] & bit)
266 tmp[0] |= 0x04;
267 if (lut->m2d[3] & bit)
268 tmp[0] |= 0x08;
269
270 if (lut->m3 & bit)
271 tmp[0] |= 0x10;
272 if (lut->m3s & bit)
273 tmp[0] |= 0x20;
274 if (lut->m4 & bit)
275 tmp[0] |= 0x40;
276
277 if (lut->m0d[0] & bit)
278 tmp[1] |= 0x01;
279 if (lut->m0d[1] & bit)
280 tmp[1] |= 0x02;
281 if (lut->m0d[2] & bit)
282 tmp[1] |= 0x04;
283 if (lut->m0d[3] & bit)
284 tmp[1] |= 0x08;
285
286 if (lut->m1d[0] & bit)
287 tmp[1] |= 0x10;
288 if (lut->m1d[1] & bit)
289 tmp[1] |= 0x20;
290 if (lut->m1d[2] & bit)
291 tmp[1] |= 0x40;
292 if (lut->m1d[3] & bit)
293 tmp[1] |= 0x80;
294
295 sigma_write_register(WRITE_TRIGGER_SELECT0, tmp, sizeof(tmp));
296 sigma_set_register(WRITE_TRIGGER_SELECT1, 0x30 | i);
297 }
298
299 /* Send the parameters */
300 sigma_write_register(WRITE_TRIGGER_SELECT0, (uint8_t *) &lut->params,
301 sizeof(lut->params));
302
303 return SIGROK_OK;
304}
305
fefa1800 306/* Generate the bitbang stream for programming the FPGA. */
28a35d8a 307static int bin2bitbang(const char *filename,
fefa1800 308 unsigned char **buf, size_t *buf_size)
28a35d8a 309{
fefa1800 310 FILE *f;
28a35d8a
HE
311 long file_size;
312 unsigned long offset = 0;
313 unsigned char *p;
314 uint8_t *compressed_buf, *firmware;
315 uLongf csize, fwsize;
316 const int buffer_size = 65536;
317 size_t i;
fefa1800
UH
318 int c, ret, bit, v;
319 uint32_t imm = 0x3f6df2ab;
28a35d8a 320
fefa1800 321 f = fopen(filename, "r");
28a35d8a
HE
322 if (!f) {
323 g_warning("fopen(\"%s\", \"r\")", filename);
324 return -1;
325 }
326
327 if (-1 == fseek(f, 0, SEEK_END)) {
328 g_warning("fseek on %s failed", filename);
329 fclose(f);
330 return -1;
331 }
332
333 file_size = ftell(f);
334
335 fseek(f, 0, SEEK_SET);
336
28a35d8a
HE
337 compressed_buf = g_malloc(file_size);
338 firmware = g_malloc(buffer_size);
339
340 if (!compressed_buf || !firmware) {
341 g_warning("Error allocating buffers");
342 return -1;
343 }
344
28a35d8a
HE
345 csize = 0;
346 while ((c = getc(f)) != EOF) {
347 imm = (imm + 0xa853753) % 177 + (imm * 0x8034052);
348 compressed_buf[csize++] = c ^ imm;
349 }
350 fclose(f);
351
352 fwsize = buffer_size;
353 ret = uncompress(firmware, &fwsize, compressed_buf, csize);
354 if (ret < 0) {
355 g_free(compressed_buf);
356 g_free(firmware);
357 g_warning("Could not unpack Sigma firmware. (Error %d)\n", ret);
358 return -1;
359 }
360
361 g_free(compressed_buf);
362
363 *buf_size = fwsize * 2 * 8;
364
fefa1800 365 *buf = p = (unsigned char *)g_malloc(*buf_size);
28a35d8a
HE
366
367 if (!p) {
368 g_warning("Error allocating buffers");
369 return -1;
370 }
371
372 for (i = 0; i < fwsize; ++i) {
28a35d8a 373 for (bit = 7; bit >= 0; --bit) {
fefa1800 374 v = firmware[i] & 1 << bit ? 0x40 : 0x00;
28a35d8a
HE
375 p[offset++] = v | 0x01;
376 p[offset++] = v;
377 }
378 }
379
380 g_free(firmware);
381
382 if (offset != *buf_size) {
383 g_free(*buf);
384 g_warning("Error reading firmware %s "
fefa1800
UH
385 "offset=%ld, file_size=%ld, buf_size=%zd\n",
386 filename, offset, file_size, *buf_size);
28a35d8a
HE
387
388 return -1;
389 }
390
391 return 0;
392}
393
394static int hw_init(char *deviceinfo)
395{
396 struct sigrok_device_instance *sdi;
397
398 deviceinfo = deviceinfo;
399
400 ftdi_init(&ftdic);
401
fefa1800
UH
402 /* Look for SIGMAs. */
403 if (ftdi_usb_open_desc(&ftdic, USB_VENDOR, USB_PRODUCT,
404 USB_DESCRIPTION, NULL) < 0)
28a35d8a
HE
405 return 0;
406
fefa1800 407 /* Register SIGMA device. */
28a35d8a
HE
408 sdi = sigrok_device_instance_new(0, ST_INITIALIZING,
409 USB_VENDOR_NAME, USB_MODEL_NAME, USB_MODEL_VERSION);
410 if (!sdi)
411 return 0;
412
413 device_instances = g_slist_append(device_instances, sdi);
414
fefa1800 415 /* We will open the device again when we need it. */
28a35d8a
HE
416 ftdi_usb_close(&ftdic);
417
418 return 1;
419}
420
f6564c8d 421static int upload_firmware(int firmware_idx)
28a35d8a
HE
422{
423 int ret;
424 unsigned char *buf;
425 unsigned char pins;
426 size_t buf_size;
28a35d8a 427 unsigned char result[32];
e8397563 428 char firmware_path[128];
28a35d8a 429
fefa1800 430 /* Make sure it's an ASIX SIGMA. */
28a35d8a
HE
431 if ((ret = ftdi_usb_open_desc(&ftdic,
432 USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) {
28a35d8a 433 g_warning("ftdi_usb_open failed: %s",
fefa1800 434 ftdi_get_error_string(&ftdic));
28a35d8a
HE
435 return 0;
436 }
437
438 if ((ret = ftdi_set_bitmode(&ftdic, 0xdf, BITMODE_BITBANG)) < 0) {
439 g_warning("ftdi_set_bitmode failed: %s",
fefa1800 440 ftdi_get_error_string(&ftdic));
28a35d8a
HE
441 return 0;
442 }
443
fefa1800 444 /* Four times the speed of sigmalogan - Works well. */
28a35d8a
HE
445 if ((ret = ftdi_set_baudrate(&ftdic, 750000)) < 0) {
446 g_warning("ftdi_set_baudrate failed: %s",
fefa1800 447 ftdi_get_error_string(&ftdic));
28a35d8a
HE
448 return 0;
449 }
450
fefa1800 451 /* Force the FPGA to reboot. */
28a35d8a
HE
452 sigma_write(suicide, sizeof(suicide));
453 sigma_write(suicide, sizeof(suicide));
454 sigma_write(suicide, sizeof(suicide));
455 sigma_write(suicide, sizeof(suicide));
456
fefa1800 457 /* Prepare to upload firmware (FPGA specific). */
28a35d8a
HE
458 sigma_write(init, sizeof(init));
459
460 ftdi_usb_purge_buffers(&ftdic);
461
fefa1800 462 /* Wait until the FPGA asserts INIT_B. */
28a35d8a
HE
463 while (1) {
464 ret = sigma_read(result, 1);
465 if (result[0] & 0x20)
466 break;
467 }
468
9ddb2a12 469 /* Prepare firmware. */
e8397563 470 snprintf(firmware_path, sizeof(firmware_path), "%s/%s", FIRMWARE_DIR,
f6564c8d
HE
471 firmware_files[firmware_idx]);
472
e8397563 473 if (-1 == bin2bitbang(firmware_path, &buf, &buf_size)) {
28a35d8a 474 g_warning("An error occured while reading the firmware: %s",
e8397563 475 firmware_path);
28a35d8a
HE
476 return SIGROK_ERR;
477 }
478
fefa1800 479 /* Upload firmare. */
28a35d8a
HE
480 sigma_write(buf, buf_size);
481
482 g_free(buf);
483
484 if ((ret = ftdi_set_bitmode(&ftdic, 0x00, BITMODE_RESET)) < 0) {
9ddb2a12 485 g_warning("ftdi_set_bitmode failed: %s",
fefa1800 486 ftdi_get_error_string(&ftdic));
28a35d8a
HE
487 return SIGROK_ERR;
488 }
489
490 ftdi_usb_purge_buffers(&ftdic);
491
fefa1800 492 /* Discard garbage. */
28a35d8a
HE
493 while (1 == sigma_read(&pins, 1))
494 ;
495
fefa1800 496 /* Initialize the logic analyzer mode. */
28a35d8a
HE
497 sigma_write(logic_mode_start, sizeof(logic_mode_start));
498
fefa1800 499 /* Expect a 3 byte reply. */
28a35d8a
HE
500 ret = sigma_read(result, 3);
501 if (ret != 3 ||
502 result[0] != 0xa6 || result[1] != 0x55 || result[2] != 0xaa) {
fefa1800 503 g_warning("Configuration failed. Invalid reply received.");
28a35d8a
HE
504 return SIGROK_ERR;
505 }
506
f6564c8d
HE
507 cur_firmware = firmware_idx;
508
509 return SIGROK_OK;
510}
511
512static int hw_opendev(int device_index)
513{
514 struct sigrok_device_instance *sdi;
515 int ret;
516
9ddb2a12 517 /* Make sure it's an ASIX SIGMA. */
f6564c8d
HE
518 if ((ret = ftdi_usb_open_desc(&ftdic,
519 USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) {
520
521 g_warning("ftdi_usb_open failed: %s",
522 ftdi_get_error_string(&ftdic));
523
524 return 0;
525 }
28a35d8a
HE
526
527 if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
528 return SIGROK_ERR;
529
530 sdi->status = ST_ACTIVE;
531
f6564c8d
HE
532 return SIGROK_OK;
533}
534
6aac7737
HE
535static int set_samplerate(struct sigrok_device_instance *sdi,
536 uint64_t samplerate)
f6564c8d 537{
e8397563 538 int i, ret;
f6564c8d
HE
539
540 sdi = sdi;
541
542 for (i = 0; supported_samplerates[i]; i++) {
543 if (supported_samplerates[i] == samplerate)
544 break;
545 }
546 if (supported_samplerates[i] == 0)
547 return SIGROK_ERR_SAMPLERATE;
548
e8397563
HE
549 if (samplerate <= MHZ(50)) {
550 ret = upload_firmware(0);
f78898e9 551 num_probes = 16;
e8397563 552 }
f78898e9 553 if (samplerate == MHZ(100)) {
e8397563 554 ret = upload_firmware(1);
f78898e9
HE
555 num_probes = 8;
556 }
557 else if (samplerate == MHZ(200)) {
e8397563 558 ret = upload_firmware(2);
f78898e9
HE
559 num_probes = 4;
560 }
f6564c8d 561
e8397563 562 cur_samplerate = samplerate;
f78898e9 563 samples_per_event = 16 / num_probes;
6aac7737 564 sigma.state = SIGMA_IDLE;
f6564c8d 565
28a35d8a
HE
566 g_message("Firmware uploaded");
567
e8397563 568 return ret;
28a35d8a
HE
569}
570
c53d793f
HE
571/*
572 * In 100 and 200 MHz mode, only a single pin rising/falling can be
573 * set as trigger. In other modes, two rising/falling triggers can be set,
574 * in addition to value/mask trigger for any number of probes.
575 *
576 * The Sigma supports complex triggers using boolean expressions, but this
577 * has not been implemented yet.
578 */
57bbf56b
HE
579static int configure_probes(GSList *probes)
580{
581 struct probe *probe;
582 GSList *l;
583 int trigger_set = 0;
a42aec7f 584 int probebit;
57bbf56b 585
c53d793f 586 memset(&trigger, 0, sizeof(struct sigma_trigger));
eec5275e 587
57bbf56b
HE
588 for (l = probes; l; l = l->next) {
589 probe = (struct probe *)l->data;
a42aec7f 590 probebit = 1 << (probe->index - 1);
57bbf56b
HE
591
592 if (!probe->enabled || !probe->trigger)
593 continue;
594
ee492173 595 if (cur_samplerate >= MHZ(100)) {
c53d793f 596 /* Fast trigger support. */
ee492173 597 if (trigger_set) {
6aac7737
HE
598 g_warning("Asix Sigma only supports a single "
599 "pin trigger in 100 and 200 "
600 "MHz mode.");
ee492173
HE
601 return SIGROK_ERR;
602 }
603 if (probe->trigger[0] == 'f')
a42aec7f 604 trigger.fallingmask |= probebit;
ee492173 605 else if (probe->trigger[0] == 'r')
a42aec7f 606 trigger.risingmask |= probebit;
ee492173
HE
607 else {
608 g_warning("Asix Sigma only supports "
609 "rising/falling trigger in 100 "
610 "and 200 MHz mode.");
611 return SIGROK_ERR;
612 }
57bbf56b 613
c53d793f 614 ++trigger_set;
ee492173 615 } else {
c53d793f
HE
616 /* Simple trigger support (event). */
617 if (probe->trigger[0] == '1') {
a42aec7f
HE
618 trigger.simplevalue |= probebit;
619 trigger.simplemask |= probebit;
c53d793f
HE
620 }
621 else if (probe->trigger[0] == '0') {
a42aec7f
HE
622 trigger.simplevalue &= ~probebit;
623 trigger.simplemask |= probebit;
c53d793f
HE
624 }
625 else if (probe->trigger[0] == 'f') {
a42aec7f 626 trigger.fallingmask |= probebit;
c53d793f
HE
627 ++trigger_set;
628 }
629 else if (probe->trigger[0] == 'r') {
a42aec7f 630 trigger.risingmask |= probebit;
c53d793f
HE
631 ++trigger_set;
632 }
ee492173 633
c53d793f
HE
634 if (trigger_set > 2) {
635 g_warning("Asix Sigma only supports 2 rising/"
636 "falling triggers.");
ee492173
HE
637 return SIGROK_ERR;
638 }
ee492173 639 }
57bbf56b
HE
640 }
641
642 return SIGROK_OK;
643}
644
28a35d8a
HE
645static void hw_closedev(int device_index)
646{
647 device_index = device_index;
648
649 ftdi_usb_close(&ftdic);
650}
651
28a35d8a
HE
652static void hw_cleanup(void)
653{
654}
655
28a35d8a
HE
656static void *hw_get_device_info(int device_index, int device_info_id)
657{
658 struct sigrok_device_instance *sdi;
659 void *info = NULL;
660
661 if (!(sdi = get_sigrok_device_instance(device_instances, device_index))) {
662 fprintf(stderr, "It's NULL.\n");
663 return NULL;
664 }
665
666 switch (device_info_id) {
667 case DI_INSTANCE:
668 info = sdi;
669 break;
670 case DI_NUM_PROBES:
edca2c5c 671 info = GINT_TO_POINTER(16);
28a35d8a
HE
672 break;
673 case DI_SAMPLERATES:
674 info = &samplerates;
675 break;
676 case DI_TRIGGER_TYPES:
57bbf56b 677 info = (char *)TRIGGER_TYPES;
28a35d8a
HE
678 break;
679 case DI_CUR_SAMPLERATE:
680 info = &cur_samplerate;
681 break;
682 }
683
684 return info;
685}
686
28a35d8a
HE
687static int hw_get_status(int device_index)
688{
689 struct sigrok_device_instance *sdi;
690
691 sdi = get_sigrok_device_instance(device_instances, device_index);
692 if (sdi)
693 return sdi->status;
694 else
695 return ST_NOT_FOUND;
696}
697
28a35d8a
HE
698static int *hw_get_capabilities(void)
699{
700 return capabilities;
701}
702
703static int hw_set_configuration(int device_index, int capability, void *value)
704{
705 struct sigrok_device_instance *sdi;
706 int ret;
f6564c8d 707
28a35d8a
HE
708 if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
709 return SIGROK_ERR;
710
711 if (capability == HWCAP_SAMPLERATE) {
f6564c8d 712 ret = set_samplerate(sdi, *(uint64_t*) value);
28a35d8a 713 } else if (capability == HWCAP_PROBECONFIG) {
57bbf56b 714 ret = configure_probes(value);
28a35d8a
HE
715 } else if (capability == HWCAP_LIMIT_MSEC) {
716 limit_msec = strtoull(value, NULL, 10);
717 ret = SIGROK_OK;
57bbf56b
HE
718 } else if (capability == HWCAP_CAPTURE_RATIO) {
719 capture_ratio = strtoull(value, NULL, 10);
720 ret = SIGROK_OK;
721 } else if (capability == HWCAP_PROBECONFIG) {
722 ret = configure_probes((GSList *) value);
28a35d8a
HE
723 } else {
724 ret = SIGROK_ERR;
725 }
726
727 return ret;
728}
729
36b1c8e6
HE
730/* Software trigger to determine exact trigger position. */
731static int get_trigger_offset(uint16_t *samples, uint16_t last_sample,
732 struct sigma_trigger *t)
733{
734 int i;
735
736 for (i = 0; i < 8; ++i) {
737 if (i > 0)
738 last_sample = samples[i-1];
739
740 /* Simple triggers. */
741 if ((samples[i] & t->simplemask) != t->simplevalue)
742 continue;
743
744 /* Rising edge. */
745 if ((last_sample & t->risingmask) != 0 || (samples[i] &
746 t->risingmask) != t->risingmask)
747 continue;
748
749 /* Falling edge. */
750 if ((last_sample & t->fallingmask) != t->fallingmask || (samples[i] &
751 t->fallingmask) != 0)
752 continue;
753
754 break;
755 }
756
757 /* If we did not match, return original trigger pos. */
758 return i & 0x7;
759}
760
28a35d8a 761/*
fefa1800
UH
762 * Decode chunk of 1024 bytes, 64 clusters, 7 events per cluster.
763 * Each event is 20ns apart, and can contain multiple samples.
f78898e9
HE
764 *
765 * For 200 MHz, events contain 4 samples for each channel, spread 5 ns apart.
766 * For 100 MHz, events contain 2 samples for each channel, spread 10 ns apart.
767 * For 50 MHz and below, events contain one sample for each channel,
768 * spread 20 ns apart.
28a35d8a
HE
769 */
770static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
57bbf56b 771 uint16_t *lastsample, int triggerpos, void *user_data)
28a35d8a 772{
fefa1800 773 uint16_t tsdiff, ts;
f78898e9 774 uint16_t samples[65536 * samples_per_event];
28a35d8a 775 struct datafeed_packet packet;
f78898e9 776 int i, j, k, l, numpad, tosend;
fefa1800 777 size_t n = 0, sent = 0;
f78898e9 778 int clustersize = EVENTS_PER_CLUSTER * samples_per_event;
fefa1800 779 uint16_t *event;
f78898e9 780 uint16_t cur_sample;
57bbf56b 781 int triggerts = -1;
ee492173
HE
782 int triggeroff = 0;
783
4ae1f451 784 /* Check if trigger is in this chunk. */
ee492173
HE
785 if (triggerpos != -1) {
786 if (cur_samplerate <= MHZ(50))
36b1c8e6 787 triggerpos -= EVENTS_PER_CLUSTER - 1;
ee492173
HE
788 else
789 triggeroff = 3;
790
791 if (triggerpos < 0)
792 triggerpos = 0;
57bbf56b 793
ee492173
HE
794 /* Find in which cluster the trigger occured. */
795 triggerts = triggerpos / 7;
796 }
28a35d8a 797
eec5275e 798 /* For each ts. */
28a35d8a 799 for (i = 0; i < 64; ++i) {
fefa1800 800 ts = *(uint16_t *) &buf[i * 16];
28a35d8a
HE
801 tsdiff = ts - *lastts;
802 *lastts = ts;
803
fefa1800
UH
804 /* Pad last sample up to current point. */
805 numpad = tsdiff * samples_per_event - clustersize;
28a35d8a 806 if (numpad > 0) {
f78898e9
HE
807 for (j = 0; j < numpad; ++j)
808 samples[j] = *lastsample;
809
810 n = numpad;
28a35d8a
HE
811 }
812
57bbf56b
HE
813 /* Send samples between previous and this timestamp to sigrok. */
814 sent = 0;
815 while (sent < n) {
816 tosend = MIN(2048, n - sent);
817
818 packet.type = DF_LOGIC16;
819 packet.length = tosend * sizeof(uint16_t);
820 packet.payload = samples + sent;
821 session_bus(user_data, &packet);
28a35d8a 822
57bbf56b
HE
823 sent += tosend;
824 }
825 n = 0;
826
827 event = (uint16_t *) &buf[i * 16 + 2];
f78898e9
HE
828 cur_sample = 0;
829
830 /* For each event in cluster. */
28a35d8a 831 for (j = 0; j < 7; ++j) {
f78898e9
HE
832
833 /* For each sample in event. */
28a35d8a 834 for (k = 0; k < samples_per_event; ++k) {
f78898e9
HE
835 cur_sample = 0;
836
837 /* For each probe. */
838 for (l = 0; l < num_probes; ++l)
edca2c5c
HE
839 cur_sample |= (!!(event[j] & (1 << (l *
840 samples_per_event + k))))
841 << l;
f78898e9
HE
842
843 samples[n++] = cur_sample;
28a35d8a
HE
844 }
845 }
846
eec5275e 847 /* Send data up to trigger point (if triggered). */
fefa1800 848 sent = 0;
57bbf56b
HE
849 if (i == triggerts) {
850 /*
36b1c8e6
HE
851 * Trigger is not always accurate to sample because of
852 * pipeline delay. However, it always triggers before
853 * the actual event. We therefore look at the next
854 * samples to pinpoint the exact position of the trigger.
57bbf56b 855 */
36b1c8e6 856 tosend = get_trigger_offset(samples, *lastsample, &trigger);
57bbf56b
HE
857
858 if (tosend > 0) {
859 packet.type = DF_LOGIC16;
860 packet.length = tosend * sizeof(uint16_t);
861 packet.payload = samples;
862 session_bus(user_data, &packet);
863
864 sent += tosend;
865 }
28a35d8a 866
57bbf56b
HE
867 packet.type = DF_TRIGGER;
868 packet.length = 0;
869 packet.payload = 0;
28a35d8a 870 session_bus(user_data, &packet);
28a35d8a 871 }
57bbf56b 872
eec5275e 873 /* Send rest of the chunk to sigrok. */
57bbf56b
HE
874 tosend = n - sent;
875
876 packet.type = DF_LOGIC16;
877 packet.length = tosend * sizeof(uint16_t);
878 packet.payload = samples + sent;
879 session_bus(user_data, &packet);
ee492173
HE
880
881 *lastsample = samples[n - 1];
28a35d8a
HE
882 }
883
f78898e9 884 return SIGROK_OK;
28a35d8a
HE
885}
886
887static int receive_data(int fd, int revents, void *user_data)
888{
889 struct datafeed_packet packet;
28a35d8a
HE
890 const int chunks_per_read = 32;
891 unsigned char buf[chunks_per_read * CHUNK_SIZE];
6aac7737
HE
892 int bufsz, numchunks, i, newchunks;
893 uint32_t running_msec;
28a35d8a 894 struct timeval tv;
28a35d8a
HE
895
896 fd = fd;
897 revents = revents;
898
6aac7737 899 numchunks = sigma.stoppos / 512;
28a35d8a 900
6aac7737 901 if (sigma.state == SIGMA_IDLE)
28a35d8a
HE
902 return FALSE;
903
6aac7737 904 if (sigma.state == SIGMA_CAPTURE) {
28a35d8a 905
6aac7737
HE
906 /* Check if the timer has expired, or memory is full. */
907 gettimeofday(&tv, 0);
908 running_msec = (tv.tv_sec - start_tv.tv_sec) * 1000 +
909 (tv.tv_usec - start_tv.tv_usec) / 1000;
28a35d8a 910
6aac7737
HE
911 if (running_msec < limit_msec && numchunks < 32767)
912 return FALSE;
28a35d8a 913
6aac7737
HE
914 hw_stop_acquisition(-1, user_data);
915
916 return FALSE;
917
918 } else if (sigma.state == SIGMA_DOWNLOAD) {
919 if (sigma.chunks_downloaded >= numchunks) {
920 /* End of samples. */
921 packet.type = DF_END;
922 packet.length = 0;
923 session_bus(user_data, &packet);
924
925 sigma.state = SIGMA_IDLE;
f78898e9 926
6aac7737
HE
927 return TRUE;
928 }
929
930 newchunks = MIN(chunks_per_read,
931 numchunks - sigma.chunks_downloaded);
28a35d8a
HE
932
933 g_message("Downloading sample data: %.0f %%",
6aac7737 934 100.0 * sigma.chunks_downloaded / numchunks);
28a35d8a 935
6aac7737
HE
936 bufsz = sigma_read_dram(sigma.chunks_downloaded,
937 newchunks, buf);
28a35d8a 938
fefa1800 939 /* Find first ts. */
6aac7737
HE
940 if (sigma.chunks_downloaded == 0) {
941 sigma.lastts = *(uint16_t *) buf - 1;
942 sigma.lastsample = 0;
943 }
28a35d8a 944
fefa1800 945 /* Decode chunks and send them to sigrok. */
28a35d8a 946 for (i = 0; i < newchunks; ++i) {
6aac7737 947 if (sigma.chunks_downloaded + i == sigma.triggerchunk)
57bbf56b 948 decode_chunk_ts(buf + (i * CHUNK_SIZE),
6aac7737
HE
949 &sigma.lastts, &sigma.lastsample,
950 sigma.triggerpos & 0x1ff,
951 user_data);
57bbf56b
HE
952 else
953 decode_chunk_ts(buf + (i * CHUNK_SIZE),
6aac7737 954 &sigma.lastts, &sigma.lastsample,
57bbf56b 955 -1, user_data);
28a35d8a
HE
956 }
957
6aac7737 958 sigma.chunks_downloaded += newchunks;
28a35d8a
HE
959 }
960
28a35d8a
HE
961 return TRUE;
962}
963
c53d793f
HE
964/* Build a LUT entry used by the trigger functions. */
965static void build_lut_entry(uint16_t value, uint16_t mask, uint16_t *entry)
ee492173
HE
966{
967 int i, j, k, bit;
968
f758d074 969 /* For each quad probe. */
ee492173 970 for (i = 0; i < 4; ++i) {
c53d793f 971 entry[i] = 0xffff;
ee492173 972
f758d074 973 /* For each bit in LUT. */
ee492173
HE
974 for (j = 0; j < 16; ++j)
975
f758d074 976 /* For each probe in quad. */
ee492173
HE
977 for (k = 0; k < 4; ++k) {
978 bit = 1 << (i * 4 + k);
979
c53d793f
HE
980 /* Set bit in entry */
981 if ((mask & bit) &&
982 ((!(value & bit)) !=
4ae1f451 983 (!(j & (1 << k)))))
c53d793f 984 entry[i] &= ~(1 << j);
ee492173
HE
985 }
986 }
c53d793f 987}
ee492173 988
c53d793f
HE
989/* Add a logical function to LUT mask. */
990static void add_trigger_function(enum triggerop oper, enum triggerfunc func,
991 int index, int neg, uint16_t *mask)
992{
993 int i, j;
994 int x[2][2], tmp, a, b, aset, bset, rset;
995
996 memset(x, 0, 4 * sizeof(int));
997
998 /* Trigger detect condition. */
999 switch (oper) {
1000 case OP_LEVEL:
1001 x[0][1] = 1;
1002 x[1][1] = 1;
1003 break;
1004 case OP_NOT:
1005 x[0][0] = 1;
1006 x[1][0] = 1;
1007 break;
1008 case OP_RISE:
1009 x[0][1] = 1;
1010 break;
1011 case OP_FALL:
1012 x[1][0] = 1;
1013 break;
1014 case OP_RISEFALL:
1015 x[0][1] = 1;
1016 x[1][0] = 1;
1017 break;
1018 case OP_NOTRISE:
1019 x[1][1] = 1;
1020 x[0][0] = 1;
1021 x[1][0] = 1;
1022 break;
1023 case OP_NOTFALL:
1024 x[1][1] = 1;
1025 x[0][0] = 1;
1026 x[0][1] = 1;
1027 break;
1028 case OP_NOTRISEFALL:
1029 x[1][1] = 1;
1030 x[0][0] = 1;
1031 break;
1032 }
1033
1034 /* Transpose if neg is set. */
1035 if (neg) {
1036 for (i = 0; i < 2; ++i)
1037 for (j = 0; j < 2; ++j) {
1038 tmp = x[i][j];
1039 x[i][j] = x[1-i][1-j];
1040 x[1-i][1-j] = tmp;
1041 }
1042 }
1043
1044 /* Update mask with function. */
1045 for (i = 0; i < 16; ++i) {
1046 a = (i >> (2 * index + 0)) & 1;
1047 b = (i >> (2 * index + 1)) & 1;
1048
1049 aset = (*mask >> i) & 1;
1050 bset = x[b][a];
1051
1052 if (func == FUNC_AND || func == FUNC_NAND)
1053 rset = aset & bset;
1054 else if (func == FUNC_OR || func == FUNC_NOR)
1055 rset = aset | bset;
1056 else if (func == FUNC_XOR || func == FUNC_NXOR)
1057 rset = aset ^ bset;
1058
1059 if (func == FUNC_NAND || func == FUNC_NOR || func == FUNC_NXOR)
1060 rset = !rset;
1061
1062 *mask &= ~(1 << i);
1063
1064 if (rset)
1065 *mask |= 1 << i;
1066 }
1067}
1068
1069/*
1070 * Build trigger LUTs used by 50 MHz and lower sample rates for supporting
1071 * simple pin change and state triggers. Only two transitions (rise/fall) can be
1072 * set at any time, but a full mask and value can be set (0/1).
1073 */
1074static int build_basic_trigger(struct triggerlut *lut)
1075{
1076 int i,j;
4ae1f451 1077 uint16_t masks[2] = { 0, 0 };
c53d793f
HE
1078
1079 memset(lut, 0, sizeof(struct triggerlut));
1080
1081 /* Contant for simple triggers. */
1082 lut->m4 = 0xa000;
1083
1084 /* Value/mask trigger support. */
1085 build_lut_entry(trigger.simplevalue, trigger.simplemask, lut->m2d);
1086
1087 /* Rise/fall trigger support. */
1088 for (i = 0, j = 0; i < 16; ++i) {
1089 if (trigger.risingmask & (1 << i) ||
1090 trigger.fallingmask & (1 << i))
1091 masks[j++] = 1 << i;
1092 }
1093
1094 build_lut_entry(masks[0], masks[0], lut->m0d);
1095 build_lut_entry(masks[1], masks[1], lut->m1d);
1096
1097 /* Add glue logic */
1098 if (masks[0] || masks[1]) {
1099 /* Transition trigger. */
1100 if (masks[0] & trigger.risingmask)
1101 add_trigger_function(OP_RISE, FUNC_OR, 0, 0, &lut->m3);
1102 if (masks[0] & trigger.fallingmask)
1103 add_trigger_function(OP_FALL, FUNC_OR, 0, 0, &lut->m3);
1104 if (masks[1] & trigger.risingmask)
1105 add_trigger_function(OP_RISE, FUNC_OR, 1, 0, &lut->m3);
1106 if (masks[1] & trigger.fallingmask)
1107 add_trigger_function(OP_FALL, FUNC_OR, 1, 0, &lut->m3);
1108 } else {
1109 /* Only value/mask trigger. */
1110 lut->m3 = 0xffff;
1111 }
ee492173 1112
c53d793f 1113 /* Triggertype: event. */
ee492173
HE
1114 lut->params.selres = 3;
1115
1116 return SIGROK_OK;
1117}
1118
28a35d8a
HE
1119static int hw_start_acquisition(int device_index, gpointer session_device_id)
1120{
1121 struct sigrok_device_instance *sdi;
1122 struct datafeed_packet packet;
1123 struct datafeed_header header;
9ddb2a12
UH
1124 struct clockselect_50 clockselect;
1125 int frac;
57bbf56b
HE
1126 uint8_t triggerselect;
1127 struct triggerinout triggerinout_conf;
ee492173 1128 struct triggerlut lut;
a42aec7f 1129 int triggerpin;
28a35d8a
HE
1130
1131 session_device_id = session_device_id;
1132
1133 if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
1134 return SIGROK_ERR;
1135
1136 device_index = device_index;
1137
ed09fd07 1138 /* If the samplerate has not been set, default to 50 MHz. */
9ddb2a12 1139 if (cur_firmware == -1)
ed09fd07 1140 set_samplerate(sdi, MHZ(50));
e8397563 1141
eec5275e 1142 /* Enter trigger programming mode. */
28a35d8a
HE
1143 sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20);
1144
eec5275e 1145 /* 100 and 200 MHz mode. */
57bbf56b
HE
1146 if (cur_samplerate >= MHZ(100)) {
1147 sigma_set_register(WRITE_TRIGGER_SELECT1, 0x81);
1148
a42aec7f
HE
1149 /* Find which pin to trigger on from mask. */
1150 for (triggerpin = 0; triggerpin < 8; ++triggerpin)
1151 if ((trigger.risingmask | trigger.fallingmask) &
1152 (1 << triggerpin))
1153 break;
1154
1155 /* Set trigger pin and light LED on trigger. */
1156 triggerselect = (1 << LEDSEL1) | (triggerpin & 0x7);
1157
1158 /* Default rising edge. */
1159 if (trigger.fallingmask)
1160 triggerselect |= 1 << 3;
57bbf56b 1161
eec5275e 1162 /* All other modes. */
57bbf56b 1163 } else if (cur_samplerate <= MHZ(50)) {
ee492173
HE
1164 build_basic_trigger(&lut);
1165
1166 sigma_write_trigger_lut(&lut);
57bbf56b
HE
1167
1168 triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0);
1169 }
1170
eec5275e 1171 /* Setup trigger in and out pins to default values. */
57bbf56b
HE
1172 memset(&triggerinout_conf, 0, sizeof(struct triggerinout));
1173 triggerinout_conf.trgout_bytrigger = 1;
1174 triggerinout_conf.trgout_enable = 1;
1175
28a35d8a 1176 sigma_write_register(WRITE_TRIGGER_OPTION,
57bbf56b
HE
1177 (uint8_t *) &triggerinout_conf,
1178 sizeof(struct triggerinout));
28a35d8a 1179
eec5275e 1180 /* Go back to normal mode. */
57bbf56b 1181 sigma_set_register(WRITE_TRIGGER_SELECT1, triggerselect);
28a35d8a 1182
edca2c5c
HE
1183 /* Set clock select register. */
1184 if (cur_samplerate == MHZ(200))
1185 /* Enable 4 probes. */
1186 sigma_set_register(WRITE_CLOCK_SELECT, 0xf0);
1187 else if (cur_samplerate == MHZ(100))
1188 /* Enable 8 probes. */
1189 sigma_set_register(WRITE_CLOCK_SELECT, 0x00);
1190 else {
1191 /*
9ddb2a12 1192 * 50 MHz mode (or fraction thereof). Any fraction down to
eec5275e 1193 * 50 MHz / 256 can be used, but is not supported by sigrok API.
edca2c5c 1194 */
9ddb2a12 1195 frac = MHZ(50) / cur_samplerate - 1;
edca2c5c 1196
9ddb2a12
UH
1197 clockselect.async = 0;
1198 clockselect.fraction = frac;
1199 clockselect.disabled_probes = 0;
edca2c5c
HE
1200
1201 sigma_write_register(WRITE_CLOCK_SELECT,
9ddb2a12
UH
1202 (uint8_t *) &clockselect,
1203 sizeof(clockselect));
edca2c5c
HE
1204 }
1205
fefa1800 1206 /* Setup maximum post trigger time. */
11fc8d9d 1207 sigma_set_register(WRITE_POST_TRIGGER, (capture_ratio * 255) / 100);
28a35d8a 1208
eec5275e 1209 /* Start acqusition. */
28a35d8a
HE
1210 gettimeofday(&start_tv, 0);
1211 sigma_set_register(WRITE_MODE, 0x0d);
1212
28a35d8a
HE
1213 /* Send header packet to the session bus. */
1214 packet.type = DF_HEADER;
1215 packet.length = sizeof(struct datafeed_header);
1216 packet.payload = &header;
1217 header.feed_version = 1;
1218 gettimeofday(&header.starttime, NULL);
1219 header.samplerate = cur_samplerate;
1220 header.protocol_id = PROTO_RAW;
edca2c5c 1221 header.num_probes = num_probes;
28a35d8a
HE
1222 session_bus(session_device_id, &packet);
1223
57bbf56b
HE
1224 /* Add capture source. */
1225 source_add(0, G_IO_IN, 10, receive_data, session_device_id);
1226
6aac7737
HE
1227 sigma.state = SIGMA_CAPTURE;
1228
28a35d8a
HE
1229 return SIGROK_OK;
1230}
1231
28a35d8a
HE
1232static void hw_stop_acquisition(int device_index, gpointer session_device_id)
1233{
6aac7737
HE
1234 uint8_t modestatus;
1235
28a35d8a
HE
1236 device_index = device_index;
1237 session_device_id = session_device_id;
1238
fefa1800 1239 /* Stop acquisition. */
28a35d8a
HE
1240 sigma_set_register(WRITE_MODE, 0x11);
1241
6aac7737
HE
1242 /* Set SDRAM Read Enable. */
1243 sigma_set_register(WRITE_MODE, 0x02);
1244
1245 /* Get the current position. */
1246 sigma_read_pos(&sigma.stoppos, &sigma.triggerpos);
1247
1248 /* Check if trigger has fired. */
1249 modestatus = sigma_get_register(READ_MODE);
1250 if (modestatus & 0x20) {
1251 sigma.triggerchunk = sigma.triggerpos / 512;
1252
1253 } else
1254 sigma.triggerchunk = -1;
1255
1256 sigma.chunks_downloaded = 0;
1257
1258 sigma.state = SIGMA_DOWNLOAD;
28a35d8a
HE
1259}
1260
28a35d8a
HE
1261struct device_plugin asix_sigma_plugin_info = {
1262 "asix-sigma",
1263 1,
1264 hw_init,
1265 hw_cleanup,
28a35d8a
HE
1266 hw_opendev,
1267 hw_closedev,
1268 hw_get_device_info,
1269 hw_get_status,
1270 hw_get_capabilities,
1271 hw_set_configuration,
1272 hw_start_acquisition,
9ddb2a12 1273 hw_stop_acquisition,
28a35d8a 1274};