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