• Main Page
  • Related Pages
  • Data Structures
  • Files
  • File List
  • Globals

llcontrol-syncECM-core.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * File: llcontrol-syncECM-core.c
00004  *
00005  * $RCSfile: llcontrol-syncECM-core.c,v $
00006  * 
00007  * Copyright (C) 2001 D-TACQ Solutions Ltd
00008  * not to be used without owner's permission
00009  *
00010  * Description:
00011  *     application implementing the LOW LATENCY CONTROL feature
00012  *
00013  * $Id: llcontrol-sync2v-core.c,v 1.1 2009/03/26 14:52:03 pgm Exp $
00014  * $Log: llcontrol-sync2v-core.c,v $
00015  * Revision 1.1  2009/03/26 14:52:03  pgm
00016  * split sync2v, acq216 from main core
00017  *
00018  * Revision 1.1.4.27  2009/03/26 12:40:36  pgm
00019  * reuse same dac_src for each card, avoid data overrun
00020  */
00021 
00022 /** @file llcontrol-syncECM-core.c demonstrates SYNC_ECM mode. (archive) */
00023 
00024 #include "local.h"
00025 
00026 #include <assert.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 
00030 #include <errno.h>
00031 #include <fcntl.h>
00032 #include <sys/ioctl.h>
00033 #include <sys/mman.h>
00034 #include <sys/stat.h>
00035 #include <sys/time.h>
00036 #include <sys/types.h>
00037 #include <stdio.h>
00038 #include <unistd.h>
00039 
00040 #include <popt.h>
00041 
00042 #include "acq32ioctl.h"
00043 #include "acq32busprot.h"
00044 
00045 #include "llif.h"
00046 #include "llprotocol.h"
00047 
00048 
00049 #include "llcontrol.h"
00050 #include "x86timer.h"
00051 
00052 #define FLAVOR "ACQ196"
00053 #include "llcontrol-core.h"
00054 
00055 
00056 void appEnterLLC_SYNC_ECM(
00057         int icard, struct MU *mu, struct TestDescription *td)
00058 /** set up LLCV2_INIT buffer and enter mode.
00059  *  Buffer set up as 4K block at offset 0
00060  * @todo - this overwrites settings from initV2Stats(), initV2Stats is therefore redundant.
00061 */
00062 {
00063         u32* init_buf = getVaddr(EACHBUF(td), 0);
00064         u32 target_pa = getBusAddr(EACHBUF(td), 0);
00065 
00066         /** set up for single 4K buffer */
00067         llcv2_hb_offset = 0;
00068 
00069         /** uses V2 synchronization */
00070         updateTstats = v2_updateTstats;
00071         waitDmaDone  = card_v2_WaitDmaDone;
00072 
00073         init_buf[LLCV2_INIT_MARKER] = LLCV2_INIT_MAGIC_MARKER;
00074         init_buf[LLCV2_INIT_AI_HSBT] = target_pa + LLCV2_AI_HSBT;
00075         init_buf[LLCV2_INIT_AO_HSBS] = target_pa + LLCV2_AO_HSBS;
00076         init_buf[LLCV2_INIT_DO_HSBS] = target_pa + LLCV2_DO_HSBS;
00077         init_buf[LLCV2_INIT_STATUS_HSBT]  = target_pa + LLCV2_STATUS_HSBT;
00078 
00079         enterLLC_SYNC_ECM(
00080                 mu, td->clkpos, td->trpos, 
00081                 td->arg.divisor,td->internal_loopback,
00082                 commandModifiers(td),
00083                 target_pa );
00084 }
00085 
00086 
00087 int runSYNC_ECM(struct TestDescription *td, int soft_clock)
00088 /** runs the test SYNC_ECM mode.
00089  * PSEUDO-CODE:
00090  *
00091  - (1) Clear the latch timer
00092  - (2) Set a local memory target address and arm the capture
00093  - (3) Poll for counter running (hardware counter starts on external gate)
00094  - (4) Iterate for required number of samples:
00095  - (5)     [optionally send a soft clock command]  trigger an acquisition
00096  - (6)     Wait for DMA Done - at this point data is available in target mem.
00097  *         A "real" control application is probably getting most of its calcs 
00098  *         done here rather than simply polling
00099  - (7)     [Get the latch (sample) and current uSec counters from the boards - 
00100  *          only if interested]
00101  - (8)     Check the process has not stopped (external gate high)
00102  - (b)     write data to host side buffer(LLCV2_AO_HSBS) 
00103  - (b.1)
00104          * take the incoming value on feedback_channel
00105          * and propagate to all DACS.
00106          * default is to assume HAWG on DAC0
00107          * (so feedback_channel better be 0 !),
00108          * but td->update_dacs makes a better test.
00109  - (b.15)  
00110          * special case where we are DRIVING the
00111          * initial DAC signal from host side. 
00112  - (b.2)
00113          *  simple feedforward case - just drive all DACS
00114          *  from AWG pattern.
00115  */
00116 {
00117         struct TimingStats tstats[MAXCARDS] = {};
00118         struct DacBuf {
00119                 MFA mfa;
00120                 void* bbb;
00121         } dac_buf[MAXCARDS];
00122 #define EACHBBB      (dac_buf[icard].bbb)
00123 #define EACHDAC_BASE (EACHBBB + LLCV2_AO_HSBS)
00124 #define EACHDAC_BASE16 ((u16*)EACHDAC_BASE)
00125 #define V2SETDACS(src, icard) \
00126         memcpy(EACHDAC_BASE, (src), DAC_SAMPLE_SIZE)
00127 
00128         u32 cmd = LLC_MAKE_DECIM(td->decimation);
00129 #define OFFSET 0
00130 
00131         unsigned ipoll = 0;
00132         int uses_dacs = td->update_dacs || td->feedback;
00133         void* dac_data;
00134 
00135         EACHCARD_INIT;
00136 
00137         if (uses_dacs) FOREACHCARD { /* (a) */
00138                 EACHBBB = getVaddr(EACHBUF(td), 0);
00139                 printf("card %d uses_dacs EACHBBB %p "
00140                        "EACHDAC_BASE %p bus 0x%08x\n",
00141                        icard, EACHBBB, EACHDAC_BASE,
00142                        getBusAddr(EACHBUF(td), LLCV2_AO_HSBS) );
00143         }
00144 
00145         FOREACHCARD{ /* (1) */
00146                 llSetTlatch(EACHMBX(td), tstats[icard].tlatch = 0xffffffff);
00147                 llv2InitDmaDone(
00148                         getVaddr(EACHBUF(td), LLCV2_OFFSET_STATUS_HSBT));
00149         }
00150    
00151         FOREACHCARD{ /* (2) */
00152                 updateTargetAddr(cmd+LLC_CSR_M_ARM, EACHCARD(td), OFFSET);
00153         }
00154 
00155         if (td->update_dacs){
00156                 dac_data = td_get_next_dac_data(td);    
00157                 FOREACHCARD{
00158                         V2SETDACS(dac_data, icard);
00159                 }
00160         }       
00161 
00162         // wait for gate /* (3) */
00163 
00164         while( !llCounterRunning(FIRSTMBX(td), cmd) ){ 
00165                 POLLALERT(ipoll, "Polling for Counter Running\n");
00166         }
00167 
00168         INIT_TIMER;
00169         /* WORKTODO - assumes all cards now running */
00170 
00171         for ( td->iter = 0; td->iter != td->iterations; ++td->iter ){ /* (4) */
00172                 if (soft_clock) FOREACHCARD{ /* (5) */
00173                         llSetCmd(EACHMBX(td), cmd+LLC_CSR_M_SOFTCLOCK);
00174                 }
00175         
00176                 FOREACHCARD{                                  /* (6)+(7) */
00177                         MARK_TIME(1, "waitDmaDone() before");
00178                         tstats[icard].tlatch = waitDmaDone(EACHCARD(td));
00179                         MARK_TIME(2, "waitDmaDone() after");
00180                 }
00181 
00182                 if (!td->min_latency_test) FOREACHCARD{        /* (6)+(7) */
00183                         updateTstats(cmd, EACHCARD(td), &tstats[icard]);    
00184                 }
00185 
00186                 
00187                 if (td->do_work){
00188                         doApplicationWork(td, OFFSET);
00189                 }
00190 
00191                 if (td->feedback) { /* (b.1) */
00192                         u16 *pvin = (u16 *)getVaddr(FIRSTBUF(td), OFFSET);
00193                         u16 vin = pvin[td->feedback_channel];
00194                         u32 feedback = vin << 16 | vin;
00195 
00196                         PRINTF(1)("feedback 0x%08x\n", feedback);
00197 
00198                         FOREACHCARD{   
00199                                 MARK_TIME(3, "feedback 1");
00200                                 memset32(EACHDAC_BASE, feedback, DAC_COUNT/2);
00201 
00202                                 if (td->update_dacs){ /* (b.15) */
00203 
00204                                         u16* excite = td_get_next_dac_data(td);
00205                                 
00206                                         EACHDAC_BASE16[td->feedback_channel] 
00207                                          = excite[td->feedback_channel];
00208                                 }
00209                                 MARK_TIME(4, "feedback 2");
00210                         }
00211                 }else if (td->update_dacs){ /** (b.2) */
00212                         dac_data = td_get_next_dac_data(td);
00213                         FOREACHCARD{
00214                                 V2SETDACS(dac_data, icard);
00215                                 MARK_TIME(5, "update_dacs");
00216                         }
00217                 }
00218 
00219 #if IGNORE_COUNTER_STOP
00220         /* check process completion.
00221          * if hardware_gateoff is employed, then the app would need
00222          * to make use of a pre-arranged DIO encoding for on/off instead
00223          * Stub out if not needed, as it represents unnecessary
00224          * command handling for the target
00225          */              
00226                 if (!td->hardware_gate_off &&
00227                      !llCounterRunning(FIRSTMBX(td), cmd )){          /* (8) */
00228                         fprintf( stderr, "Trigger is off - stop\n" );
00229                         break;
00230                 }
00231 #endif          
00232                 FOREACHCARD_MARK_TIME(9, "after llCounterRunning check");
00233 
00234                 if (td->tlog){          
00235                         FOREACHCARD{
00236                                 tstats[icard].target_poll =
00237                                         getMboxPollcount(EACHMBX(td));
00238                                 MARK_TIME(10, "10");
00239                                 updateTimingStats(
00240                                         td->stats_buf[icard], 
00241                                         td->iter, 
00242                                         &tstats[icard]);
00243                         }
00244                 }       
00245                 TIMER_CHECK_OVERFLOW;
00246         }
00247 
00248         G_quit = 1;
00249         return 0;
00250 #undef EACHMFA
00251 #undef EACHBBB
00252 #undef EACHDAC_BASE
00253 #undef EACHDAC_BASE16
00254 }
00255 

Generated on Wed Jan 5 2011 for llcontrol by  doxygen 1.7.1