]> sigrok.org Git - libsigrok.git/blame - src/hardware/microchip-pickit2/protocol.c
microchip-pickit2: Minor cosmetics.
[libsigrok.git] / src / hardware / microchip-pickit2 / protocol.c
CommitLineData
a5c0259c
GS
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2018 Gerhard Sittig <gerhard.sittig@gmx.net>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <config.h>
bde6a99b 21#include <string.h>
a5c0259c
GS
22#include "protocol.h"
23
bde6a99b
GS
24#define PICKIT2_PACKET_LENGTH 64
25#define PICKIT2_USB_ENDPOINT 1
26#define PICKIT2_USB_TIMEOUT 250
27
28#define PICKIT2_CMD_CHKSTAT 0xa2
29#define PICKIT2_CMD_CHKVOLT 0xa3
30#define PICKIT2_CMD_READ 0xac
31#define PICKIT2_CMD_PADCHAR 0xad
32#define PICKIT2_CMD_SETUP 0xb8
33#define PICKIT2_CMD_SETPOS 0xb9
34
35#define PICKIT2_SEL_BANK0 0x06
36#define PICKIT2_SEL_BANK1 0x07
37
38struct pickit2_cmd {
39 size_t length;
40 uint8_t raw[PICKIT2_PACKET_LENGTH];
41};
42
43static void pickit2_cmd_clear(struct pickit2_cmd *cmd)
44{
bde6a99b
GS
45 if (!cmd)
46 return;
47 memset(&cmd->raw[0], PICKIT2_CMD_PADCHAR, PICKIT2_PACKET_LENGTH);
48 cmd->length = 0;
49}
50
51static void pickit2_cmd_append(struct pickit2_cmd *cmd, uint8_t b)
52{
bde6a99b
GS
53 if (!cmd)
54 return;
55 if (cmd->length == PICKIT2_PACKET_LENGTH)
56 return;
57 cmd->raw[cmd->length++] = b;
58}
59
60static int pickit2_usb_send(const struct sr_dev_inst *sdi, struct pickit2_cmd *cmd)
61{
62 struct sr_usb_dev_inst *usb;
63 int ret, sent;
64 GString *text;
65
66 if (!cmd)
67 return SR_OK;
68 usb = sdi->conn;
69 if (!usb)
70 return SR_ERR_ARG;
71
72 text = sr_hexdump_new(&cmd->raw[0], cmd->length);
e760f2cd 73 sr_dbg("USB sent: %s", text->str);
bde6a99b
GS
74 sr_hexdump_free(text);
75
76 ret = libusb_interrupt_transfer(usb->devhdl,
77 LIBUSB_ENDPOINT_OUT | PICKIT2_USB_ENDPOINT,
78 &cmd->raw[0], PICKIT2_PACKET_LENGTH,
79 &sent, PICKIT2_USB_TIMEOUT);
80 if (ret < 0) {
81 sr_err("USB transmit error: %s.", libusb_error_name(ret));
82 return SR_ERR_IO;
83 }
84 if (sent != PICKIT2_PACKET_LENGTH) {
85 sr_err("USB short send: %d/%d bytes.",
86 sent, PICKIT2_PACKET_LENGTH);
87 return SR_ERR_IO;
88 }
89
90 return SR_OK;
91}
92
93static int pickit2_usb_recv(const struct sr_dev_inst *sdi, struct pickit2_cmd *cmd)
94{
95 struct sr_usb_dev_inst *usb;
96 int ret, rcvd;
97 GString *text;
98
99 if (!cmd)
100 return SR_ERR_ARG;
101 usb = sdi->conn;
102 if (!usb)
103 return SR_ERR_ARG;
104
105 ret = libusb_interrupt_transfer(usb->devhdl,
106 LIBUSB_ENDPOINT_IN | PICKIT2_USB_ENDPOINT,
107 &cmd->raw[0], PICKIT2_PACKET_LENGTH,
108 &rcvd, PICKIT2_USB_TIMEOUT);
109 if (ret < 0) {
110 if (ret == LIBUSB_ERROR_TIMEOUT)
111 sr_dbg("USB receive error: %s.", libusb_error_name(ret));
112 else
113 sr_err("USB receive error: %s.", libusb_error_name(ret));
114 return SR_ERR_IO;
115 }
116
117 text = sr_hexdump_new(&cmd->raw[0], rcvd);
e760f2cd 118 sr_dbg("USB recv: %s", text->str);
bde6a99b
GS
119 sr_hexdump_free(text);
120
121 cmd->length = rcvd;
122 if (rcvd != PICKIT2_PACKET_LENGTH) {
123 sr_err("USB short recv: %d/%d bytes.",
124 rcvd, PICKIT2_PACKET_LENGTH);
125 return SR_ERR_IO;
126 }
127
128 return SR_OK;
129}
130
131/* Send a request, (optionally) keep reading until response became available. */
132static int pickit2_usb_send_recv(const struct sr_dev_inst *sdi,
133 struct pickit2_cmd *send_cmd, struct pickit2_cmd *recv_cmd, int do_wait)
134{
135 int ret;
136
137 /* Send the command when one got specified. Ignore errors. */
138 if (send_cmd)
139 (void)pickit2_usb_send(sdi, send_cmd);
140
141 /*
142 * Try receiving data, always ignore errors. When requested by
143 * the caller then keep receiving until response data became
144 * available.
145 */
146 if (!recv_cmd)
147 return SR_OK;
148 do {
149 ret = pickit2_usb_recv(sdi, recv_cmd);
150 if (ret == SR_OK)
151 return SR_OK;
152 if (!do_wait)
153 return ret;
154 } while (1);
155 /* UNREACH */
156}
157
158SR_PRIV int microchip_pickit2_setup_trigger(const struct sr_dev_inst *sdi)
159{
160 static const uint8_t trigger_channel_masks[PICKIT2_CHANNEL_COUNT] = {
161 /* Bit positions for channels in trigger registers. */
162 0x04, 0x08, 0x10,
163 };
164 static const uint16_t captureratio_magics[] = {
165 /* TODO
166 * How to exactly calculate these magic 16bit values?
167 * They seem to neither match a percentage value nor a
168 * sample count (assuming 1 window holds 1K samples).
169 * As long as the formula is unknown, we are stuck with
170 * looking up magic values from a table of few pre-sets.
171 */
172 0x0000, /* unspecified ratio value */
173 0x03cc, 0x000a, 0x0248, /* 10%/50%/90% in the first window */
174 0x07b4, 0x0b9c, 0x0f84, /* 10% "plus 1/2/3 window widths" */
175 };
176
177 struct dev_context *devc;
178 uint8_t trig_en, trig_lvl, trig_edge, trig_rep, trig_div;
179 uint16_t trig_pos;
180 uint64_t rate;
181 size_t trig_pos_idx, ch_idx;
182 uint8_t ch_mask, ch_cond;
183 struct pickit2_cmd cmd;
184
185 devc = sdi->priv;
186
187 /* Translate user specs to internal setup values. */
188 trig_en = trig_lvl = trig_edge = 0;
189 for (ch_idx = 0; ch_idx < PICKIT2_CHANNEL_COUNT; ch_idx++) {
190 if (!devc->triggers[ch_idx])
191 continue;
192 ch_mask = trigger_channel_masks[ch_idx];
193 ch_cond = devc->triggers[ch_idx];
194 trig_en |= ch_mask;
195 switch (ch_cond) {
196 case SR_TRIGGER_ONE:
197 case SR_TRIGGER_RISING:
198 trig_lvl |= ch_mask;
199 break;
200 }
201 switch (ch_cond) {
202 case SR_TRIGGER_FALLING:
203 case SR_TRIGGER_RISING:
204 trig_edge |= ch_mask;
205 break;
206 }
207 }
208 trig_rep = 1;
209 trig_rep = MIN(trig_rep, 255);
210 trig_rep = MAX(trig_rep, 1);
211 if (!trig_en)
212 trig_rep = 0;
213 rate = devc->samplerates[devc->curr_samplerate_idx];
214 rate = SR_MHZ(1) / rate - 1;
215 trig_div = rate & 0xff;
216 trig_pos_idx = devc->trigpos;
217 if (trig_pos_idx >= ARRAY_SIZE(captureratio_magics))
218 trig_pos_idx = 0;
219 trig_pos = captureratio_magics[trig_pos_idx];
220
221 /* Construct the SETUP packet. */
222 pickit2_cmd_clear(&cmd);
223 pickit2_cmd_append(&cmd, PICKIT2_CMD_SETUP);
224 pickit2_cmd_append(&cmd, 0x01);
225 pickit2_cmd_append(&cmd, trig_en);
226 pickit2_cmd_append(&cmd, trig_lvl);
227 pickit2_cmd_append(&cmd, trig_edge);
228 pickit2_cmd_append(&cmd, trig_rep);
229 pickit2_cmd_append(&cmd, trig_pos % 256);
230 pickit2_cmd_append(&cmd, trig_pos / 256);
231 pickit2_cmd_append(&cmd, trig_div);
232
233 /*
234 * Transmit the SETUP packet. Only send it out, poll for the
235 * response later. When a trigger is involved, the response may
236 * take considerable amounts of time to arrive. We want apps
237 * to remain responsive during that period of time.
238 */
239 (void)pickit2_usb_send_recv(sdi, &cmd, NULL, FALSE);
240
241 return SR_OK;
242}
243
244/* Read specified bank data at given offset into caller provided buffer. */
245static int pickit2_retrieve_bank(struct sr_dev_inst *sdi,
246 size_t bank_idx, size_t offset, uint8_t **buf, size_t *len)
247{
248 struct pickit2_cmd send_cmd, recv_cmd;
249 int ret;
250 size_t copy_iter, copy_len;
251
252 /* Construct and send the SETPOS packet. No response expected. */
253 pickit2_cmd_clear(&send_cmd);
254 pickit2_cmd_append(&send_cmd, PICKIT2_CMD_SETPOS);
255 pickit2_cmd_append(&send_cmd, offset & 0xff);
256 pickit2_cmd_append(&send_cmd, PICKIT2_SEL_BANK0 + bank_idx);
257 ret = pickit2_usb_send_recv(sdi, &send_cmd, NULL, FALSE);
258 if (ret != SR_OK)
259 return ret;
260 sr_dbg("read bank: pos set");
261
262 /* Run two READ cycles, get 2x 64 bytes => 128 bytes raw data. */
263 pickit2_cmd_clear(&send_cmd);
264 pickit2_cmd_append(&send_cmd, PICKIT2_CMD_READ);
265 copy_iter = 2;
266 while (copy_iter-- > 0) {
267 ret = pickit2_usb_send_recv(sdi, &send_cmd, &recv_cmd, TRUE);
268 if (ret != SR_OK)
269 return ret;
270 copy_len = MIN(PICKIT2_PACKET_LENGTH, *len);
271 memcpy(*buf, &recv_cmd.raw[0], copy_len);
272 *buf += copy_len;
273 *len -= copy_len;
274 }
275
276 return SR_OK;
277}
278
279/* Read all of the (banked, raw) sample data after acquisition completed. */
280static int pickit2_retrieve_sample_data(struct sr_dev_inst *sdi)
281{
282 struct dev_context *devc;
283 uint8_t *rdpos;
284 size_t rdlen;
285 int ret;
286
287 devc = sdi->priv;
288 rdpos = &devc->samples_raw[0];
289 rdlen = sizeof(devc->samples_raw);
290
291 ret = pickit2_retrieve_bank(sdi, 0, 0x00, &rdpos, &rdlen);
292 if (ret)
293 return ret;
294 ret = pickit2_retrieve_bank(sdi, 0, 0x80, &rdpos, &rdlen);
295 if (ret)
296 return ret;
297 ret = pickit2_retrieve_bank(sdi, 1, 0x00, &rdpos, &rdlen);
298 if (ret)
299 return ret;
300 ret = pickit2_retrieve_bank(sdi, 1, 0x80, &rdpos, &rdlen);
301 if (ret)
302 return ret;
303
304 return SR_OK;
305}
306
307/* Send converted sample data to the sigrok session. */
308static int pickit2_submit_logic_data(struct sr_dev_inst *sdi)
309{
310 struct dev_context *devc;
311 struct {
312 uint8_t raw_mask, conv_mask;
313 } ch_map[PICKIT2_CHANNEL_COUNT] = {
314 { 0x04, 0x01, },
315 { 0x08, 0x02, },
316 { 0x01, 0x04, },
317 };
318 uint8_t *raw_buf, raw_byte, *conv_buf;
319 size_t raw_len, conv_len;
320 uint64_t limit;
321 struct sr_datafeed_packet packet;
322 struct sr_datafeed_logic logic;
323
324 devc = sdi->priv;
325
326 /*
327 * TODO Manipulate (or create) the above channel mapping table.
328 * Remove disabled channels, create dense output format.
329 * Could:
330 * - Loop over the index, check the corresponding channel's
331 * state, clear out the conv_mask part and shift down all
332 * subsequent conv_mask parts.
333 */
334
335 /*
336 * Convert raw dump (two samples per byte, at odd positions) to
337 * internal sigrok format (one sample per byte, at increasing
338 * offsets which start at 0).
339 */
340#define handle_nibble(n) do { \
341 uint8_t conv_byte; \
342 size_t ch_idx; \
343 conv_byte = 0x00; \
344 for (ch_idx = 0; ch_idx < PICKIT2_CHANNEL_COUNT; ch_idx++) { \
345 if ((n) & ch_map[ch_idx].raw_mask) \
346 conv_byte |= ch_map[ch_idx].conv_mask; \
347 } \
348 *conv_buf++ = conv_byte; \
349 conv_len++; \
350} while (0)
351
352 raw_len = sizeof(devc->samples_raw);
353 raw_buf = &devc->samples_raw[raw_len];
354 conv_buf = &devc->samples_conv[0];
355 conv_len = 0;
356 while (raw_len-- > 0) {
357 raw_byte = *(--raw_buf);
358 handle_nibble((raw_byte >> 0) & 0x0f);
359 handle_nibble((raw_byte >> 4) & 0x0f);
360 }
361
362 /* Submit a logic packet to the sigrok session. */
363 packet.type = SR_DF_LOGIC;
364 packet.payload = &logic;
365 logic.unitsize = sizeof(uint8_t);
366 logic.data = &devc->samples_conv[0];
367 logic.length = conv_len;
368 limit = devc->sw_limits.limit_samples;
369 if (limit && limit < logic.length)
370 logic.length = limit;
371 sr_session_send(sdi, &packet);
372
373 return SR_OK;
374}
375
376static gboolean pickit2_status_is_cancel(uint16_t status)
377{
378 /* "Button press" and "transfer timeout" translate to "cancelled". */
379 static const uint16_t status_cancel_mask = 0x4004;
380
381 sr_dbg("recv: status 0x%04x", status);
382 if ((status & status_cancel_mask) == status_cancel_mask)
383 return TRUE;
384 return FALSE;
385}
386
387/* Periodically invoked poll routine, checking for incoming receive data. */
a5c0259c
GS
388SR_PRIV int microchip_pickit2_receive_data(int fd, int revents, void *cb_data)
389{
bde6a99b 390 struct sr_dev_inst *sdi;
a5c0259c 391 struct dev_context *devc;
bde6a99b
GS
392 struct pickit2_cmd cmd;
393 int ret;
394 uint16_t status;
a5c0259c
GS
395
396 (void)fd;
bde6a99b 397 (void)revents;
a5c0259c 398
bde6a99b
GS
399 sdi = cb_data;
400 if (!sdi)
a5c0259c 401 return TRUE;
bde6a99b
GS
402 devc = sdi->priv;
403 if (!devc)
a5c0259c
GS
404 return TRUE;
405
bde6a99b
GS
406 /* Waiting for the trigger condition? */
407 if (devc->state == STATE_WAIT) {
408 /* Keep waiting until status becomes available. */
409 ret = pickit2_usb_send_recv(sdi, NULL, &cmd, FALSE);
410 if (ret != SR_OK)
411 return TRUE;
412 /* Check status flags for cancel requests. */
413 devc->state = STATE_DATA;
414 status = RL16(&cmd.raw[0]);
415 if (pickit2_status_is_cancel(status)) {
416 sr_info("User cancelled acquisition.");
417 sr_dev_acquisition_stop(sdi);
418 return TRUE;
419 }
420 sr_dbg("recv: Data has become available.");
421 /* FALLTHROUGH */
a5c0259c
GS
422 }
423
bde6a99b
GS
424 /*
425 * Retrieve acquired sample data (blocking, acquisition has
426 * completed and samples are few), and stop acquisition (have
427 * the poll routine unregistered).
428 */
429 ret = pickit2_retrieve_sample_data(sdi);
430 if (ret != SR_OK)
431 return ret;
432 ret = pickit2_submit_logic_data(sdi);
433 if (ret != SR_OK)
434 return ret;
435 sr_dev_acquisition_stop(sdi);
a5c0259c
GS
436 return TRUE;
437}