Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals | Related Pages

RodModule.cxx

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

Generated on Thu Dec 22 20:17:08 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5