libsigrok
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines
chronovu_la8.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 <fcntl.h>
00023 #include <unistd.h>
00024 #include <sys/stat.h>
00025 #include "sigrok.h"
00026 #include "sigrok-internal.h"
00027 
00028 #define NUM_PACKETS             2048
00029 #define PACKET_SIZE             4096
00030 #define DEFAULT_NUM_PROBES      8
00031 
00032 /**
00033  * Convert the LA8 'divcount' value to the respective samplerate (in Hz).
00034  *
00035  * LA8 hardware: sample period = (divcount + 1) * 10ns.
00036  * Min. value for divcount: 0x00 (10ns sample period, 100MHz samplerate).
00037  * Max. value for divcount: 0xfe (2550ns sample period, 392.15kHz samplerate).
00038  *
00039  * @param divcount The divcount value as needed by the hardware.
00040  *
00041  * @return The samplerate in Hz, or 0xffffffffffffffff upon errors.
00042  */
00043 static uint64_t divcount_to_samplerate(uint8_t divcount)
00044 {
00045         if (divcount == 0xff)
00046                 return 0xffffffffffffffffULL;
00047 
00048         return SR_MHZ(100) / (divcount + 1);
00049 }
00050 
00051 static int format_match(const char *filename)
00052 {
00053         struct stat stat_buf;
00054         int ret;
00055 
00056         if (!filename) {
00057                 sr_err("la8 in: %s: filename was NULL", __func__);
00058                 // return SR_ERR; /* FIXME */
00059                 return FALSE;
00060         }
00061 
00062         if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
00063                 sr_err("la8 in: %s: input file '%s' does not exist",
00064                        __func__, filename);
00065                 // return SR_ERR; /* FIXME */
00066                 return FALSE;
00067         }
00068 
00069         if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
00070                 sr_err("la8 in: %s: input file '%s' not a regular file",
00071                        __func__, filename);
00072                 // return SR_ERR; /* FIXME */
00073                 return FALSE;
00074         }
00075 
00076         /* Only accept files of length 8MB + 5 bytes. */
00077         ret = stat(filename, &stat_buf);
00078         if (ret != 0) {
00079                 sr_err("la8 in: %s: Error getting file size of '%s'",
00080                        __func__, filename);
00081                 return FALSE;
00082         }
00083         if (stat_buf.st_size != (8 * 1024 * 1024 + 5)) {
00084                 sr_dbg("la8 in: %s: File size must be exactly 8388613 bytes ("
00085                        "it actually is %d bytes in size), so this is not a "
00086                        "ChronoVu LA8 file.", __func__, stat_buf.st_size);
00087                 return FALSE;
00088         }
00089 
00090         /* TODO: Check for divcount != 0xff. */
00091 
00092         return TRUE;
00093 }
00094 
00095 static int init(struct sr_input *in)
00096 {
00097         int num_probes, i;
00098         char name[SR_MAX_PROBENAME_LEN + 1];
00099 
00100         if (in->param && in->param[0]) {
00101                 num_probes = strtoul(in->param, NULL, 10);
00102                 if (num_probes < 1) {
00103                         sr_err("la8 in: %s: strtoul failed", __func__);
00104                         return SR_ERR;
00105                 }
00106         } else {
00107                 num_probes = DEFAULT_NUM_PROBES;
00108         }
00109 
00110         /* Create a virtual device. */
00111         in->vdev = sr_dev_new(NULL, 0);
00112 
00113         for (i = 0; i < num_probes; i++) {
00114                 snprintf(name, SR_MAX_PROBENAME_LEN, "%d", i);
00115                 /* TODO: Check return value. */
00116                 sr_dev_probe_add(in->vdev, name);
00117         }
00118 
00119         return SR_OK;
00120 }
00121 
00122 static int loadfile(struct sr_input *in, const char *filename)
00123 {
00124         struct sr_datafeed_header header;
00125         struct sr_datafeed_packet packet;
00126         struct sr_datafeed_logic logic;
00127         uint8_t buf[PACKET_SIZE], divcount;
00128         int i, fd, size, num_probes;
00129         uint64_t samplerate;
00130 
00131         /* TODO: Use glib functions! GIOChannel, g_fopen, etc. */
00132         if ((fd = open(filename, O_RDONLY)) == -1) {
00133                 sr_err("la8 in: %s: file open failed", __func__);
00134                 return SR_ERR;
00135         }
00136 
00137         num_probes = g_slist_length(in->vdev->probes);
00138 
00139         /* Seek to the end of the file, and read the divcount byte. */
00140         divcount = 0x00; /* TODO: Don't hardcode! */
00141 
00142         /* Convert the divcount value to a samplerate. */
00143         samplerate = divcount_to_samplerate(divcount);
00144         if (samplerate == 0xffffffffffffffffULL) {
00145                 close(fd); /* FIXME */
00146                 return SR_ERR;
00147         }
00148         sr_dbg("la8 in: %s: samplerate is %" PRIu64, __func__, samplerate);
00149 
00150         /* Send header packet to the session bus. */
00151         sr_dbg("la8 in: %s: sending SR_DF_HEADER packet", __func__);
00152         packet.type = SR_DF_HEADER;
00153         packet.payload = &header;
00154         header.feed_version = 1;
00155         gettimeofday(&header.starttime, NULL);
00156         header.num_logic_probes = num_probes;
00157         header.samplerate = samplerate;
00158         sr_session_send(in->vdev, &packet);
00159 
00160         /* TODO: Handle trigger point. */
00161 
00162         /* Send data packets to the session bus. */
00163         sr_dbg("la8 in: %s: sending SR_DF_LOGIC data packets", __func__);
00164         packet.type = SR_DF_LOGIC;
00165         packet.payload = &logic;
00166         logic.unitsize = (num_probes + 7) / 8;
00167         logic.data = buf;
00168 
00169         /* Send 8MB of total data to the session bus in small chunks. */
00170         for (i = 0; i < NUM_PACKETS; i++) {
00171                 /* TODO: Handle errors, handle incomplete reads. */
00172                 size = read(fd, buf, PACKET_SIZE);
00173                 logic.length = size;
00174                 sr_session_send(in->vdev, &packet);
00175         }
00176         close(fd); /* FIXME */
00177 
00178         /* Send end packet to the session bus. */
00179         sr_dbg("la8 in: %s: sending SR_DF_END", __func__);
00180         packet.type = SR_DF_END;
00181         packet.payload = NULL;
00182         sr_session_send(in->vdev, &packet);
00183 
00184         return SR_OK;
00185 }
00186 
00187 SR_PRIV struct sr_input_format input_chronovu_la8 = {
00188         .id = "chronovu-la8",
00189         .description = "ChronoVu LA8",
00190         .format_match = format_match,
00191         .init = init,
00192         .loadfile = loadfile,
00193 };
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines