00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <glib.h>
00024 #include "config.h"
00025 #include "sigrok.h"
00026 #include "sigrok-internal.h"
00027
00028 struct context {
00029 unsigned int num_enabled_probes;
00030 unsigned int unitsize;
00031 char *probelist[SR_MAX_NUM_PROBES + 1];
00032 char *header;
00033 };
00034
00035 #define MAX_HEADER_LEN \
00036 (1024 + (SR_MAX_NUM_PROBES * (SR_MAX_PROBENAME_LEN + 10)))
00037
00038 static const char *gnuplot_header = "\
00039 # Sample data in space-separated columns format usable by gnuplot\n\
00040 #\n\
00041 # Generated by: %s on %s%s\
00042 # Period: %s\n\
00043 #\n\
00044 # Column\tProbe\n\
00045 # -------------------------------------\
00046 ----------------------------------------\n\
00047 # 0\t\tSample counter (for internal gnuplot purposes)\n%s\n";
00048
00049 static const char *gnuplot_header_comment = "\
00050 # Comment: Acquisition with %d/%d probes at %s\n";
00051
00052 static int init(struct sr_output *o)
00053 {
00054 struct context *ctx;
00055 struct sr_probe *probe;
00056 GSList *l;
00057 uint64_t samplerate;
00058 unsigned int i;
00059 int b, num_probes;
00060 char *c, *frequency_s;
00061 char wbuf[1000], comment[128];
00062 time_t t;
00063
00064 if (!o) {
00065 sr_err("gnuplot out: %s: o was NULL", __func__);
00066 return SR_ERR_ARG;
00067 }
00068
00069 if (!o->dev) {
00070 sr_err("gnuplot out: %s: o->dev was NULL", __func__);
00071 return SR_ERR_ARG;
00072 }
00073
00074 if (!o->dev->driver) {
00075 sr_err("gnuplot out: %s: o->dev->driver was NULL", __func__);
00076 return SR_ERR_ARG;
00077 }
00078
00079 if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
00080 sr_err("gnuplot out: %s: ctx malloc failed", __func__);
00081 return SR_ERR_MALLOC;
00082 }
00083
00084 if (!(ctx->header = g_try_malloc0(MAX_HEADER_LEN + 1))) {
00085 sr_err("gnuplot out: %s: ctx->header malloc failed", __func__);
00086 g_free(ctx);
00087 return SR_ERR_MALLOC;
00088 }
00089
00090 o->internal = ctx;
00091 ctx->num_enabled_probes = 0;
00092 for (l = o->dev->probes; l; l = l->next) {
00093 probe = l->data;
00094 if (!probe->enabled)
00095 continue;
00096 ctx->probelist[ctx->num_enabled_probes++] = probe->name;
00097 }
00098 ctx->probelist[ctx->num_enabled_probes] = 0;
00099 ctx->unitsize = (ctx->num_enabled_probes + 7) / 8;
00100
00101 num_probes = g_slist_length(o->dev->probes);
00102 comment[0] = '\0';
00103 if (sr_dev_has_hwcap(o->dev, SR_HWCAP_SAMPLERATE)) {
00104 samplerate = *((uint64_t *) o->dev->driver->dev_info_get(
00105 o->dev->driver_index, SR_DI_CUR_SAMPLERATE));
00106 if (!(frequency_s = sr_samplerate_string(samplerate))) {
00107 sr_err("gnuplot out: %s: sr_samplerate_string failed",
00108 __func__);
00109 g_free(ctx->header);
00110 g_free(ctx);
00111 return SR_ERR;
00112 }
00113 snprintf(comment, 127, gnuplot_header_comment,
00114 ctx->num_enabled_probes, num_probes, frequency_s);
00115 g_free(frequency_s);
00116 }
00117
00118
00119 wbuf[0] = '\0';
00120 for (i = 0; i < ctx->num_enabled_probes; i++) {
00121 c = (char *)&wbuf + strlen((const char *)&wbuf);
00122 sprintf(c, "# %d\t\t%s\n", i + 1, ctx->probelist[i]);
00123 }
00124
00125 if (!(frequency_s = sr_period_string(samplerate))) {
00126 sr_err("gnuplot out: %s: sr_period_string failed", __func__);
00127 g_free(ctx->header);
00128 g_free(ctx);
00129 return SR_ERR;
00130 }
00131
00132 t = time(NULL);
00133 b = snprintf(ctx->header, MAX_HEADER_LEN, gnuplot_header,
00134 PACKAGE_STRING, ctime(&t), comment, frequency_s,
00135 (char *)&wbuf);
00136 g_free(frequency_s);
00137
00138 if (b < 0) {
00139 sr_err("gnuplot out: %s: sprintf failed", __func__);
00140 g_free(ctx->header);
00141 g_free(ctx);
00142 return SR_ERR;
00143 }
00144
00145 return 0;
00146 }
00147
00148 static int event(struct sr_output *o, int event_type, uint8_t **data_out,
00149 uint64_t *length_out)
00150 {
00151 if (!o) {
00152 sr_err("gnuplot out: %s: o was NULL", __func__);
00153 return SR_ERR_ARG;
00154 }
00155
00156 if (!data_out) {
00157 sr_err("gnuplot out: %s: data_out was NULL", __func__);
00158 return SR_ERR_ARG;
00159 }
00160
00161 if (!length_out) {
00162 sr_err("gnuplot out: %s: length_out was NULL", __func__);
00163 return SR_ERR_ARG;
00164 }
00165
00166 switch (event_type) {
00167 case SR_DF_TRIGGER:
00168
00169 break;
00170 case SR_DF_END:
00171 g_free(o->internal);
00172 o->internal = NULL;
00173 break;
00174 default:
00175 sr_err("gnuplot out: %s: unsupported event type: %d",
00176 __func__, event_type);
00177 break;
00178 }
00179
00180 *data_out = NULL;
00181 *length_out = 0;
00182
00183 return SR_OK;
00184 }
00185
00186 static int data(struct sr_output *o, const uint8_t *data_in,
00187 uint64_t length_in, uint8_t **data_out, uint64_t *length_out)
00188 {
00189 struct context *ctx;
00190 unsigned int max_linelen, outsize, p, curbit, i;
00191 uint64_t sample;
00192 static uint64_t samplecount = 0, old_sample = 0;
00193 uint8_t *outbuf, *c;
00194
00195 if (!o) {
00196 sr_err("gnuplot out: %s: o was NULL", __func__);
00197 return SR_ERR_ARG;
00198 }
00199
00200 if (!o->internal) {
00201 sr_err("gnuplot out: %s: o->internal was NULL", __func__);
00202 return SR_ERR_ARG;
00203 }
00204
00205 if (!data_in) {
00206 sr_err("gnuplot out: %s: data_in was NULL", __func__);
00207 return SR_ERR_ARG;
00208 }
00209
00210 if (!data_out) {
00211 sr_err("gnuplot out: %s: data_out was NULL", __func__);
00212 return SR_ERR_ARG;
00213 }
00214
00215 if (!length_out) {
00216 sr_err("gnuplot out: %s: length_out was NULL", __func__);
00217 return SR_ERR_ARG;
00218 }
00219
00220 ctx = o->internal;
00221 max_linelen = 16 + ctx->num_enabled_probes * 2;
00222 outsize = length_in / ctx->unitsize * max_linelen;
00223 if (ctx->header)
00224 outsize += strlen(ctx->header);
00225
00226 if (!(outbuf = g_try_malloc0(outsize))) {
00227 sr_err("gnuplot out: %s: outbuf malloc failed", __func__);
00228 return SR_ERR_MALLOC;
00229 }
00230
00231 outbuf[0] = '\0';
00232 if (ctx->header) {
00233
00234 strncpy((char *)outbuf, ctx->header, outsize);
00235 g_free(ctx->header);
00236 ctx->header = NULL;
00237 }
00238
00239 for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) {
00240
00241 memcpy(&sample, data_in + i, ctx->unitsize);
00242
00243
00244
00245
00246
00247 if (samplecount++ != 0 && sample == old_sample) {
00248 if (i != (length_in - ctx->unitsize))
00249 continue;
00250 }
00251 old_sample = sample;
00252
00253
00254 c = outbuf + strlen((const char *)outbuf);
00255 sprintf((char *)c, "%" PRIu64 "\t", samplecount++);
00256
00257
00258 for (p = 0; p < ctx->num_enabled_probes; p++) {
00259 curbit = (sample & ((uint64_t) (1 << p))) >> p;
00260 c = outbuf + strlen((const char *)outbuf);
00261 sprintf((char *)c, "%d ", curbit);
00262 }
00263
00264 c = outbuf + strlen((const char *)outbuf);
00265 sprintf((char *)c, "\n");
00266 }
00267
00268 *data_out = outbuf;
00269 *length_out = strlen((const char *)outbuf);
00270
00271 return SR_OK;
00272 }
00273
00274 SR_PRIV struct sr_output_format output_gnuplot = {
00275 .id = "gnuplot",
00276 .description = "Gnuplot",
00277 .df_type = SR_DF_LOGIC,
00278 .init = init,
00279 .data = data,
00280 .event = event,
00281 };
00282
00283
00284 #if 0
00285 static int analog_init(struct sr_output *o)
00286 {
00287 struct context *ctx;
00288 struct sr_probe *probe;
00289 GSList *l;
00290 uint64_t samplerate;
00291 unsigned int i;
00292 int b, num_probes;
00293 char *c, *frequency_s;
00294 char wbuf[1000], comment[128];
00295 time_t t;
00296
00297 if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
00298 sr_err("gnuplot out: %s: ctx malloc failed", __func__);
00299 return SR_ERR_MALLOC;
00300 }
00301
00302 if (!(ctx->header = g_try_malloc0(MAX_HEADER_LEN + 1))) {
00303 g_free(ctx);
00304 sr_err("gnuplot out: %s: ctx->header malloc failed", __func__);
00305 return SR_ERR_MALLOC;
00306 }
00307
00308 o->internal = ctx;
00309 ctx->num_enabled_probes = 0;
00310 for (l = o->dev->probes; l; l = l->next) {
00311 probe = l->data;
00312 if (!probe->enabled)
00313 continue;
00314 ctx->probelist[ctx->num_enabled_probes++] = probe->name;
00315 }
00316 ctx->probelist[ctx->num_enabled_probes] = 0;
00317
00318 ctx->unitsize = sizeof(struct sr_analog_sample) +
00319 (ctx->num_enabled_probes * sizeof(struct sr_analog_probe));
00320
00321 num_probes = g_slist_length(o->dev->probes);
00322 comment[0] = '\0';
00323 if (o->dev->driver && sr_dev_has_hwcap(o->dev, SR_HWCAP_SAMPLERATE)) {
00324 samplerate = *((uint64_t *) o->dev->driver->dev_info_get(
00325 o->dev->driver_index, SR_DI_CUR_SAMPLERATE));
00326 if (!(frequency_s = sr_samplerate_string(samplerate))) {
00327 g_free(ctx->header);
00328 g_free(ctx);
00329 return SR_ERR;
00330 }
00331 snprintf(comment, 127, gnuplot_header_comment,
00332 ctx->num_enabled_probes, num_probes, frequency_s);
00333 g_free(frequency_s);
00334 }
00335
00336
00337 wbuf[0] = '\0';
00338 for (i = 0; i < ctx->num_enabled_probes; i++) {
00339 c = (char *)&wbuf + strlen((char *)&wbuf);
00340 sprintf(c, "# %d\t\t%s\n", i + 1, ctx->probelist[i]);
00341 }
00342
00343 if (!(frequency_s = sr_period_string(samplerate))) {
00344 g_free(ctx->header);
00345 g_free(ctx);
00346 return SR_ERR;
00347 }
00348 t = time(NULL);
00349 b = snprintf(ctx->header, MAX_HEADER_LEN, gnuplot_header,
00350 PACKAGE_STRING, ctime(&t), comment, frequency_s,
00351 (char *)&wbuf);
00352 g_free(frequency_s);
00353
00354 if (b < 0) {
00355 g_free(ctx->header);
00356 g_free(ctx);
00357 return SR_ERR;
00358 }
00359
00360 return 0;
00361 }
00362
00363 static int analog_data(struct sr_output *o, uint8_t *data_in,
00364 uint64_t length_in, uint8_t **data_out,
00365 uint64_t *length_out)
00366 {
00367 struct context *ctx;
00368 unsigned int max_linelen, outsize, p, i;
00369
00370 static uint64_t samplecount = 0;
00371 uint8_t *outbuf, *c;
00372 struct sr_analog_sample *sample;
00373
00374 ctx = o->internal;
00375
00376 max_linelen = 16 + ctx->num_enabled_probes * 30;
00377 outsize = length_in / ctx->unitsize * max_linelen;
00378 if (ctx->header)
00379 outsize += strlen(ctx->header);
00380
00381 if (!(outbuf = g_try_malloc0(outsize))) {
00382 sr_err("gnuplot out: %s: outbuf malloc failed", __func__);
00383 return SR_ERR_MALLOC;
00384 }
00385
00386 outbuf[0] = '\0';
00387 if (ctx->header) {
00388
00389 strncpy(outbuf, ctx->header, outsize);
00390 g_free(ctx->header);
00391 ctx->header = NULL;
00392 }
00393
00394 for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) {
00395
00396 sample = (struct sr_analog_sample *) (data_in + i);
00397
00398
00399 c = outbuf + strlen(outbuf);
00400 sprintf(c, "%" PRIu64 "\t", samplecount++);
00401
00402
00403 for (p = 0; p < ctx->num_enabled_probes; p++) {
00404
00405 c = outbuf + strlen(outbuf);
00406
00407
00408
00409
00410
00411
00412 sprintf(c, "%f ", (double) ((int16_t) (sample->probes[p].val &
00413 ((1 << sample->probes[p].res) - 1))));
00414 }
00415
00416 c = outbuf + strlen(outbuf);
00417 sprintf(c, "\n");
00418 }
00419
00420 *data_out = outbuf;
00421 *length_out = strlen(outbuf);
00422
00423 return SR_OK;
00424 }
00425
00426 struct sr_output_format output_analog_gnuplot = {
00427 .id = "analog_gnuplot",
00428 .description = "Gnuplot analog",
00429 .df_type = SR_DF_ANALOG,
00430 .init = analog_init,
00431 .data = analog_data,
00432 .event = event,
00433 };
00434 #endif