]> sigrok.org Git - libsigrok.git/blame - output/output_ols.c
Initial support for the OLS output format.
[libsigrok.git] / output / output_ols.c
CommitLineData
ab224f7b
UH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2011 Uwe Hermann <uwe@hermann-uwe.de>
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 2 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/*
22 * Output format for the OpenBench Logic Sniffer "Alternative" Java client.
23 * Details: https://github.com/jawi/ols/wiki/OLS-data-file-format
24 */
25
26#include <stdlib.h>
27#include <string.h>
28#include <glib.h>
29#include <sigrok.h>
30#include "config.h"
31
32struct context {
33 unsigned int num_enabled_probes;
34 unsigned int unitsize;
35 char *probelist[MAX_NUM_PROBES + 1];
36 char *header;
37};
38
39/* FIXME */
40#define MAX_HEADER_LEN 2048
41
42/* TODO: Support cursors? */
43#define OLS_HEADER \
44"# Generated by: %s on %s%s\n" \
45"# Probe list used for capturing:\n" \
46"# Number:\tName:\n" \
47"%s" \
48";Size: %" PRIu64 "\n" \
49";Rate: %" PRIu64 "\n" \
50";Channels: %d\n" \
51";EnabledChannels: -1\n" \
52";Compressed: true\n" \
53";AbsoluteLength: %" PRIu64 "\n" \
54";CursorEnabled: false\n" \
55";Cursor0: -9223372036854775808\n" \
56";Cursor1: -9223372036854775808\n" \
57";Cursor2: -9223372036854775808\n" \
58";Cursor3: -9223372036854775808\n" \
59";Cursor4: -9223372036854775808\n" \
60";Cursor5: -9223372036854775808\n" \
61";Cursor6: -9223372036854775808\n" \
62";Cursor7: -9223372036854775808\n" \
63";Cursor8: -9223372036854775808\n" \
64";Cursor9: -9223372036854775808\n"
65
66const char *ols_header_comment = "\
67# Comment: Acquisition with %d/%d probes at %s";
68
69static int init(struct output *o)
70{
71 struct context *ctx;
72 struct probe *probe;
73 GSList *l;
74 uint64_t samplerate;
75 unsigned int i;
76 int b, num_probes;
77 char *c, *frequency_s;
78 char wbuf[1000], comment[128];
79 time_t t;
80
81 if (!(ctx = calloc(1, sizeof(struct context))))
82 return SIGROK_ERR_MALLOC;
83
84 if (!(ctx->header = calloc(1, MAX_HEADER_LEN + 1))) {
85 free(ctx);
86 return SIGROK_ERR_MALLOC;
87 }
88
89 o->internal = ctx;
90 ctx->num_enabled_probes = 0;
91 for (l = o->device->probes; l; l = l->next) {
92 probe = l->data;
93 if (!probe->enabled)
94 continue;
95 ctx->probelist[ctx->num_enabled_probes++] = probe->name;
96 }
97 ctx->probelist[ctx->num_enabled_probes] = 0;
98 ctx->unitsize = (ctx->num_enabled_probes + 7) / 8;
99
100 num_probes = g_slist_length(o->device->probes);
101 comment[0] = '\0';
102
103 /* TODO: Currently not available in the demo module. */
104
105 if (o->device->plugin) {
106 samplerate = *((uint64_t *) o->device->plugin->get_device_info(
107 o->device->plugin_index, DI_CUR_SAMPLERATE));
108 if (!(frequency_s = sigrok_samplerate_string(samplerate))) {
109 free(ctx->header);
110 free(ctx);
111 return SIGROK_ERR;
112 }
113 snprintf(comment, 127, ols_header_comment,
114 ctx->num_enabled_probes, num_probes, frequency_s);
115 free(frequency_s);
116 }
117
118 /* Columns / channels */
119 wbuf[0] = '\0';
120 for (i = 0; i < ctx->num_enabled_probes; i++) {
121 c = (char *)&wbuf + strlen((char *)&wbuf);
122 sprintf(c, "# %d\t\t%s\n", i + 1, ctx->probelist[i]);
123 }
124
125 if (!(frequency_s = sigrok_period_string(samplerate))) {
126 free(ctx->header);
127 free(ctx);
128 return SIGROK_ERR;
129 }
130
131 t = time(NULL);
132
133 /* TODO: Special handling for the demo driver. */
134 /* TODO: Don't hardcode numsamples! */
135 /* TODO: Check if num_enabled_probes/channels setting is correct. */
136 b = snprintf(ctx->header, MAX_HEADER_LEN, OLS_HEADER,
137 PACKAGE_STRING, ctime(&t),
138 comment,
139 (const char *)&wbuf,
140 (uint64_t)10000 /* numsamples */,
141 samplerate,
142 ctx->num_enabled_probes,
143 (uint64_t)10000 /* numsamples */);
144
145 /* TODO: Yield errors on stuff the OLS format doesn't support. */
146
147 free(frequency_s);
148
149 if (b < 0) {
150 free(ctx->header);
151 free(ctx);
152 return SIGROK_ERR;
153 }
154
155 return 0;
156}
157
158static int event(struct output *o, int event_type, char **data_out,
159 uint64_t *length_out)
160{
161 struct context *ctx;
162
163 ctx = o->internal;
164 switch (event_type) {
165 case DF_TRIGGER:
166 /* TODO */
167 break;
168 case DF_END:
169 free(o->internal);
170 o->internal = NULL;
171 break;
172 }
173
174 *data_out = NULL;
175 *length_out = 0;
176
177 return SIGROK_OK;
178}
179
180static int data(struct output *o, char *data_in, uint64_t length_in,
181 char **data_out, uint64_t *length_out)
182{
183 struct context *ctx;
184 unsigned int max_linelen, outsize, p, curbit, i;
185 uint64_t sample;
186 static uint64_t samplecount = 0;
187 char *outbuf, *c;
188
189 ctx = o->internal;
190 max_linelen = 100; /* FIXME */
191 outsize = length_in / ctx->unitsize * max_linelen;
192 if (ctx->header)
193 outsize += strlen(ctx->header);
194
195 if (!(outbuf = calloc(1, outsize)))
196 return SIGROK_ERR_MALLOC;
197
198 outbuf[0] = '\0';
199 if (ctx->header) {
200 /* The header is still here, this must be the first packet. */
201 strncpy(outbuf, ctx->header, outsize);
202 free(ctx->header);
203 ctx->header = NULL;
204 }
205
206 for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) {
207 memcpy(&sample, data_in + i, ctx->unitsize);
208
209 c = outbuf + strlen(outbuf);
210 /* FIXME: OLS seems to only support 2^31 total samples? */
211 sprintf(c, "%08x@%" PRIu64 "\n", (uint32_t)sample,
212 samplecount++);
213 }
214
215 *data_out = outbuf;
216 *length_out = strlen(outbuf);
217
218 return SIGROK_OK;
219}
220
221struct output_format output_ols = {
222 "ols",
223 "OpenBench Logic Sniffer",
224 DF_LOGIC,
225 init,
226 data,
227 event,
228};