]> sigrok.org Git - libsigrok.git/blob - output/output_text.c
output: if device has no plugin, don't report samplerate
[libsigrok.git] / output / output_text.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2010 Bert Vermeulen <bert@biot.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 <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <glib.h>
24 #include <sigrok.h>
25
26 #define DEFAULT_BPL_BITS 64
27 #define DEFAULT_BPL_HEX  256
28
29 struct context {
30         unsigned int num_enabled_probes;
31         int samples_per_line;
32         unsigned int unitsize;
33         int line_offset;
34         int linebuf_len;
35         char *probelist[65];
36         char *linebuf;
37         int spl_cnt;
38         uint8_t *linevalues;
39         char *header;
40         int mark_trigger;
41 };
42
43 static void flush_linebufs(struct context *ctx, char *outbuf)
44 {
45         static int max_probename_len = 0;
46         int len, i;
47
48         if (ctx->linebuf[0] == 0)
49                 return;
50
51         if (max_probename_len == 0) {
52                 /* First time through... */
53                 for (i = 0; ctx->probelist[i]; i++) {
54                         len = strlen(ctx->probelist[i]);
55                         if (len > max_probename_len)
56                                 max_probename_len = len;
57                 }
58         }
59
60         for (i = 0; ctx->probelist[i]; i++) {
61                 sprintf(outbuf + strlen(outbuf), "%*s:%s\n", max_probename_len,
62                         ctx->probelist[i], ctx->linebuf + i * ctx->linebuf_len);
63         }
64
65         /* Mark trigger with ^ */
66         if (ctx->mark_trigger != -1)
67                 sprintf(outbuf + strlen(outbuf), "T:%*s^\n",
68                         ctx->mark_trigger + (ctx->mark_trigger / 8), "");
69
70         memset(ctx->linebuf, 0, i * ctx->linebuf_len);
71 }
72
73 static int init(struct output *o, int default_spl)
74 {
75         struct context *ctx;
76         struct probe *probe;
77         GSList *l;
78         uint64_t samplerate;
79         int num_probes;
80         char *samplerate_s;
81
82         ctx = malloc(sizeof(struct context));
83         o->internal = ctx;
84         ctx->num_enabled_probes = 0;
85
86         for (l = o->device->probes; l; l = l->next) {
87                 probe = l->data;
88                 if (probe->enabled)
89                         ctx->probelist[ctx->num_enabled_probes++] = probe->name;
90         }
91
92         ctx->probelist[ctx->num_enabled_probes] = 0;
93         ctx->unitsize = (ctx->num_enabled_probes + 7) / 8;
94         ctx->line_offset = 0;
95         ctx->spl_cnt = 0;
96         ctx->mark_trigger = -1;
97
98         if (o->param && o->param[0])
99                 ctx->samples_per_line = strtoul(o->param, NULL, 10);
100         else
101                 ctx->samples_per_line = default_spl;
102
103         if (o->device->plugin) {
104                 ctx->header = malloc(512);
105                 num_probes = g_slist_length(o->device->probes);
106                 samplerate = *((uint64_t *) o->device->plugin->get_device_info(
107                                 o->device->plugin_index, DI_CUR_SAMPLERATE));
108                 snprintf(ctx->header, 512, "Acquisition with %d/%d probes at ",
109                          ctx->num_enabled_probes, num_probes);
110
111                 if ((samplerate_s = sigrok_samplerate_string(samplerate)) == NULL)
112                         return -1; /* FIXME */
113                 snprintf(ctx->header + strlen(ctx->header), 512, "%s\n", samplerate_s);
114                 free(samplerate_s);
115         } else {
116                 /*
117                  * device has no plugin: this is just a dummy device, the data
118                  * comes from a file.
119                  */
120                 ctx->header = NULL;
121         }
122
123         ctx->linebuf_len = ctx->samples_per_line * 2;
124         ctx->linebuf = calloc(1, num_probes * ctx->linebuf_len);
125         ctx->linevalues = calloc(1, num_probes);
126
127         return 0;
128 }
129
130 static int event(struct output *o, int event_type, char **data_out,
131                  uint64_t *length_out)
132 {
133         struct context *ctx;
134         int outsize;
135         char *outbuf;
136
137         ctx = o->internal;
138         switch (event_type) {
139         case DF_TRIGGER:
140                 ctx->mark_trigger = ctx->spl_cnt;
141                 break;
142         case DF_END:
143                 outsize = ctx->num_enabled_probes
144                                 * (ctx->samples_per_line + 20) + 512;
145                 outbuf = calloc(1, outsize);
146                 flush_linebufs(ctx, outbuf);
147                 *data_out = outbuf;
148                 *length_out = strlen(outbuf);
149                 free(o->internal);
150                 o->internal = NULL;
151                 break;
152         }
153
154         return SIGROK_OK;
155 }
156
157 static int init_bits(struct output *o)
158 {
159         return init(o, DEFAULT_BPL_BITS);
160 }
161
162 static int data_bits(struct output *o, char *data_in, uint64_t length_in,
163                      char **data_out, uint64_t *length_out)
164 {
165         struct context *ctx;
166         unsigned int outsize, offset, p;
167         uint64_t sample;
168         char *outbuf;
169
170         ctx = o->internal;
171         outsize = length_in / ctx->unitsize * ctx->num_enabled_probes *
172                   ctx->samples_per_line + 512;
173         outbuf = calloc(1, outsize + 1);
174         if (ctx->header) {
175                 /* The header is still here, this must be the first packet. */
176                 strncpy(outbuf, ctx->header, outsize);
177                 free(ctx->header);
178                 ctx->header = NULL;
179         } else
180                 outbuf[0] = 0;
181
182         if (length_in >= ctx->unitsize) {
183                 for (offset = 0; offset <= length_in - ctx->unitsize;
184                      offset += ctx->unitsize) {
185                         memcpy(&sample, data_in + offset, ctx->unitsize);
186                         for (p = 0; p < ctx->num_enabled_probes; p++) {
187                                 if (sample & ((uint64_t) 1 << p))
188                                         ctx->linebuf[p * ctx->linebuf_len +
189                                                      ctx->line_offset] = '1';
190                                 else
191                                         ctx->linebuf[p * ctx->linebuf_len +
192                                                      ctx->line_offset] = '0';
193                         }
194                         ctx->line_offset++;
195                         ctx->spl_cnt++;
196
197                         /* Add a space every 8th bit. */
198                         if ((ctx->spl_cnt & 7) == 0) {
199                                 for (p = 0; p < ctx->num_enabled_probes; p++)
200                                         ctx->linebuf[p * ctx->linebuf_len +
201                                                      ctx->line_offset] = ' ';
202                                 ctx->line_offset++;
203                         }
204
205                         /* End of line. */
206                         if (ctx->spl_cnt >= ctx->samples_per_line) {
207                                 flush_linebufs(ctx, outbuf);
208                                 ctx->line_offset = ctx->spl_cnt = 0;
209                                 ctx->mark_trigger = -1;
210                         }
211                 }
212         } else
213                 g_message("short buffer (length_in=%" PRIu64 ")", length_in);
214
215         *data_out = outbuf;
216         *length_out = strlen(outbuf);
217
218         return SIGROK_OK;
219 }
220
221 static int init_hex(struct output *o)
222 {
223         return init(o, DEFAULT_BPL_BITS);
224 }
225
226 static int data_hex(struct output *o, char *data_in, uint64_t length_in,
227                     char **data_out, uint64_t *length_out)
228 {
229         struct context *ctx;
230         unsigned int outsize, offset, p;
231         uint64_t sample;
232         char *outbuf;
233
234         ctx = o->internal;
235         outsize = length_in / ctx->unitsize * ctx->num_enabled_probes *
236                   ctx->samples_per_line + 512;
237         outbuf = calloc(1, outsize + 1);
238         if (ctx->header) {
239                 /* The header is still here, this must be the first packet. */
240                 strncpy(outbuf, ctx->header, outsize);
241                 free(ctx->header);
242                 ctx->header = NULL;
243         } else
244                 outbuf[0] = 0;
245
246         ctx->line_offset = 0;
247         for (offset = 0; offset <= length_in - ctx->unitsize;
248              offset += ctx->unitsize) {
249                 memcpy(&sample, data_in + offset, ctx->unitsize);
250                 for (p = 0; p < ctx->num_enabled_probes; p++) {
251                         ctx->linevalues[p] <<= 1;
252                         if (sample & ((uint64_t) 1 << p))
253                                 ctx->linevalues[p] |= 1;
254                         sprintf(ctx->linebuf + (p * ctx->linebuf_len) +
255                                 ctx->line_offset, "%.2x", ctx->linevalues[p]);
256                 }
257                 ctx->spl_cnt++;
258
259                 /* Add a space after every complete hex byte. */
260                 if ((ctx->spl_cnt & 7) == 0) {
261                         for (p = 0; p < ctx->num_enabled_probes; p++)
262                                 ctx->linebuf[p * ctx->linebuf_len +
263                                              ctx->line_offset + 2] = ' ';
264                         ctx->line_offset += 3;
265                 }
266
267                 /* End of line. */
268                 if (ctx->spl_cnt >= ctx->samples_per_line) {
269                         flush_linebufs(ctx, outbuf);
270                         ctx->line_offset = ctx->spl_cnt = 0;
271                 }
272         }
273
274         *data_out = outbuf;
275         *length_out = strlen(outbuf);
276
277         return SIGROK_OK;
278 }
279
280 struct output_format output_text_bits = {
281         "bits",
282         "Text (bits)",
283         init_bits,
284         data_bits,
285         event,
286 };
287
288 struct output_format output_text_hex = {
289         "hex",
290         "Text (hexadecimal)",
291         init_hex,
292         data_hex,
293         event,
294 };