libsigrok
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines
demo.c
Go to the documentation of this file.
00001 /*
00002  * This file is part of the sigrok project.
00003  *
00004  * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
00005  * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00020  */
00021 
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <string.h>
00025 #ifdef _WIN32
00026 #include <io.h>
00027 #include <fcntl.h>
00028 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
00029 #endif
00030 #include "sigrok.h"
00031 #include "sigrok-internal.h"
00032 
00033 /* TODO: Number of probes should be configurable. */
00034 #define NUM_PROBES             8
00035 
00036 #define DEMONAME               "Demo device"
00037 
00038 /* The size of chunks to send through the session bus. */
00039 /* TODO: Should be configurable. */
00040 #define BUFSIZE                4096
00041 
00042 /* Supported patterns which we can generate */
00043 enum {
00044         /**
00045          * Pattern which spells "sigrok" using '0's (with '1's as "background")
00046          * when displayed using the 'bits' output format.
00047          */
00048         PATTERN_SIGROK,
00049 
00050         /** Pattern which consists of (pseudo-)random values on all probes. */
00051         PATTERN_RANDOM,
00052 
00053         /**
00054          * Pattern which consists of incrementing numbers.
00055          * TODO: Better description.
00056          */
00057         PATTERN_INC,
00058 
00059         /** Pattern where all probes have a low logic state. */
00060         PATTERN_ALL_LOW,
00061 
00062         /** Pattern where all probes have a high logic state. */
00063         PATTERN_ALL_HIGH,
00064 };
00065 
00066 /* FIXME: Should not be global. */
00067 SR_PRIV GIOChannel *channels[2];
00068 
00069 struct context {
00070         int pipe_fds[2];
00071         uint8_t sample_generator;
00072         uint8_t thread_running;
00073         uint64_t samples_counter;
00074         int dev_index;
00075         void *session_dev_id;
00076         GTimer *timer;
00077 };
00078 
00079 static int hwcaps[] = {
00080         SR_HWCAP_LOGIC_ANALYZER,
00081         SR_HWCAP_DEMO_DEV,
00082         SR_HWCAP_SAMPLERATE,
00083         SR_HWCAP_PATTERN_MODE,
00084         SR_HWCAP_LIMIT_SAMPLES,
00085         SR_HWCAP_LIMIT_MSEC,
00086         SR_HWCAP_CONTINUOUS,
00087 };
00088 
00089 static struct sr_samplerates samplerates = {
00090         SR_HZ(1),
00091         SR_GHZ(1),
00092         SR_HZ(1),
00093         NULL,
00094 };
00095 
00096 static const char *pattern_strings[] = {
00097         "sigrok",
00098         "random",
00099         "incremental",
00100         "all-low",
00101         "all-high",
00102         NULL,
00103 };
00104 
00105 /* We name the probes 0-7 on our demo driver. */
00106 static const char *probe_names[NUM_PROBES + 1] = {
00107         "0",
00108         "1",
00109         "2",
00110         "3",
00111         "4",
00112         "5",
00113         "6",
00114         "7",
00115         NULL,
00116 };
00117 
00118 static uint8_t pattern_sigrok[] = {
00119         0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
00120         0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
00121         0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
00122         0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
00123         0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
00124         0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
00125         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00126         0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00127 };
00128 
00129 /* Private, per-device-instance driver context. */
00130 /* TODO: struct context as with the other drivers. */
00131 
00132 /* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
00133 static GSList *dev_insts = NULL;
00134 static uint64_t cur_samplerate = SR_KHZ(200);
00135 static uint64_t limit_samples = 0;
00136 static uint64_t limit_msec = 0;
00137 static int default_pattern = PATTERN_SIGROK;
00138 static GThread *my_thread;
00139 static int thread_running;
00140 
00141 static int hw_dev_acquisition_stop(int dev_index, void *cb_data);
00142 
00143 static int hw_init(const char *devinfo)
00144 {
00145         struct sr_dev_inst *sdi;
00146 
00147         /* Avoid compiler warnings. */
00148         (void)devinfo;
00149 
00150         sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
00151         if (!sdi) {
00152                 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
00153                 return 0;
00154         }
00155 
00156         dev_insts = g_slist_append(dev_insts, sdi);
00157 
00158         return 1;
00159 }
00160 
00161 static int hw_dev_open(int dev_index)
00162 {
00163         /* Avoid compiler warnings. */
00164         (void)dev_index;
00165 
00166         /* Nothing needed so far. */
00167 
00168         return SR_OK;
00169 }
00170 
00171 static int hw_dev_close(int dev_index)
00172 {
00173         /* Avoid compiler warnings. */
00174         (void)dev_index;
00175 
00176         /* Nothing needed so far. */
00177 
00178         return SR_OK;
00179 }
00180 
00181 static int hw_cleanup(void)
00182 {
00183         /* Nothing needed so far. */
00184         return SR_OK;
00185 }
00186 
00187 static void *hw_dev_info_get(int dev_index, int dev_info_id)
00188 {
00189         struct sr_dev_inst *sdi;
00190         void *info = NULL;
00191 
00192         if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
00193                 sr_err("demo: %s: sdi was NULL", __func__);
00194                 return NULL;
00195         }
00196 
00197         switch (dev_info_id) {
00198         case SR_DI_INST:
00199                 info = sdi;
00200                 break;
00201         case SR_DI_NUM_PROBES:
00202                 info = GINT_TO_POINTER(NUM_PROBES);
00203                 break;
00204         case SR_DI_PROBE_NAMES:
00205                 info = probe_names;
00206                 break;
00207         case SR_DI_SAMPLERATES:
00208                 info = &samplerates;
00209                 break;
00210         case SR_DI_CUR_SAMPLERATE:
00211                 info = &cur_samplerate;
00212                 break;
00213         case SR_DI_PATTERNS:
00214                 info = &pattern_strings;
00215                 break;
00216         }
00217 
00218         return info;
00219 }
00220 
00221 static int hw_dev_status_get(int dev_index)
00222 {
00223         /* Avoid compiler warnings. */
00224         (void)dev_index;
00225 
00226         return SR_ST_ACTIVE;
00227 }
00228 
00229 static int *hw_hwcap_get_all(void)
00230 {
00231         return hwcaps;
00232 }
00233 
00234 static int hw_dev_config_set(int dev_index, int hwcap, void *value)
00235 {
00236         int ret;
00237         char *stropt;
00238 
00239         /* Avoid compiler warnings. */
00240         (void)dev_index;
00241 
00242         if (hwcap == SR_HWCAP_PROBECONFIG) {
00243                 /* Nothing to do, but must be supported */
00244                 ret = SR_OK;
00245         } else if (hwcap == SR_HWCAP_SAMPLERATE) {
00246                 cur_samplerate = *(uint64_t *)value;
00247                 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
00248                        cur_samplerate);
00249                 ret = SR_OK;
00250         } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
00251                 limit_samples = *(uint64_t *)value;
00252                 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
00253                        limit_samples);
00254                 ret = SR_OK;
00255         } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
00256                 limit_msec = *(uint64_t *)value;
00257                 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
00258                        limit_msec);
00259                 ret = SR_OK;
00260         } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
00261                 stropt = value;
00262                 ret = SR_OK;
00263                 if (!strcmp(stropt, "sigrok")) {
00264                         default_pattern = PATTERN_SIGROK;
00265                 } else if (!strcmp(stropt, "random")) {
00266                         default_pattern = PATTERN_RANDOM;
00267                 } else if (!strcmp(stropt, "incremental")) {
00268                         default_pattern = PATTERN_INC;
00269                 } else if (!strcmp(stropt, "all-low")) {
00270                         default_pattern = PATTERN_ALL_LOW;
00271                 } else if (!strcmp(stropt, "all-high")) {
00272                         default_pattern = PATTERN_ALL_HIGH;
00273                 } else {
00274                         ret = SR_ERR;
00275                 }
00276                 sr_dbg("demo: %s: setting pattern to %d", __func__,
00277                        default_pattern);
00278         } else {
00279                 ret = SR_ERR;
00280         }
00281 
00282         return ret;
00283 }
00284 
00285 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
00286 {
00287         static uint64_t p = 0;
00288         struct context *ctx = data;
00289         uint64_t i;
00290 
00291         /* TODO: Needed? */
00292         memset(buf, 0, size);
00293 
00294         switch (ctx->sample_generator) {
00295         case PATTERN_SIGROK: /* sigrok pattern */
00296                 for (i = 0; i < size; i++) {
00297                         *(buf + i) = ~(pattern_sigrok[p] >> 1);
00298                         if (++p == 64)
00299                                 p = 0;
00300                 }
00301                 break;
00302         case PATTERN_RANDOM: /* Random */
00303                 for (i = 0; i < size; i++)
00304                         *(buf + i) = (uint8_t)(rand() & 0xff);
00305                 break;
00306         case PATTERN_INC: /* Simple increment */
00307                 for (i = 0; i < size; i++)
00308                         *(buf + i) = i;
00309                 break;
00310         case PATTERN_ALL_LOW: /* All probes are low */
00311                 memset(buf, 0x00, size);
00312                 break;
00313         case PATTERN_ALL_HIGH: /* All probes are high */
00314                 memset(buf, 0xff, size);
00315                 break;
00316         default:
00317                 sr_err("demo: %s: unknown pattern %d", __func__,
00318                        ctx->sample_generator);
00319                 break;
00320         }
00321 }
00322 
00323 /* Thread function */
00324 static void thread_func(void *data)
00325 {
00326         struct context *ctx = data;
00327         uint8_t buf[BUFSIZE];
00328         uint64_t nb_to_send = 0;
00329         int bytes_written;
00330         double time_cur, time_last, time_diff;
00331 
00332         time_last = g_timer_elapsed(ctx->timer, NULL);
00333 
00334         while (thread_running) {
00335                 /* Rate control */
00336                 time_cur = g_timer_elapsed(ctx->timer, NULL);
00337 
00338                 time_diff = time_cur - time_last;
00339                 time_last = time_cur;
00340 
00341                 nb_to_send = cur_samplerate * time_diff;
00342 
00343                 if (limit_samples) {
00344                         nb_to_send = MIN(nb_to_send,
00345                                       limit_samples - ctx->samples_counter);
00346                 }
00347 
00348                 /* Make sure we don't overflow. */
00349                 nb_to_send = MIN(nb_to_send, BUFSIZE);
00350 
00351                 if (nb_to_send) {
00352                         samples_generator(buf, nb_to_send, data);
00353                         ctx->samples_counter += nb_to_send;
00354 
00355                         g_io_channel_write_chars(channels[1], (gchar *)&buf,
00356                                 nb_to_send, (gsize *)&bytes_written, NULL);
00357                 }
00358 
00359                 /* Check if we're done. */
00360                 if ((limit_msec && time_cur * 1000 > limit_msec) ||
00361                     (limit_samples && ctx->samples_counter >= limit_samples))
00362                 {
00363                         close(ctx->pipe_fds[1]);
00364                         thread_running = 0;
00365                 }
00366 
00367                 g_usleep(10);
00368         }
00369 }
00370 
00371 /* Callback handling data */
00372 static int receive_data(int fd, int revents, void *cb_data)
00373 {
00374         struct sr_datafeed_packet packet;
00375         struct sr_datafeed_logic logic;
00376         static uint64_t samples_received = 0;
00377         unsigned char c[BUFSIZE];
00378         gsize z;
00379 
00380         /* Avoid compiler warnings. */
00381         (void)fd;
00382         (void)revents;
00383 
00384         do {
00385                 g_io_channel_read_chars(channels[0],
00386                                         (gchar *)&c, BUFSIZE, &z, NULL);
00387 
00388                 if (z > 0) {
00389                         packet.type = SR_DF_LOGIC;
00390                         packet.payload = &logic;
00391                         logic.length = z;
00392                         logic.unitsize = 1;
00393                         logic.data = c;
00394                         sr_session_send(cb_data, &packet);
00395                         samples_received += z;
00396                 }
00397         } while (z > 0);
00398 
00399         if (!thread_running && z <= 0) {
00400                 /* Make sure we don't receive more packets. */
00401                 g_io_channel_shutdown(channels[0], FALSE, NULL);
00402 
00403                 /* Send last packet. */
00404                 packet.type = SR_DF_END;
00405                 sr_session_send(cb_data, &packet);
00406 
00407                 return FALSE;
00408         }
00409 
00410         return TRUE;
00411 }
00412 
00413 static int hw_dev_acquisition_start(int dev_index, void *cb_data)
00414 {
00415         struct sr_datafeed_packet *packet;
00416         struct sr_datafeed_header *header;
00417         struct context *ctx;
00418 
00419         /* TODO: 'ctx' is never g_free()'d? */
00420         if (!(ctx = g_try_malloc(sizeof(struct context)))) {
00421                 sr_err("demo: %s: ctx malloc failed", __func__);
00422                 return SR_ERR_MALLOC;
00423         }
00424 
00425         ctx->sample_generator = default_pattern;
00426         ctx->session_dev_id = cb_data;
00427         ctx->dev_index = dev_index;
00428         ctx->samples_counter = 0;
00429 
00430         if (pipe(ctx->pipe_fds)) {
00431                 /* TODO: Better error message. */
00432                 sr_err("demo: %s: pipe() failed", __func__);
00433                 return SR_ERR;
00434         }
00435 
00436         channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
00437         channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
00438 
00439         /* Set channel encoding to binary (default is UTF-8). */
00440         g_io_channel_set_encoding(channels[0], NULL, NULL);
00441         g_io_channel_set_encoding(channels[1], NULL, NULL);
00442 
00443         /* Make channels to unbuffered. */
00444         g_io_channel_set_buffered(channels[0], FALSE);
00445         g_io_channel_set_buffered(channels[1], FALSE);
00446 
00447         sr_source_add(ctx->pipe_fds[0], G_IO_IN | G_IO_ERR, 40,
00448                       receive_data, ctx->session_dev_id);
00449 
00450         /* Run the demo thread. */
00451         g_thread_init(NULL);
00452         /* This must to be done between g_thread_init() & g_thread_create(). */
00453         ctx->timer = g_timer_new();
00454         thread_running = 1;
00455         my_thread =
00456             g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
00457         if (!my_thread) {
00458                 sr_err("demo: %s: g_thread_create failed", __func__);
00459                 return SR_ERR; /* TODO */
00460         }
00461 
00462         if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
00463                 sr_err("demo: %s: packet malloc failed", __func__);
00464                 return SR_ERR_MALLOC;
00465         }
00466 
00467         if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
00468                 sr_err("demo: %s: header malloc failed", __func__);
00469                 return SR_ERR_MALLOC;
00470         }
00471 
00472         packet->type = SR_DF_HEADER;
00473         packet->payload = header;
00474         header->feed_version = 1;
00475         gettimeofday(&header->starttime, NULL);
00476         header->samplerate = cur_samplerate;
00477         header->num_logic_probes = NUM_PROBES;
00478         sr_session_send(ctx->session_dev_id, packet);
00479         g_free(header);
00480         g_free(packet);
00481 
00482         return SR_OK;
00483 }
00484 
00485 /* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
00486 static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
00487 {
00488         /* Avoid compiler warnings. */
00489         (void)dev_index;
00490         (void)cb_data;
00491 
00492         /* Stop generate thread. */
00493         thread_running = 0;
00494 
00495         return SR_OK;
00496 }
00497 
00498 SR_PRIV struct sr_dev_driver demo_driver_info = {
00499         .name = "demo",
00500         .longname = "Demo driver and pattern generator",
00501         .api_version = 1,
00502         .init = hw_init,
00503         .cleanup = hw_cleanup,
00504         .dev_open = hw_dev_open,
00505         .dev_close = hw_dev_close,
00506         .dev_info_get = hw_dev_info_get,
00507         .dev_status_get = hw_dev_status_get,
00508         .hwcap_get_all = hw_hwcap_get_all,
00509         .dev_config_set = hw_dev_config_set,
00510         .dev_acquisition_start = hw_dev_acquisition_start,
00511         .dev_acquisition_stop = hw_dev_acquisition_stop,
00512 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines