00001 //#include "otsdaq-components/DAQHardware/PSI46DigFirmware.h" 00002 //#include "otsdaq-components/DAQHardware/PSI46DigFirmwareDefinitions.h" 00003 //#include "otsdaq-core/BitManipulator/BitManipulator.h" 00004 //#include "otsdaq-components/DetectorHardware/PSI46DigROCDefinitions.h" 00005 //#include "otsdaq-core/MessageFacility/MessageFacility.h" 00006 //#include "otsdaq-core/Macros/CoutMacros.h" 00007 //#include <sys/socket.h> 00008 //#include <netinet/in.h> 00009 //#include <arpa/inet.h> 00010 //#include <iostream> 00011 //#include <cstdlib> 00012 // 00013 //using namespace ots; 00014 // 00015 // 00017 //PSI46DigFirmware::PSI46DigFirmware(unsigned int version, std::string type) : 00018 // FrontEndFirmwareBase(version), 00019 // stripCSRRegisterValue_(0) 00020 //{ 00021 // protocolInstance_ = FrontEndFirmwareBase::getInstance(type,version); 00022 // assert(protocolInstance_ != NULL); 00023 // //returns either new OtsUDPFirmware or new PurdueFirmwareCore, 00024 // //now we can call write/read etc with protocol->write, protocol->read, etc 00025 //} 00026 // 00028 //PSI46DigFirmware::~PSI46DigFirmware(void) 00029 //{ 00030 // delete protocolInstance_; 00031 // protocolInstance_= NULL; 00032 //} 00033 // 00035 //int PSI46DigFirmware::init(void) 00036 //{ 00037 // return 0; 00038 //} 00039 // 00041 //std::string PSI46DigFirmware::configureClocks(std::string source, double frequency) 00042 //{ 00043 // std::cout << __COUT_HDR_FL__ << "Writing Clock configuration!" << std::endl; 00044 // 00045 // std::string buffer; 00046 // //NoNeedNowwrite(buffer, ETHIO_DESTINATION_PORT, 0x0000b798); // Listen port for ethio stuff 00047 // 00048 // setPacketSizeStripCSR(6); 00049 // setExternalBCOClockSourceStripCSR(source); //(source) 00050 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); // Reset CSR - reset trigger counter, external 27 MHz clock 00051 // 00052 // resetDCMStripCSR(true); 00053 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); // Set reset to DCM 00054 // 00055 // resetDCMStripCSR(false); 00056 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); // Clear reset to DCM 00057 // 00058 // ; 00059 // protocolInstance_->waitClear(buffer, STRIP_CSR, waitDCMResetStripCSR()); // Wait for DCM to lock 00060 // 00061 // protocolInstance_->write(buffer, STRIP_TRIM_CSR, 0x00002000); // MCLKB edge for channel 5 // was 0x00002000 00062 // 00063 // setFrequencyFromClockState(buffer, frequency); 00064 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00065 // 00066 // resetDCMStripCSR(true); 00067 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00068 // 00069 // resetDCMStripCSR(false); 00070 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00071 // 00072 // protocolInstance_->waitClear(buffer, STRIP_CSR, waitDCMResetStripCSR()); // Wait for DCM to lock 00073 // std::cout << __COUT_HDR_FL__ << "stripCSRRegisterValue :" << std::hex << stripCSRRegisterValue_ << std::dec << std::endl; 00074 // 00075 // return buffer; 00076 //} 00077 // 00079 //std::string PSI46DigFirmware::resetDetector(int channel) 00080 //{ 00081 // std::cout << __COUT_HDR_FL__ << "Resetting detector!" << std::endl; 00082 // std::string buffer; 00083 // if (channel == -1)//reset all channels 00084 // { 00085 // //protocolInstance_->write(buffer,STRIP_RESET,0xd000003f); // Issue reset 00086 // protocolInstance_->write(buffer, STRIP_RESET, 0xf000003f); // Issue reset // was 0xf000003f 00087 // protocolInstance_->waitClear(buffer, STRIP_RESET, 0xf0000000); // Wait for reset to complete // was 0xf0000000 00088 // } else 00089 // { 00090 // protocolInstance_->write(buffer, STRIP_RESET, 0xf000003f); // Issue reset 00091 // protocolInstance_->waitClear(buffer, STRIP_RESET, 0xf0000000); // Wait for reset to complete 00092 // } 00093 // 00094 // return buffer; 00095 //} 00096 // 00098 //std::string PSI46DigFirmware::enableTrigger(void) 00099 //{ 00100 // std::string buffer; 00101 // std::cout << __COUT_HDR_FL__ << "Enabling Trigger!!!" << std::endl; 00102 // std::cout << __COUT_HDR_FL__ << "stripCSRRegisterValue in :" << std::hex << stripCSRRegisterValue_ << std::dec << std::endl; 00103 // 00104 // setHaltStripCSR(1);//WARNING THIS IS CLEARED BY THE MASTER BUT IF THERE IS NO MASTER NOTHING WORKS UNLESS THE BIT IS UNSET 00105 // //setHaltStripCSR(0);//WARNING THIS IS CLEARED BY THE MASTER BUT IF THERE IS NO MASTER NOTHING WORKS UNLESS THE BIT IS UNSET 00106 // sendTriggerDataStripCSR(true); 00107 // sendTriggerNumberStripCSR(true); 00108 // sendBCOStripCSR(true); 00109 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00110 // 00111 // stripTriggerCSRRegisterValue_ = 0; 00112 // BCOOffset(4); 00113 // protocolInstance_->write(buffer, STRIP_TRIG_CSR, stripTriggerCSRRegisterValue_); // BCO offset // was 0x00000004 00114 // 00115 // // write(buffer,STRIP_TRIG_INPUT_0,0x1f060040); // PSI46Dig GOTHIT trigger input - timed in for the 27 MHz external clock 00116 // // write(buffer,STRIP_TRIG_INPUT_3,0x3f874040); // Unbiased trigger input + external trigger 00117 // 00118 // configureStripTriggerUnbiased(buffer); 00119 // 00120 // configureTriggerInputs(buffer); 00121 // 00122 // //FIXME for IP .36 the number to set is 0x20401000 00123 // 00124 // if (version_ == 1) 00125 // protocolInstance_->write(buffer, STRIP_TRIG_INPUT_3, 0x20401000); // Turn on streaming hits along with BCO data 00126 // else if (version_ == 2) 00127 // protocolInstance_->write(buffer, STRIP_TRIG_INPUT_3, 0x20301000); // Turn on streaming hits along with BCO data 00128 // else 00129 // { 00130 // std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "what version is this?" << version_ << std::endl; 00131 // assert(0); 00132 // } 00133 // std::cout << __COUT_HDR_FL__ << "stripCSRRegisterValue out:" << std::hex << stripCSRRegisterValue_ << std::dec << std::endl; 00134 // std::cout << __COUT_HDR_FL__ << "Done enabling Trigger!!!" << std::endl; 00135 // 00136 // return buffer; 00137 //} 00138 // 00140 //std::string PSI46DigFirmware::resetBCO(void) 00141 //{ 00142 // std::cout << __COUT_HDR_FL__ << "Reset BCO!!!" << std::endl; 00143 // std::cout << __COUT_HDR_FL__ << "stripCSRRegisterValue in :" << std::hex << stripCSRRegisterValue_ << std::dec << std::endl; 00144 // std::string buffer; 00145 // 00146 // resetTriggerCounterStripCSR(buffer); 00147 // //write(buffer, STRIP_CSR, stripCSRRegisterValue_);//the write is done in the reset 00148 // std::cout << __COUT_HDR_FL__ << "stripCSRRegisterValue :" << std::hex << stripCSRRegisterValue_ << std::dec << std::endl; 00149 // 00150 // //msg->Write(STRIP_SC_CSR,0x90000b95|(chmask<<16)); 00151 // //write(buffer,STRIP_SC_CSR,0x900f0b95);// This is the <SCR,set> command with the bit set to sync SHIFT with BCO=0. 00152 // 00153 // 00154 // enableBCOStripCSR(true); 00155 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00156 // std::cout << __COUT_HDR_FL__ << "stripCSRRegisterValue out:" << std::hex << stripCSRRegisterValue_ << std::dec << std::endl; 00157 // std::cout << __COUT_HDR_FL__ << "Done reset BCO!!!" << std::endl; 00158 // 00159 // return buffer; 00160 //} 00161 // 00163 //std::string PSI46DigFirmware::startStream(bool channel0, bool channel1, bool channel2, bool channel3, bool channel4, bool channel5) 00164 //{ 00165 // std::cout << __COUT_HDR_FL__ << "Start Stream!" << std::endl; 00166 // std::cout << __COUT_HDR_FL__ << "stripCSRRegisterValue in:" << std::hex << stripCSRRegisterValue_ << std::dec << std::endl; 00167 // std::string buffer; 00168 // 00169 // std::cout << __COUT_HDR_FL__ << " channel0 " << channel0 << " channel1 " << channel1 << " channel2 " << channel2 << " channel3 " << channel3 << " channel4 " << channel4 << " channel5 " << channel5 << std::endl; 00170 // 00171 // enableChannelsStripCSR(channel0, channel1, channel2, channel3, channel4, channel5); 00172 // // if (version_ == 1) 00173 // // enableChannelsStripCSR(true, true, true, true, false, false); 00174 // // else if (version_ == 2) 00175 // // enableChannelsStripCSR(true, true, true, true, true, true); 00176 // 00177 // enableStreamStripCSR(true); // Turn on streaming hits along with BCO data // was 0x0f000f30 00178 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00179 // 00180 // std::cout << __COUT_HDR_FL__ << "stripCSRRegisterValue out:" << std::hex << stripCSRRegisterValue_ << std::dec << std::endl; 00181 // std::cout << __COUT_HDR_FL__ << "Done start Stream!" << std::endl; 00182 // 00183 // return buffer; 00184 //} 00185 // 00187 //std::string PSI46DigFirmware::stopStream(void) 00188 //{ 00189 // std::string buffer; 00190 // enableChannelsStripCSR(false, false, false, false, false, false); 00191 // enableStreamStripCSR(false); 00192 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00193 // return buffer; 00194 //} 00195 // 00197 //void PSI46DigFirmware::makeDACSequence(FirmwareSequence<uint64_t>& sequence, 00198 // unsigned int channel, const ROCStream& rocStream) 00199 //{ 00200 // const ROCDACs& rocDACs = rocStream.getROCDACs(); 00201 // for (DACList::const_iterator it = rocDACs.getDACList().begin(); it 00202 // != rocDACs.getDACList().end(); it++) 00203 // { 00204 // //if(it->first != "SendData" && it->first != "RejectHits") continue; 00205 // uint64_t data = PSI46DigROCDefinitions::makeDACWriteCommand( 00206 // rocStream.getFEWROCAddress(), it->first, it->second.second); 00207 // sequence.pushBack(ChannelFIFOAddress[channel], data); 00208 // sequence.pushBack(ChannelFIFOAddress[channel], 00209 // BitManipulator::insertBits(data, (uint64_t) 0x48, 56, 8)); 00210 // //set WRITE 00211 // sequence.pushBack(ChannelFIFOAddress[channel], 00212 // BitManipulator::insertBits(data, (uint64_t) 1, 60, 1)); 00213 // //clr WRITE 00214 // sequence.pushBack(ChannelFIFOAddress[channel], 00215 // BitManipulator::insertBits(data, (uint64_t) 0, 60, 1)); 00216 // //clr TALK 00217 // sequence.pushBack(ChannelFIFOAddress[channel], 00218 // BitManipulator::insertBits(data, (uint64_t) 0, 62, 1)); 00219 // sequence.pushBack(ChannelFIFOAddress[channel], 00220 // BitManipulator::insertBits(data, (uint64_t) 0x40, 56, 8)); 00221 // //break; 00222 // } 00223 //} 00224 // 00226 //void PSI46DigFirmware::makeDACSequence(FirmwareSequence<uint32_t>& sequence, 00227 // unsigned int channel, const ROCStream& rocStream) 00228 //{ 00229 // const ROCDACs& rocDACs = rocStream.getROCDACs(); 00230 // for (DACList::const_iterator it = rocDACs.getDACList().begin(); it 00231 // != rocDACs.getDACList().end(); it++) 00232 // { 00233 // /*RYAN 00234 // //if(it->first != "SendData" && it->first != "RejectHits") continue; 00235 // uint64_t data = PSI46DigROCDefinitions::makeDACWriteCommand(rocStream.getFEWROCAddress(), it->first, it->second.second); 00236 // sequence.pushBack(ChannelFIFOAddress[channel], data); 00237 // sequence.pushBack(ChannelFIFOAddress[channel], BitManipulator::insertBits(data,(uint32_t)0x48,56,8)); 00238 // //set WRITE 00239 // sequence.pushBack(ChannelFIFOAddress[channel], BitManipulator::insertBits(data,(uint32_t)1,60,1)); 00240 // //clr WRITE 00241 // sequence.pushBack(ChannelFIFOAddress[channel], BitManipulator::insertBits(data,(uint32_t)0,60,1)); 00242 // //clr TALK 00243 // sequence.pushBack(ChannelFIFOAddress[channel], BitManipulator::insertBits(data,(uint32_t)0,62,1)); 00244 // sequence.pushBack(ChannelFIFOAddress[channel], BitManipulator::insertBits(data,(uint32_t)0x40,56,8)); 00245 // */ 00246 // 00247 // //if(it->first != "SendData" && it->first != "RejectHits") continue; 00248 // uint32_t data = PSI46DigROCDefinitions::makeDACWriteHeader( 00249 // rocStream.getFEWROCAddress(), it->first); 00250 // //Insert channel 00251 // BitManipulator::insertBits(data, 1, 16 + channel, 1); 00252 // sequence.pushBack(ChannelFIFOAddress[channel], it->second.second); 00253 // std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "Register: " << it->first << " value: " 00254 // << it->second.second << std::hex << " -> Data: " << data << std::dec 00255 // << std::endl; 00256 // sequence.pushBack(STRIP_SC_CSR, data); 00257 // } 00258 //} 00259 // 00261 //void PSI46DigFirmware::makeDACBuffer(std::string& buffer, 00262 // unsigned int channel, const ROCStream& rocStream) 00263 //{ 00264 // std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "Channel: " << channel << std::endl; 00265 // const ROCDACs& rocDACs = rocStream.getROCDACs(); 00266 // for (DACList::const_iterator it = rocDACs.getDACList().begin(); it != rocDACs.getDACList().end(); it++) 00267 // { 00268 // std::string bufferElement; 00269 // protocolInstance_->waitClear(bufferElement, STRIP_SC_CSR, 0x80000000); 00270 // uint32_t registerHeader = 0; 00271 // //FIXME This must go in the PSI46DigROCDefinitions stuff 00272 // if (it->first != "RejectHits" && it->first != "SendData") 00273 // { 00274 // protocolInstance_->write(bufferElement, ChannelFIFOAddress[channel], it->second.second); 00275 // registerHeader = PSI46DigROCDefinitions::makeDACWriteHeader( 00276 // rocStream.getFEWROCAddress(), it->first); 00277 // //std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "Register: " << it->first << " value: " << it->second.second << hex << " -> Data: " << registerHeader << dec << std::endl; 00278 // //Insert channel 00279 // BitManipulator::insertBits(registerHeader, 1, 16 + channel, 1); 00280 // } 00281 // else 00282 // { 00283 // if (it->second.second == 1 || it->second.second == 2) 00284 // { 00285 // registerHeader = PSI46DigROCDefinitions::makeDACSetHeader( 00286 // rocStream.getFEWROCAddress(), it->first); 00287 // //Insert channel 00288 // BitManipulator::insertBits(registerHeader, 1, 16 + channel, 1); 00289 // } 00290 // else if (it->second.second == 0 || it->second.second == 5) 00291 // { 00292 // registerHeader = PSI46DigROCDefinitions::makeDACResetHeader( 00293 // rocStream.getFEWROCAddress(), it->first); 00294 // //Insert channel 00295 // BitManipulator::insertBits(registerHeader, 1, 16 + channel, 1); 00296 // } 00297 // else 00298 // std::cout << __COUT_HDR_FL__ << "Register value for : " << it->first 00299 // << " doesn't have a value I expect -> value = " 00300 // << it->second.second << std::endl; 00301 // 00302 // } 00303 // //std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "Register: " << it->first << " value: " << it->second.second << hex << " -> Data: " << registerHeader << dec << std::endl; 00304 // protocolInstance_->write(bufferElement, STRIP_SC_CSR, registerHeader); 00305 // protocolInstance_->waitClear(bufferElement, STRIP_SC_CSR, 0x80000000); 00306 // 00307 // //buffer.push_back(bufferElement); 00308 // buffer += bufferElement; 00309 // //break; 00310 // } 00311 //} 00312 // 00314 //void PSI46DigFirmware:: makeDACBuffer(std::vector<std::string>& buffer, unsigned int channel, const ROCStream& rocStream) 00315 //{ 00316 // 00317 // std::cout << __COUT_HDR_FL__ << "\tMaking DAC Buffer" << std::endl; 00318 // 00319 // int limitCount = 0; 00320 // unsigned int singleVectorCount = 0; 00321 // 00322 // std::string alternateBuffer; 00323 // 00324 // std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "Channel: " << channel << std::endl; 00325 // const ROCDACs& rocDACs = rocStream.getROCDACs(); 00326 // //std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "Number of DACs: " << rocDACs.getDACList().size() << std::endl; 00327 // std::string bufferElement; 00328 // for (DACList::const_iterator it = rocDACs.getDACList().begin(); it != rocDACs.getDACList().end(); it++) 00329 // { 00330 // protocolInstance_->waitClear(bufferElement, STRIP_SC_CSR, 0x80000000); 00331 // uint32_t registerHeader = 0; 00332 // //FIXME This must go in the PSI46DigROCDefinitions stuff 00333 // if (it->first != "RejectHits" && it->first != "SendData") 00334 // { 00335 // protocolInstance_->write(bufferElement, ChannelFIFOAddress[channel], it->second.second); 00336 // registerHeader = PSI46DigROCDefinitions::makeDACWriteHeader( 00337 // rocStream.getFEWROCAddress(), it->first); 00338 // std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "Register: " << it->first << " value: " << it->second.second << std::hex << " -> Data: " << registerHeader << std::dec << std::endl; 00339 // //Insert channel 00340 // BitManipulator::insertBits(registerHeader, 1, 16 + channel, 1); 00341 // } 00342 // else 00343 // { 00344 // if (it->second.second == 1 || it->second.second == 2) 00345 // { 00346 // registerHeader = PSI46DigROCDefinitions::makeDACSetHeader( 00347 // rocStream.getFEWROCAddress(), it->first); 00348 // //Insert channel 00349 // BitManipulator::insertBits(registerHeader, 1, 16 + channel, 1); 00350 // } 00351 // else if (it->second.second == 0 || it->second.second == 5) 00352 // { 00353 // registerHeader = PSI46DigROCDefinitions::makeDACResetHeader( 00354 // rocStream.getFEWROCAddress(), it->first); 00355 // //Insert channel 00356 // BitManipulator::insertBits(registerHeader, 1, 16 + channel, 1); 00357 // } 00358 // else 00359 // std::cout << __COUT_HDR_FL__ << "Register value for : " << it->first 00360 // << " doesn't have a value I expect -> value = " 00361 // << it->second.second << std::endl; 00362 // 00363 // } 00364 // //std::cout << __COUT_HDR_FL__ << __PRETTY_FUNCTION__ << "Register: " << it->first << " value: " << it->second.second << hex << " -> Data: " << registerHeader << dec << std::endl; 00365 // protocolInstance_->write(bufferElement, STRIP_SC_CSR, registerHeader); 00366 // protocolInstance_->waitClear(bufferElement, STRIP_SC_CSR, 0x80000000); 00367 // 00368 // //alternateBuffer += bufferElement; 00369 // limitCount++; 00370 // singleVectorCount++; 00371 // 00372 // if (limitCount == STIB_DAC_WRITE_MAX) 00373 // { 00374 // std::cout << __COUT_HDR_FL__ << "\tBuffer lenght:" << bufferElement.size() << std::endl; 00375 // buffer.push_back(bufferElement); 00376 // limitCount = 0; 00377 // bufferElement.clear(); 00378 // } 00379 // else if (singleVectorCount == rocDACs.getDACList().size()) //case for imcomplete packet 00380 // { 00381 // buffer.push_back(bufferElement); 00382 // } 00383 // 00384 // //buffer.push_back(bufferElement); 00385 // //break; 00386 // } 00387 // std::cout << __COUT_HDR_FL__ << "\tDone making DAC Buffer" << std::endl; 00388 // 00389 //} 00390 // 00392 //void PSI46DigFirmware::makeMaskBuffer(std::string& buffer, unsigned int channel, 00393 // const ROCStream& rocStream) 00394 //{ 00395 // std::cout << __COUT_HDR_FL__ << "Making mask! " << std::endl; 00396 // makeMaskBuffer(buffer, channel, rocStream, "Kill"); 00397 // // makeMaskSequence(buffer, channel, rocStream, "Inject"); 00398 //} 00399 // 00401 //void PSI46DigFirmware::makeMaskBuffer(std::string& buffer, unsigned int channel, const ROCStream& rocStream, const std::string& registerName) 00402 //{ 00403 // std::cout << __COUT_HDR_FL__ << "\tMaking mask! " << std::endl; 00404 // int chipId = rocStream.getFEWROCAddress(); 00405 // std::string mask = rocStream.getROCMask(); 00406 // std::cout << __COUT_HDR_FL__ << "\tMask length: " << mask.length() << std::endl; 00407 // 00408 // unsigned int data[4] = { 0, 0, 0, 0 }; 00409 // 00410 // char val; 00411 // //int j = 0; 00412 // for (unsigned int d = 0; d < 4; d++) 00413 // { //d goes from 0 to 4. 4 bytes 00414 // //std::cout << __COUT_HDR_FL__ << "---------------------" << d << "-------------------" << std::endl; 00415 // for (unsigned int m = 0; m < 8 * 4; m++) 00416 // { //m goes from 0 to 31, since each byte has 8 bits, there are 32 bits 00417 // val = mask[(8 * 4 * d) + m]; //assigns to val the value of the corresponding bit. 0-31, 32-63, 64-95, 96-127. it goes through each of the 128 bits 00418 // //std::cout << __COUT_HDR_FL__ << "---------------------" << j++ << std::endl; 00419 // //std::cout << __COUT_HDR_FL__ << "data[" << d << "] before: " << hex << data[d] << dec << std::endl; 00420 // data[d] |= (unsigned int) atoi(&val) << (8 * 4 - 1 - m); 00421 // //std::cout << __COUT_HDR_FL__ << "(unsigned int) atoi(&val): " << (unsigned int) atoi(&val) << std::endl; 00422 // //std::cout << __COUT_HDR_FL__ << "data[" << d << "] after: " << hex << data[d] << dec << std::endl; 00423 // //std::cout << __COUT_HDR_FL__ << hex << "D: " << data[d] << " Val: " << (unsigned int)atoi(&val) << " index: " << dec << (8*4-1-m) << " bit: " << mask[(8*4*d)+m] << dec << std::endl; 00424 // } 00425 // // 00426 // } 00427 // 00428 // int i, ierr; 00429 // unsigned int w; 00430 // unsigned char len = 4; 00431 // unsigned char addr = 17;//Kill 00432 // unsigned char bitMask = 1 << channel; 00433 // unsigned char inst = WRITE; 00434 // 00435 // protocolInstance_->waitClear(buffer, STRIP_SC_CSR, 0x80000000); 00436 // 00437 // for (i = 0; i < 4; i++) 00438 // //write(buffer, STRIP_SCI + 4 * i, data[i]); 00439 // protocolInstance_->write(buffer, STRIP_SCI + 4 * (4 - i - 1), data[i]); 00440 // 00441 // w = 0x80000000 | (len << 24) | (bitMask << 16) | (inst << 10) | (addr << 5) | chipId; 00442 // 00443 // ierr = protocolInstance_->write(buffer, STRIP_SC_CSR, w); 00444 // 00445 // protocolInstance_->waitClear(buffer, STRIP_SC_CSR, 0x80000000); 00446 //} 00447 // 00449 //void PSI46DigFirmware::makeMaskSequence(FirmwareSequence<uint64_t>& sequence, 00450 // unsigned int channel, const ROCStream& rocStream) 00451 //{ 00452 // std::cout << __COUT_HDR_FL__ << "Making mask! " << std::endl; 00453 // makeMaskSequence(sequence, channel, rocStream, "Kill"); 00454 // // makeMaskSequence(sequence, channel, rocStream, "Inject"); 00455 //} 00456 // 00458 //void PSI46DigFirmware::makeMaskSequence(FirmwareSequence<uint32_t>& sequence, 00459 // unsigned int channel, const ROCStream& rocStream) 00460 //{ 00461 // std::cout << __COUT_HDR_FL__ << "Making mask! " << std::endl; 00462 // makeMaskSequence(sequence, channel, rocStream, "Kill"); 00463 // // makeMaskSequence(channel,rocStream,sequence,"Inject"); 00464 //} 00465 // 00467 //void PSI46DigFirmware::makeMaskSequence(FirmwareSequence<uint64_t>& sequence, 00468 // unsigned int channel, const ROCStream& rocStream, 00469 // const std::string& registerName) 00470 //{ 00471 // int chipId = rocStream.getFEWROCAddress();//9, 14 or 21 bcast 00472 // std::string mask = rocStream.getROCMask(); 00473 // std::cout << __COUT_HDR_FL__ << "Mask length: " << mask.length() << std::endl; 00474 // 00475 // uint64_t uInt64Data = 0; 00476 // std::string stringData = ""; 00477 // 00478 // //have to manually set every bit for mask writes. 00479 // //reset fifo 00480 // //download every bit (shift_in and shift_ctrl) to fifo (setup muxes and control lines) 00481 // //configure muxes for readout 00482 // //commence readout 00483 // 00484 // //FIFO Controls - byte 5 (7:0) 00485 // //7 - FIFO Clock 00486 // //6 - Shift Ctrl bit 00487 // //MASK_CELL_H - Shift In bit 00488 // //MUX Controls - byte 0 (7:0) 00489 // //7 - Read En/Output MUX sel (1 for masks) 00490 // //1 - Write En for mux 00491 // //0 - Reset Fifo 00492 // 00493 // //reset fifo 00494 // BitManipulator::insertBits(uInt64Data, 0x1, 56, 8); 00495 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00496 // 00497 // //configure fifo for write 00498 // BitManipulator::insertBits(uInt64Data, 0x2, 56, 8); 00499 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00500 // 00501 // //Download every bit (shift_in and shift_control) to fifo (setup muxes and control lines) 00502 // //Bit 7 of data is FIFO clock, bit 6 is shift_control, bit 5 is shift_in 00503 // //start bits (ctrl 0, data 0 => ctrl 1, data 0) 00504 // 00505 // BitManipulator::insertBits(uInt64Data, 0x40, 16, 8);//(0<<7) | (1<<6) | (0<<5) 00506 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00507 // BitManipulator::insertBits(uInt64Data, 0xc0, 16, 8);//(1<<7) | (1<<6) | (0<<5) -> clock the data in the fifo 00508 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00509 // 00510 // stringData = PSI46DigROCDefinitions::makeMaskWriteCommand(chipId, 00511 // registerName, mask); 00512 // 00513 // uint8_t data; 00514 // for (unsigned int s = 0; s < stringData.length(); s++) 00515 // for (int b = 8 - 1; b >= 0 && (s * 8 + 8 - b < 13 + 128); b--) 00516 // { 00517 // //std::cout << __COUT_HDR_FL__ << "S: " << s << " val: " << std::stringData.data()[s] << " b: " << b << " bit: " << ((stringData.data()[s]>>b)&1) << std::endl; 00518 // data = 0x40 | (((stringData.data()[s] >> b) & 1) << 5); 00519 // BitManipulator::insertBits(uInt64Data, (uint64_t) data, 16, 8); 00520 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00521 // data |= 0x80; 00522 // BitManipulator::insertBits(uInt64Data, (uint64_t) data, 16, 8); 00523 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00524 // } 00525 // 00526 // //reset Shift Control 00527 // BitManipulator::insertBits(uInt64Data, 0x0, 16, 8); 00528 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00529 // BitManipulator::insertBits(uInt64Data, 0x80, 16, 8); 00530 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00531 // 00532 // //configure muxes for readout 00533 // BitManipulator::insertBits(uInt64Data, 0x0, 56, 8); 00534 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00535 // 00536 // //commence readout 00537 // BitManipulator::insertBits(uInt64Data, 0x80, 56, 8); 00538 // sequence.pushBack(ChannelFIFOAddress[channel], uInt64Data); 00539 // 00540 //} 00541 // 00543 //void PSI46DigFirmware::makeMaskSequence(FirmwareSequence<uint32_t>& sequence, 00544 // unsigned int channel, const ROCStream& rocStream, 00545 // const std::string& registerName) 00546 //{} 00547 // 00549 //std::string PSI46DigFirmware::readCSRRegister() 00550 //{ 00551 // std::string buffer; 00552 // read(buffer,STRIP_CSR); 00553 // return buffer; 00554 //} 00555 // 00557 //void PSI46DigFirmware::setFrequencyFromClockState(std::string& buffer, double frequency) 00558 //{ 00559 // std::cout << __COUT_HDR_FL__ << "Setting up clock frequency!!!" << std::endl; 00560 // 00561 // int quotient; 00562 // int numerator; 00563 // int denominator; 00564 // double realClockFrequency; 00565 // 00566 // if (BitManipulator::readBits(stripCSRRegisterValue_, 17, 1) == 1) //if fastBCO is enabled 00567 // quotient = 4; 00568 // else //normal cases 00569 // quotient = 8; 00570 // 00571 // if (isClockStateExternal()) //base freq: 54MHz 00572 // { 00573 // realClockFrequency = EXTERNAL_CLOCK_FREQUENCY / quotient; //this is the REAL frequency being used 00574 // } 00575 // else //base freq: 66.667MHz 00576 // { 00577 // realClockFrequency = INTERNAL_CLOCK_FREQUENCY / quotient; //this is the REAL frequency being used 00578 // } 00579 // 00580 // double factor = frequency / realClockFrequency; 00581 // 00582 // //The device needs the denominator and the denominator to be load into a 5 bit register 00583 // //It will take two initial numerator and denominator bigger than necessary (to do not loose precision) 00584 // //and divide them for their gcd. If they still do not fit in 5 bit, they are trunked (divided by 2) 00585 // //untill they are less than 32 00586 // numerator = factor * 100; //we will work with 2 digits precision after the decimal point 00587 // denominator = 100; 00588 // 00589 // do 00590 // { 00591 // //We will need the GCD at some point in order to simplify fractions //taken from other sources 00592 // int gcd = numerator; 00593 // int rest = denominator; 00594 // int tmp; 00595 // 00596 // while (rest != 0) 00597 // { 00598 // tmp = rest; 00599 // rest = gcd % tmp; 00600 // gcd = tmp; 00601 // } 00602 // //Done finding the GCD 00603 // 00604 // if (gcd == 1) //if there's no GCD, just divide by 2 to find the nearest approssimation with less bits 00605 // { 00606 // numerator /= 2; 00607 // denominator /= 2; 00608 // } 00609 // else 00610 // { 00611 // numerator /= gcd; 00612 // denominator /= gcd; 00613 // } 00614 // 00615 // } 00616 // while (denominator >= 32 || numerator >= 32); 00617 // std::cout << __COUT_HDR_FL__ << "Numerator: " << numerator << std::endl; 00618 // std::cout << __COUT_HDR_FL__ << "Denominator: " << denominator << std::endl; 00619 // setFrequencyRatio(buffer, numerator, denominator); 00620 // std::cout << __COUT_HDR_FL__ << "Done with clock frequency setup!!!" << std::endl; 00621 //} 00623 //bool PSI46DigFirmware::isClockStateExternal() //returns true if the clock state is External 00624 //{ 00625 // if (BitManipulator::readBits(stripCSRRegisterValue_, 16, 1) == 1) 00626 // return true; 00627 // else 00628 // return false; 00629 //} 00630 // 00632 //void PSI46DigFirmware::setCSRRegister(uint32_t total) 00633 //{ 00634 // stripCSRRegisterValue_ = total; 00635 //} 00636 // 00638 //void PSI46DigFirmware::setPacketSizeStripCSR(uint32_t size) 00639 //{ 00640 // if (size > 31) 00641 // std::cout << __COUT_HDR_FL__ 00642 // << "ERROR: Maximum packet size is 31 while here you are trying to set " 00643 // << size << " packets!" << std::endl; 00644 // BitManipulator::insertBits(stripCSRRegisterValue_, size, 3, 5); 00645 // //write(buffer,STRIP_CSR, stripSCRRegisterValue_); 00646 //} 00647 // 00649 //void PSI46DigFirmware::enableChannelsStripCSR(bool channel0, bool channel1, 00650 // bool channel2, bool channel3, bool channel4, bool channel5) 00651 //{ 00652 // BitManipulator::insertBits(stripCSRRegisterValue_, ((uint32_t) channel0) 00653 // + ((uint32_t) channel1 << 1) + ((uint32_t) channel2 << 2) 00654 // + ((uint32_t) channel3 << 3) + ((uint32_t) channel4 << 4) 00655 // + ((uint32_t) channel5 << 5), 8, 6); 00656 //} 00657 // 00659 //void PSI46DigFirmware::setExternalBCOClockSourceStripCSR(std::string clockSource) 00660 //{ 00661 // if (clockSource == "External") 00662 // BitManipulator::insertBits(stripCSRRegisterValue_, 1, 16, 1); 00663 // else if (clockSource == "Internal") 00664 // BitManipulator::insertBits(stripCSRRegisterValue_, 0, 16, 1); 00665 //} 00666 // 00668 //void PSI46DigFirmware::setHaltStripCSR(bool set) 00669 //{ 00670 // BitManipulator::insertBits(stripCSRRegisterValue_, (uint32_t) set, 17, 1); 00671 //} 00672 // 00674 //void PSI46DigFirmware::enableBCOStripCSR(bool enable) 00675 //{ 00676 // BitManipulator::insertBits(stripCSRRegisterValue_, (uint32_t) enable, 19, 1); 00677 //} 00678 // 00680 //void PSI46DigFirmware::flushBuffersStripCSR(void) 00681 //{ 00682 // BitManipulator::insertBits(stripCSRRegisterValue_, 1, 20, 1); 00683 //} 00684 // 00686 //void PSI46DigFirmware::resetTriggerCounterStripCSR(std::string& buffer) 00687 //{ 00688 // BitManipulator::insertBits(stripCSRRegisterValue_, 1, 21, 1); 00689 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00690 // 00691 // BitManipulator::insertBits(stripCSRRegisterValue_, 0, 21, 1); 00692 // protocolInstance_->write(buffer, STRIP_CSR, stripCSRRegisterValue_); 00693 //} 00694 // 00696 //void PSI46DigFirmware::resetBCOCounterStripCSR(void) 00697 //{ 00698 // BitManipulator::insertBits(stripCSRRegisterValue_, 1, 22, 1); 00699 //} 00700 // 00702 //void PSI46DigFirmware::enableTriggerStripCSR(bool enable) 00703 //{ 00704 // BitManipulator::insertBits(stripCSRRegisterValue_, (uint32_t) enable, 23, 1); 00705 //} 00706 // 00708 //void PSI46DigFirmware::sendTriggerDataStripCSR(bool send) 00709 //{ 00710 // BitManipulator::insertBits(stripCSRRegisterValue_, (uint32_t) send, 24, 1); 00711 //} 00712 // 00714 //void PSI46DigFirmware::sendTriggerNumberStripCSR(bool send) 00715 //{ 00716 // BitManipulator::insertBits(stripCSRRegisterValue_, (uint32_t) send, 25, 1); 00717 //} 00718 // 00720 //void PSI46DigFirmware::sendBCOStripCSR(bool send) 00721 //{ 00722 // BitManipulator::insertBits(stripCSRRegisterValue_, (uint32_t) send, 26, 1); 00723 //} 00724 // 00726 //void PSI46DigFirmware::enableStreamStripCSR(bool enable) 00727 //{ 00728 // BitManipulator::insertBits(stripCSRRegisterValue_, (uint32_t) enable, 27, 1); 00729 //} 00730 // 00732 //void PSI46DigFirmware::resetDCMStripCSR(bool clear) 00733 //{ 00734 // BitManipulator::insertBits(stripCSRRegisterValue_, (uint32_t) clear, 31, 1); 00735 //} 00736 // 00738 //uint32_t PSI46DigFirmware::waitDCMResetStripCSR(void) 00739 //{ 00740 // uint32_t bitToCheck = 0; 00741 // BitManipulator::insertBits(bitToCheck, 1, 31, 2); 00742 // return bitToCheck; 00743 //} 00744 // 00746 //void PSI46DigFirmware::resetDAC(void) 00747 //{ 00748 // BitManipulator::insertBits(stripResetRegisterValue_, 1, 27, 1); 00749 //} 00750 // 00752 //void PSI46DigFirmware::resetLink(bool channel0, bool channel1, bool channel2, 00753 // bool channel3, bool channel4, bool channel5) 00754 //{ 00755 // stripResetRegisterValue_ = 0; 00756 // BitManipulator::insertBits(stripResetRegisterValue_, 00757 // ((uint32_t) channel0) + ((uint32_t) channel1 << 1) 00758 // + ((uint32_t) channel2 << 2) + ((uint32_t) channel3 << 3) 00759 // + ((uint32_t) channel4 << 4) + ((uint32_t) channel5 << 5), 00760 // 0, 6); 00761 // BitManipulator::insertBits(stripResetRegisterValue_, 1, 29, 1); 00762 // /* 00763 // write(buffer, STRIP_RESET, (1<<28) + 00764 // ((uint32_t)channel0) + 00765 // ((uint32_t)channel1<<1) + 00766 // ((uint32_t)channel2<<2) + 00767 // ((uint32_t)channel3<<3) + 00768 // ((uint32_t)channel4<<4) + 00769 // ((uint32_t)channel5<<5) 00770 // ); 00771 // */ 00772 //} 00773 // 00775 //void PSI46DigFirmware::clearErrors(bool channel0, bool channel1, bool channel2, 00776 // bool channel3, bool channel4, bool channel5) 00777 //{ 00778 // stripResetRegisterValue_ = 0; 00779 // BitManipulator::insertBits(stripResetRegisterValue_, 00780 // ((uint32_t) channel0) + ((uint32_t) channel1 << 1) 00781 // + ((uint32_t) channel2 << 2) + ((uint32_t) channel3 << 3) 00782 // + ((uint32_t) channel4 << 4) + ((uint32_t) channel5 << 5), 00783 // 0, 6); 00784 // BitManipulator::insertBits(stripResetRegisterValue_, 1, 29, 1); 00785 //} 00786 // 00788 //void PSI46DigFirmware::clearFIFO(bool channel0, bool channel1, bool channel2, 00789 // bool channel3, bool channel4, bool channel5) 00790 //{ 00791 // stripResetRegisterValue_ = 0; 00792 // BitManipulator::insertBits(stripResetRegisterValue_, 00793 // ((uint32_t) channel0) + ((uint32_t) channel1 << 1) 00794 // + ((uint32_t) channel2 << 2) + ((uint32_t) channel3 << 3) 00795 // + ((uint32_t) channel4 << 4) + ((uint32_t) channel5 << 5), 00796 // 0, 6); 00797 // BitManipulator::insertBits(stripResetRegisterValue_, 1, 30, 1); 00798 //} 00799 // 00801 //void PSI46DigFirmware::resetChip(bool channel0, bool channel1, bool channel2, 00802 // bool channel3, bool channel4, bool channel5) 00803 //{ 00804 // stripResetRegisterValue_ = 0; 00805 // BitManipulator::insertBits(stripResetRegisterValue_, 00806 // ((uint32_t) channel0) + ((uint32_t) channel1 << 1) 00807 // + ((uint32_t) channel2 << 2) + ((uint32_t) channel3 << 3) 00808 // + ((uint32_t) channel4 << 4) + ((uint32_t) channel5 << 5), 00809 // 0, 6); 00810 // BitManipulator::insertBits(stripResetRegisterValue_, 1, 31, 1); 00811 //} 00812 // 00814 //void PSI46DigFirmware::setFrequencyRatio(std::string& buffer, int numerator, int denominator) 00815 //{ 00816 // //The device need to load numerator minus one and denominator minus one, with an internal address of 0x50 and 052 respectively 00817 // protocolInstance_->write(buffer, STRIP_BCO_DCM, 0x80500000 + (numerator - 1)); // Set BCOCLK numerator // was 0x80500003 00818 // protocolInstance_->waitClear(buffer, STRIP_BCO_DCM, 0xf0000000); // Wait DCM write to finish // was 0x80000000 00819 // 00820 // protocolInstance_->write(buffer, STRIP_BCO_DCM, 0x80520000 + (denominator - 1)); // Set BCOCLK denominator // was 0x80520001 00821 // protocolInstance_->waitClear(buffer, STRIP_BCO_DCM, 0xf0000000); // Wait DCM write to finish - BCO frequency should be 13.513 MHz // was 0x80000000 00822 //} 00823 // 00825 //void PSI46DigFirmware::BCOOffset(uint32_t offset) 00826 //{ 00827 // BitManipulator::insertBits(stripTriggerCSRRegisterValue_, offset, 0, 4); 00828 //} 00829 // 00831 //void PSI46DigFirmware::selectSpyFIFO(uint32_t input) 00832 //{ 00833 // BitManipulator::insertBits(stripTriggerCSRRegisterValue_, input, 4, 3); 00834 //} 00835 // 00837 //void PSI46DigFirmware::halt(bool halt) 00838 //{ 00839 // BitManipulator::insertBits(stripTriggerCSRRegisterValue_, (uint32_t) halt, 7, 1); 00840 //} 00841 // 00843 //void PSI46DigFirmware::configureStripTriggerUnbiased(std::string& buffer) 00844 //{ 00845 // protocolInstance_->write(buffer, STRIP_TRIG_UNBIASED, 0x002805c); // Configure unbiased trigger 00846 //} 00847 // 00849 //void PSI46DigFirmware::configureTriggerInputs(std::string& buffer) 00850 //{ 00851 // protocolInstance_->write(buffer, STRIP_TRIG_INPUT_0, 0x3f440000); // PSI46Dig GOTHIT trigger input channel 0,1 00852 // protocolInstance_->write(buffer, STRIP_TRIG_INPUT_1, 0x3f440000); // PSI46Dig GOTHIT trigger input channel 2,3 00853 // protocolInstance_->write(buffer, STRIP_TRIG_INPUT_2, 0x0); // PSI46Dig GOTHIT trigger input channel 4,5 00854 //} 00855 // 00857 // //======================================================================================================================== 00858 // void PSI46DigFirmware::chipID(uint32_t size) 00859 // { 00860 // BitManipulator::insertBits(stripSCRegisterValue_, size, 0, 5); 00861 // } 00862 // 00863 // //======================================================================================================================== 00864 // void PSI46DigFirmware::addressSlowControls(uint32_t size) 00865 // { 00866 // BitManipulator::insertBits(stripSCRegisterValue_, size, 5, 5); 00867 // } 00868 // 00869 // //======================================================================================================================== 00870 // void PSI46DigFirmware::instructionSlowControls(uint32_t size) 00871 // { 00872 // BitManipulator::insertBits(stripSCRegisterValue_, size, 10, 3); 00873 // } 00874 // 00875 // //======================================================================================================================== 00876 // void PSI46DigFirmware::channelreadSelect(uint32_t size) 00877 // { 00878 // BitManipulator::insertBits(stripSCRegisterValue_, size, 13, 3); 00879 // } 00880 // 00881 // //======================================================================================================================== 00882 // void PSI46DigFirmware::channelMask(uint32_t size) 00883 // { 00884 // BitManipulator::insertBits(stripSCRegisterValue_, size, 16, 8); 00885 // } 00886 // 00887 // //======================================================================================================================== 00888 // void PSI46DigFirmware::bitsLength(uint32_t length) 00889 // { 00890 // BitManipulator::insertBits(stripSCRegisterValue_, length, 26, 3); 00891 // } 00892 // 00893 // 00894 // //======================================================================================================================== 00895 // void PSI46DigFirmware::syncFallingBCO(bool sync) 00896 // { 00897 // BitManipulator::insertBits(stripSCRegisterValue_, (uint32_t)sync, 28, 1); 00898 // } 00899 // 00900 // //======================================================================================================================== 00901 // void PSI46DigFirmware::syncRisingBCO(bool sync) 00902 // { 00903 // BitManipulator::insertBits(stripSCRegisterValue_, (uint32_t)sync, 29, 1); 00904 // } 00905 // 00906 // //======================================================================================================================== 00907 // void PSI46DigFirmware::setRaw(bool set) 00908 // { 00909 // BitManipulator::insertBits(stripSCRegisterValue_, (uint32_t)set, 30, 1); 00910 // } 00911 // 00912 // //======================================================================================================================== 00913 // void PSI46DigFirmware::initSlowControls(bool init) 00914 // { 00915 // BitManipulator::insertBits(stripSCRegisterValue_, (uint32_t)init, 31, 1); 00916 // } 00917 // 00918 // //======================================================================================================================== 00919 // void PSI46DigFirmware::resetCount(bool reset) 00920 // { 00921 // BitManipulator::insertBits(stripAnalysisCSRRegisterValue_, (uint32_t)reset, 30, 1); 00922 // } 00923 // 00924 // //======================================================================================================================== 00925 // void PSI46DigFirmware::setBCO_0(uint32_t void PSI46DigFirmware::BCOOffset(uint32_t offset) 00926 // { 00927 // BitManipulator::insertBits(stripTrigCSRRegisterValue_, offset, 0, 4); 00928 // }input) 00929 // { 00930 // BitManipulator::insertBits(trigInputRegisterValue_, input, 0, 8); 00931 // } 00932 // 00933 // //======================================================================================================================== 00934 // void PSI46DigFirmware::setBCO_1(uint32_t input) 00935 // { 00936 // BitManipulator::insertBits(trigInputRegisterValue_, input, 8, 8); 00937 // } 00938 // 00939 // //======================================================================================================================== 00940 // void PSI46DigFirmware::trimFracBCO_0(uint32_t input) 00941 // { 00942 // BitManipulator::insertBits(trigInputRegisterValue_, input, 16, 4); 00943 // } 00944 // 00945 // //======================================================================================================================== 00946 // void PSI46DigFirmware::trimFracBCO_1(uint32_t input) 00947 // { 00948 // BitManipulator::insertBits(trigInputRegisterValue_, input, 20, 4); 00949 // } 00950 // 00951 // //======================================================================================================================== 00952 // void PSI46DigFirmware::enable_0(bool enable) 00953 // { 00954 // BitManipulator::insertBits(trigInputRegisterValue_, (uint32_t)enable, 28, 1); 00955 // } 00956 // 00957 // //======================================================================================================================== 00958 // void PSI46DigFirmware::enable_1(bool enable) 00959 // { 00960 // BitManipulator::insertBits(trigInputRegisterValue_, (uint32_t)enable, 29, 1); 00961 // } 00962 // 00963 // */ 00964 // 00965 // 00966 // 00967 // 00973 //#include "otsdaq-core/Macros/CoutMacros.h" 02196 //