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

llcontrol-sync2v-core.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * File: llcontrol-sync2v-core.c
00004  *
00005  * $RCSfile: llcontrol-sync2v-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.3 2009/08/06 18:31:42 pgm Exp $
00014  * $Log: llcontrol-sync2v-core.c,v $
00015  * Revision 1.3  2009/08/06 18:31:42  pgm
00016  * README.RFM
00017  *
00018  * Revision 1.2  2009/04/02 13:19:01  pgm
00019  * docs away
00020  *
00021  * Revision 1.1  2009/03/26 14:52:03  pgm
00022  * split sync2v, acq216 from main core
00023  *
00024  * Revision 1.1.4.27  2009/03/26 12:40:36  pgm
00025  * reuse same dac_src for each card, avoid data overrun
00026  */
00027 
00028 /** @file llcontrol-sync2v-core.c demonstrates <b>SYNC_2V</b> mode. 
00029  - ./set.sync2v
00030  - llcontrol [opts] -W SYNC2V <a>ECM</a>
00031  
00032  - SYNC2V optimises the data transfer by reducing the number of 
00033     transfers-per-cycle to 2:
00034   - VI : all the inputs in one block.
00035   - VO : all the outputs in one block.
00036    - definitions of offsets in VI, VO are in acq32busprot.h, look for
00037     <b>LLCV2_</b>
00038 */
00039 #include "local.h"
00040 
00041 #include <assert.h>
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 
00045 #include <errno.h>
00046 #include <fcntl.h>
00047 #include <sys/ioctl.h>
00048 #include <sys/mman.h>
00049 #include <sys/stat.h>
00050 #include <sys/time.h>
00051 #include <sys/types.h>
00052 #include <stdio.h>
00053 #include <unistd.h>
00054 
00055 #include <popt.h>
00056 
00057 #include "acq32ioctl.h"
00058 #include "acq32busprot.h"
00059 
00060 #include "llif.h"
00061 #include "llprotocol.h"
00062 
00063 
00064 #include "llcontrol.h"
00065 #include "x86timer.h"
00066 
00067 #define FLAVOR "ACQ196"
00068 #include "llcontrol-core.h"
00069 
00070 
00071 static void sync_2v_updateTstats(
00072         u32 cmd, struct Card* card, struct TimingStats* tstats)
00073 /** updates timing stats from embedded host buffer data */
00074 {
00075 #define SAMPLE_SIZE (96*2)   /* WORKTODO */
00076         u32* stats = getVaddr(card->buf, card->sync_2v_offset_status_hsbt);
00077         tstats->tinst = llv2_extend32(stats[LLC_SYNC2V_IN_MBOX2], 
00078                                       stats[LLC_SYNC2V_IN_TINST]);
00079         tstats->tprocess = LLC_GET_TCYCLE(stats[LLC_SYNC2V_IN_MBOX0]);
00080 }
00081 
00082 static u32 card_sync_2v_WaitDmaDone(struct Card* card)
00083 {
00084         return card->tlatch = llv2WaitDmaDone_2v(card->mbx, 
00085                   getVaddr(card->buf, card->sync_2v_offset_status_hsbt),
00086                   card->tlatch
00087         );
00088 }
00089 
00090 void appEnterLLC_SYNC_2V(
00091         int icard, struct MU *mu, struct TestDescription *td)
00092 /** set up LLCV2_INIT buffer and enter mode.
00093  *  Buffer set up as 4K block at offset 0
00094  * @todo - this overwrites settings from initV2Stats(), initV2Stats is therefore redundant.
00095 */
00096 {
00097         u32* init_buf = getVaddr(EACHBUF(td), 0);
00098         u32 target_pa = getBusAddr(EACHBUF(td), 0);
00099         struct Card* card = &td->cards[icard];
00100 
00101         PRINTF(2)("appEnterLLC_SYNC_2V() va:%p pa:0x%08x\n",
00102                 init_buf, target_pa);
00103 
00104                         
00105         /** set up for single 4K buffer */
00106         llcv2_hb_offset = 0;
00107         card->sync_2v_offset_status_hsbt = 
00108                 LLCV2_AI_HSBT + td->channels*sizeof(short);
00109         card->tlatch = 0;
00110 
00111         /** uses V2 synchronization */
00112         updateTstats = sync_2v_updateTstats;
00113         waitDmaDone  = card_sync_2v_WaitDmaDone;
00114 
00115         init_buf[LLCV2_INIT_MARKER] = LLCV2_INIT_MAGIC_MARKER;
00116         init_buf[LLCV2_INIT_AI_HSBT] = target_pa + LLCV2_AI_HSBT;
00117         init_buf[LLCV2_INIT_AO_HSBS] = target_pa + LLCV2_AO_HSBS;
00118 
00119         
00120         enterLLC_SYNC_ECM(
00121                 mu, td->clkpos, td->trpos, 
00122                 td->arg.divisor,td->internal_loopback,
00123                 commandModifiers(td),
00124                 target_pa );
00125 }
00126 
00127 int runSYNC_2V(struct TestDescription *td, int soft_clock)
00128 /** runs the test SYNC_2V mode.
00129  * PSEUDO-CODE:
00130  *
00131  - (1) Clear the latch timer
00132  - (2) Set a local memory target address and arm the capture
00133  - (3) Poll for counter running (hardware counter starts on external gate)
00134  - (4) Iterate for required number of samples:
00135  - (5)     [optionally send a soft clock command]  trigger an acquisition
00136  - (6)     Wait for DMA Done - at this point data is available in target mem.
00137  *         A "real" control application is probably getting most of its calcs 
00138  *         done here rather than simply polling
00139  - (7)     [Get the latch (sample) and current uSec counters from the boards - 
00140  *          only if interested]
00141  - (8)     Check the process has not stopped (external gate high)
00142  - (b)     write data to host side buffer(LLCV2_AO_HSBS) 
00143  - (b.1)
00144          * take the incoming value on feedback_channel
00145          * and propagate to all DACS.
00146          * default is to assume HAWG on DAC0
00147          * (so feedback_channel better be 0 !),
00148          * but td->update_dacs makes a better test.
00149  - (b.15)  
00150          * special case where we are DRIVING the
00151          * initial DAC signal from host side. 
00152  - (b.2)
00153          *  simple feedforward case - just drive all DACS
00154          *  from AWG pattern.
00155  */
00156 {
00157         struct TimingStats tstats[MAXCARDS] = {};
00158         struct DacBuf {
00159                 MFA mfa;
00160                 void* bbb;
00161         } dac_buf[MAXCARDS];
00162 #define EACHBBB      (dac_buf[icard].bbb)
00163 #define EACHDAC_BASE (EACHBBB + LLCV2_AO_HSBS)
00164 #define EACHDAC_BASE16 ((u16*)EACHDAC_BASE)
00165 #define V2SETDACS(src, icard) \
00166         memcpy(EACHDAC_BASE, (src)+(icard)*32, DAC_SAMPLE_SIZE)
00167 
00168         u32 cmd = LLC_MAKE_DECIM(td->decimation);
00169 #define OFFSET 0
00170 
00171         int uses_dacs = td->update_dacs || td->feedback;
00172         void* dac_data;
00173 
00174         EACHCARD_INIT;
00175 
00176         if (uses_dacs) FOREACHCARD { /* (a) */
00177                 EACHBBB = getVaddr(EACHBUF(td), 0);
00178                 printf("card %d uses_dacs EACHBBB %p "
00179                        "EACHDAC_BASE %p bus 0x%08x\n",
00180                        icard, EACHBBB, EACHDAC_BASE,
00181                        getBusAddr(EACHBUF(td), LLCV2_AO_HSBS) );
00182         }
00183 
00184         FOREACHCARD{ /* (1) */
00185                 llSetTlatch(EACHMBX(td), tstats[icard].tlatch = 0xffffffff);
00186                 llv2InitDmaDone(
00187                         getVaddr(EACHBUF(td), 
00188                                  EACHCARD(td)->sync_2v_offset_status_hsbt));
00189         }
00190    
00191         FOREACHCARD{ /* (2) */
00192                 updateTargetAddr(cmd+LLC_CSR_M_ARM, EACHCARD(td), OFFSET);
00193         }
00194 
00195         if (td->update_dacs){
00196                 dac_data = td_get_next_dac_data(td);    
00197                 FOREACHCARD{
00198                         V2SETDACS(dac_data, icard);
00199                 }
00200         }       
00201 
00202 #if 0
00203         // wait for gate /* (3) */
00204 
00205         while( !llCounterRunning(FIRSTMBX(td), cmd) ){ 
00206                 POLLALERT(ipoll, "Polling for Counter Running\n");
00207         }
00208 #endif
00209         INIT_TIMER;
00210         /* WORKTODO - assumes all cards now running */
00211 
00212         for ( td->iter = 0; td->iter != td->iterations; ++td->iter ){ /* (4) */
00213                 if (soft_clock) FOREACHCARD{ /* (5) */
00214                         llSetCmd(EACHMBX(td), cmd+LLC_CSR_M_SOFTCLOCK);
00215                 }
00216         
00217                 FOREACHCARD{                                  /* (6)+(7) */
00218                         MARK_TIME(1, "waitDmaDone() before");
00219                         tstats[icard].tlatch = waitDmaDone(EACHCARD(td));
00220                         MARK_TIME(2, "waitDmaDone() after");
00221                 }
00222 
00223                 if (!td->min_latency_test) FOREACHCARD{        /* (6)+(7) */
00224                         updateTstats(cmd, EACHCARD(td), &tstats[icard]);    
00225                 }
00226 
00227                 
00228                 if (td->do_work){
00229                         doApplicationWork(td, OFFSET);
00230                 }
00231 
00232                 if (td->feedback) { /* (b.1) */
00233                         u16 *pvin = (u16 *)getVaddr(FIRSTBUF(td), OFFSET);
00234                         u16 vin = pvin[td->feedback_channel];
00235                         u32 feedback = vin << 16 | vin;
00236 
00237                         PRINTF(1)("feedback 0x%08x\n", feedback);
00238 
00239                         FOREACHCARD{   
00240                                 MARK_TIME(3, "feedback 1");
00241                                 memset32(EACHDAC_BASE, feedback, DAC_COUNT/2);
00242 
00243                                 if (td->update_dacs){ /* (b.15) */
00244 
00245                                         u16* excite = td_get_next_dac_data(td);
00246                                 
00247                                         EACHDAC_BASE16[td->feedback_channel] 
00248                                          = excite[td->feedback_channel];
00249                                 }
00250                                 MARK_TIME(4, "feedback 2");
00251                         }
00252                 }else if (td->update_dacs){ /** (b.2) */
00253                         dac_data = td_get_next_dac_data(td);
00254                         FOREACHCARD{
00255                                 V2SETDACS(dac_data, icard);
00256                                 MARK_TIME(5, "update_dacs");
00257                         }
00258                 }
00259 
00260 #if IGNORE_COUNTER_STOP
00261 /** @todo - check counter running in local memory */
00262         /* check process completion.
00263          * if hardware_gateoff is employed, then the app would need
00264          * to make use of a pre-arranged DIO encoding for on/off instead
00265          */              
00266                 if (!td->hardware_gate_off &&
00267                      !llCounterRunning(FIRSTMBX(td), cmd )){          /* (8) */
00268                         fprintf( stderr, "Trigger is off - stop\n" );
00269                         break;
00270                 }
00271 #endif          
00272                 FOREACHCARD_MARK_TIME(9, "after llCounterRunning check");
00273 
00274                 if (td->tlog){          
00275                         FOREACHCARD{
00276                                 tstats[icard].target_poll =
00277                                         getMboxPollcount(EACHMBX(td));
00278                                 MARK_TIME(10, "10");
00279                                 updateTimingStats(
00280                                         td->stats_buf[icard], 
00281                                         td->iter, 
00282                                         &tstats[icard]);
00283                         }
00284                 }       
00285                 TIMER_CHECK_OVERFLOW;
00286         }
00287 
00288         G_quit = 1;
00289         return 0;
00290 #undef EACHMFA
00291 #undef EACHBBB
00292 #undef EACHDAC_BASE
00293 #undef EACHDAC_BASE16
00294 }
00295 

Generated on Wed Jan 5 2011 for llcontrol by  doxygen 1.7.1