]> sigrok.org Git - libsigrok.git/blob - hardware/asix-sigma/asix-sigma.c
This commit adds initial support for the Asix Sigma Logic Analyzer. Currently, only...
[libsigrok.git] / hardware / asix-sigma / asix-sigma.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * ASIX Sigma Logic Analyzer Driver
5  *
6  * Copyright (C) 2010
7  *
8  *      Håvard Espeland   <gus@ping.uio.no>,
9  *      Martin Stensgård  <mastensg@ping.uio.no>
10  *      Carl Henrik Lunde <chlunde@ping.uio.no>
11  *
12  * This program is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26 #include <ftdi.h>
27 #include <string.h>
28 #include <zlib.h>
29
30 #include "sigrok.h"
31 #include "asix-sigma.h"
32
33 #define USB_VENDOR                      0xa600
34 #define USB_PRODUCT                     0xa000
35 #define USB_DESCRIPTION                 "ASIX SIGMA"
36 #define USB_VENDOR_NAME                 "ASIX"
37 #define USB_MODEL_NAME                  "SIGMA"
38 #define USB_MODEL_VERSION               ""
39 #define FIRMWARE                        FIRMWARE_DIR "/asix-sigma-200.firmware"
40
41 static GSList *device_instances = NULL;
42
43 // XXX These should be per device
44 static struct ftdi_context ftdic;
45 static uint64_t cur_samplerate = MHZ(200);
46 static uint32_t limit_msec = 0;
47 static struct timeval start_tv;
48
49 static uint64_t supported_samplerates[] = {
50         MHZ(200),
51         0,
52 };
53
54 static struct samplerates samplerates = {
55         MHZ(200),
56         MHZ(200),
57         0,
58         supported_samplerates,
59 };
60
61 static int capabilities[] = {
62         HWCAP_LOGIC_ANALYZER,
63         HWCAP_SAMPLERATE,
64
65         /* These are really implemented in the driver, not the hardware. */
66         HWCAP_LIMIT_MSEC,
67         0,
68 };
69
70 static int sigma_read(void* buf, size_t size)
71 {
72         int ret;
73         ret = ftdi_read_data(&ftdic, (unsigned char*) buf, size);
74         if (ret < 0) {
75                 g_warning("ftdi_read_data failed: %s",
76                         ftdi_get_error_string(&ftdic));
77         }
78
79         return ret;
80 }
81
82 static int sigma_write(void* buf, size_t size)
83 {
84         int ret;
85         ret = ftdi_write_data(&ftdic, (unsigned char*) buf, size);
86         if (ret < 0) {
87                 g_warning("ftdi_write_data failed: %s",
88                         ftdi_get_error_string(&ftdic));
89         }
90         else if ((size_t) ret != size) {
91                 g_warning("ftdi_write_data did not complete write\n");
92         }
93
94         return ret;
95 }
96
97 static int sigma_write_register(uint8_t reg, uint8_t *data, size_t len)
98 {
99         size_t i;
100         uint8_t buf[len + 2];
101         int idx = 0;
102
103         buf[idx++] = REG_ADDR_LOW | (reg & 0xf);
104         buf[idx++] = REG_ADDR_HIGH | (reg >> 4);
105
106         for (i=0; i<len; ++i) {
107                 buf[idx++] = REG_DATA_LOW | (data[i] & 0xf);
108                 buf[idx++] = REG_DATA_HIGH_WRITE | (data[i] >> 4);
109         }
110
111         return sigma_write(buf, idx);
112 }
113
114 static int sigma_set_register(uint8_t reg, uint8_t value)
115 {
116         return sigma_write_register(reg, &value, 1);
117 }
118
119 static int sigma_read_register(uint8_t reg, uint8_t *data, size_t len)
120 {
121         uint8_t buf[3];
122         buf[0] = REG_ADDR_LOW | (reg & 0xf);
123         buf[1] = REG_ADDR_HIGH | (reg >> 4);
124
125         buf[2] = REG_READ_ADDR;
126
127         sigma_write(buf, sizeof(buf));
128
129         return sigma_read(data, len);
130 }
131
132 static uint8_t sigma_get_register(uint8_t reg)
133 {
134         uint8_t value;
135         if (1 != sigma_read_register(reg, &value, 1)) {
136                 g_warning("Sigma_get_register: 1 byte expected");
137                 return 0;
138         }
139
140         return value;
141 }
142
143 static int sigma_read_pos(uint32_t *stoppos, uint32_t *triggerpos)
144 {
145         uint8_t buf[] = {
146                 REG_ADDR_LOW | READ_TRIGGER_POS_LOW,
147
148                 REG_READ_ADDR | NEXT_REG,
149                 REG_READ_ADDR | NEXT_REG,
150                 REG_READ_ADDR | NEXT_REG,
151                 REG_READ_ADDR | NEXT_REG,
152                 REG_READ_ADDR | NEXT_REG,
153                 REG_READ_ADDR | NEXT_REG,
154         };
155
156         uint8_t result[6];
157
158         sigma_write(buf, sizeof(buf));
159
160         sigma_read(result, sizeof(result));
161
162         *triggerpos = result[0] | (result[1] << 8) | (result[2] << 16);
163         *stoppos = result[3] | (result[4] << 8) | (result[5] << 16);
164
165         return 1;
166 }
167
168 static int sigma_read_dram(uint16_t startchunk, size_t numchunks, uint8_t *data)
169 {
170         size_t i;
171         uint8_t buf[4096];
172         int idx = 0;
173
174         /* Send the startchunk. Index start with 1 */
175         buf[0] = startchunk >> 8;
176         buf[1] = startchunk & 0xff;
177         sigma_write_register(WRITE_MEMROW, buf, 2);
178
179         /* Read the DRAM */
180         buf[idx++] = REG_DRAM_BLOCK;
181         buf[idx++] = REG_DRAM_WAIT_ACK;
182
183         for (i = 0; i < numchunks; ++i) {
184                 /* Alternate bit to copy from dram to cache */
185                 if (i != numchunks-1)
186                         buf[idx++] = REG_DRAM_BLOCK | (((i+1) % 2) << 4);
187
188                 buf[idx++] = REG_DRAM_BLOCK_DATA | ((i % 2) << 4);
189
190                 if (i != numchunks-1)
191                         buf[idx++] = REG_DRAM_WAIT_ACK;
192         }
193
194         sigma_write(buf, idx);
195
196         return sigma_read(data, numchunks * CHUNK_SIZE);
197 }
198
199
200 /* Generate the bitbang stream for programming the FPGA */
201 static int bin2bitbang(const char *filename,
202                        unsigned char **buf, size_t* buf_size)
203 {
204         FILE *f = fopen(filename, "r");
205         long file_size;
206         unsigned long offset = 0;
207         unsigned char *p;
208         uint8_t *compressed_buf, *firmware;
209         uLongf csize, fwsize;
210         const int buffer_size = 65536;
211         size_t i;
212         int c, ret;
213
214         if (!f) {
215                 g_warning("fopen(\"%s\", \"r\")", filename);
216                 return -1;
217         }
218
219         if (-1 == fseek(f, 0, SEEK_END)) {
220                 g_warning("fseek on %s failed", filename);
221                 fclose(f);
222                 return -1;
223         }
224
225         file_size = ftell(f);
226
227         fseek(f, 0, SEEK_SET);
228
229
230         compressed_buf = g_malloc(file_size);
231         firmware = g_malloc(buffer_size);
232
233         if (!compressed_buf || !firmware) {
234                 g_warning("Error allocating buffers");
235                 return -1;
236         }
237
238         uint32_t imm = 0x3f6df2ab;
239         csize = 0;
240         while ((c = getc(f)) != EOF) {
241                 imm = (imm + 0xa853753) % 177 + (imm * 0x8034052);
242                 compressed_buf[csize++] = c ^ imm;
243         }
244         fclose(f);
245
246         fwsize = buffer_size;
247         ret = uncompress(firmware, &fwsize, compressed_buf, csize);
248         if (ret < 0) {
249                 g_free(compressed_buf);
250                 g_free(firmware);
251                 g_warning("Could not unpack Sigma firmware. (Error %d)\n", ret);
252                 return -1;
253         }
254
255         g_free(compressed_buf);
256
257         *buf_size = fwsize * 2 * 8;
258
259         *buf = p = (unsigned char*) g_malloc(*buf_size);
260
261         if (!p) {
262                 g_warning("Error allocating buffers");
263                 return -1;
264         }
265
266         for (i = 0; i < fwsize; ++i) {
267                 int bit;
268                 for (bit = 7; bit >= 0; --bit) {
269                         int v = firmware[i] & 1 << bit ? 0x40 : 0x00;
270                         p[offset++] = v | 0x01;
271                         p[offset++] = v;
272                 }
273         }
274
275         g_free(firmware);
276
277         if (offset != *buf_size) {
278                 g_free(*buf);
279                 g_warning("Error reading firmware %s "
280                         "offset=%ld, file_size=%ld, buf_size=%zd\n",
281                         filename, offset, file_size, *buf_size);
282
283                 return -1;
284         }
285
286         return 0;
287 }
288
289 static int hw_init(char *deviceinfo)
290 {
291         struct sigrok_device_instance *sdi;
292
293         deviceinfo = deviceinfo;
294
295         ftdi_init(&ftdic);
296
297         /* Look for SIGMAs */
298         if (ftdi_usb_open_desc(&ftdic, USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL) < 0)
299                 return 0;
300
301         /* Register SIGMA device */
302         sdi = sigrok_device_instance_new(0, ST_INITIALIZING,
303                         USB_VENDOR_NAME, USB_MODEL_NAME, USB_MODEL_VERSION);
304         if (!sdi)
305                 return 0;
306
307         device_instances = g_slist_append(device_instances, sdi);
308
309         /* We will open the device again when we need it */
310         ftdi_usb_close(&ftdic);
311
312         return 1;
313 }
314
315
316 static int hw_opendev(int device_index)
317 {
318         int ret;
319         unsigned char *buf;
320         unsigned char pins;
321         size_t buf_size;
322         struct sigrok_device_instance *sdi;
323         unsigned char result[32];
324
325         /* Make sure it's an ASIX SIGMA */
326         if ((ret = ftdi_usb_open_desc(&ftdic,
327                 USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) {
328
329                 g_warning("ftdi_usb_open failed: %s",
330                         ftdi_get_error_string(&ftdic));
331
332                 return 0;
333         }
334
335         if ((ret = ftdi_set_bitmode(&ftdic, 0xdf, BITMODE_BITBANG)) < 0) {
336                 g_warning("ftdi_set_bitmode failed: %s",
337                         ftdi_get_error_string(&ftdic));
338
339                 return 0;
340         }
341
342         /* Four times the speed of sigmalogan - Works well */
343         if ((ret = ftdi_set_baudrate(&ftdic, 750000)) < 0) {
344                 g_warning("ftdi_set_baudrate failed: %s",
345                         ftdi_get_error_string(&ftdic));
346
347                 return 0;
348         }
349
350         /* Force the FPGA to reboot */
351         unsigned char suicide[] = {
352                 0x84, 0x84, 0x88, 0x84, 0x88, 0x84, 0x88, 0x84,
353         };
354
355         sigma_write(suicide, sizeof(suicide));
356         sigma_write(suicide, sizeof(suicide));
357         sigma_write(suicide, sizeof(suicide));
358         sigma_write(suicide, sizeof(suicide));
359
360         /* Prepare to upload firmware (FPGA specific) */
361         unsigned char init[] = {
362                 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
363         };
364
365         sigma_write(init, sizeof(init));
366
367         ftdi_usb_purge_buffers(&ftdic);
368
369         /* Wait until the FPGA asserts INIT_B */
370         while (1) {
371                 ret = sigma_read(result, 1);
372                 if (result[0] & 0x20)
373                         break;
374         }
375
376         /* Prepare firmware */
377         if (-1 == bin2bitbang(FIRMWARE, &buf, &buf_size)) {
378                 g_warning("An error occured while reading the firmware: %s",
379                         FIRMWARE);
380
381                 return SIGROK_ERR;
382         }
383
384         /* Upload firmare */
385         sigma_write(buf, buf_size);
386
387         g_free(buf);
388
389         if ((ret = ftdi_set_bitmode(&ftdic, 0x00, BITMODE_RESET)) < 0) {
390                 g_warning("ftdi_set_bitmode failed: %s",
391                         ftdi_get_error_string(&ftdic));
392
393                 return SIGROK_ERR;
394         }
395
396         ftdi_usb_purge_buffers(&ftdic);
397
398         /* Discard garbage */
399         while (1 == sigma_read(&pins, 1))
400                 ;
401
402         /* Initialize the logic analyzer mode */
403         unsigned char logic_mode_start[] = {
404                 0x00, 0x40, 0x0f, 0x25, 0x35, 0x40,
405                 0x2a, 0x3a, 0x40, 0x03, 0x20, 0x38
406         };
407
408         sigma_write(logic_mode_start, sizeof(logic_mode_start));
409
410         /* Expect a 3 byte reply */
411         ret = sigma_read(result, 3);
412         if (ret != 3 ||
413             result[0] != 0xa6 || result[1] != 0x55 || result[2] != 0xaa) {
414
415                 g_warning("Sigma configuration failed. Invalid reply received.");
416                 return SIGROK_ERR;
417         }
418
419         /* Works like a charm */
420
421         if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
422                 return SIGROK_ERR;
423
424         sdi->status = ST_ACTIVE;
425
426         g_message("Firmware uploaded");
427
428         return SIGROK_OK;
429 }
430
431
432 static void hw_closedev(int device_index)
433 {
434         device_index = device_index;
435
436         ftdi_usb_close(&ftdic);
437 }
438
439
440 static void hw_cleanup(void)
441 {
442 }
443
444
445 static void *hw_get_device_info(int device_index, int device_info_id)
446 {
447         struct sigrok_device_instance *sdi;
448         void *info = NULL;
449
450         if (!(sdi = get_sigrok_device_instance(device_instances, device_index))) {
451                 fprintf(stderr, "It's NULL.\n");
452                 return NULL;
453         }
454
455         switch (device_info_id) {
456         case DI_INSTANCE:
457                 info = sdi;
458                 break;
459         case DI_NUM_PROBES:
460                 info = GINT_TO_POINTER(4);
461                 break;
462         case DI_SAMPLERATES:
463                 info = &samplerates;
464                 break;
465         case DI_TRIGGER_TYPES:
466                 info = 0;//TRIGGER_TYPES;
467                 break;
468         case DI_CUR_SAMPLERATE:
469                 info = &cur_samplerate;
470                 break;
471         }
472
473         return info;
474 }
475
476
477 static int hw_get_status(int device_index)
478 {
479         struct sigrok_device_instance *sdi;
480
481         sdi = get_sigrok_device_instance(device_instances, device_index);
482         if (sdi)
483                 return sdi->status;
484         else
485                 return ST_NOT_FOUND;
486 }
487
488
489 static int *hw_get_capabilities(void)
490 {
491         return capabilities;
492 }
493
494 static int hw_set_configuration(int device_index, int capability, void *value)
495 {
496         struct sigrok_device_instance *sdi;
497         int ret;
498         uint64_t *tmp_u64;
499
500         if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
501                 return SIGROK_ERR;
502
503         if (capability == HWCAP_SAMPLERATE) {
504                 tmp_u64 = (uint64_t*) value;
505                 /* Only 200 MHz implemented */
506                 ret = SIGROK_OK;
507         } else if (capability == HWCAP_PROBECONFIG) {
508                 ret = SIGROK_OK;
509         } else if (capability == HWCAP_LIMIT_MSEC) {
510                 limit_msec = strtoull(value, NULL, 10);
511                 ret = SIGROK_OK;
512         } else {
513                 ret = SIGROK_ERR;
514         }
515
516         return ret;
517 }
518
519
520 /*
521    Decode chunk of 1024 bytes, 64 clusters, 7 events per cluster.
522    Each event is 20ns apart, and can contain multiple samples.
523    For 200 MHz, an event contains 4 samples for each channel, spread 5 ns apart
524  */
525 static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
526                            uint8_t *lastsample, void *user_data)
527 {
528         const int samples_per_event = 4;
529         uint16_t tsdiff;
530         uint16_t ts;
531
532         uint8_t samples[65536 * samples_per_event];
533
534         struct datafeed_packet packet;
535
536         int i, j, k;
537         size_t n = 0;
538
539         int clustersize = EVENTS_PER_CLUSTER * samples_per_event; /* 4 for 200 MHz */
540
541         /* For each ts */
542         for (i = 0; i < 64; ++i) {
543                 ts = *(uint16_t*) &buf[i*16];
544                 tsdiff = ts - *lastts;
545                 *lastts = ts;
546
547                 /* Pad last sample up to current point */
548                 int numpad = tsdiff * samples_per_event - clustersize;
549                 if (numpad > 0) {
550                         memset(samples, *lastsample,
551                                tsdiff*samples_per_event - clustersize);
552                         n = tsdiff*samples_per_event - clustersize;
553                 }
554
555                 uint16_t *event = (uint16_t*) &buf[i*16+2];
556
557                 /* For each sample in cluster */
558                 for (j = 0; j < 7; ++j) {
559                         for (k = 0; k < samples_per_event; ++k) {
560                                 /* Extract samples from bytestream.
561                                    Samples are packed together in a short */
562                                 samples[n++] =
563                                         ((!!(event[j] & (1 << (k+0x0)))) << 0) |
564                                         ((!!(event[j] & (1 << (k+0x4)))) << 1) |
565                                         ((!!(event[j] & (1 << (k+0x8)))) << 2) |
566                                         ((!!(event[j] & (1 << (k+0xc)))) << 3);
567                         }
568                 }
569
570                 *lastsample = samples[n-1];
571
572                 /* Send to sigrok */
573                 size_t sent = 0;
574                 while (sent < n) {
575                         int tosend = MIN(4096, n-sent);
576
577                         packet.type = DF_LOGIC8;
578                         packet.length = tosend;
579                         packet.payload = samples+sent;
580                         session_bus(user_data, &packet);
581
582                         sent += tosend;
583                 }
584         }
585
586         return 0;
587 }
588
589 static int receive_data(int fd, int revents, void *user_data)
590 {
591         struct datafeed_packet packet;
592
593         const int chunks_per_read = 32;
594         unsigned char buf[chunks_per_read * CHUNK_SIZE];
595         int bufsz;
596
597         uint32_t triggerpos, stoppos;
598         int numchunks;
599         struct timeval tv;
600         uint32_t running_msec;
601
602         uint16_t lastts = 0;
603         uint8_t lastsample = 0;
604         int curchunk, i;
605
606         fd = fd;
607         revents = revents;
608
609         /* Get the current position */
610         sigma_read_pos(&stoppos, &triggerpos);
611         numchunks = stoppos / 512;
612
613         /* Check if the has expired, or memory is full */
614         gettimeofday(&tv, 0);
615         running_msec = (tv.tv_sec - start_tv.tv_sec) * 1000 +
616                 (tv.tv_usec - start_tv.tv_usec) / 1000;
617
618         if (running_msec < limit_msec && numchunks < 32767)
619                 return FALSE;
620
621         /* Stop Acqusition */
622         sigma_set_register(WRITE_MODE, 0x11);
623
624         /* Set SDRAM Read Enable */
625         sigma_set_register(WRITE_MODE, 0x02);
626
627         /* Get the current position */
628         sigma_read_pos(&stoppos, &triggerpos);
629
630         /* Download sample data */
631         for (curchunk = 0; curchunk < numchunks;) {
632                 int newchunks = MIN(chunks_per_read, numchunks - curchunk);
633
634                 g_message("Downloading sample data: %.0f %%",
635                                 100.0 * curchunk / numchunks);
636
637                 bufsz = sigma_read_dram(curchunk, newchunks, buf);
638
639                 /* Find first ts */
640                 if (curchunk == 0) {
641                         lastts = *(uint16_t*) buf - 1;
642                 }
643
644                 /* Decode chunks and send them to sigrok */
645                 for (i = 0; i < newchunks; ++i) {
646                         decode_chunk_ts(buf + (i * CHUNK_SIZE),
647                                         &lastts, &lastsample, user_data);
648                 }
649
650                 curchunk += newchunks;
651         }
652
653         /* End of data */
654         packet.type = DF_END;
655         packet.length = 0;
656         session_bus(user_data, &packet);
657
658         return TRUE;
659 }
660
661 static int hw_start_acquisition(int device_index, gpointer session_device_id)
662 {
663         struct sigrok_device_instance *sdi;
664         struct datafeed_packet packet;
665         struct datafeed_header header;
666
667         session_device_id = session_device_id;
668
669         if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
670                 return SIGROK_ERR;
671
672         device_index = device_index;
673
674         /* Setup trigger (by trigger-in) */
675         sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20);
676
677         /* More trigger setup */
678         uint8_t trigger_option[2] = { 0x38, 0x00 };
679         sigma_write_register(WRITE_TRIGGER_OPTION,
680                         trigger_option, sizeof(trigger_option));
681
682         /* Trigger normal (falling edge) */
683         sigma_set_register(WRITE_TRIGGER_SELECT1, 0x08);
684
685         /* Enable pins (200 MHz, 4 pins) */
686         sigma_set_register(WRITE_CLOCK_SELECT, 0xf0);
687
688         /* Setup maximum post trigger time */
689         sigma_set_register(WRITE_POST_TRIGGER, 0xff);
690
691         /* Start Acqusition (Software trigger start) */
692         gettimeofday(&start_tv, 0);
693         sigma_set_register(WRITE_MODE, 0x0d);
694
695
696         /* Add capture source */
697         source_add(0, G_IO_IN, 10, receive_data, session_device_id);
698
699         receive_data(0, 1, session_device_id);
700
701         /* Send header packet to the session bus. */
702         packet.type = DF_HEADER;
703         packet.length = sizeof(struct datafeed_header);
704         packet.payload = &header;
705         header.feed_version = 1;
706         gettimeofday(&header.starttime, NULL);
707         header.samplerate = cur_samplerate;
708         header.protocol_id = PROTO_RAW;
709         header.num_probes = 4;
710         session_bus(session_device_id, &packet);
711
712         return SIGROK_OK;
713 }
714
715
716 static void hw_stop_acquisition(int device_index, gpointer session_device_id)
717 {
718         device_index = device_index;
719         session_device_id = session_device_id;
720
721         /* Stop Acqusition */
722         sigma_set_register(WRITE_MODE, 0x11);
723
724         // XXX Set some state to indicate that data should be sent to sigrok
725         //     Now, we just wait for timeout
726 }
727
728
729
730 struct device_plugin asix_sigma_plugin_info = {
731         "asix-sigma",
732         1,
733         hw_init,
734         hw_cleanup,
735
736         hw_opendev,
737         hw_closedev,
738         hw_get_device_info,
739         hw_get_status,
740         hw_get_capabilities,
741         hw_set_configuration,
742         hw_start_acquisition,
743         hw_stop_acquisition
744 };
745
746 // vim:noexpandtab:ts=8 sts=8 sw=8