]> sigrok.org Git - libsigrok.git/blame - hardware/sysclk-lwla/lwla.c
demo: Keep separate counters for logic and analog sources.
[libsigrok.git] / hardware / sysclk-lwla / lwla.c
CommitLineData
5874e88d
DE
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2014 Daniel Elstner <daniel.kitta@gmail.com>
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 "lwla.h"
21#include "protocol.h"
22#include "libsigrok-internal.h"
23
24SR_PRIV int lwla_send_bitstream(const struct sr_usb_dev_inst *usb,
25 const char *filename)
26{
27 GMappedFile *file;
28 GError *error;
29 char *stream;
30 size_t length;
31 int ret;
32 int xfer_len;
33
34 if (usb == NULL || filename == NULL)
35 return SR_ERR_ARG;
36
37 sr_info("Downloading FPGA bitstream at '%s'.", filename);
38
39 /* Map bitstream file into memory. */
40 error = NULL;
41 file = g_mapped_file_new(filename, FALSE, &error);
42 if (!file) {
43 sr_err("Unable to open bitstream file: %s.", error->message);
44 g_error_free(error);
45 return SR_ERR;
46 }
47 stream = g_mapped_file_get_contents(file);
48 length = g_mapped_file_get_length(file);
49
50 /* Sanity check. */
51 if (!stream || length < 4 || RB32(stream) != length) {
52 sr_err("Invalid FPGA bitstream.");
53 g_mapped_file_unref(file);
54 return SR_ERR;
55 }
56
57 /* Transfer the entire bitstream in one URB. */
58 ret = libusb_bulk_transfer(usb->devhdl, EP_BITSTREAM,
59 (unsigned char *)stream, length,
60 &xfer_len, USB_TIMEOUT);
313c7a7d
DE
61 g_mapped_file_unref(file);
62
5874e88d
DE
63 if (ret != 0) {
64 sr_err("Failed to transfer bitstream: %s.",
65 libusb_error_name(ret));
5874e88d
DE
66 return SR_ERR;
67 }
68 if (xfer_len != (int)length) {
69 sr_err("Failed to transfer bitstream: incorrect length "
70 "%d != %d.", xfer_len, (int)length);
5874e88d
DE
71 return SR_ERR;
72 }
5874e88d
DE
73 sr_info("FPGA bitstream download of %d bytes done.", xfer_len);
74
75 /* This delay appears to be necessary for reliable operation. */
76 g_usleep(30000);
77
78 return SR_OK;
79}
80
81SR_PRIV int lwla_send_command(const struct sr_usb_dev_inst *usb,
82 const uint16_t *command, int cmd_len)
83{
84 int ret;
313c7a7d 85 int xfer_len;
5874e88d 86
313c7a7d 87 if (usb == NULL || command == NULL || cmd_len <= 0)
5874e88d
DE
88 return SR_ERR_ARG;
89
313c7a7d 90 xfer_len = 0;
5874e88d
DE
91 ret = libusb_bulk_transfer(usb->devhdl, EP_COMMAND,
92 (unsigned char *)command, cmd_len * 2,
93 &xfer_len, USB_TIMEOUT);
94 if (ret != 0) {
95 sr_dbg("Failed to send command %u: %s.",
96 LWLA_READ16(command), libusb_error_name(ret));
97 return SR_ERR;
98 }
99 if (xfer_len != cmd_len * 2) {
100 sr_dbg("Failed to send command %u: incorrect length %d != %d.",
101 LWLA_READ16(command), xfer_len, cmd_len * 2);
102 return SR_ERR;
103 }
104 return SR_OK;
105}
106
107SR_PRIV int lwla_receive_reply(const struct sr_usb_dev_inst *usb,
108 uint16_t *reply, int reply_len, int expect_len)
109{
110 int ret;
313c7a7d 111 int xfer_len;
5874e88d 112
313c7a7d 113 if (usb == NULL || reply == NULL || reply_len <= 0)
5874e88d
DE
114 return SR_ERR_ARG;
115
313c7a7d 116 xfer_len = 0;
5874e88d
DE
117 ret = libusb_bulk_transfer(usb->devhdl, EP_REPLY,
118 (unsigned char *)reply, reply_len * 2,
119 &xfer_len, USB_TIMEOUT);
120 if (ret != 0) {
121 sr_dbg("Failed to receive reply: %s.", libusb_error_name(ret));
122 return SR_ERR;
123 }
124 if (xfer_len != expect_len * 2) {
125 sr_dbg("Failed to receive reply: incorrect length %d != %d.",
126 xfer_len, expect_len * 2);
127 return SR_ERR;
128 }
129 return SR_OK;
130}
131
132SR_PRIV int lwla_read_reg(const struct sr_usb_dev_inst *usb,
133 uint16_t reg, uint32_t *value)
134{
135 int ret;
136 uint16_t command[2];
313c7a7d 137 uint16_t reply[256]; /* full EP buffer to avoid overflows */
5874e88d
DE
138
139 command[0] = LWLA_WORD(CMD_READ_REG);
140 command[1] = LWLA_WORD(reg);
141
142 ret = lwla_send_command(usb, command, G_N_ELEMENTS(command));
143
144 if (ret != SR_OK)
145 return ret;
146
147 ret = lwla_receive_reply(usb, reply, G_N_ELEMENTS(reply), 2);
148
149 if (ret == SR_OK)
150 *value = LWLA_READ32(reply);
151
152 return ret;
153}
154
155SR_PRIV int lwla_write_reg(const struct sr_usb_dev_inst *usb,
156 uint16_t reg, uint32_t value)
157{
158 uint16_t command[4];
159
160 command[0] = LWLA_WORD(CMD_WRITE_REG);
161 command[1] = LWLA_WORD(reg);
162 command[2] = LWLA_WORD_0(value);
163 command[3] = LWLA_WORD_1(value);
164
165 return lwla_send_command(usb, command, G_N_ELEMENTS(command));
166}
167
168SR_PRIV int lwla_write_regs(const struct sr_usb_dev_inst *usb,
169 const struct regval_pair *regvals, int count)
170{
171 int i;
172 int ret;
173
174 ret = SR_OK;
175
176 for (i = 0; i < count; ++i) {
177 ret = lwla_write_reg(usb, regvals[i].reg, regvals[i].val);
178
179 if (ret != SR_OK)
180 break;
181 }
182
183 return ret;
184}