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