]> sigrok.org Git - libsigrok.git/blob - src/input/feed_queue.c
ca91af3756602d7ccb50fe47de365d2eef817e8f
[libsigrok.git] / src / input / feed_queue.c
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
24 struct feed_queue_logic {
25         const struct sr_dev_inst *sdi;
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
34 SR_API struct feed_queue_logic *feed_queue_logic_alloc(
35         const struct sr_dev_inst *sdi,
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
60 SR_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
82 SR_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
98 SR_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
113 SR_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
123 struct feed_queue_analog {
124         const struct sr_dev_inst *sdi;
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;
135         float scale_factor;
136 };
137
138 SR_API struct feed_queue_analog *feed_queue_analog_alloc(
139         const struct sr_dev_inst *sdi,
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
166 SR_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
190 SR_API int feed_queue_analog_submit(struct feed_queue_analog *q,
191         float data, size_t count)
192 {
193         int ret;
194
195         if (q->scale_factor)
196                 data *= q->scale_factor;
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
209 SR_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
225 SR_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 }