]> sigrok.org Git - libsigrok.git/blob - hardware/zeroplus-logic-cube/analyzer.c
Start of code base layout restructuring.
[libsigrok.git] / hardware / zeroplus-logic-cube / analyzer.c
1 /*
2  Copyright (c) 2010 Sven Peter <sven@fail0verflow.com>
3  Copyright (c) 2010 Haxx Enterprises <bushing@gmail.com>
4  All rights reserved.
5
6  Redistribution and use in source and binary forms, with or
7  without modification, are permitted provided that the following
8  conditions are met:
9
10  * Redistributions of source code must retain the above copyright notice,
11    this list of conditions and the following disclaimer.
12
13  * Redistributions in binary form must reproduce the above copyright notice,
14    this list of conditions and the following disclaimer in the documentation
15    and/or other materials provided with the distribution.
16
17   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27   THE POSSIBILITY OF SUCH DAMAGE.
28
29 */
30 #include <assert.h>
31
32 #include "analyzer.h"
33 #include "gl_usb.h"
34
35 enum {
36         HARD_DATA_CHECK_SUM = 0x00,
37         PASS_WORD,
38
39         DEVICE_ID0                      = 0x10,
40         DEVICE_ID1,
41
42         START_STATUS            = 0x20,
43         DEVICE_STATUS           = 0x21,
44         FREQUENCY_REG0          = 0x30,
45         FREQUENCY_REG1,
46         FREQUENCY_REG2,
47         FREQUENCY_REG3,
48         FREQUENCY_REG4,
49         MEMORY_LENGTH,
50         CLOCK_SOURCE,
51
52         TRIGGER_STATUS0         = 0x40,
53         TRIGGER_STATUS1,
54         TRIGGER_STATUS2,
55         TRIGGER_STATUS3,
56         TRIGGER_STATUS4,
57         TRIGGER_STATUS5,
58         TRIGGER_STATUS6,
59         TRIGGER_STATUS7,
60         TRIGGER_STATUS8,
61
62         TRIGGER_COUNT0          = 0x50,
63         TRIGGER_COUNT1,
64
65         TRIGGER_LEVEL0          = 0x55,
66         TRIGGER_LEVEL1,
67         TRIGGER_LEVEL2,
68         TRIGGER_LEVEL3,
69
70         RAMSIZE_TRIGGERBAR_ADDRESS0     = 0x60,
71         RAMSIZE_TRIGGERBAR_ADDRESS1,
72         RAMSIZE_TRIGGERBAR_ADDRESS2,
73         TRIGGERBAR_ADDRESS0,
74         TRIGGERBAR_ADDRESS1,
75         TRIGGERBAR_ADDRESS2,
76         DONT_CARE_TRIGGERBAR,
77
78         FILTER_ENABLE                   = 0x70,
79         FILTER_STATUS,
80
81         ENABLE_DELAY_TIME0      = 0x7A,
82         ENABLE_DELAY_TIME1,
83
84         ENABLE_INSERT_DATA0 = 0x80,
85         ENABLE_INSERT_DATA1,
86         ENABLE_INSERT_DATA2,
87         ENABLE_INSERT_DATA3,
88         COMPRESSION_TYPE0,
89         COMPRESSION_TYPE1,
90
91         TRIGGER_ADDRESS0        = 0x90,
92         TRIGGER_ADDRESS1,
93         TRIGGER_ADDRESS2,
94
95         NOW_ADDRESS0            = 0x96,
96         NOW_ADDRESS1,
97         NOW_ADDRESS2,
98
99         STOP_ADDRESS0           = 0x9B,
100         STOP_ADDRESS1,
101         STOP_ADDRESS2,
102
103         READ_RAM_STATUS         = 0xA0
104 };
105
106 static int g_trigger_status[9] = {0};
107 static int g_trigger_count = 1;
108
109 static int g_filter_status[8] = {0};
110 static int g_filter_enable = 0;
111
112 static int g_freq_value = 100;
113 static int g_freq_scale = FREQ_SCALE_MHZ;
114 static int g_memory_size = MEMORY_SIZE_512K;
115 static int g_ramsize_triggerbar_addr = 0x80000>>2;
116 static int g_triggerbar_addr = 0x3fe;
117 static int g_compression = COMPRESSION_NONE;
118
119 // maybe unk specifies an "endpoint" or "register" of sorts
120 static int analyzer_write_status(libusb_device_handle *devh, unsigned char unk, unsigned char flags)
121 {
122         assert(unk <= 3);
123         return gl_reg_write(devh, START_STATUS, unk << 6 | flags);
124 }
125
126 static int __analyzer_set_freq(libusb_device_handle *devh, int freq, int scale)
127 {
128         int reg0=0, divisor=0, reg2=0;
129         switch (scale) {
130                 case FREQ_SCALE_MHZ: // MHz
131                         if (freq >= 100 && freq <= 200) {
132                                 reg0 = freq * 0.1;
133                                 divisor = 1;
134                                 reg2 = 0;
135                                 break;
136                         }
137                         if (freq >= 50 && freq < 100) {
138                                 reg0 = freq * 0.2;
139                                 divisor = 2;
140                                 reg2 = 0;
141                                 break;
142                         }
143                         if (freq >= 10 && freq < 50) {
144                                 if (freq == 25) {
145                                         reg0 = 25;
146                                         divisor = 5;
147                                         reg2 = 1;
148                                         break;
149                                 } else {
150                                         reg0 = freq * 0.5;
151                                         divisor = 5;
152                                         reg2 = 1;
153                                         break;
154                                 }
155                         }
156                         if (freq >= 2 && freq < 10) {
157                                 divisor = 5;
158                                 reg0 = freq * 2;
159                                 reg2 = 2;
160                                 break;
161                         }
162                         if (freq == 1) {
163                                 divisor = 5;
164                                 reg2 = 16;
165                                 reg0 = 5;
166                                 break;
167                         }
168                         divisor = 5;
169                         reg0 = 5;
170                         reg2 = 64;
171                         break;
172                 case FREQ_SCALE_HZ: // Hz
173                         if (freq >= 500 && freq < 1000) {
174                                 reg0 = freq * 0.01;
175                                 divisor = 10;
176                                 reg2 = 64;
177                                 break;
178                         }
179                         if (freq >= 300 && freq < 500) {
180                                 reg0 = freq * 0.005 * 8;
181                                 divisor = 5;
182                                 reg2 = 67;
183                                 break;
184                         }
185                         if (freq >= 100 && freq < 300) {
186                                 reg0 = freq * 0.005 * 16;
187                                 divisor = 5;
188                                 reg2 = 68;
189                                 break;
190                         }
191                         divisor = 5;
192                         reg0 = 5;
193                         reg2 = 64;
194                         break;
195                 case FREQ_SCALE_KHZ: // KHz
196                         if (freq >= 500 && freq < 1000) {
197                                 reg0 = freq * 0.01;
198                                 divisor = 5;
199                                 reg2 = 17;
200                                 break;
201                         }
202                         if (freq >= 100 && freq < 500) {
203                                 reg0 = freq * 0.05;
204                                 divisor = 5;
205                                 reg2 = 32;
206                                 break;
207                         }
208                         if (freq >= 50 && freq < 100) {
209                                 reg0 = freq * 0.1;
210                                 divisor = 5;
211                                 reg2 = 33;
212                                 break;
213                         }
214                         if (freq >= 10 && freq < 50) {
215                                 if (freq == 25) {
216                                         reg0 = 25;
217                                         divisor = 5;
218                                         reg2 = 49;
219                                         break;
220                                 }
221                                 reg0 = freq * 0.5;
222                                 divisor = 5;
223                                 reg2 = 48;
224                                 break;
225                         }
226                         if (freq >= 2 && freq < 10) {
227                                 divisor = 5;
228                                 reg0 = freq * 2;
229                                 reg2 = 50;
230                                 break;
231                         }
232                         divisor = 5;
233                         reg0 = 5;
234                         reg2 = 64;
235                         break;
236                 default:
237                         divisor = 5;
238                         reg0 = 5;
239                         reg2 = 64;
240                         break;
241         }
242         if (gl_reg_write(devh, FREQUENCY_REG0, divisor) < 0)
243                 return -1; // divisor maybe?
244
245         if (gl_reg_write(devh, FREQUENCY_REG1, reg0) < 0)
246                 return -1; // 10 / 0.2
247
248         if (gl_reg_write(devh, FREQUENCY_REG2, 0x02) < 0)
249                 return -1; // always 2
250
251         if (gl_reg_write(devh, FREQUENCY_REG4, reg2) < 0)
252                 return -1;
253
254         return 0;
255 }
256
257 static void __analyzer_set_ramsize_trigger_address(libusb_device_handle *devh, unsigned int address)
258 {
259         gl_reg_write(devh, RAMSIZE_TRIGGERBAR_ADDRESS0, (address >>  0) & 0xFF);
260         gl_reg_write(devh, RAMSIZE_TRIGGERBAR_ADDRESS1, (address >>  8) & 0xFF);
261         gl_reg_write(devh, RAMSIZE_TRIGGERBAR_ADDRESS2, (address >> 16) & 0xFF);
262 }
263
264 static void __analyzer_set_triggerbar_address(libusb_device_handle *devh, unsigned int address)
265 {
266         gl_reg_write(devh, TRIGGERBAR_ADDRESS0, (address >>  0) & 0xFF);
267         gl_reg_write(devh, TRIGGERBAR_ADDRESS1, (address >>  8) & 0xFF);
268         gl_reg_write(devh, TRIGGERBAR_ADDRESS2, (address >> 16) & 0xFF);
269 }
270
271 static void __analyzer_set_compression(libusb_device_handle *devh, unsigned int type)
272 {
273         gl_reg_write(devh, COMPRESSION_TYPE0, (type >> 0) & 0xFF);
274         gl_reg_write(devh, COMPRESSION_TYPE1, (type >> 8) & 0xFF);
275 }
276
277 static void __analyzer_set_trigger_count(libusb_device_handle *devh, unsigned int count)
278 {
279         gl_reg_write(devh, TRIGGER_COUNT0, (count >> 0) & 0xFF);
280         gl_reg_write(devh, TRIGGER_COUNT1, (count >> 8) & 0xFF);
281 }
282
283 static void analyzer_write_enable_insert_data(libusb_device_handle *devh)
284 {
285         gl_reg_write(devh, ENABLE_INSERT_DATA0, 0x12);
286         gl_reg_write(devh, ENABLE_INSERT_DATA1, 0x34);
287         gl_reg_write(devh, ENABLE_INSERT_DATA2, 0x56);
288         gl_reg_write(devh, ENABLE_INSERT_DATA3, 0x78);
289 }
290
291 static void analyzer_set_filter(libusb_device_handle *devh)
292 {
293         int i;
294         gl_reg_write(devh, FILTER_ENABLE, g_filter_enable);
295         for (i = 0; i < 8; i++)
296                 gl_reg_write(devh, FILTER_STATUS + i, g_filter_status[i]);
297 }
298
299 void analyzer_reset(libusb_device_handle *devh)
300 {
301         analyzer_write_status(devh, 3, STATUS_FLAG_NONE); // reset device
302         analyzer_write_status(devh, 3, STATUS_FLAG_RESET); // reset device
303 }
304
305 void analyzer_initialize(libusb_device_handle *devh)
306 {
307         analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
308         analyzer_write_status(devh, 1, STATUS_FLAG_INIT);
309         analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
310 }
311
312 void analyzer_wait(libusb_device_handle *devh, int set, int unset)
313 {
314         int status;
315         while(1) {
316                 status = gl_reg_read(devh, DEVICE_STATUS);
317                 if ((status & set) && ((status & unset) == 0))
318                         return;
319         }
320 }
321
322 void analyzer_read_start(libusb_device_handle *devh)
323 {
324         int i;
325
326         analyzer_write_status(devh, 3, STATUS_FLAG_20 | STATUS_FLAG_READ);
327
328         for (i = 0; i < 8; i++)
329                 (void)gl_reg_read(devh, READ_RAM_STATUS);
330 }
331
332 int analyzer_read_data(libusb_device_handle *devh, void *buffer, unsigned int size)
333 {
334         return gl_read_bulk(devh, buffer, size);
335 }
336
337 void analyzer_read_stop(libusb_device_handle *devh)
338 {
339         analyzer_write_status(devh, 3, STATUS_FLAG_20);
340         analyzer_write_status(devh, 3, STATUS_FLAG_NONE);
341 }
342
343 void analyzer_start(libusb_device_handle *devh)
344 {
345         analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
346         analyzer_write_status(devh, 1, STATUS_FLAG_INIT);
347         analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
348         analyzer_write_status(devh, 1, STATUS_FLAG_GO);
349 }
350
351 void analyzer_configure(libusb_device_handle *devh)
352 {
353         // Write_Start_Status
354         analyzer_write_status(devh, 1, STATUS_FLAG_RESET);
355         analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
356
357         // Start_Config_Outside_Device ?
358         analyzer_write_status(devh, 1, STATUS_FLAG_INIT);
359         analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
360
361         //SetData_To_Frequence_Reg
362         __analyzer_set_freq(devh, g_freq_value, g_freq_scale);
363
364         //SetMemory_Length
365         gl_reg_write(devh, MEMORY_LENGTH, g_memory_size);
366
367         //Sele_Inside_Outside_Clock
368         gl_reg_write(devh, CLOCK_SOURCE, 0x03);
369
370         //Set_Trigger_Status
371         int i;
372         for (i = 0; i < 9; i++)
373                 gl_reg_write(devh, TRIGGER_STATUS0 + i, g_trigger_status[i]);
374
375         __analyzer_set_trigger_count(devh, g_trigger_count);
376
377         //Set_Trigger_Level
378         gl_reg_write(devh, TRIGGER_LEVEL0, 0x31);
379         gl_reg_write(devh, TRIGGER_LEVEL1, 0x31);
380         gl_reg_write(devh, TRIGGER_LEVEL2, 0x31);
381         gl_reg_write(devh, TRIGGER_LEVEL3, 0x31);
382
383         __analyzer_set_ramsize_trigger_address(devh, g_ramsize_triggerbar_addr); // size of actual memory >> 2
384         __analyzer_set_triggerbar_address(devh, g_triggerbar_addr);
385
386         //Set_Dont_Care_TriggerBar
387         gl_reg_write(devh, DONT_CARE_TRIGGERBAR, 0x01);
388
389         //Enable_Status
390         analyzer_set_filter(devh);
391
392         //Set_Enable_Delay_Time
393         gl_reg_write(devh, 0x7a, 0x00);
394         gl_reg_write(devh, 0x7b, 0x00);
395         analyzer_write_enable_insert_data(devh);
396         __analyzer_set_compression(devh,g_compression);
397 }
398
399 void analyzer_add_trigger(int channel, int type)
400 {
401         if ((channel & 0xf) >= 8)
402                 return;
403
404         if (type == TRIGGER_HIGH || type == TRIGGER_LOW) {
405                 int i;
406                 if (channel & CHANNEL_A)
407                         i = 0;
408                 else if (channel & CHANNEL_B)
409                         i = 2;
410                 else if (channel & CHANNEL_C)
411                         i = 4;
412                 else if (channel & CHANNEL_D)
413                         i = 6;
414                 else
415                         return;
416                 if ((channel & 0xf) >= 4) {
417                         i++;
418                         channel -= 4;
419                 }
420                 g_trigger_status[i] |= 1 << ((2 * channel) + (type == TRIGGER_LOW ? 1 : 0));
421         } else {
422                 if (type == TRIGGER_POSEDGE)
423                         g_trigger_status[8] = 0x40;
424                 else if(type == TRIGGER_NEGEDGE)
425                         g_trigger_status[8] = 0x80;
426                 else
427                         g_trigger_status[8] = 0xc0;
428
429                 // FIXME: just guessed the index; need to verify
430                 if (channel & CHANNEL_B)
431                         g_trigger_status[8] += 8;
432                 else if (channel & CHANNEL_C)
433                         g_trigger_status[8] += 16;
434                 else if (channel & CHANNEL_D)
435                         g_trigger_status[8] += 24;
436                 g_trigger_status[8] += channel % 8;
437         }
438 }
439
440 void analyzer_add_filter(int channel, int type)
441 {
442         if (type != FILTER_HIGH && type != FILTER_LOW)
443                 return;
444         if ((channel & 0xf) >= 8)
445                 return;
446
447         int i;
448         if (channel & CHANNEL_A)
449                 i = 0;
450         else if (channel & CHANNEL_B)
451                 i = 2;
452         else if (channel & CHANNEL_C)
453                 i = 4;
454         else if (channel & CHANNEL_D)
455                 i = 6;
456         else
457                 return;
458         if ((channel & 0xf) >= 4) {
459                 i++;
460                 channel -= 4;
461         }
462         g_filter_status[i] |= 1 << ((2 * channel) + (type == FILTER_LOW ? 1 : 0));
463         g_filter_enable = 1;
464 }
465
466 void analyzer_set_trigger_count(int count)
467 {
468         g_trigger_count = count;
469 }
470
471 void analyzer_set_freq(int freq, int scale)
472 {
473         g_freq_value = freq;
474         g_freq_scale = scale;
475 }
476
477 void analyzer_set_memory_size(unsigned int size)
478 {
479         g_memory_size = size;
480 }
481
482
483 void analyzer_set_ramsize_trigger_address(unsigned int address)
484 {
485         g_ramsize_triggerbar_addr = address;
486 }
487
488 void analyzer_set_triggerbar_address(unsigned int address)
489 {
490         g_triggerbar_addr = address;
491 }
492
493 unsigned int analyzer_read_id(libusb_device_handle *devh)
494 {
495         return gl_reg_read(devh, DEVICE_ID1) << 8 | gl_reg_read(devh, DEVICE_ID0);
496 }
497
498 unsigned int analyzer_get_stop_address(libusb_device_handle *devh)
499 {
500         return gl_reg_read(devh, STOP_ADDRESS2) << 16 | gl_reg_read(devh, STOP_ADDRESS1) << 8 | gl_reg_read(devh, STOP_ADDRESS0);
501 }
502
503 unsigned int analyzer_get_now_address(libusb_device_handle *devh)
504 {
505         return gl_reg_read(devh, NOW_ADDRESS2) << 16 | gl_reg_read(devh, NOW_ADDRESS1) << 8 | gl_reg_read(devh, NOW_ADDRESS0);
506 }
507
508 unsigned int analyzer_get_trigger_address(libusb_device_handle *devh)
509 {
510         return gl_reg_read(devh, TRIGGER_ADDRESS2) << 16 | gl_reg_read(devh, TRIGGER_ADDRESS1) << 8 | gl_reg_read(devh, TRIGGER_ADDRESS0);
511 }
512
513 void analyzer_set_compression(unsigned int type)
514 {
515         g_compression = type;
516 }
517
518 void analyzer_wait_button(libusb_device_handle *devh)
519 {
520         analyzer_wait(devh, STATUS_BUTTON_PRESSED, 0);
521 }
522
523 void analyzer_wait_data(libusb_device_handle *devh)
524 {
525         analyzer_wait(devh, STATUS_READY | 8, STATUS_BUSY);
526 }
527
528 int analyzer_decompress(void *input, unsigned int input_len, void *output, unsigned int output_len)
529 {
530         unsigned char *in = input;
531         unsigned char *out = output;
532         unsigned int A, B, C, count;
533         unsigned int written = 0;
534
535         while (input_len > 0) {
536                 A = *in++;
537                 B = *in++;
538                 C = *in++;
539                 count = (*in++) + 1;
540
541                 if (count > output_len)
542                         count = output_len;
543                 output_len -= count;
544                 written += count;
545
546                 while (count--) {
547                         *out++ = A;
548                         *out++ = B;
549                         *out++ = C;
550                         *out++ = 0; // channel D
551                 }
552
553                 input_len -= 4;
554                 if (output_len == 0)
555                         break;
556         }
557
558         return written;
559 }