libsigrok
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines
csv.c
Go to the documentation of this file.
00001 /*
00002  * This file is part of the sigrok project.
00003  *
00004  * Copyright (C) 2011 Uwe Hermann <uwe@hermann-uwe.de>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
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         uint64_t samplerate;
00033         GString *header;
00034         char separator;
00035 };
00036 
00037 /*
00038  * TODO:
00039  *  - Option to specify delimiter character and/or string.
00040  *  - Option to (not) print metadata as comments.
00041  *  - Option to specify the comment character(s), e.g. # or ; or C/C++-style.
00042  *  - Option to (not) print samplenumber / time as extra column.
00043  *  - Option to "compress" output (only print changed samples, VCD-like).
00044  *  - Option to print comma-separated bits, or whole bytes/words (for 8/16
00045  *    probe LAs) as ASCII/hex etc. etc.
00046  *  - Trigger support.
00047  */
00048 
00049 static int init(struct sr_output *o)
00050 {
00051         struct context *ctx;
00052         struct sr_probe *probe;
00053         GSList *l;
00054         int num_probes;
00055         uint64_t samplerate;
00056         time_t t;
00057         unsigned int i;
00058 
00059         if (!o) {
00060                 sr_err("csv out: %s: o was NULL", __func__);
00061                 return SR_ERR_ARG;
00062         }
00063 
00064         if (!o->dev) {
00065                 sr_err("csv out: %s: o->dev was NULL", __func__);
00066                 return SR_ERR_ARG;
00067         }
00068 
00069         if (!o->dev->driver) {
00070                 sr_err("csv out: %s: o->dev->driver was NULL", __func__);
00071                 return SR_ERR_ARG;
00072         }
00073 
00074         if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
00075                 sr_err("csv out: %s: ctx malloc failed", __func__);
00076                 return SR_ERR_MALLOC;
00077         }
00078 
00079         o->internal = ctx;
00080 
00081         /* Get the number of probes, their names, and the unitsize. */
00082         /* TODO: Error handling. */
00083         for (l = o->dev->probes; l; l = l->next) {
00084                 probe = l->data;
00085                 if (!probe->enabled)
00086                         continue;
00087                 ctx->probelist[ctx->num_enabled_probes++] = probe->name;
00088         }
00089         ctx->probelist[ctx->num_enabled_probes] = 0;
00090         ctx->unitsize = (ctx->num_enabled_probes + 7) / 8;
00091 
00092         num_probes = g_slist_length(o->dev->probes);
00093 
00094         if (sr_dev_has_hwcap(o->dev, SR_HWCAP_SAMPLERATE)) {
00095                 samplerate = *((uint64_t *) o->dev->driver->dev_info_get(
00096                                 o->dev->driver_index, SR_DI_CUR_SAMPLERATE));
00097                 /* TODO: Error checks. */
00098         } else {
00099                 samplerate = 0; /* TODO: Error or set some value? */
00100         }
00101         ctx->samplerate = samplerate;
00102 
00103         ctx->separator = ',';
00104 
00105         ctx->header = g_string_sized_new(512);
00106 
00107         t = time(NULL);
00108 
00109         /* Some metadata */
00110         g_string_append_printf(ctx->header, "; CSV, generated by %s on %s",
00111                                PACKAGE_STRING, ctime(&t));
00112         g_string_append_printf(ctx->header, "; Samplerate: %"PRIu64"\n",
00113                                ctx->samplerate);
00114 
00115         /* Columns / channels */
00116         g_string_append_printf(ctx->header, "; Channels (%d/%d): ",
00117                                ctx->num_enabled_probes, num_probes);
00118         for (i = 0; i < ctx->num_enabled_probes; i++)
00119                 g_string_append_printf(ctx->header, "%s, ", ctx->probelist[i]);
00120         g_string_append_printf(ctx->header, "\n");
00121 
00122         return 0; /* TODO: SR_OK? */
00123 }
00124 
00125 static int event(struct sr_output *o, int event_type, uint8_t **data_out,
00126                  uint64_t *length_out)
00127 {
00128         struct context *ctx;
00129 
00130         if (!o) {
00131                 sr_err("csv out: %s: o was NULL", __func__);
00132                 return SR_ERR_ARG;
00133         }
00134 
00135         if (!(ctx = o->internal)) {
00136                 sr_err("csv out: %s: o->internal was NULL", __func__);
00137                 return SR_ERR_ARG;
00138         }
00139 
00140         if (!data_out) {
00141                 sr_err("csv out: %s: data_out was NULL", __func__);
00142                 return SR_ERR_ARG;
00143         }
00144 
00145         switch (event_type) {
00146         case SR_DF_TRIGGER:
00147                 sr_dbg("csv out: %s: SR_DF_TRIGGER event", __func__);
00148                 /* TODO */
00149                 *data_out = NULL;
00150                 *length_out = 0;
00151                 break;
00152         case SR_DF_END:
00153                 sr_dbg("csv out: %s: SR_DF_END event", __func__);
00154                 /* TODO */
00155                 *data_out = NULL;
00156                 *length_out = 0;
00157                 g_free(o->internal);
00158                 o->internal = NULL;
00159                 break;
00160         default:
00161                 sr_err("csv out: %s: unsupported event type: %d", __func__,
00162                        event_type);
00163                 *data_out = NULL;
00164                 *length_out = 0;
00165                 break;
00166         }
00167 
00168         return SR_OK;
00169 }
00170 
00171 static int data(struct sr_output *o, const uint8_t *data_in,
00172                 uint64_t length_in, uint8_t **data_out, uint64_t *length_out)
00173 {
00174         struct context *ctx;
00175         GString *outstr;
00176         uint64_t sample, i;
00177         int j;
00178 
00179         if (!o) {
00180                 sr_err("csv out: %s: o was NULL", __func__);
00181                 return SR_ERR_ARG;
00182         }
00183 
00184         if (!(ctx = o->internal)) {
00185                 sr_err("csv out: %s: o->internal was NULL", __func__);
00186                 return SR_ERR_ARG;
00187         }
00188 
00189         if (!data_in) {
00190                 sr_err("csv out: %s: data_in was NULL", __func__);
00191                 return SR_ERR_ARG;
00192         }
00193 
00194         if (ctx->header) {
00195                 /* First data packet. */
00196                 outstr = ctx->header;
00197                 ctx->header = NULL;
00198         } else {
00199                 outstr = g_string_sized_new(512);
00200         }
00201 
00202         for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) {
00203                 memcpy(&sample, data_in + i, ctx->unitsize);
00204                 for (j = ctx->num_enabled_probes - 1; j >= 0; j--) {
00205                         g_string_append_printf(outstr, "%d%c",
00206                                 (int)((sample & (1 << j)) >> j),
00207                                 ctx->separator);
00208                 }
00209                 g_string_append_printf(outstr, "\n");
00210         }
00211 
00212         *data_out = (uint8_t *)outstr->str;
00213         *length_out = outstr->len;
00214         g_string_free(outstr, FALSE);
00215 
00216         return SR_OK;
00217 }
00218 
00219 SR_PRIV struct sr_output_format output_csv = {
00220         .id = "csv",
00221         .description = "Comma-separated values (CSV)",
00222         .df_type = SR_DF_LOGIC,
00223         .init = init,
00224         .data = data,
00225         .event = event,
00226 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines