]> sigrok.org Git - libsigrok.git/blob - src/input/feed_queue.c
98443244a235281f9cb422ed800b8a067995e572
[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         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(struct sr_dev_inst *sdi,
35         size_t sample_count, size_t unit_size)
36 {
37         struct feed_queue_logic *q;
38
39         q = g_malloc0(sizeof(*q));
40         q->sdi = sdi;
41         q->unit_size = unit_size;
42         q->alloc_count = sample_count;
43         q->data_bytes = g_try_malloc(q->alloc_count * q->unit_size);
44         if (!q->data_bytes) {
45                 g_free(q);
46                 return NULL;
47         }
48
49         memset(&q->packet, 0, sizeof(q->packet));
50         memset(&q->logic, 0, sizeof(q->logic));
51         q->packet.type = SR_DF_LOGIC;
52         q->packet.payload = &q->logic;
53         q->logic.unitsize = q->unit_size;
54         q->logic.data = q->data_bytes;
55
56         return q;
57 }
58
59 SR_API int feed_queue_logic_submit(struct feed_queue_logic *q,
60         const uint8_t *data, size_t count)
61 {
62         uint8_t *wrptr;
63         int ret;
64
65         wrptr = &q->data_bytes[q->fill_count * q->unit_size];
66         while (count--) {
67                 memcpy(wrptr, data, q->unit_size);
68                 wrptr += q->unit_size;
69                 q->fill_count++;
70                 if (q->fill_count == q->alloc_count) {
71                         ret = feed_queue_logic_flush(q);
72                         if (ret != SR_OK)
73                                 return ret;
74                         wrptr = &q->data_bytes[0];
75                 }
76         }
77
78         return SR_OK;
79 }
80
81 SR_API int feed_queue_logic_flush(struct feed_queue_logic *q)
82 {
83         int ret;
84
85         if (!q->fill_count)
86                 return SR_OK;
87
88         q->logic.length = q->fill_count * q->unit_size;
89         ret = sr_session_send(q->sdi, &q->packet);
90         if (ret != SR_OK)
91                 return ret;
92         q->fill_count = 0;
93
94         return SR_OK;
95 }
96
97 SR_API void feed_queue_logic_free(struct feed_queue_logic *q)
98 {
99
100         if (!q)
101                 return;
102
103         g_free(q->data_bytes);
104         g_free(q);
105 }
106
107 struct feed_queue_analog {
108         struct sr_dev_inst *sdi;
109         size_t alloc_count;
110         size_t fill_count;
111         float *data_values;
112         int digits;
113         struct sr_datafeed_packet packet;
114         struct sr_datafeed_analog analog;
115         struct sr_analog_encoding encoding;
116         struct sr_analog_meaning meaning;
117         struct sr_analog_spec spec;
118         GSList *channels;
119 };
120
121 SR_API struct feed_queue_analog *feed_queue_analog_alloc(struct sr_dev_inst *sdi,
122         size_t sample_count, int digits, struct sr_channel *ch)
123 {
124         struct feed_queue_analog *q;
125
126         q = g_malloc0(sizeof(*q));
127         q->sdi = sdi;
128         q->alloc_count = sample_count;
129         q->data_values = g_try_malloc(q->alloc_count * sizeof(float));
130         if (!q->data_values) {
131                 g_free(q);
132                 return NULL;
133         }
134         q->digits = digits;
135         q->channels = g_slist_append(NULL, ch);
136
137         memset(&q->packet, 0, sizeof(q->packet));
138         sr_analog_init(&q->analog, &q->encoding, &q->meaning, &q->spec, digits);
139         q->packet.type = SR_DF_ANALOG;
140         q->packet.payload = &q->analog;
141         q->encoding.is_signed = TRUE;
142         q->meaning.channels = q->channels;
143         q->analog.data = q->data_values;
144
145         return q;
146 }
147
148 SR_API int feed_queue_analog_submit(struct feed_queue_analog *q,
149         float data, size_t count)
150 {
151         int ret;
152
153         while (count--) {
154                 q->data_values[q->fill_count++] = data;
155                 if (q->fill_count == q->alloc_count) {
156                         ret = feed_queue_analog_flush(q);
157                         if (ret != SR_OK)
158                                 return ret;
159                 }
160         }
161
162         return SR_OK;
163 }
164
165 SR_API int feed_queue_analog_flush(struct feed_queue_analog *q)
166 {
167         int ret;
168
169         if (!q->fill_count)
170                 return SR_OK;
171
172         q->analog.num_samples = q->fill_count;
173         ret = sr_session_send(q->sdi, &q->packet);
174         if (ret != SR_OK)
175                 return ret;
176         q->fill_count = 0;
177
178         return SR_OK;
179 }
180
181 SR_API void feed_queue_analog_free(struct feed_queue_analog *q)
182 {
183
184         if (!q)
185                 return;
186
187         g_free(q->data_values);
188         g_slist_free(q->channels);
189         g_free(q);
190 }