]> sigrok.org Git - libsigrok.git/blame - src/input/feed_queue.c
feed queue: add scaling, MQ and unit to analog feed submission
[libsigrok.git] / src / input / feed_queue.c
CommitLineData
47a102f9
GS
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2020 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 <libsigrok/libsigrok.h>
21#include "libsigrok-internal.h"
22#include <string.h>
23
24struct feed_queue_logic {
57140e5a 25 const struct sr_dev_inst *sdi;
47a102f9
GS
26 size_t unit_size;
27 size_t alloc_count;
28 size_t fill_count;
29 uint8_t *data_bytes;
30 struct sr_datafeed_packet packet;
31 struct sr_datafeed_logic logic;
32};
33
57140e5a
GS
34SR_API struct feed_queue_logic *feed_queue_logic_alloc(
35 const struct sr_dev_inst *sdi,
47a102f9
GS
36 size_t sample_count, size_t unit_size)
37{
38 struct feed_queue_logic *q;
39
40 q = g_malloc0(sizeof(*q));
41 q->sdi = sdi;
42 q->unit_size = unit_size;
43 q->alloc_count = sample_count;
44 q->data_bytes = g_try_malloc(q->alloc_count * q->unit_size);
45 if (!q->data_bytes) {
46 g_free(q);
47 return NULL;
48 }
49
50 memset(&q->packet, 0, sizeof(q->packet));
51 memset(&q->logic, 0, sizeof(q->logic));
52 q->packet.type = SR_DF_LOGIC;
53 q->packet.payload = &q->logic;
54 q->logic.unitsize = q->unit_size;
55 q->logic.data = q->data_bytes;
56
57 return q;
58}
59
60SR_API int feed_queue_logic_submit(struct feed_queue_logic *q,
61 const uint8_t *data, size_t count)
62{
63 uint8_t *wrptr;
64 int ret;
65
66 wrptr = &q->data_bytes[q->fill_count * q->unit_size];
67 while (count--) {
68 memcpy(wrptr, data, q->unit_size);
69 wrptr += q->unit_size;
70 q->fill_count++;
71 if (q->fill_count == q->alloc_count) {
72 ret = feed_queue_logic_flush(q);
73 if (ret != SR_OK)
74 return ret;
75 wrptr = &q->data_bytes[0];
76 }
77 }
78
79 return SR_OK;
80}
81
82SR_API int feed_queue_logic_flush(struct feed_queue_logic *q)
83{
84 int ret;
85
86 if (!q->fill_count)
87 return SR_OK;
88
89 q->logic.length = q->fill_count * q->unit_size;
90 ret = sr_session_send(q->sdi, &q->packet);
91 if (ret != SR_OK)
92 return ret;
93 q->fill_count = 0;
94
95 return SR_OK;
96}
97
f478c3e6
GS
98SR_API int feed_queue_logic_send_trigger(struct feed_queue_logic *q)
99{
100 int ret;
101
102 ret = feed_queue_logic_flush(q);
103 if (ret != SR_OK)
104 return ret;
105
106 ret = std_session_send_df_trigger(q->sdi);
107 if (ret != SR_OK)
108 return ret;
109
110 return SR_OK;
111}
112
47a102f9
GS
113SR_API void feed_queue_logic_free(struct feed_queue_logic *q)
114{
115
116 if (!q)
117 return;
118
119 g_free(q->data_bytes);
120 g_free(q);
121}
122
123struct feed_queue_analog {
57140e5a 124 const struct sr_dev_inst *sdi;
47a102f9
GS
125 size_t alloc_count;
126 size_t fill_count;
127 float *data_values;
128 int digits;
129 struct sr_datafeed_packet packet;
130 struct sr_datafeed_analog analog;
131 struct sr_analog_encoding encoding;
132 struct sr_analog_meaning meaning;
133 struct sr_analog_spec spec;
134 GSList *channels;
43e6f7a7 135 float scale_factor;
47a102f9
GS
136};
137
57140e5a
GS
138SR_API struct feed_queue_analog *feed_queue_analog_alloc(
139 const struct sr_dev_inst *sdi,
47a102f9
GS
140 size_t sample_count, int digits, struct sr_channel *ch)
141{
142 struct feed_queue_analog *q;
143
144 q = g_malloc0(sizeof(*q));
145 q->sdi = sdi;
146 q->alloc_count = sample_count;
147 q->data_values = g_try_malloc(q->alloc_count * sizeof(float));
148 if (!q->data_values) {
149 g_free(q);
150 return NULL;
151 }
152 q->digits = digits;
153 q->channels = g_slist_append(NULL, ch);
154
155 memset(&q->packet, 0, sizeof(q->packet));
156 sr_analog_init(&q->analog, &q->encoding, &q->meaning, &q->spec, digits);
157 q->packet.type = SR_DF_ANALOG;
158 q->packet.payload = &q->analog;
159 q->encoding.is_signed = TRUE;
160 q->meaning.channels = q->channels;
161 q->analog.data = q->data_values;
162
163 return q;
164}
165
43e6f7a7
GS
166SR_API int feed_queue_analog_params(struct feed_queue_analog *q,
167 float scale_factor,
168 enum sr_mq mq, enum sr_mqflag mq_flag, enum sr_unit unit)
169{
170 int ret;
171
172 if (!q)
173 return SR_ERR_ARG;
174
175 ret = feed_queue_analog_flush(q);
176 if (ret != SR_OK)
177 return ret;
178
179 q->scale_factor = scale_factor;
180 if (q->scale_factor == 1.0)
181 q->scale_factor = 0.0;
182
183 q->meaning->mq = mq;
184 q->meaning->mqflags = mqflags;
185 q->meaning->unit = unit;
186
187 return SR_OK;
188}
189
47a102f9
GS
190SR_API int feed_queue_analog_submit(struct feed_queue_analog *q,
191 float data, size_t count)
192{
193 int ret;
194
43e6f7a7
GS
195 if (q->scale_factor)
196 data *= q->scale_factor;
47a102f9
GS
197 while (count--) {
198 q->data_values[q->fill_count++] = data;
199 if (q->fill_count == q->alloc_count) {
200 ret = feed_queue_analog_flush(q);
201 if (ret != SR_OK)
202 return ret;
203 }
204 }
205
206 return SR_OK;
207}
208
209SR_API int feed_queue_analog_flush(struct feed_queue_analog *q)
210{
211 int ret;
212
213 if (!q->fill_count)
214 return SR_OK;
215
216 q->analog.num_samples = q->fill_count;
217 ret = sr_session_send(q->sdi, &q->packet);
218 if (ret != SR_OK)
219 return ret;
220 q->fill_count = 0;
221
222 return SR_OK;
223}
224
225SR_API void feed_queue_analog_free(struct feed_queue_analog *q)
226{
227
228 if (!q)
229 return;
230
231 g_free(q->data_values);
232 g_slist_free(q->channels);
233 g_free(q);
234}