]>
Commit | Line | Data |
---|---|---|
c463dcf0 MC |
1 | /* |
2 | * This file is part of the libsigrok project. | |
3 | * | |
4 | * Copyright (C) 2013 Marcus Comstedt <marcus@mc.pp.se> | |
fec7aa6a MC |
5 | * Copyright (C) 2013 Bert Vermeulen <bert@biot.com> |
6 | * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk> | |
c463dcf0 MC |
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 | ||
15abcf0f MC |
22 | #include <stdint.h> |
23 | #include <string.h> | |
24 | #include <glib.h> | |
25 | #include <glib/gstdio.h> | |
26 | #include <stdio.h> | |
27 | #include <errno.h> | |
28 | #include <math.h> | |
29 | #include "libsigrok.h" | |
30 | #include "libsigrok-internal.h" | |
515ab088 | 31 | #include "protocol.h" |
15abcf0f MC |
32 | |
33 | #define FPGA_FIRMWARE_18 FIRMWARE_DIR"/saleae-logic16-fpga-18.bitstream" | |
34 | #define FPGA_FIRMWARE_33 FIRMWARE_DIR"/saleae-logic16-fpga-33.bitstream" | |
35 | ||
7b5daad4 MC |
36 | #define MAX_SAMPLE_RATE SR_MHZ(100) |
37 | #define MAX_4CH_SAMPLE_RATE SR_MHZ(50) | |
38 | #define MAX_7CH_SAMPLE_RATE SR_MHZ(40) | |
39 | #define MAX_8CH_SAMPLE_RATE SR_MHZ(32) | |
40 | #define MAX_10CH_SAMPLE_RATE SR_MHZ(25) | |
41 | #define MAX_13CH_SAMPLE_RATE SR_MHZ(16) | |
42 | ||
43 | #define BASE_CLOCK_0_FREQ SR_MHZ(100) | |
44 | #define BASE_CLOCK_1_FREQ SR_MHZ(160) | |
45 | ||
15abcf0f MC |
46 | #define COMMAND_START_ACQUISITION 1 |
47 | #define COMMAND_ABORT_ACQUISITION_ASYNC 2 | |
48 | #define COMMAND_WRITE_EEPROM 6 | |
49 | #define COMMAND_READ_EEPROM 7 | |
50 | #define COMMAND_WRITE_LED_TABLE 0x7a | |
51 | #define COMMAND_SET_LED_MODE 0x7b | |
52 | #define COMMAND_RETURN_TO_BOOTLOADER 0x7c | |
53 | #define COMMAND_ABORT_ACQUISITION_SYNC 0x7d | |
54 | #define COMMAND_FPGA_UPLOAD_INIT 0x7e | |
55 | #define COMMAND_FPGA_UPLOAD_SEND_DATA 0x7f | |
56 | #define COMMAND_FPGA_WRITE_REGISTER 0x80 | |
57 | #define COMMAND_FPGA_READ_REGISTER 0x81 | |
58 | #define COMMAND_GET_REVID 0x82 | |
59 | ||
60 | #define WRITE_EEPROM_COOKIE1 0x42 | |
61 | #define WRITE_EEPROM_COOKIE2 0x55 | |
62 | #define READ_EEPROM_COOKIE1 0x33 | |
63 | #define READ_EEPROM_COOKIE2 0x81 | |
64 | #define ABORT_ACQUISITION_SYNC_PATTERN 0x55 | |
65 | ||
7b5daad4 MC |
66 | #define MAX_EMPTY_TRANSFERS 64 |
67 | ||
15abcf0f MC |
68 | static void encrypt(uint8_t *dest, const uint8_t *src, uint8_t cnt) |
69 | { | |
70 | uint8_t state1 = 0x9b, state2 = 0x54; | |
96484e22 | 71 | uint8_t t, v; |
15abcf0f MC |
72 | int i; |
73 | ||
96484e22 UH |
74 | for (i = 0; i < cnt; i++) { |
75 | v = src[i]; | |
15abcf0f MC |
76 | t = (((v ^ state2 ^ 0x2b) - 0x05) ^ 0x35) - 0x39; |
77 | t = (((t ^ state1 ^ 0x5a) - 0xb0) ^ 0x38) - 0x45; | |
78 | dest[i] = state2 = t; | |
79 | state1 = v; | |
80 | } | |
81 | } | |
82 | ||
83 | static void decrypt(uint8_t *dest, const uint8_t *src, uint8_t cnt) | |
84 | { | |
85 | uint8_t state1 = 0x9b, state2 = 0x54; | |
96484e22 | 86 | uint8_t t, v; |
15abcf0f | 87 | int i; |
96484e22 UH |
88 | |
89 | for (i = 0; i < cnt; i++) { | |
90 | v = src[i]; | |
15abcf0f MC |
91 | t = (((v + 0x45) ^ 0x38) + 0xb0) ^ 0x5a ^ state1; |
92 | t = (((t + 0x39) ^ 0x35) + 0x05) ^ 0x2b ^ state2; | |
93 | dest[i] = state1 = t; | |
94 | state2 = v; | |
95 | } | |
96 | } | |
97 | ||
98 | static int do_ep1_command(const struct sr_dev_inst *sdi, | |
99 | const uint8_t *command, uint8_t cmd_len, | |
100 | uint8_t *reply, uint8_t reply_len) | |
101 | { | |
102 | uint8_t buf[64]; | |
103 | struct sr_usb_dev_inst *usb; | |
104 | int ret, xfer; | |
105 | ||
106 | usb = sdi->conn; | |
107 | ||
108 | if (cmd_len < 1 || cmd_len > 64 || reply_len > 64 || | |
98fec29e | 109 | !command || (reply_len > 0 && !reply)) |
15abcf0f MC |
110 | return SR_ERR_ARG; |
111 | ||
112 | encrypt(buf, command, cmd_len); | |
113 | ||
114 | ret = libusb_bulk_transfer(usb->devhdl, 1, buf, cmd_len, &xfer, 1000); | |
115 | if (ret != 0) { | |
96484e22 | 116 | sr_dbg("Failed to send EP1 command 0x%02x: %s.", |
15abcf0f MC |
117 | command[0], libusb_error_name(ret)); |
118 | return SR_ERR; | |
119 | } | |
120 | if (xfer != cmd_len) { | |
96484e22 UH |
121 | sr_dbg("Failed to send EP1 command 0x%02x: incorrect length " |
122 | "%d != %d.", xfer, cmd_len); | |
15abcf0f MC |
123 | return SR_ERR; |
124 | } | |
125 | ||
126 | if (reply_len == 0) | |
127 | return SR_OK; | |
128 | ||
96484e22 UH |
129 | ret = libusb_bulk_transfer(usb->devhdl, 0x80 | 1, buf, reply_len, |
130 | &xfer, 1000); | |
15abcf0f | 131 | if (ret != 0) { |
96484e22 | 132 | sr_dbg("Failed to receive reply to EP1 command 0x%02x: %s.", |
15abcf0f MC |
133 | command[0], libusb_error_name(ret)); |
134 | return SR_ERR; | |
135 | } | |
136 | if (xfer != reply_len) { | |
96484e22 UH |
137 | sr_dbg("Failed to receive reply to EP1 command 0x%02x: " |
138 | "incorrect length %d != %d.", xfer, reply_len); | |
15abcf0f MC |
139 | return SR_ERR; |
140 | } | |
141 | ||
142 | decrypt(reply, buf, reply_len); | |
143 | ||
144 | return SR_OK; | |
145 | } | |
146 | ||
147 | static int read_eeprom(const struct sr_dev_inst *sdi, | |
148 | uint8_t address, uint8_t length, uint8_t *buf) | |
149 | { | |
150 | uint8_t command[5] = { | |
151 | COMMAND_READ_EEPROM, | |
152 | READ_EEPROM_COOKIE1, | |
153 | READ_EEPROM_COOKIE2, | |
154 | address, | |
155 | length, | |
156 | }; | |
157 | ||
158 | return do_ep1_command(sdi, command, 5, buf, length); | |
159 | } | |
160 | ||
161 | static int upload_led_table(const struct sr_dev_inst *sdi, | |
162 | const uint8_t *table, uint8_t offset, uint8_t cnt) | |
163 | { | |
96484e22 | 164 | uint8_t chunk, command[64]; |
15abcf0f MC |
165 | int ret; |
166 | ||
98fec29e | 167 | if (cnt < 1 || cnt + offset > 64 || !table) |
15abcf0f MC |
168 | return SR_ERR_ARG; |
169 | ||
170 | while (cnt > 0) { | |
96484e22 | 171 | chunk = (cnt > 32 ? 32 : cnt); |
15abcf0f MC |
172 | |
173 | command[0] = COMMAND_WRITE_LED_TABLE; | |
174 | command[1] = offset; | |
175 | command[2] = chunk; | |
96484e22 | 176 | memcpy(command + 3, table, chunk); |
15abcf0f | 177 | |
96484e22 UH |
178 | ret = do_ep1_command(sdi, command, 3 + chunk, NULL, 0); |
179 | if (ret != SR_OK) | |
15abcf0f MC |
180 | return ret; |
181 | ||
182 | table += chunk; | |
183 | offset += chunk; | |
184 | cnt -= chunk; | |
185 | } | |
186 | ||
187 | return SR_OK; | |
188 | } | |
189 | ||
190 | static int set_led_mode(const struct sr_dev_inst *sdi, | |
191 | uint8_t animate, uint16_t t2reload, uint8_t div, | |
192 | uint8_t repeat) | |
193 | { | |
194 | uint8_t command[6] = { | |
195 | COMMAND_SET_LED_MODE, | |
196 | animate, | |
96484e22 UH |
197 | t2reload & 0xff, |
198 | t2reload >> 8, | |
15abcf0f MC |
199 | div, |
200 | repeat, | |
201 | }; | |
202 | ||
203 | return do_ep1_command(sdi, command, 6, NULL, 0); | |
204 | } | |
205 | ||
206 | static int read_fpga_register(const struct sr_dev_inst *sdi, | |
207 | uint8_t address, uint8_t *value) | |
208 | { | |
209 | uint8_t command[3] = { | |
210 | COMMAND_FPGA_READ_REGISTER, | |
211 | 1, | |
212 | address, | |
213 | }; | |
214 | ||
215 | return do_ep1_command(sdi, command, 3, value, 1); | |
216 | } | |
217 | ||
218 | static int write_fpga_registers(const struct sr_dev_inst *sdi, | |
219 | uint8_t (*regs)[2], uint8_t cnt) | |
220 | { | |
221 | uint8_t command[64]; | |
222 | int i; | |
223 | ||
224 | if (cnt < 1 || cnt > 31) | |
225 | return SR_ERR_ARG; | |
226 | ||
227 | command[0] = COMMAND_FPGA_WRITE_REGISTER; | |
228 | command[1] = cnt; | |
96484e22 UH |
229 | for (i = 0; i < cnt; i++) { |
230 | command[2 + 2 * i] = regs[i][0]; | |
231 | command[3 + 2 * i] = regs[i][1]; | |
15abcf0f MC |
232 | } |
233 | ||
96484e22 | 234 | return do_ep1_command(sdi, command, 2 * (cnt + 1), NULL, 0); |
15abcf0f MC |
235 | } |
236 | ||
237 | static int write_fpga_register(const struct sr_dev_inst *sdi, | |
238 | uint8_t address, uint8_t value) | |
239 | { | |
240 | uint8_t regs[2] = { address, value }; | |
96484e22 | 241 | |
15abcf0f MC |
242 | return write_fpga_registers(sdi, ®s, 1); |
243 | } | |
244 | ||
15abcf0f MC |
245 | static uint8_t map_eeprom_data(uint8_t v) |
246 | { | |
186dde8d | 247 | return (((v ^ 0x80) + 0x44) ^ 0xd5) + 0x69; |
15abcf0f MC |
248 | } |
249 | ||
250 | static int prime_fpga(const struct sr_dev_inst *sdi) | |
251 | { | |
252 | uint8_t eeprom_data[16]; | |
186dde8d | 253 | uint8_t old_reg_10, version; |
15abcf0f MC |
254 | uint8_t regs[8][2] = { |
255 | {10, 0x00}, | |
256 | {10, 0x40}, | |
257 | {12, 0}, | |
258 | {10, 0xc0}, | |
259 | {10, 0x40}, | |
96484e22 UH |
260 | {6, 0}, |
261 | {7, 1}, | |
262 | {7, 0} | |
15abcf0f MC |
263 | }; |
264 | int i, ret; | |
265 | ||
266 | if ((ret = read_eeprom(sdi, 16, 16, eeprom_data)) != SR_OK) | |
267 | return ret; | |
268 | ||
269 | if ((ret = read_fpga_register(sdi, 10, &old_reg_10)) != SR_OK) | |
270 | return ret; | |
271 | ||
186dde8d MC |
272 | regs[0][1] = (old_reg_10 &= 0x7f); |
273 | regs[1][1] |= old_reg_10; | |
274 | regs[3][1] |= old_reg_10; | |
275 | regs[4][1] |= old_reg_10; | |
276 | ||
96484e22 | 277 | for (i = 0; i < 16; i++) { |
15abcf0f MC |
278 | regs[2][1] = eeprom_data[i]; |
279 | regs[5][1] = map_eeprom_data(eeprom_data[i]); | |
280 | if (i) | |
281 | ret = write_fpga_registers(sdi, ®s[2], 6); | |
282 | else | |
283 | ret = write_fpga_registers(sdi, ®s[0], 8); | |
284 | if (ret != SR_OK) | |
285 | return ret; | |
286 | } | |
287 | ||
288 | if ((ret = write_fpga_register(sdi, 10, old_reg_10)) != SR_OK) | |
289 | return ret; | |
290 | ||
186dde8d | 291 | if ((ret = read_fpga_register(sdi, 0, &version)) != SR_OK) |
15abcf0f MC |
292 | return ret; |
293 | ||
6f479a0a PZ |
294 | if (version != 0x10 && version != 0x40 && version != 0x41) { |
295 | sr_err("Unsupported FPGA version: 0x%02x.", version); | |
15abcf0f MC |
296 | return SR_ERR; |
297 | } | |
298 | ||
299 | return SR_OK; | |
300 | } | |
301 | ||
302 | static void make_heartbeat(uint8_t *table, int len) | |
303 | { | |
304 | int i, j; | |
305 | ||
306 | memset(table, 0, len); | |
307 | len >>= 3; | |
96484e22 UH |
308 | for (i = 0; i < 2; i++) |
309 | for (j = 0; j < len; j++) | |
310 | *table++ = sin(j * M_PI / len) * 255; | |
15abcf0f MC |
311 | } |
312 | ||
313 | static int configure_led(const struct sr_dev_inst *sdi) | |
314 | { | |
315 | uint8_t table[64]; | |
316 | int ret; | |
317 | ||
318 | make_heartbeat(table, 64); | |
319 | if ((ret = upload_led_table(sdi, table, 0, 64)) != SR_OK) | |
320 | return ret; | |
321 | ||
322 | return set_led_mode(sdi, 1, 6250, 0, 1); | |
323 | } | |
324 | ||
325 | static int upload_fpga_bitstream(const struct sr_dev_inst *sdi, | |
326 | enum voltage_range vrange) | |
327 | { | |
328 | struct dev_context *devc; | |
329 | int offset, chunksize, ret; | |
330 | const char *filename; | |
96484e22 | 331 | uint8_t len, buf[256 * 62], command[64]; |
15abcf0f | 332 | FILE *fw; |
15abcf0f MC |
333 | |
334 | devc = sdi->priv; | |
335 | ||
336 | if (devc->cur_voltage_range == vrange) | |
337 | return SR_OK; | |
338 | ||
6f479a0a PZ |
339 | if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL) { |
340 | switch (vrange) { | |
341 | case VOLTAGE_RANGE_18_33_V: | |
342 | filename = FPGA_FIRMWARE_18; | |
343 | break; | |
344 | case VOLTAGE_RANGE_5_V: | |
345 | filename = FPGA_FIRMWARE_33; | |
346 | break; | |
347 | default: | |
348 | sr_err("Unsupported voltage range."); | |
349 | return SR_ERR; | |
350 | } | |
15abcf0f | 351 | |
6f479a0a | 352 | sr_info("Uploading FPGA bitstream at %s.", filename); |
98fec29e | 353 | if (!(fw = g_fopen(filename, "rb"))) { |
6f479a0a PZ |
354 | sr_err("Unable to open bitstream file %s for reading: %s.", |
355 | filename, strerror(errno)); | |
356 | return SR_ERR; | |
357 | } | |
15abcf0f | 358 | |
6f479a0a PZ |
359 | buf[0] = COMMAND_FPGA_UPLOAD_INIT; |
360 | if ((ret = do_ep1_command(sdi, buf, 1, NULL, 0)) != SR_OK) { | |
361 | fclose(fw); | |
362 | return ret; | |
363 | } | |
15abcf0f | 364 | |
6f479a0a PZ |
365 | while (1) { |
366 | chunksize = fread(buf, 1, sizeof(buf), fw); | |
367 | if (chunksize == 0) | |
368 | break; | |
369 | ||
370 | for (offset = 0; offset < chunksize; offset += 62) { | |
371 | len = (offset + 62 > chunksize ? | |
372 | chunksize - offset : 62); | |
373 | command[0] = COMMAND_FPGA_UPLOAD_SEND_DATA; | |
374 | command[1] = len; | |
375 | memcpy(command + 2, buf + offset, len); | |
376 | ret = do_ep1_command(sdi, command, len + 2, NULL, 0); | |
377 | if (ret != SR_OK) { | |
378 | fclose(fw); | |
379 | return ret; | |
380 | } | |
15abcf0f | 381 | } |
15abcf0f | 382 | |
6f479a0a PZ |
383 | sr_info("Uploaded %d bytes.", chunksize); |
384 | } | |
385 | fclose(fw); | |
386 | sr_info("FPGA bitstream upload done."); | |
15abcf0f | 387 | } |
15abcf0f MC |
388 | |
389 | if ((ret = prime_fpga(sdi)) != SR_OK) | |
390 | return ret; | |
391 | ||
392 | if ((ret = configure_led(sdi)) != SR_OK) | |
393 | return ret; | |
394 | ||
15abcf0f MC |
395 | devc->cur_voltage_range = vrange; |
396 | return SR_OK; | |
397 | } | |
398 | ||
7b5daad4 | 399 | static int abort_acquisition_sync(const struct sr_dev_inst *sdi) |
15abcf0f MC |
400 | { |
401 | static const uint8_t command[2] = { | |
402 | COMMAND_ABORT_ACQUISITION_SYNC, | |
403 | ABORT_ACQUISITION_SYNC_PATTERN, | |
404 | }; | |
405 | uint8_t reply, expected_reply; | |
406 | int ret; | |
407 | ||
408 | if ((ret = do_ep1_command(sdi, command, 2, &reply, 1)) != SR_OK) | |
409 | return ret; | |
410 | ||
411 | expected_reply = ~command[1]; | |
412 | if (reply != expected_reply) { | |
413 | sr_err("Invalid response for abort acquisition command: " | |
96484e22 | 414 | "0x%02x != 0x%02x.", reply, expected_reply); |
15abcf0f MC |
415 | return SR_ERR; |
416 | } | |
417 | ||
418 | return SR_OK; | |
419 | } | |
420 | ||
96484e22 UH |
421 | SR_PRIV int logic16_setup_acquisition(const struct sr_dev_inst *sdi, |
422 | uint64_t samplerate, uint16_t channels) | |
7b5daad4 MC |
423 | { |
424 | uint8_t clock_select, reg1, reg10; | |
425 | uint64_t div; | |
426 | int i, ret, nchan = 0; | |
db11d7d2 MC |
427 | struct dev_context *devc; |
428 | ||
429 | devc = sdi->priv; | |
7b5daad4 MC |
430 | |
431 | if (samplerate == 0 || samplerate > MAX_SAMPLE_RATE) { | |
432 | sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate); | |
433 | return SR_ERR; | |
434 | } | |
435 | ||
436 | if (BASE_CLOCK_0_FREQ % samplerate == 0 && | |
437 | (div = BASE_CLOCK_0_FREQ / samplerate) <= 256) { | |
438 | clock_select = 0; | |
439 | } else if (BASE_CLOCK_1_FREQ % samplerate == 0 && | |
440 | (div = BASE_CLOCK_1_FREQ / samplerate) <= 256) { | |
441 | clock_select = 1; | |
442 | } else { | |
443 | sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate); | |
444 | return SR_ERR; | |
445 | } | |
446 | ||
96484e22 UH |
447 | for (i = 0; i < 16; i++) |
448 | if (channels & (1U << i)) | |
7b5daad4 MC |
449 | nchan++; |
450 | ||
451 | if ((nchan >= 13 && samplerate > MAX_13CH_SAMPLE_RATE) || | |
452 | (nchan >= 10 && samplerate > MAX_10CH_SAMPLE_RATE) || | |
453 | (nchan >= 8 && samplerate > MAX_8CH_SAMPLE_RATE) || | |
454 | (nchan >= 7 && samplerate > MAX_7CH_SAMPLE_RATE) || | |
455 | (nchan >= 4 && samplerate > MAX_4CH_SAMPLE_RATE)) { | |
456 | sr_err("Unable to sample at %" PRIu64 "Hz " | |
457 | "with this many channels.", samplerate); | |
458 | return SR_ERR; | |
459 | } | |
460 | ||
96484e22 UH |
461 | ret = upload_fpga_bitstream(sdi, devc->selected_voltage_range); |
462 | if (ret != SR_OK) | |
db11d7d2 MC |
463 | return ret; |
464 | ||
7b5daad4 MC |
465 | if ((ret = read_fpga_register(sdi, 1, ®1)) != SR_OK) |
466 | return ret; | |
467 | ||
7754fb4d MC |
468 | /* Ignore FIFO overflow on previous capture */ |
469 | reg1 &= ~0x20; | |
470 | ||
6f479a0a | 471 | if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 != 0x08) { |
a11e10ec UH |
472 | sr_dbg("Invalid state at acquisition setup register 1: 0x%02x != 0x08. " |
473 | "Proceeding anyway.", reg1); | |
7b5daad4 MC |
474 | } |
475 | ||
476 | if ((ret = write_fpga_register(sdi, 1, 0x40)) != SR_OK) | |
477 | return ret; | |
478 | ||
479 | if ((ret = write_fpga_register(sdi, 10, clock_select)) != SR_OK) | |
480 | return ret; | |
481 | ||
96484e22 | 482 | if ((ret = write_fpga_register(sdi, 4, (uint8_t)(div - 1))) != SR_OK) |
7b5daad4 MC |
483 | return ret; |
484 | ||
485 | if ((ret = write_fpga_register(sdi, 2, (uint8_t)(channels & 0xff))) != SR_OK) | |
486 | return ret; | |
487 | ||
488 | if ((ret = write_fpga_register(sdi, 3, (uint8_t)(channels >> 8))) != SR_OK) | |
489 | return ret; | |
490 | ||
491 | if ((ret = write_fpga_register(sdi, 1, 0x42)) != SR_OK) | |
492 | return ret; | |
493 | ||
494 | if ((ret = write_fpga_register(sdi, 1, 0x40)) != SR_OK) | |
495 | return ret; | |
496 | ||
497 | if ((ret = read_fpga_register(sdi, 1, ®1)) != SR_OK) | |
498 | return ret; | |
499 | ||
6f479a0a | 500 | if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 != 0x48) { |
5cfcab66 | 501 | sr_dbg("Invalid state at acquisition setup register 1: 0x%02x != 0x48. " |
cd3c4df3 | 502 | "Proceeding anyway.", reg1); |
7b5daad4 MC |
503 | } |
504 | ||
505 | if ((ret = read_fpga_register(sdi, 10, ®10)) != SR_OK) | |
506 | return ret; | |
507 | ||
6f479a0a | 508 | if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg10 != clock_select) { |
a11e10ec UH |
509 | sr_dbg("Invalid state at acquisition setup register 10: 0x%02x != 0x%02x. " |
510 | "Proceeding anyway.", reg10, clock_select); | |
7b5daad4 MC |
511 | } |
512 | ||
513 | return SR_OK; | |
514 | } | |
515 | ||
96484e22 | 516 | SR_PRIV int logic16_start_acquisition(const struct sr_dev_inst *sdi) |
7b5daad4 MC |
517 | { |
518 | static const uint8_t command[1] = { | |
519 | COMMAND_START_ACQUISITION, | |
520 | }; | |
521 | int ret; | |
522 | ||
523 | if ((ret = do_ep1_command(sdi, command, 1, NULL, 0)) != SR_OK) | |
524 | return ret; | |
525 | ||
526 | return write_fpga_register(sdi, 1, 0x41); | |
527 | } | |
528 | ||
96484e22 | 529 | SR_PRIV int logic16_abort_acquisition(const struct sr_dev_inst *sdi) |
7b5daad4 MC |
530 | { |
531 | static const uint8_t command[1] = { | |
532 | COMMAND_ABORT_ACQUISITION_ASYNC, | |
533 | }; | |
534 | int ret; | |
535 | uint8_t reg1, reg8, reg9; | |
6f479a0a PZ |
536 | struct dev_context *devc; |
537 | ||
538 | devc = sdi->priv; | |
7b5daad4 MC |
539 | |
540 | if ((ret = do_ep1_command(sdi, command, 1, NULL, 0)) != SR_OK) | |
541 | return ret; | |
542 | ||
543 | if ((ret = write_fpga_register(sdi, 1, 0x00)) != SR_OK) | |
544 | return ret; | |
545 | ||
546 | if ((ret = read_fpga_register(sdi, 1, ®1)) != SR_OK) | |
547 | return ret; | |
548 | ||
6f479a0a | 549 | if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && (reg1 & ~0x20) != 0x08) { |
7754fb4d | 550 | sr_dbg("Invalid state at acquisition stop: 0x%02x != 0x08.", reg1 & ~0x20); |
7b5daad4 MC |
551 | return SR_ERR; |
552 | } | |
553 | ||
554 | if ((ret = read_fpga_register(sdi, 8, ®8)) != SR_OK) | |
555 | return ret; | |
556 | ||
557 | if ((ret = read_fpga_register(sdi, 9, ®9)) != SR_OK) | |
558 | return ret; | |
559 | ||
6f479a0a | 560 | if (devc->fpga_variant == FPGA_VARIANT_ORIGINAL && reg1 & 0x20) { |
7754fb4d MC |
561 | sr_warn("FIFO overflow, capture data may be truncated."); |
562 | return SR_ERR; | |
563 | } | |
564 | ||
7b5daad4 MC |
565 | return SR_OK; |
566 | } | |
567 | ||
96484e22 | 568 | SR_PRIV int logic16_init_device(const struct sr_dev_inst *sdi) |
15abcf0f | 569 | { |
6f479a0a | 570 | uint8_t version; |
15abcf0f MC |
571 | struct dev_context *devc; |
572 | int ret; | |
573 | ||
574 | devc = sdi->priv; | |
575 | ||
576 | devc->cur_voltage_range = VOLTAGE_RANGE_UNKNOWN; | |
577 | ||
7b5daad4 | 578 | if ((ret = abort_acquisition_sync(sdi)) != SR_OK) |
15abcf0f MC |
579 | return ret; |
580 | ||
581 | if ((ret = read_eeprom(sdi, 8, 8, devc->eeprom_data)) != SR_OK) | |
582 | return ret; | |
583 | ||
6f479a0a PZ |
584 | /* mcupro Saleae16 has firmware pre-stored in FPGA. |
585 | So, we can query it right away. */ | |
586 | if (read_fpga_register(sdi, 0, &version) == SR_OK && | |
587 | (version == 0x40 || version == 0x41)) { | |
588 | sr_info("mcupro Saleae16 detected."); | |
589 | devc->fpga_variant = FPGA_VARIANT_MCUPRO; | |
590 | } else { | |
591 | sr_info("Original Saleae Logic16 detected."); | |
592 | devc->fpga_variant = FPGA_VARIANT_ORIGINAL; | |
593 | } | |
594 | ||
96484e22 UH |
595 | ret = upload_fpga_bitstream(sdi, devc->selected_voltage_range); |
596 | if (ret != SR_OK) | |
15abcf0f MC |
597 | return ret; |
598 | ||
599 | return SR_OK; | |
600 | } | |
601 | ||
102f1239 | 602 | static void finish_acquisition(struct sr_dev_inst *sdi) |
7b5daad4 MC |
603 | { |
604 | struct sr_datafeed_packet packet; | |
102f1239 BV |
605 | struct dev_context *devc; |
606 | ||
607 | devc = sdi->priv; | |
7b5daad4 MC |
608 | |
609 | /* Terminate session. */ | |
610 | packet.type = SR_DF_END; | |
611 | sr_session_send(devc->cb_data, &packet); | |
612 | ||
613 | /* Remove fds from polling. */ | |
102f1239 | 614 | usb_source_remove(sdi->session, devc->ctx); |
7b5daad4 MC |
615 | |
616 | devc->num_transfers = 0; | |
617 | g_free(devc->transfers); | |
618 | g_free(devc->convbuffer); | |
863357fb BV |
619 | if (devc->stl) { |
620 | soft_trigger_logic_free(devc->stl); | |
621 | devc->stl = NULL; | |
622 | } | |
7b5daad4 MC |
623 | } |
624 | ||
625 | static void free_transfer(struct libusb_transfer *transfer) | |
626 | { | |
102f1239 | 627 | struct sr_dev_inst *sdi; |
7b5daad4 MC |
628 | struct dev_context *devc; |
629 | unsigned int i; | |
630 | ||
102f1239 BV |
631 | sdi = transfer->user_data; |
632 | devc = sdi->priv; | |
7b5daad4 MC |
633 | |
634 | g_free(transfer->buffer); | |
635 | transfer->buffer = NULL; | |
636 | libusb_free_transfer(transfer); | |
637 | ||
638 | for (i = 0; i < devc->num_transfers; i++) { | |
639 | if (devc->transfers[i] == transfer) { | |
640 | devc->transfers[i] = NULL; | |
641 | break; | |
642 | } | |
643 | } | |
644 | ||
645 | devc->submitted_transfers--; | |
646 | if (devc->submitted_transfers == 0) | |
102f1239 | 647 | finish_acquisition(sdi); |
7b5daad4 MC |
648 | } |
649 | ||
650 | static void resubmit_transfer(struct libusb_transfer *transfer) | |
651 | { | |
652 | int ret; | |
653 | ||
654 | if ((ret = libusb_submit_transfer(transfer)) == LIBUSB_SUCCESS) | |
655 | return; | |
656 | ||
657 | free_transfer(transfer); | |
658 | /* TODO: Stop session? */ | |
659 | ||
660 | sr_err("%s: %s", __func__, libusb_error_name(ret)); | |
661 | } | |
662 | ||
a989cdbe BV |
663 | static size_t convert_sample_data(struct dev_context *devc, |
664 | uint8_t *dest, size_t destcnt, const uint8_t *src, size_t srccnt) | |
c463dcf0 | 665 | { |
7b5daad4 MC |
666 | uint16_t *channel_data; |
667 | int i, cur_channel; | |
668 | size_t ret = 0; | |
96484e22 | 669 | uint16_t sample, channel_mask; |
7b5daad4 MC |
670 | |
671 | srccnt /= 2; | |
672 | ||
673 | channel_data = devc->channel_data; | |
674 | cur_channel = devc->cur_channel; | |
675 | ||
96484e22 | 676 | while (srccnt--) { |
7b5daad4 MC |
677 | sample = src[0] | (src[1] << 8); |
678 | src += 2; | |
679 | ||
680 | channel_mask = devc->channel_masks[cur_channel]; | |
681 | ||
96484e22 | 682 | for (i = 15; i >= 0; --i, sample >>= 1) |
7b5daad4 MC |
683 | if (sample & 1) |
684 | channel_data[i] |= channel_mask; | |
685 | ||
686 | if (++cur_channel == devc->num_channels) { | |
687 | cur_channel = 0; | |
96484e22 | 688 | if (destcnt < 16 * 2) { |
7b5daad4 MC |
689 | sr_err("Conversion buffer too small!"); |
690 | break; | |
691 | } | |
96484e22 UH |
692 | memcpy(dest, channel_data, 16 * 2); |
693 | memset(channel_data, 0, 16 * 2); | |
694 | dest += 16 * 2; | |
1b822521 | 695 | ret += 16; |
96484e22 | 696 | destcnt -= 16 * 2; |
7b5daad4 MC |
697 | } |
698 | } | |
699 | ||
700 | devc->cur_channel = cur_channel; | |
c463dcf0 | 701 | |
7b5daad4 MC |
702 | return ret; |
703 | } | |
704 | ||
55462b8b | 705 | SR_PRIV void LIBUSB_CALL logic16_receive_transfer(struct libusb_transfer *transfer) |
7b5daad4 MC |
706 | { |
707 | gboolean packet_has_error = FALSE; | |
708 | struct sr_datafeed_packet packet; | |
709 | struct sr_datafeed_logic logic; | |
102f1239 | 710 | struct sr_dev_inst *sdi; |
c463dcf0 | 711 | struct dev_context *devc; |
863357fb BV |
712 | size_t new_samples, num_samples; |
713 | int trigger_offset; | |
5a971f66 | 714 | int pre_trigger_samples; |
7b5daad4 | 715 | |
102f1239 BV |
716 | sdi = transfer->user_data; |
717 | devc = sdi->priv; | |
7b5daad4 MC |
718 | |
719 | /* | |
720 | * If acquisition has already ended, just free any queued up | |
721 | * transfer that come in. | |
722 | */ | |
863357fb | 723 | if (devc->sent_samples < 0) { |
7b5daad4 MC |
724 | free_transfer(transfer); |
725 | return; | |
726 | } | |
727 | ||
974fb0ff BV |
728 | sr_info("receive_transfer(): status %s received %d bytes.", |
729 | libusb_error_name(transfer->status), transfer->actual_length); | |
7b5daad4 MC |
730 | |
731 | switch (transfer->status) { | |
732 | case LIBUSB_TRANSFER_NO_DEVICE: | |
863357fb | 733 | devc->sent_samples = -2; |
7b5daad4 MC |
734 | free_transfer(transfer); |
735 | return; | |
736 | case LIBUSB_TRANSFER_COMPLETED: | |
737 | case LIBUSB_TRANSFER_TIMED_OUT: /* We may have received some data though. */ | |
738 | break; | |
739 | default: | |
740 | packet_has_error = TRUE; | |
741 | break; | |
742 | } | |
c463dcf0 | 743 | |
7b5daad4 | 744 | if (transfer->actual_length & 1) { |
96484e22 UH |
745 | sr_err("Got an odd number of bytes from the device. " |
746 | "This should not happen."); | |
747 | /* Bail out right away. */ | |
7b5daad4 MC |
748 | packet_has_error = TRUE; |
749 | devc->empty_transfer_count = MAX_EMPTY_TRANSFERS; | |
750 | } | |
c463dcf0 | 751 | |
7b5daad4 MC |
752 | if (transfer->actual_length == 0 || packet_has_error) { |
753 | devc->empty_transfer_count++; | |
754 | if (devc->empty_transfer_count > MAX_EMPTY_TRANSFERS) { | |
755 | /* | |
756 | * The FX2 gave up. End the acquisition, the frontend | |
757 | * will work out that the samplecount is short. | |
758 | */ | |
863357fb | 759 | devc->sent_samples = -2; |
7b5daad4 MC |
760 | free_transfer(transfer); |
761 | } else { | |
762 | resubmit_transfer(transfer); | |
763 | } | |
764 | return; | |
765 | } else { | |
766 | devc->empty_transfer_count = 0; | |
767 | } | |
c463dcf0 | 768 | |
863357fb | 769 | new_samples = convert_sample_data(devc, devc->convbuffer, |
a989cdbe | 770 | devc->convbuffer_size, transfer->buffer, transfer->actual_length); |
863357fb BV |
771 | |
772 | if (new_samples > 0) { | |
773 | if (devc->trigger_fired) { | |
774 | /* Send the incoming transfer to the session bus. */ | |
775 | packet.type = SR_DF_LOGIC; | |
776 | packet.payload = &logic; | |
777 | if (devc->limit_samples && | |
778 | new_samples > devc->limit_samples - devc->sent_samples) | |
779 | new_samples = devc->limit_samples - devc->sent_samples; | |
a989cdbe BV |
780 | logic.length = new_samples * 2; |
781 | logic.unitsize = 2; | |
863357fb BV |
782 | logic.data = devc->convbuffer; |
783 | sr_session_send(devc->cb_data, &packet); | |
784 | devc->sent_samples += new_samples; | |
785 | } else { | |
786 | trigger_offset = soft_trigger_logic_check(devc->stl, | |
5a971f66 | 787 | devc->convbuffer, new_samples * 2, &pre_trigger_samples); |
863357fb | 788 | if (trigger_offset > -1) { |
5a971f66 | 789 | devc->sent_samples += pre_trigger_samples; |
863357fb BV |
790 | packet.type = SR_DF_LOGIC; |
791 | packet.payload = &logic; | |
792 | num_samples = new_samples - trigger_offset; | |
793 | if (devc->limit_samples && | |
794 | num_samples > devc->limit_samples - devc->sent_samples) | |
795 | num_samples = devc->limit_samples - devc->sent_samples; | |
a989cdbe BV |
796 | logic.length = num_samples * 2; |
797 | logic.unitsize = 2; | |
798 | logic.data = devc->convbuffer + trigger_offset * 2; | |
863357fb BV |
799 | sr_session_send(devc->cb_data, &packet); |
800 | devc->sent_samples += num_samples; | |
801 | ||
802 | devc->trigger_fired = TRUE; | |
803 | } | |
2db95906 MC |
804 | } |
805 | ||
7b5daad4 | 806 | if (devc->limit_samples && |
863357fb BV |
807 | (uint64_t)devc->sent_samples >= devc->limit_samples) { |
808 | devc->sent_samples = -2; | |
7b5daad4 MC |
809 | free_transfer(transfer); |
810 | return; | |
811 | } | |
c463dcf0 MC |
812 | } |
813 | ||
7b5daad4 | 814 | resubmit_transfer(transfer); |
c463dcf0 | 815 | } |