Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

GrMC4020Source.h

Go to the documentation of this file.
00001 /* -*- Mode: c++ -*- */ 00002 /* 00003 * Copyright 2001 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio 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, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00020 * Boston, MA 02111-1307, USA. 00021 */ 00022 #ifndef _GRMC4020SOURCE_H_ 00023 #define _GRMC4020SOURCE_H_ 00024 00025 extern "C" { 00026 #include <sys/ioctl.h> 00027 #include <fcntl.h> 00028 #include <errno.h> 00029 #include <assert.h> 00030 } 00031 00032 #include <VrSource.h> 00033 #include <GrMC4020Buffer.h> 00034 #include <mc4020.h> 00035 00036 static const char *GRMC_DEVICE_NAME = "/dev/mc4020_0"; 00037 static const unsigned long GRMC_DEFAULT_CONFIG_BITMASK = MCC_CH0_EN | MCC_ALL_5V; 00038 static const double GRMC_DEFAULT_SAMPLE_FREQ = 20e6; 00039 00040 #define SAMPLES_PER_PAGE (PAGE_SIZE / sizeof (oType)) 00041 00042 00043 // FIXME ought to be configurable 00044 #define MC4020_BUFFER_SIZE (16L << 20) // 16 MB 00045 00046 00047 template<class oType> 00048 class GrMC4020Source: public VrSource<oType> { 00049 00050 public: 00051 virtual const char *name() { return "GrMC4020Source"; } 00052 00053 virtual float memoryTouched() { 00054 return 0; //no outputs are cached 00055 } 00056 00057 virtual int work2(VrSampleRange output, void *o[]); 00058 virtual void initOutputBuffer(int n); 00059 00060 GrMC4020Source(double sample_freq = GRMC_DEFAULT_SAMPLE_FREQ, 00061 unsigned long a_bitmask = GRMC_DEFAULT_CONFIG_BITMASK); 00062 00063 protected: 00064 int device_fd; 00065 unsigned long config_bitmask; 00066 unsigned long buffersize_pages; 00067 00068 // we own num_pages starting at page_index 00069 00070 unsigned long page_index; // driver page index of first page we own 00071 VrSampleIndex sample_index; // sample index that corresponds to page_index 00072 unsigned long num_pages; // number of driver pages we own 00073 00074 unsigned long npages_to_free (); 00075 unsigned long index_sub (unsigned long a, unsigned long b); 00076 }; 00077 00078 template<class oType> unsigned long 00079 GrMC4020Source<oType>::index_sub (unsigned long a, unsigned long b) 00080 { 00081 long s = a - b; 00082 00083 if (s < 0) 00084 s += buffersize_pages; 00085 00086 assert (s >= 0 && (unsigned long) s < buffersize_pages); 00087 return s; 00088 } 00089 00097 template<class oType> unsigned long 00098 GrMC4020Source<oType>::npages_to_free () 00099 { 00100 VrSampleIndex minRP = proc_minRP (); 00101 00102 // round down to page boundary 00103 minRP &= ~((VrSampleIndex) SAMPLES_PER_PAGE - 1); 00104 00105 assert (minRP != (VrSampleIndex) -1); 00106 assert (minRP >= sample_index); 00107 00108 return (unsigned long) (minRP - sample_index) / SAMPLES_PER_PAGE; 00109 } 00110 00111 template<class oType> int 00112 GrMC4020Source<oType>::work2(VrSampleRange output, void *ao[]) 00113 { 00114 struct mc4020_status status; 00115 VrSampleIndex target_index = output.index + output.size; 00116 unsigned long npgs; 00117 int last_lost = 0; 00118 00119 sync(output.index); 00120 00121 // fprintf (stderr, "@"); 00122 00123 while ((sample_index + num_pages * SAMPLES_PER_PAGE) < target_index){ 00124 npgs = npages_to_free (); 00125 00126 // fprintf (stderr, "f: %lu\n", npgs); 00127 00128 status.num = npgs; // free npgs pages 00129 status.index = page_index; // starting here 00130 00131 // free the pages and get new active region 00132 if (ioctl(device_fd, GIOCSETGETSTATUS, &status) < 0) { 00133 perror("GrMC4020Source: failed to get mc4020 status"); 00134 exit(-1); 00135 } 00136 00137 // how many pages did the beginning of our buffer advance? 00138 // new_index - old_index 00139 unsigned long delta = index_sub (status.index, page_index); 00140 assert (npgs == delta); 00141 00142 sample_index += delta * SAMPLES_PER_PAGE; 00143 00144 // fprintf (stderr, "G: %lu\n", index_sub (status.index + status.num, page_index + num_pages)); 00145 00146 // remember new range 00147 page_index = status.index; 00148 num_pages = status.num; 00149 00150 // do something about overruns 00151 if(status.lost && !last_lost) { 00152 // fprintf(stderr,"GrMC4020Source: overrun\n"); 00153 fputc ('O', stderr); 00154 } 00155 last_lost = status.lost; 00156 } 00157 00158 return output.size; 00159 } 00160 00161 00162 template<class oType> void 00163 GrMC4020Source<oType>::initOutputBuffer (int n) 00164 { 00165 if (n != 0) { 00166 fprintf(stderr,"GrMC4020Source can only have one output buffer.\n"); 00167 exit(-1); 00168 } 00169 outBuffer[0] = new GrMC4020Buffer (this, device_fd, 00170 buffersize_pages * PAGE_SIZE); 00171 } 00172 00173 template<class oType> 00174 GrMC4020Source<oType>::GrMC4020Source(double sample_freq, unsigned long bitmask) 00175 : device_fd(-1), page_index(0), sample_index(0), num_pages(0) 00176 { 00177 struct mc4020_config c; 00178 00179 buffersize_pages = MC4020_BUFFER_SIZE / PAGE_SIZE; 00180 00181 if ((device_fd = open(GRMC_DEVICE_NAME, O_RDONLY)) < 0) { 00182 perror(GRMC_DEVICE_NAME); 00183 exit(1); 00184 } 00185 00186 if ((bitmask & MCC_CLK_MASK) == MCC_CLK_INTERNAL) 00187 c.scan_rate = (unsigned long) sample_freq; 00188 else 00189 c.scan_rate = 2; // minimum divisor 00190 00191 config_bitmask = (bitmask & ~MCC_ASRC_MASK) | MCC_ASRC_BNC; // ensure some sanity 00192 00193 if ((bitmask & (MCC_CH0_EN | MCC_CH1_EN | MCC_CH2_EN | MCC_CH3_EN)) == 0){ 00194 fprintf (stderr, "GrMC4020Source: you must enable at least one channel\n"); 00195 exit (1); 00196 } 00197 00198 c.bitmask = config_bitmask; 00199 00200 if (ioctl (device_fd, GIOCSETCONFIG, &c) < 0){ 00201 perror ("can't set GrMC4020Source configuration (GIOCSETCONFIG)"); 00202 exit (1); 00203 } 00204 00205 if (ioctl (device_fd, GIOCSETBUFSIZE, buffersize_pages * PAGE_SIZE) < 0) { 00206 fprintf (stderr, "buffersize = %ld (%#lx)\n", MC4020_BUFFER_SIZE, MC4020_BUFFER_SIZE); 00207 perror("GrMC4020Buffer(allocateBuffer): Failed to set buffersize"); 00208 exit(-1); 00209 } 00210 00211 if (ioctl (device_fd, GIOCSTART) < 0){ 00212 perror ("GIOCSTART failed"); 00213 exit (1); 00214 } 00215 00216 00217 setSamplingFrequency (sample_freq); 00218 00219 setOutputSize (SAMPLES_PER_PAGE); 00220 } 00221 00222 #endif

Generated on Wed Aug 4 02:22:04 2004 for GNU Radio by doxygen 1.3.8