Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   Related Pages  

/var/pcce/usera/hill/rcc_1.2/RodDaq/RodCrate/RodModule.cxx

Go to the documentation of this file.
00001 //File: RodModule.cxx
00002 // $Header: /afs/cern.ch/user/s/sctpixel/private/cvsroot/RodDaq/RodCrate/RodModule.cxx,v 1.7 2002/12/19 16:22:25 tmeyer Exp $
00003 
00004 #include "RodModule.h"
00005 
00006 //! Namespace for the common routines for SCT and PIXEL ROD software. 
00007 namespace SctPixelRod {
00008 
00009 // Flag to force endian-ness swap before calls to HPI registers.  This should be
00010 // a temporary patch.
00011 // JCH 7 Jan 2003. Change swap from 1 to 0.
00012 static long endianSwap = 0;
00013 static const long rodInitTimeout = 1;
00014 
00015 //******************************Class HpiException**************************
00016 //
00017 // Description:
00018 //  This class is thrown if an error in an HPI read/write operation is detected.
00019 //   
00020 //  Author(s):
00021 //    Tom Meyer (meyer@iastate.edu) - originator
00022 
00023 //      Constructors. Use defaults for destructor, copy, and assignment.
00024 
00025 HpiException::HpiException( std::string descriptor, unsigned long calcAddr,
00026                             unsigned long readAddr) {
00027   m_descriptor = descriptor;
00028   m_calcAddr = calcAddr;
00029   m_readAddr = readAddr;
00030   }
00031   
00032 //***************************Class RodException**************************
00033 //
00034 // Description:
00035 //  This class is thrown if an error in a ROD operation is detected.
00036 //   
00037 //  Author(s):
00038 //    Tom Meyer (meyer@iastate.edu) - originator
00039 
00040 //      Constructors. Use defaults for destructor, copy, and assignment.
00041 
00042 RodException::RodException( std::string descriptor) {
00043   m_descriptor = descriptor;
00044   m_numData = 0;
00045   m_data1 = m_data2 = 0;
00046   }
00047 RodException::RodException( std::string descriptor, unsigned long data1) {
00048   m_descriptor = descriptor;
00049   m_numData = 1;
00050   m_data1 = data1;
00051   m_data2 = 0;
00052   }
00053 RodException::RodException( std::string descriptor, unsigned long data1,
00054                             unsigned long data2) {
00055   m_descriptor = descriptor;
00056   m_numData = 2;
00057   m_data1 = data1;
00058   m_data2 = data2;
00059   }
00060   
00061 //********************************Class RodModule***************************
00062 //
00063 // Description:
00064 //  This is a derived class providing the software interface for VME ROD modules.
00065 //   
00066 //  Author(s):
00067 //    Tom Meyer (meyer@iastate.edu) - originator
00068 
00069 //---------------------------------Constructor------------------------------                                    
00070 /*
00071 This is the only constructor to use.
00072 */
00073 
00074 RodModule::RodModule( unsigned long baseAddr, unsigned long mapSize, 
00075      VmeInterface & ourInterface, long numSlaves) throw (RodException&,
00076      VmeException&) :
00077      VmeModule(baseAddr, mapSize, ourInterface) {
00078   m_slot = baseAddr>>24;
00079   m_serialNumber = 0xFFFFFFFF;  // Will be overwritten during init
00080   m_numSlaves = numSlaves; 
00081   m_finBufferSize = 4096; 
00082   m_masterImageName = std::string("");
00083   try {
00084     m_myVmePort = new VmePort(m_baseAddress, m_mapSize, VmeInterface::A32, 
00085                   m_ourInterface); 
00086   }
00087   catch (std::bad_alloc & ba) {
00088     throw RodException("Failed to get VME Port.");
00089   }
00090   for (long i=0; i<4; i++) {
00091     m_slaveEmifName[i]= std::string("");
00092     m_slaveIpramName[i]= std::string("");
00093     m_slaveIdramName[i]= std::string("");
00094     m_slaveExtName[i]= std::string("");
00095   }
00096   for (long i=0; i<N_TXT_BUFFS; i++) {
00097     m_textBuff[i] = 0;
00098   };
00099   m_myTextState = TEXT_IDLE;
00100   m_myPrimState = PRIM_IDLE;
00101   m_textType = TEXT_UNDEF;
00102 }
00103 
00104 //---------------------------------Destructor------------------------------                                    
00105 /*
00106 Be sure to delete all VME Ports.
00107 */
00108 
00109 RodModule::~RodModule() {
00110   delete(m_myVmePort);
00111   m_myVmePort = 0;
00112   return;
00113 }
00114 
00115 //  Member methods
00116 
00117 //--------------------------------initialize---------------------------------                                 
00118 
00119 /* This method performs all actions necessary to place a properly loaded ROD 
00120 in its initialized state, except for initializing the slave DSPs. This must be done
00121 separately using initSlaveDsp().
00122 
00123 Activities:
00124     Reset the ROD
00125     Read ROD serial number
00126     Load 0x000l000l into Master DSP HPIC register. (Says low order 16-bit word
00127                                                     comes first)
00128     Read back HPIC to verify
00129     Retrieve pointers to text buffer structs
00130     Initialize PrimList and TextBuff state variables
00131 */
00132 void RodModule::initialize() throw (RodException &, VmeException &) {
00133 
00134   unsigned long hpicReadback;   // for debugging
00135   const unsigned long rodResetValue = 0x000000c0;
00136   unsigned long rodReset;
00137   unsigned long rodRegValue;
00138   
00139 // Reset the ROD so it starts in a known state
00140   rodRegValue = readRodStatusReg(0);
00141   if (endianSwap) {
00142     rodReset = endianReverse32(rodResetValue);
00143   }
00144   else {
00145     rodReset = rodResetValue;
00146   }
00147   m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], rodReset);
00148   sleep(1000);
00149   rodRegValue = readRodStatusReg(0);
00150 
00151 // Read ROD serial number 
00152   m_serialNumber = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[6]);
00153   if (endianSwap) m_serialNumber = endianReverse32(m_serialNumber); // Temporary (I hope)
00154   m_serialNumber = m_serialNumber & 0x3ff;   // Mask to get 10 least significant bits
00155    
00156 //      Initialize Master HPIC register to set half-word order
00157 
00158   unsigned long hpicValue = 0x00010001;
00159 
00160   hpiLoad(HPIC, hpicValue);
00161   hpicReadback = hpiFetch(HPIC);         // for debugging
00162   sleep(100);
00163 
00164 // Wait for MasterDSP init
00165   for (long i=0; ; ++i) {
00166     if (readRodStatusBit(0, SR_RUNNING)) {
00167       break;
00168     }
00169     if (i>rodInitTimeout*10) throw RodException("Master DSP init timed out. Tries, Limit:", i,
00170         rodInitTimeout);
00171     sleep(100);
00172   }
00173 
00174   for (int i=0; i< N_TXT_BUFFS; i++) {
00175     m_textBuff[i] = (unsigned long *)mdspSingleRead(REPLY_BUFF_BASE + 4*i);
00176   }
00177 
00178 //  Reinitialize state variables
00179   m_myTextState = TEXT_IDLE;
00180   m_myPrimState = PRIM_IDLE;
00181 
00182 return;
00183 }
00184 
00185 //---------------------------------reset------------------------------------                                
00186 
00187 /* This method resets the ROD.
00188 */
00189 
00190 void RodModule::reset() throw (RodException&, VmeException &) {
00191   // Reset all FPGAs and DSPs (bit 7 = 0x80)
00192   const unsigned long rodResetValue = 0x000000c0;
00193   unsigned long rodReset;
00194   
00195   if (endianSwap) {
00196     rodReset = endianReverse32(rodResetValue);
00197   }
00198   else {
00199     rodReset = rodResetValue;
00200   }
00201   m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], rodReset);
00202   sleep(10000);
00203    
00204   // Clear IDRAM
00205   unsigned long * buff;
00206   try {
00207     buff = new unsigned long[IDRAM_SZ/sizeof(long)]={0};//Allocate a buffer of zeros
00208   }
00209   catch (std::bad_alloc & ba) {
00210     throw RodException("Reset() failed to allocate buffer. Size=",
00211                                   IDRAM_SZ/sizeof(long));
00212   }
00213   mdspBlockWrite(IDRAM_BASE, buff, IDRAM_SZ/sizeof(long));
00214   delete buff;
00215   
00216   // Reset all DSPs
00217   resetMasterDsp();
00218   sleep(50);
00219   for (long i=0; i<m_numSlaves; i++) {
00220     resetSlaveDsp(i);
00221     sleep(50);
00222   };
00223   
00224   //  Reinitialize state variables
00225   m_myTextState = TEXT_IDLE;
00226   m_myPrimState = PRIM_IDLE;
00227   
00228 return;
00229 }
00230 
00231 //---------------------------------status-----------------------------------                                
00232 
00233 /* This method reports the status of the ROD.
00234 For now, it simply prints to standard output.
00235 */
00236 void RodModule::status() throw() {
00237     cout << "Slot: " << m_slot;
00238     cout << "Serial Number:" << m_serialNumber;
00239     cout << "Number of slave DSPs: " << m_numSlaves;
00240     cout << endl;
00241     hex(cout);
00242     cout << "Status registers[0-2]: ";
00243     try {
00244       for (int i=0; i<3; i++) {
00245         cout << readRodStatusReg(i) << " " ;
00246       }
00247     }
00248     catch (VmeException &) {
00249       cout << "status() can read ROD status registers." << flush;
00250     }
00251     cout << endl;
00252     
00253     cout << "Command registers[0-1]: ";
00254     try {
00255       for (int i=0; i<2; i++) {
00256         cout << readRodCommandReg(i) << " " ;
00257       }
00258     }
00259     catch (VmeException &) {
00260       cout << "status() can read ROD command registers." << flush;
00261     }
00262 
00263     dec(cout);
00264     cout << "Primitive state: " << getPrimState() << " Text State: " << 
00265           getTextState();
00266     cout << endl;
00267 return;
00268 }
00269 
00270 //--------------------------------initSlaveDsp-------------------------------                       
00271 void RodModule::initSlaveDsp(const std::string & emifFile, const std::string & ipramFile,
00272      const std::string & idramFile,const std::string & extFile,
00273      const long slaveNumber) throw (RodException&, NoImageFile&, VmeException &) {
00274 
00275   unsigned long readBack;
00276   unsigned long hpicValue = 0x00010001;
00277  
00278   if ((slaveNumber < 0) || (slaveNumber >= m_numSlaves)) throw RodException(
00279        "Slave Number out of Range. slaveNumber, m_numSlaves:", slaveNumber, 
00280        m_numSlaves);
00281       
00282 // Set HPIC registers to make first halfword the most significant
00283   slvHpiLoad(SLAVE_HPIC_BASE, hpicValue, slaveNumber);
00284   readBack = slvHpiFetch(SLAVE_HPIC_BASE, slaveNumber);
00285   
00286 // Load the memory images and remember the file names
00287   loadSlaveImage(emifFile, SLAVE_EMIF_ADDR, slaveNumber);
00288   m_slaveEmifName[slaveNumber] = emifFile;
00289   loadSlaveImage(ipramFile, SLAVE_IPRAM_ADDR, slaveNumber);
00290   m_slaveIpramName[slaveNumber] = ipramFile;
00291   loadSlaveImage(idramFile, SLAVE_IDRAM_ADDR, slaveNumber);
00292   m_slaveIdramName[slaveNumber] = idramFile;
00293   loadSlaveImage(extFile, SLAVE_CE2_ADDR, slaveNumber);
00294   m_slaveExtName[slaveNumber] = extFile;
00295   
00296 // Send the START_SLAVE_EXECUTING primitive. Do the primList dialog synchronously
00297   startSlave(slaveNumber);
00298   return;
00299 }
00300 
00301 
00302 //--------------------------------loadSlaveImage-------------------------------                       
00303 void RodModule::loadSlaveImage(const std::string & fileName, const unsigned long address,
00304      const long slaveNum, char opt='n') throw (NoImageFile&, RodException&, 
00305                                                VmeException &) {
00306   
00307   long numWords;   
00308   int fileSize;
00309   ifstream fin;
00310   fin.open(fileName.c_str(),ios::binary);
00311   if (fin.is_open()) {
00312   
00313 // Get size of file
00314     fin.seekg(0, ios::end);  // go to end of file
00315     fileSize = fin.tellg();  // file size is current location
00316     fin.seekg(0, ios::beg);  // go back to beginning of file
00317     
00318 // Create buffer and fill it with file contents
00319     char * buffer; 
00320     try {
00321       buffer = new char[fileSize];
00322     }
00323     catch (std::bad_alloc & ba) {
00324       throw RodException(
00325                   "loadSlaveImage buffer failed to allocate. buffer, fileSize:",
00326                   (unsigned long)buffer, (unsigned long)fileSize);
00327     }
00328     fin.read(buffer, fileSize);
00329 
00330 // Use slvBlockWrite to transfer buffer into memory
00331     numWords = (fileSize+3)/4;
00332     slvBlockWrite(address, (unsigned long*) buffer, numWords, slaveNum);
00333     
00334 // Read back buffer for verification if 'v' option was given
00335     if (opt=='v') {
00336       char* buffer2;
00337       try {
00338         buffer2 = new char[fileSize];
00339       }
00340       catch (std::bad_alloc & ba) {
00341         throw RodException(
00342                   "loadSlaveImage buffer2 failed to allocate. buffer, fileSize:",
00343                   (unsigned long)buffer, (unsigned long)fileSize);
00344       }
00345       slvBlockRead(address, (unsigned long*)buffer2, numWords, slaveNum);
00346    
00347       for (int i=0; i<fileSize; i++) {
00348         if (buffer[i] != buffer2[i]) {
00349           delete [] buffer;
00350           delete [] buffer2;
00351           fin.close();
00352           char message[] = "loadSlaveImage buffer readback invalid for file, slavenum, index: ";
00353           throw RodException( *message+fileName.c_str(), slaveNum, i);
00354         }
00355       } 
00356     }
00357     
00358 // Close the file and delete the buffer    
00359     fin.close();
00360     delete [] buffer;
00361   }
00362   else {
00363     throw NoImageFile(fileName);
00364   }
00365   return;
00366 }
00367 
00368 //--------------------------------startSlave-------------------------------                       
00369 // Starts slave executing
00370 // The default way is to have the master DSP run the START_SLAVE_EXECUTING
00371 // primitive. This is what should normally be used.
00372 // A quick "back door" way is to set the slave's DSPINT bit directly.
00373 
00374 void RodModule::startSlave(const long slaveNumber, char mode='s') 
00375                                             throw(VmeException &) {
00376   const unsigned long dspint = 0x2;
00377 
00378   if (mode == 'q') {             // The quick way: just set DSPINT directly
00379     slvHpiLoad(SLAVE_HPIC_BASE, dspint, slaveNumber);
00380   }
00381 
00382   else {                         // The slow way, a master primitive (default)
00383   long primData[4]={slaveNumber, 1, 2, 0x200000};
00384   RodPrimitive * startSlaveExec;
00385   try {
00386     startSlaveExec = new RodPrimitive(8, 1, START_SLAVE_EXECUTING, 
00387        R_START_SLAVE_EXECUTING, primData);
00388   }
00389   catch (std::bad_alloc & ba) {
00390     throw RodException(
00391       "startSlave unable to allocate startSlaveExec. slaveNumber:", slaveNumber); 
00392   }
00393   synchSendPrim(*startSlaveExec); 
00394   delete startSlaveExec;
00395   }
00396   
00397   return;
00398 }
00399 
00400 /*---------------------------------synchSendPrim------------------------------                           
00401 This version writes to cout. This needs to be changed.
00402 */
00403 void RodModule::synchSendPrim(RodPrimitive & prim) throw (RodException&, 
00404                                                          VmeException &) {
00405   RodPrimList primList(1);  // Private primList (local to this routine)
00406   long myTextLength;                            // Actual length of text message
00407   TEXT_BUFFER_TYPE myTextType;                  // Buffer type for latest message
00408   PrimState returnPState;
00409   TextBuffState returnTState;
00410 
00411 // Create a text buffer in case of error message
00412     char * myTextBuffer;
00413     try {
00414       myTextBuffer = new char[TEXT_BUFF_SIZE];
00415     }
00416     catch (std::bad_alloc & ba) {
00417       throw RodException(
00418           "synchSendPrim failed to allocate text. Size=", TEXT_BUFF_SIZE);
00419     }
00420     primList.insert(primList.begin(), prim);
00421     try {
00422       primList.bufferBuild();
00423     }
00424     catch (PrimListException &p) {
00425 //      throw (RodException(p.getDescriptor,p.getData1(), p.getData2());
00426       cout << p.getDescriptor() << " ";
00427       cout << p.getData1() << ", " << p.getData2() << "\n";
00428     };
00429     try {
00430       this->sendPrimList(&primList);
00431     }
00432     catch (HpiException &h) {
00433       hex(cout);
00434 //      throw (RodException(h.getDescriptor,h.getCalcAddr1(), h.getReadAddr());
00435       cout << h.getDescriptor() << '\n';
00436       cout << "calcAddr: " << h.getCalcAddr() << ", readAddr: " << 
00437               h.getReadAddr() << '\n';
00438       dec(cout);
00439     };
00440 
00441 // Wait for ROD to begin executing and then wait for it to finish executing
00442 // Check for error messages in text buffer and read them out if they exist.
00443 // Note: this is the synchronous way to do it. In general, it is better to do it
00444 // asynchronously.
00445     do {
00446       returnPState = this->primHandler();
00447       returnTState = this->textHandler();
00448       if (returnTState == TEXT_RQ_SET) {
00449         do {
00450           returnTState = this->textHandler();
00451         } while (returnTState != TEXT_READOUT);
00452         this->getTextBuffer(myTextBuffer, myTextLength, myTextType);
00453         this->clearTextBuffer();
00454         for (int i=0; i<myTextLength; i++) {
00455           cout << myTextBuffer[i];
00456           if (0==(i+1)%64) cout << endl;
00457           }
00458         cout << endl; 
00459       }
00460     } while (returnPState != PRIM_EXECUTING); 
00461     do {
00462        try {
00463          returnPState = this->primHandler();
00464        }
00465        catch (RodException &r) {
00466        cout << r.getDescriptor() <<", " << r.getData1() << ", " << r.getData2()
00467                << '\n';
00468        }
00469     } while (returnPState != PRIM_WAITING); 
00470     delete myTextBuffer;
00471 
00472   return;
00473 }
00474   
00475 //---------------------------------sendPrimList-------------------------------                           
00476 
00477 void RodModule::sendPrimList(RodPrimList *l) throw(VmeException &) {
00478 
00479   unsigned long * buffAddr;
00480   long buffCount;
00481 
00482   if (!l->getBuffer()) {
00483     l->bufferBuild();
00484   };
00485   buffCount = l->numWords();
00486   buffAddr = l->getBuffer();
00487   mdspBlockWrite(PRIM_BUFF_BASE, buffAddr, buffCount);
00488   m_myPrimState = PRIM_LOADED;
00489 
00490   return;  
00491 }  
00492 
00493 //---------------------------------primHandler-------------------------------                           
00494 
00495 PrimState RodModule::primHandler() throw(RodException &, VmeException &) {
00496 long wordCount;
00497 unsigned long status;
00498 unsigned long* buffptr;
00499 unsigned long replyBuffer;
00500   switch (m_myPrimState) {
00501     case PRIM_LOADED: {
00502       if (0==getDspAck()) {
00503         setInListReady();
00504         m_myPrimState = PRIM_EXECUTING;
00505       };
00506     break;
00507     };
00508     case PRIM_EXECUTING: {
00509       status = readRodStatusReg(0);
00510       if (1==getDspAck()) {
00511         if (status >> TEXT_BUFF_NOT_EMPTY[0]) {
00512 //        throw RodException ("Error buffer not empty in primHandler(PRIM_EXECUTING)");
00513         }
00514         if (1==readRodStatusBit(0,OUTLIST_READY)) {
00515           // read buffer size
00516           hpiLoad(HPIA, REPLY_BUFF_BASE);
00517           wordCount = hpiFetch(HPID_NOAUTO);
00518 
00519           // create new OutList object
00520           RodOutList* outList;
00521           try {
00522             outList = new RodOutList(wordCount);
00523           }
00524           catch (std::bad_alloc & ba) {
00525             throw RodException("Outlist creation failed. WordCount=", 
00526                                               wordCount);
00527           }
00528           if (0==outList->getBody()) throw RodException(
00529                  "Outlist failed to allocate body array.WordCount=", wordCount);
00530           this->setOutList(outList);
00531           
00532           // fill OutList object
00533           buffptr = m_myOutList->getBody();
00534           replyBuffer = REPLY_BUFF_BASE;
00535           mdspBlockRead(replyBuffer, buffptr, wordCount);
00536           m_myPrimState = PRIM_WAITING;
00537           
00538           // clear inListReady bit
00539           clearVmeCommandRegBit(INLISTRDY);
00540         }
00541         else m_myPrimState = PRIM_IDLE;
00542       }
00543     break;
00544     };
00545     default: {
00546     break;
00547     };
00548   };
00549   return m_myPrimState;
00550 };
00551 
00552 //--------------------------------deleteOutList--------------------------------
00553 
00554   void RodModule::deleteOutList() throw() {
00555   delete m_myOutList;
00556   m_myOutList = 0;
00557   return;
00558   };
00559 
00560 //---------------------------------textHandler-------------------------------                           
00561 
00562 TextBuffState RodModule::textHandler() throw(VmeException &) {
00563   unsigned long regValue;
00564   unsigned long dataPtr;
00565   long txtLength, txtLength1, txtLength2, txtWords;
00566   switch (m_myTextState) {
00567     case TEXT_IDLE: {
00568       regValue = readRodStatusReg(0) & SR_TEXT_MASK;
00569       if (0==regValue) return m_myTextState;         // Quick return if no text
00570       for (long i=0; i<4; i++) {
00571         if (regValue & SR_TEXT_BIT_MASK[i]) {
00572           m_textType = (TEXT_BUFFER_TYPE)i;
00573         };
00574         setVmeCommandRegBit(TEXT_BUFF_READ_REQ[m_textType]);
00575         m_myTextState = TEXT_RQ_SET;
00576         return m_myTextState;
00577       }
00578       break;
00579     };
00580     case TEXT_RQ_SET: {
00581       if (0==readRodStatusReg(0) & SR_TEXT_BIT_MASK[m_textType]) {
00582         return m_myTextState;
00583       };
00584       hpiLoad( HPIA, (unsigned long)m_textBuff[m_textType]);
00585       m_txtBuffer.dataEnd = hpiFetch(HPID_AUTO);
00586       m_txtBuffer.readIndx = hpiFetch(HPID_AUTO);
00587       m_txtBuffer.writeIndx = hpiFetch(HPID_AUTO);
00588       m_txtBuffer.mode = hpiFetch(HPID_AUTO);
00589       m_txtBuffer.overwrite = hpiFetch(HPID_AUTO);
00590       m_txtBuffer.overflow = hpiFetch(HPID_AUTO);
00591       m_txtBuffer.wrap = hpiFetch(HPID_AUTO);
00592       m_txtBuffer.occupied = hpiFetch(HPID_AUTO);
00593       m_txtBuffer.data = (char *)hpiFetch(HPID_AUTO);
00594       dataPtr = (unsigned long)m_txtBuffer.data;
00595       
00596 // If there was a wrap-around we need to read two blocks, otherwise only one
00597       if (m_txtBuffer.readIndx < m_txtBuffer.writeIndx) {           // No wrap
00598         txtLength = m_txtBuffer.writeIndx - m_txtBuffer.readIndx;
00599         txtWords = (txtLength+3)/4;     // Convert char count to words
00600         mdspBlockRead(dataPtr, (unsigned long*)m_textData, txtWords);
00601       }
00602       else {                                                         // Wrap
00603         txtLength1 = TEXT_BUFF_SIZE - m_txtBuffer.readIndx;
00604         txtWords = (txtLength1+3)/4;
00605         mdspBlockRead(dataPtr+4*m_txtBuffer.readIndx, (unsigned long*)m_textData, txtWords);
00606         txtLength2 = m_txtBuffer.writeIndx;
00607         txtWords = (txtLength2+3)/4;
00608         mdspBlockRead(dataPtr, (unsigned long*)(m_textData+4*txtLength1), txtWords);
00609         txtLength = txtLength1 + txtLength2;
00610       };
00611       m_myTextState = TEXT_READOUT;
00612       m_txtBuffer.occupied = txtLength;
00613       return m_myTextState;
00614       break;
00615     };
00616     default: {
00617       return m_myTextState;
00618       break;
00619     };
00620   };
00621 
00622   return m_myTextState;
00623 };
00624 
00625 
00626 //-----------------------------getTextBuffer-------------------------------                                
00627 
00628   void RodModule::getTextBuffer(char * buffer, long & length, 
00629          TEXT_BUFFER_TYPE & type) throw() {
00630     length = m_txtBuffer.occupied;
00631     type = (TEXT_BUFFER_TYPE)m_textType;
00632     for (int i=0; i<m_txtBuffer.occupied; i++) {
00633       buffer[i] = m_textData[i];
00634     };
00635     return;
00636   };
00637   
00638 //--------------------------------clearTextBuffer------------------------------
00639 
00640 void RodModule::clearTextBuffer() throw() {
00641   m_textType = TEXT_UNDEF;
00642   m_txtBuffer.occupied = 0;
00643   m_myTextState = TEXT_IDLE;
00644   return;
00645 };
00646 
00647 //----------------------------------hpiLoad------------------------------------                                
00648 
00649 void RodModule::hpiLoad(unsigned long hpiReg, unsigned long hpiValue) 
00650      throw(VmeException &) {
00651 
00652   if (endianSwap) hpiValue = endianReverse32(hpiValue); 
00653   m_myVmePort->write32(hpiReg, hpiValue);
00654 };
00655 
00656 //--------------------------------hpiFetch-------------------------------------                                
00657 
00658 unsigned long RodModule::hpiFetch(unsigned long hpiReg) 
00659               throw(VmeException &){
00660 
00661 unsigned long hpiValue;
00662 
00663   hpiValue=m_myVmePort->read32(hpiReg);
00664   if (endianSwap) hpiValue = endianReverse32(hpiValue);
00665   
00666   return hpiValue;
00667 };
00668 
00669 //-----------------------------mdspSingleRead---------------------------------                                
00670 
00671 unsigned long RodModule::mdspSingleRead(const unsigned long dspAddr) 
00672               throw(VmeException &) {
00673   unsigned long value; 
00674 
00675 //  Load the DSP address into the HPIA register 
00676   hpiLoad(HPIA, dspAddr);
00677 
00678 //      Do the read 
00679   value = m_myVmePort->read32(HPID_NOAUTO);
00680   if (endianSwap) {
00681     value = endianReverse32(value);
00682   }
00683   return value;
00684 };
00685 
00686 //------------------------------mdspSingleWrite------------------------------------                                   
00687 
00688 void RodModule::mdspSingleWrite(unsigned long dspAddr, unsigned long buffer) 
00689      throw(VmeException &) { 
00690 
00691 //  Load the HPID address into the HPIA register 
00692   hpiLoad(HPIA, dspAddr);
00693 
00694 //      Do the write 
00695   if (endianSwap) {
00696       buffer = endianReverse32(buffer);
00697   }
00698 
00699   m_myVmePort->write32(HPID_NOAUTO, buffer);
00700 
00701   return;
00702 };
00703 
00704 //-----------------------------mdspBlockRead---------------------------------                                
00705 
00706 
00707 void RodModule::mdspBlockRead(const unsigned long dspAddr, unsigned long buffer[],
00708        const long wordCount, HpidMode mode=DYNAMIC) throw (HpiException &, 
00709        VmeException &) {
00710   unsigned long hpidAddr; 
00711   long myCount, blockWordCount, wordIncr;
00712 
00713 // Determine the HPI mode to use.
00714   switch (mode) {
00715     case AUTO:
00716       hpidAddr= HPID_AUTO;
00717       break;
00718     case NO_AUTO:
00719       hpidAddr = HPID_NOAUTO; 
00720       break;
00721     case DYNAMIC:
00722     default:
00723       if (wordCount == 1){
00724         hpidAddr = HPID_NOAUTO;
00725       } 
00726       else { 
00727         hpidAddr = HPID_AUTO;
00728       };
00729       break;
00730   };
00731 
00732 //  Load the DSP address into the HPIA register 
00733   hpiLoad(HPIA, dspAddr);
00734 
00735 // Check to see that we don't access too large a block. HPID has 20 bits of 
00736 // address space available. MAX_HPID_WORD_ELEMENTS is defined in RodVmeAddresses.h
00737 
00738   if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00739     blockWordCount = MAX_HPID_WORD_ELEMENTS;
00740   }     else { 
00741     blockWordCount = wordCount;
00742   }
00743 
00744 //      Set up the transfer as a series of block transfers 
00745   for (myCount=wordCount, wordIncr=0; myCount>0;
00746                     myCount-=blockWordCount, wordIncr+=blockWordCount) {
00747 
00748 //      Recheck each block 
00749     if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00750       blockWordCount=MAX_HPID_WORD_ELEMENTS;
00751     }   
00752     else { 
00753       blockWordCount = myCount;
00754     }
00755 
00756 //      Do the transfer for this block 
00757 // Block reads seem to have a problem, use single word reads for now.
00758 //    m_myVmePort->blockRead32(hpidAddr, buffer+2*wordIncr, blockWordCount*4);
00759     for (int i=0; i<blockWordCount; i++) {
00760       buffer[2*wordIncr+i] = m_myVmePort->read32(hpidAddr);
00761     }
00762 
00763     if (endianSwap) {
00764       for (int i=0; i<blockWordCount; i++) {
00765         buffer[2*wordIncr+i] = endianReverse32(buffer[2*wordIncr+i]);
00766       }
00767     }
00768   }
00769   return;
00770 };
00771 
00772 //------------------------------mdspBlockWrite-----------------------------------  
00773 
00774 void RodModule::mdspBlockWrite(unsigned long dspAddr, unsigned long buffer[], 
00775        long wordCount, HpidMode mode=DYNAMIC) throw (HpiException &, 
00776        VmeException &) { 
00777 
00778   unsigned long hpidAddr;
00779   long myCount, blockWordCount, wordIncr;
00780 
00781 //  Load the initial dsp address into the HPIA register 
00782   hpiLoad(HPIA, dspAddr);
00783 
00784 // Determine the HPI mode to use.
00785   switch (mode) {
00786     case AUTO:
00787       hpidAddr= HPID_AUTO;
00788       break;
00789     case NO_AUTO:
00790       hpidAddr = HPID_NOAUTO; 
00791       break;
00792     case DYNAMIC:
00793     default:
00794       if (wordCount == 1){
00795         hpidAddr = HPID_NOAUTO;
00796       } 
00797       else { 
00798         hpidAddr = HPID_AUTO;
00799       };
00800       break;
00801   };
00802 
00803 // Check to see that we don't access too large a block. HPID has 20 bits of 
00804 // address space available. MAX_HPID_WORD_ELEMENTS is defined in vmeAddressMap.h
00805 
00806   if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00807     blockWordCount = MAX_HPID_WORD_ELEMENTS;
00808   }     
00809   else { 
00810     blockWordCount = wordCount;
00811   }
00812 
00813 //      Set up the transfer as a series of block transfers 
00814   for (myCount=wordCount, wordIncr=0; myCount>0;
00815                     myCount-=blockWordCount, wordIncr+=blockWordCount) {
00816 
00817 //      Recheck each block 
00818     if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00819       blockWordCount=MAX_HPID_WORD_ELEMENTS;
00820     }   
00821     else { 
00822       blockWordCount = myCount;
00823     }
00824   
00825 //      Do the transfer for this block 
00826   if (endianSwap) {
00827     for (int i=0; i<blockWordCount; i++) {
00828       buffer[2*wordIncr+i] = endianReverse32(buffer[2*wordIncr+i]);
00829     }
00830   }
00831 
00832 // blockWrite32 doesn't work reliably and write32 doesn't increment HPIA as it should.
00833 // Use single word writes and manually increment HPIA for now.
00834 //    m_myVmePort->blockWrite32(hpidAddr, &buffer[2*wordIncr], blockWordCount*4);
00835 
00836     for (int i=0; i<blockWordCount; i++) {
00837       m_myVmePort->write32(hpidAddr, buffer[2*wordIncr+i]);
00838     }
00839   }
00840   return;
00841 };
00842 
00843 //-----------------------------mdspBlockDump--------------------------------                                
00844 
00845 void RodModule::mdspBlockDump(const unsigned long firstAddress, 
00846        const unsigned long lastAddress,
00847        const std::string & fileName) throw(RodException &, VmeException &) {
00848        
00849   long numBytes;
00850   ofstream fout;
00851   numBytes = lastAddress - firstAddress + 1;
00852   fout.open(fileName.c_str(), ios::binary);
00853   if (fout.is_open()) {
00854     unsigned long * buffer;
00855     try {
00856       buffer = new unsigned long[numBytes];
00857     }
00858     catch (std::bad_alloc & ba) {
00859       throw RodException(
00860        "mdspBlockDump failed to allocate buffer; buffer size in bytes=", numBytes);
00861     }   
00862     mdspBlockRead(firstAddress, buffer, numBytes/4);
00863     fout.write(buffer, numBytes);
00864     fout.close();
00865     delete [] buffer;
00866   }
00867   else {
00868     throw RodException("mdspBlockDump failed to open file");
00869   }
00870   return;                    
00871 }
00872 
00873 //--------------------------------slvHpiLoad-----------------------------------                                
00874 
00875 void RodModule::slvHpiLoad(unsigned long hpiReg, unsigned long hpiValue,
00876                            long slaveNum) throw(VmeException &) {
00877 
00878   unsigned long address;
00879   address = hpiReg + slaveNum*SLAVE_HPI_OFFSET;
00880   
00881   mdspSingleWrite(address, hpiValue);
00882 };
00883 
00884 //------------------------------slvHpiFetch------------------------------------
00885 
00886 unsigned long RodModule::slvHpiFetch(unsigned long hpiReg, long slaveNum) 
00887               throw(VmeException &) {
00888 
00889   unsigned long hpiValue;
00890   unsigned long address;
00891   address = hpiReg + slaveNum*SLAVE_HPI_OFFSET;
00892   
00893     hpiValue=mdspSingleRead(address);
00894 
00895   return hpiValue;
00896 };
00897 
00898 //-------------------------------slvSingleRead---------------------------------
00899 unsigned long RodModule::slvSingleRead(unsigned long dspAddr, long slaveNum ) 
00900               throw(VmeException &) {
00901 
00902   unsigned long slvHpia, slvHpid;
00903   unsigned long value;
00904   slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET;
00905   slvHpid = SLAVE_HPID_NOAUTO_BASE * slaveNum*SLAVE_HPI_OFFSET;
00906 
00907 //  Load the DSP address into the HPIA register 
00908   mdspSingleWrite(slvHpia, dspAddr);
00909 
00910 //      Do the read 
00911   value = mdspSingleRead(slvHpid);
00912 
00913   return value;
00914 };
00915 
00916 //------------------------------slvSingleWrite------------------------------------                                   
00917 
00918 void RodModule::slvSingleWrite(unsigned long dspAddr, unsigned long buffer, 
00919                  long slaveNum) throw(VmeException &) { 
00920 
00921   unsigned long slvHpia, slvHpid;
00922   slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET;
00923   slvHpid = SLAVE_HPID_NOAUTO_BASE * slaveNum*SLAVE_HPI_OFFSET;
00924 
00925   mdspSingleWrite(slvHpia, dspAddr);
00926 
00927 //      Do the write 
00928   mdspSingleWrite(slvHpid, buffer);
00929 
00930   return;
00931 };
00932 
00933 //-----------------------------slvBlockRead---------------------------------                                
00934 
00935 void RodModule::slvBlockRead(const unsigned long dspAddr, unsigned long buffer[],
00936                 const long wordCount, long slaveNum, HpidMode mode=DYNAMIC) 
00937                 throw (HpiException &, VmeException &) {
00938                 
00939   unsigned long hpidAddr, dspAddrLocal, hpiaAfterFetch, hpiaAfterCalc; 
00940   long myCount, blockWordCount, wordIncr;
00941   unsigned long slvHpia, slvHpidAuto, slvHpidNoAuto;
00942   slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET;
00943   slvHpidAuto = SLAVE_HPID_AUTO_BASE + slaveNum*SLAVE_HPI_OFFSET;
00944   slvHpidNoAuto = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET;
00945 
00946 
00947 // Determine the HPI mode to use.
00948   switch (mode) {
00949     case AUTO:
00950       hpidAddr= slvHpidAuto;
00951       break;
00952     case NO_AUTO:
00953       hpidAddr = slvHpidNoAuto; 
00954       break;
00955     case DYNAMIC:
00956     default:
00957       if (wordCount == 1){
00958         hpidAddr = slvHpidNoAuto;
00959       } 
00960       else { 
00961         hpidAddr = slvHpidAuto;
00962       };
00963       break;
00964   };
00965 
00966 //  Load the DSP address into the HPIA register 
00967   mdspSingleWrite(slvHpia, dspAddr);
00968 
00969 // Check to see that we don't access too large a block. HPID has 20 bits of 
00970 // address space available. MAX_HPID_WORD_ELEMENTS is defined in RodVmeAddresses.h
00971 
00972   if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00973     blockWordCount = MAX_HPID_WORD_ELEMENTS;
00974   }     else { 
00975     blockWordCount = wordCount;
00976   }
00977 
00978 //      Set up the transfer as a series of block transfers 
00979   for (myCount=wordCount, wordIncr=0; myCount>0;
00980                     myCount-=blockWordCount, wordIncr+=blockWordCount) {
00981 
00982 //      Recheck each block 
00983     if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00984       blockWordCount=MAX_HPID_WORD_ELEMENTS;
00985     }   
00986     else { 
00987       blockWordCount = myCount;
00988     }
00989 
00990 //      Do the transfer for this block 
00991     dspAddrLocal = dspAddr+ (4*wordIncr);
00992     mdspBlockRead(hpidAddr, &buffer[2*wordIncr], blockWordCount, NO_AUTO);
00993   }
00994 
00995 //  Check HPID after transfer 
00996   hpiaAfterFetch = mdspSingleRead(slvHpia);
00997   if (wordCount == 1) {
00998     hpiaAfterCalc = dspAddr;
00999   }     else  {
01000     hpiaAfterCalc = dspAddr+wordCount*4;
01001   }
01002 /*  if (hpiaAfterFetch != hpiaAfterCalc) {
01003     throw HpiException("mslvBlockRead address check failed", hpiaAfterCalc, 
01004                        hpiaAfterFetch);
01005   }
01006 */
01007   return;
01008 };
01009 
01010 //------------------------------slvBlockWrite-----------------------------------  
01011 
01012 void RodModule::slvBlockWrite(unsigned long dspAddr, unsigned long buffer[], 
01013          long wordCount, long slaveNum, HpidMode mode=DYNAMIC) 
01014          throw (HpiException &, VmeException &) { 
01015 
01016   unsigned long hpidAddr, dspAddrLocal, hpiaAfterFetch, hpiaAfterCalc;
01017   long myCount, blockWordCount, wordIncr;
01018   unsigned long slvHpia, slvHpidAuto, slvHpidNoAuto;
01019   slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET;
01020   slvHpidAuto = SLAVE_HPID_AUTO_BASE + slaveNum*SLAVE_HPI_OFFSET;
01021   slvHpidNoAuto = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET;
01022 
01023 //  Load the initial dsp address into the HPIA register 
01024   mdspSingleWrite(slvHpia, dspAddr);
01025 
01026 // Determine the HPI mode to use.
01027   switch (mode) {
01028     case AUTO:
01029       hpidAddr= slvHpidAuto;
01030       break;
01031     case NO_AUTO:
01032       hpidAddr = slvHpidNoAuto; 
01033       break;
01034     case DYNAMIC:
01035     default:
01036       if (wordCount == 1){
01037         hpidAddr = slvHpidNoAuto;
01038       } 
01039       else { 
01040         hpidAddr = slvHpidAuto;
01041       };
01042       break;
01043   };
01044 
01045 // Check to see that we don't access too large a block. HPID has 20 bits of 
01046 // address space available. MAX_HPID_WORD_ELEMENTS is defined in vmeAddressMap.h
01047 
01048   if (wordCount>MAX_HPID_WORD_ELEMENTS) {
01049     blockWordCount = MAX_HPID_WORD_ELEMENTS;
01050   }     
01051   else { 
01052     blockWordCount = wordCount;
01053   }
01054 
01055 //      Set up the transfer as a series of block transfers 
01056   for (myCount=wordCount, wordIncr=0; myCount>0;
01057                     myCount-=blockWordCount, wordIncr+=blockWordCount) {
01058 
01059 //      Recheck each block 
01060     if (wordCount>MAX_HPID_WORD_ELEMENTS) {
01061       blockWordCount=MAX_HPID_WORD_ELEMENTS;
01062     }   
01063     else { 
01064       blockWordCount = myCount;
01065     }
01066   
01067 //      Do the transfer for this block 
01068   dspAddrLocal = dspAddr+ (4*wordIncr);
01069     mdspBlockWrite(hpidAddr, &buffer[2*wordIncr], blockWordCount, NO_AUTO);
01070   }
01071   
01072 //  Check HPID after transfer 
01073   hpiaAfterFetch = mdspSingleRead(slvHpia);
01074         
01075   if (wordCount == 1) {
01076     hpiaAfterCalc = dspAddr;
01077   }     
01078   else  {
01079     hpiaAfterCalc = dspAddr+wordCount*4-4;
01080   }
01081   
01082 /*  if (hpiaAfterFetch != hpiaAfterCalc) {
01083     throw HpiException("mdspBlockWrite address check failed", hpiaAfterCalc, 
01084                         hpiaAfterFetch);
01085   }
01086 */      
01087   return;
01088 };
01089 
01090 //------------------------------resetMasterDsp--------------------------------                                
01091 
01092 void RodModule::resetMasterDsp() throw(VmeException &) {
01093   unsigned long value=0;
01094   unsigned long rodRegValue;
01095   
01096   rodRegValue = readRodStatusReg(0);
01097   setBit(&value, 1);
01098   if (endianSwap) {
01099     value = endianReverse32(value);
01100   }
01101   m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], value);
01102   sleep(1000);
01103   rodRegValue = readRodStatusReg(0);
01104   
01105   return;
01106 };
01107 
01108 //------------------------------resetSlaveDsp--------------------------------                                
01109 
01110 void RodModule::resetSlaveDsp(long slaveNumber) throw(VmeException &) {
01111   unsigned long value=0;
01112   
01113   setBit(&value, 2+slaveNumber);
01114   if (endianSwap) {
01115     value = endianReverse32(value);
01116   }
01117   m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], value);
01118   sleep(1000);
01119   
01120   return;
01121 };
01122 
01123 
01124 //------------------------------resetAllDsps--------------------------------                                
01125 
01126 void RodModule::resetAllDsps() throw(VmeException &) {
01127   unsigned long value=0;
01128   
01129   setBit(&value, 6);
01130   if (endianSwap) {
01131     value = endianReverse32(value);
01132   }
01133   m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], value);
01134   sleep(1000);
01135   
01136   return;
01137 };
01138 
01139 //-------------------------------chipEraseHpi---------------------------------
01140 
01141 void RodModule::chipEraseHpi() throw(VmeException &) {
01142   unsigned long value = 0x10;
01143   
01144 // Commands 1 to 5
01145   commonEraseCommandsHpi(MDSP_FLASH_BOTTOM);
01146   
01147 // Command 6
01148   mdspSingleWrite(MDSP_FLASH_BOTTOM+(0x5555<<2), value);
01149   
01150 // Wait for operation to complete
01151   sleep(CHIP_ERASE_TIME_MS);
01152   return;
01153 };
01154   
01155 //--------------------------------sectorErase---------------------------------
01156 
01157 void RodModule::sectorErase(unsigned long sectorBaseAddress) 
01158                             throw(RodException &, VmeException &) {
01159   unsigned long flashBaseAddress;
01160 
01161 // Get flash base address
01162   if ((sectorBaseAddress<FPGA_FLASH_0_BOTTOM)||
01163             (sectorBaseAddress>FPGA_FLASH_2_BOTTOM+FLASH_MEMORY_SIZE)) {
01164     throw RodException("Flash sector base addr out of range, sectorBaseAddress=",
01165     sectorBaseAddress);
01166   }
01167   if (sectorBaseAddress<FPGA_FLASH_1_BOTTOM) {
01168     flashBaseAddress = FPGA_FLASH_1_BOTTOM;
01169   }
01170   else {
01171     flashBaseAddress = FPGA_FLASH_2_BOTTOM;
01172   }
01173   
01174 // Commands 1 to 5
01175   commonEraseCommands(flashBaseAddress);
01176   
01177 // Set write bit
01178   vmeWriteElementFlash(0x30, sectorBaseAddress, WRITE_COMMAND_HANDSHAKE_BIT);
01179   
01180 // Wait for operation to complete
01181   sleep(SECTOR_ERASE_TIME_MS);
01182 
01183   return;
01184 };
01185   
01186 //---------------_-------------writeByteToFlash-------------------------------
01187 
01188 void RodModule::writeByteToFlash(unsigned long address, UINT8 data) 
01189                             throw (RodException &, VmeException &) {
01190   UINT8 readData;
01191   clock_t startTime;   // start time for DQ7 data polling, in seconds
01192   long updateAddress;
01193   
01194   if (data!=0xFF) {   // if erased, don't rewrite. 0xFF is default after erasing
01195 // write data
01196     vmeWriteElementFlash(data, address, WRITE_DATA_HANDSHAKE_BIT);
01197     updateAddress = 0;
01198   }
01199   else {
01200     updateAddress = 1;
01201   }
01202   
01203 // Wait for operation to complete - data polling
01204   startTime = clock();
01205   while(1) {
01206     readData = readByteFromFlash(address, updateAddress);
01207     if (readData == data) return;
01208     else if((clock()-startTime)*CLOCKS_PER_SEC > FLASH_TIMEOUT) {
01209       throw RodException("Flash timeout in writeByteToFlash, FLASH_TIMEOUT=",
01210       (long)FLASH_TIMEOUT);
01211     }
01212   }
01213   return;
01214 };
01215 
01216 //----------------------------writeBlockToFlash-------------------------------
01217 
01218 void RodModule::writeBlockToFlash(unsigned long address, UINT8 *data, 
01219                                unsigned long numBytes) throw(VmeException &) {
01220   unsigned long index;
01221   for (index=0; index<numBytes; ++index) {
01222     if ((index%FLASH_SECTOR_SIZE)==0) {
01223       sectorErase(address+index);
01224     }
01225     writeByteToFlash(address+index, *(data+index));
01226   } 
01227   return;
01228 };
01229   
01230 //---------------------------writeBlockToFlashHpi-----------------------------
01231 
01232 void RodModule::writeBlockToFlashHpi(unsigned long address, UINT8 *data, 
01233      unsigned long numBytes) throw (RodException &, VmeException &) {
01234   unsigned long index, sectorAddr;
01235   const unsigned long eraseData=0x30;
01236   const unsigned long data1=0xAA;
01237   const unsigned long data2=0x55;
01238   const unsigned long data3=0xA0;
01239   const unsigned long addr1=MDSP_FLASH_BOTTOM+(0x5555<<2);
01240   const unsigned long addr2=MDSP_FLASH_BOTTOM+(0x2AAA<<2);
01241   unsigned long byteRelAddr;
01242   long words;
01243   
01244   for (index=0; index<numBytes; ++index) {
01245     if ((index%FLASH_SECTOR_SIZE)==0) {
01246 // implement sectorEraseHpi(address+index) inline.
01247 //    commands 1 to 5
01248       commonEraseCommandsHpi(MDSP_FLASH_BOTTOM);
01249 // 6th command
01250       sectorAddr = MDSP_FLASH_BOTTOM+
01251                   ((address+index-MDSP_FLASH_BOTTOM)<<2);
01252       mdspSingleWrite(sectorAddr, eraseData);
01253 // Wait for operation to complete
01254       sleep(SECTOR_ERASE_TIME_MS);
01255     };
01256   };
01257   
01258 // implement writeByteToFlashHpi(address+index, *(data+index)) inline.
01259   byteRelAddr = address+index-MDSP_FLASH_BOTTOM;
01260   if (*(data+index) !=0xFF) {
01261     mdspSingleWrite(addr1, (unsigned long)data1);  // 1st command
01262     mdspSingleWrite(addr2, (unsigned long)data2);  // 2nd command
01263     mdspSingleWrite(addr1, (unsigned long)data3);  // 3rd command
01264     mdspSingleWrite(MDSP_FLASH_BOTTOM+(byteRelAddr<<2),(unsigned long)(data+index));
01265   };
01266   
01267 // Verification
01268   words = (numBytes+3)/4;       // round up
01269   UINT8 *buffer;
01270   try {
01271     buffer = new UINT8[words*4];
01272   }
01273   catch (std::bad_alloc & ba) {
01274     throw RodException("writeBlockToFlashHpi unable to get buffer.");
01275   }
01276   m_myVmePort->blockRead32(address+index, (unsigned long*)buffer, words*4);
01277   for (index=0; index<numBytes; ++index) {
01278     if(*(data+index)!=*(buffer+index)) {
01279       delete [] buffer;
01280       throw RodException("writeBlockToFlashHpi verify failed. index, data:", index,
01281                  *(data+index));
01282     };
01283     delete [] buffer;
01284   }
01285   return;
01286 };
01287   
01288 //-----------------------------readByteFromFlash------------------------------
01289 
01290 UINT8 RodModule::readByteFromFlash(unsigned long address, long updateAddress) 
01291                  throw (RodException &, VmeException &){
01292   UINT8 dataByte;
01293   unsigned long commandReg;
01294   clock_t startTime;
01295   unsigned long handshakeBitValue = 0;
01296   unsigned long valueD32;
01297   
01298   if (updateAddress) {
01299     m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[4], address);
01300   }
01301 // Set rd bit
01302     setBit(&handshakeBitValue, READ_HANDSHAKE_BIT);
01303     m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[3], handshakeBitValue);
01304     
01305 // Wait for valid data
01306     startTime = clock();
01307     while (1) {
01308       commandReg = m_myVmePort->read32(FPGA_CONTROL_REG_REL_ADDR[3]);
01309       if (0==readBit(commandReg, READ_HANDSHAKE_BIT)) break;
01310       if ((clock()-startTime)>FLASH_TIMEOUT) throw RodException(
01311                           "Timeout in readByteFromFlash. Address=", address);
01312     }
01313     
01314 // Read valid data
01315   valueD32 = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[7]); 
01316   dataByte = (UINT8)(valueD32&0xFF);
01317   return dataByte;
01318 };
01319   
01320 //---------------------------vmeWriteElementFlash------------------------------
01321 
01322 void RodModule::vmeWriteElementFlash(UINT8 value, unsigned long address, 
01323            long handshakeBit) throw (RodException &, VmeException &) {
01324   unsigned long ctrlReg4Val;  // address(23:0) + data(31:24)
01325   unsigned long commandReg;
01326   clock_t startTime;
01327   unsigned long handshakeBitValue=0;
01328   
01329   ctrlReg4Val = (value<<24)| address;
01330   m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[4], ctrlReg4Val);
01331 
01332 // Set wr bit
01333   setBit(&handshakeBitValue, handshakeBit);
01334   m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[3], handshakeBitValue);
01335 
01336 // Wait for ack
01337   startTime = clock();
01338   while(1) {
01339       commandReg = m_myVmePort->read32(FPGA_CONTROL_REG_REL_ADDR[3]);
01340       if (0==readBit(commandReg, handshakeBit)) break;
01341       if ((clock()-startTime)>FLASH_TIMEOUT) throw RodException(
01342                    "Timeout in vmeWriteElementFlash. Address, value=", 
01343                    address, (unsigned long)value);
01344   }
01345   return;   
01346 };
01347 
01348 //-----------------------------readBlockFromFlash------------------------------
01349 
01350 void RodModule::readBlockFromFlash(unsigned long address, UINT8 *buffer, 
01351          unsigned long numBytes) throw(VmeException &) {
01352   unsigned long index;
01353   for (index=0; index<numBytes; ++index) {
01354     if (0==(index%FLASH_SECTOR_SIZE)) {
01355       readByteFromFlash(address+index, (long)(buffer+index));
01356     }
01357   }
01358   return;
01359 };
01360   
01361 //-----------------------------commonEraseCommands----------------------------
01362 
01363 void RodModule::commonEraseCommands(unsigned long flashBaseAddr) 
01364                                            throw(VmeException &) {
01365 
01366   const unsigned long addr1 = flashBaseAddr+0x5555;
01367   const unsigned long addr2 = flashBaseAddr+0x2AAA;
01368   
01369 // 1st command
01370   vmeWriteElementFlash(0xAA, addr1, WRITE_COMMAND_HANDSHAKE_BIT);
01371   
01372 // 2nd command
01373   vmeWriteElementFlash(0x55, addr2, WRITE_COMMAND_HANDSHAKE_BIT);
01374 
01375 // 3rd command
01376   vmeWriteElementFlash(0x80, addr1, WRITE_COMMAND_HANDSHAKE_BIT);
01377   
01378 // 4th command
01379   vmeWriteElementFlash(0xAA, addr1, WRITE_COMMAND_HANDSHAKE_BIT);
01380 
01381 // 5th command
01382   vmeWriteElementFlash(0x55, addr2, WRITE_COMMAND_HANDSHAKE_BIT);
01383 
01384   return;
01385 };
01386 
01387 //----------------------------commonEraseCommandsHpi--------------------------
01388 
01389 void RodModule::commonEraseCommandsHpi(unsigned long flashBaseAddr) 
01390                                               throw(VmeException &) {
01391 
01392   unsigned long buffer;
01393   const unsigned long addr1 = flashBaseAddr+(0x5555<<2);
01394   const unsigned long addr2 = flashBaseAddr+(0x2AAA<<2);
01395   
01396 // 1st command
01397   buffer = 0xAA;
01398   m_myVmePort->write32(addr1, buffer);
01399   
01400 // 2nd command
01401   buffer = 0x55;
01402   m_myVmePort->write32(addr2, buffer);
01403 
01404 // 3rd command
01405   buffer = 0x80;
01406   m_myVmePort->write32(addr1, buffer);
01407   
01408 // 4th command
01409   buffer = 0xAA;
01410   m_myVmePort->write32(addr1, buffer);
01411 
01412 // 5th command
01413   buffer = 0x55;
01414   m_myVmePort->write32(addr2, buffer);
01415 
01416   return;
01417 };
01418 
01419 //----------------------------------sleep-------------------------------------                                
01420 
01421 void RodModule::sleep(const double milliSecs) {
01422   clock_t start, delay;
01423   delay = clock_t(milliSecs * CLOCKS_PER_SEC/1000.); //need explicit type cast
01424                                                      //to avoid warning.
01425   start = clock();
01426   while (clock()-start< delay)   // wait until time elapses
01427      ;
01428   return;
01429 };
01430   
01431 //--------------------------------checkSum------------------------------------                                
01432 
01433 unsigned long RodModule::checkSum(const unsigned long *sourceArray, const long wordCount) {
01434   unsigned long result=0;
01435   long i;
01436   
01437   for (i=0; i<wordCount; ++i) {
01438     result ^= sourceArray[i];
01439   }
01440   return result;
01441 };
01442  
01443 //-----------------------------endianReverse32----------------------------------                                
01444 
01445 unsigned long RodModule::endianReverse32(const unsigned long inVal) {
01446   unsigned long outVal;
01447   outVal  = (inVal & 0x000000ff) << 24;
01448   outVal |= (inVal & 0x0000ff00) << 8;
01449   outVal |= (inVal & 0x00ff0000) >> 8;
01450   outVal |= (inVal & 0xff000000) >> 24;
01451   return outVal;
01452 };
01453   
01454 } //  End namespace SctPixelRod
01455 
01456 //---------------------------- Overload operator<< -----------------------------
01457 /* This overloaded operator lets us use cout to print the status of the ROD
01458 */
01459   ostream& std::operator<<(ostream& os, SctPixelRod::RodModule& rod) {
01460     os << "Slot: " << rod.getSlot() << endl;
01461     os << "Serial Number:" << rod.getSerialNumber() << endl;
01462     os << "Number of slave DSPs: " << rod.getNumSlaves() << endl;
01463     os << "Status registers[0-2]: ";
01464     try {
01465       for (int i=0; i<3; i++) {
01466         os << hex << rod.readRodStatusReg(i) << " ";
01467       }
01468       os << endl;
01469     }
01470     catch (SctPixelRod::VmeException &) {
01471       os << "VmeException while reading ROD status registers. " << endl;
01472     }
01473     
01474     os << "Command registers[0-1]: ";
01475     try {
01476       for (int i=0; i<2; i++) {
01477         os << hex << rod.readRodCommandReg(i) << " ";
01478       }
01479       os << endl;
01480     }
01481     catch (SctPixelRod::VmeException &) {
01482       os << "VmeException while reading ROD command registers. " << endl;
01483     }
01484 
01485     os << "Primitive state: " << rod.getPrimState() << " Text State: " << 
01486           rod.getTextState() << endl;
01487     return os;
01488   }
01489 
01490 

Generated on Mon Mar 3 11:16:17 2003 for SCTPixelDAQ by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001