ursa_driver.cpp
Go to the documentation of this file.
00001 
00027 #include <ursa_driver/ursa_driver.h>
00028 
00029 namespace ursa
00030 {
00031   const size_t max_line_length(64);
00032 
00034   Interface::Interface(const char *port, int baud) :
00035       port_(port), baud_(baud), connected_(false), serial_(NULL), acquiring_(
00036           false), responsive_(false), gmMode_(false), battV_(0), ramp_(6), voltage_(
00037           0) {
00038     pulses_.fill(0);
00039   }
00040 
00044   Interface::~Interface() {
00045     tx_buffer_ << "R" << "v";
00046     transmit();
00047   }
00060   void Interface::connect() {
00061     if (!serial_)
00062       serial_ = new serial::Serial();
00063     serial::Timeout timeout(serial::Timeout::simpleTimeout(1000));
00064     serial_->setTimeout(timeout);
00065     serial_->setPort(port_);
00066     serial_->setBaudrate(baud_);
00067 
00068     for (int i = 0; i < 5; i++)
00069     {
00070       if (!connected_)
00071       {
00072         try
00073         {
00074           serial_->open();
00075           stopAcquire();
00076         }
00077         catch (serial::IOException & err)
00078         {
00079         }
00080 
00081         if (serial_->isOpen())
00082         {
00083 
00084           connected_ = true;
00085           break;
00086         }
00087         else
00088         {
00089           connected_ = false;
00090           std::cout << "WARN: Unable to connect to serial port:" << port_
00091               << std::endl;
00092         }
00093       }
00094     }
00095     for (int j = 0; j < 5; j++)
00096     {
00097       if (checkComms())
00098       {
00099         responsive_ = true;
00100         return;
00101       }
00102       else
00103       {
00104         responsive_ = false;
00105         std::cout << "WARN: URSA not responding." << std::endl;
00106       }
00107     }
00108     std::cout << "ERROR: Unable to communicate with URSA" << std::endl;
00109   }
00110 
00116   void Interface::transmit() {
00117 #ifdef DEBUG_
00118     std::cout << "DEBUG: Transmitting:" << tx_buffer_.str() << std::endl;
00119 #endif
00120     ssize_t bytes_written = serial_->write(tx_buffer_.str());
00121     if (bytes_written < tx_buffer_.tellp())
00122     {
00123       std::cout << "ERROR: Serial write timeout, " << bytes_written
00124           << " bytes written of " << tx_buffer_.tellp() << "." << std::endl;
00125     }
00126     tx_buffer_.str("");
00127     usleep(100000);  //for stability
00128   }
00129 
00138   void Interface::read() {
00139     while (serial_->available())
00140     {
00141       uint8_t temp[max_line_length];
00142       long length = serial_->read(temp, max_line_length);
00143       rx_buffer_.insert(rx_buffer_.end(), temp, temp + length);
00144       //std::cout<< "RX: " << reinterpret_cast<const char*>(temp) << std::endl;
00145     }
00146 #ifdef DEBUG_
00147     std::cout << "DEBUG: Receive buffer size: " << rx_buffer_.size()
00148     << std::endl;
00149 #endif
00150     processData();
00151   }
00152 
00165   void Interface::processData() {
00166     while (rx_buffer_.size() >= 3)
00167     {
00168       if (rx_buffer_.front() == 0xff)
00169       {
00170         rx_buffer_.pop_front();      //drop the first byte it is only for sync
00171         uint8_t char1, char2, count;
00172         uint16_t energy;
00173 
00174         char1 = rx_buffer_.front();
00175         rx_buffer_.pop_front();
00176         char2 = rx_buffer_.front();
00177         rx_buffer_.pop_front();
00178 
00179         count = char1 >> 2;
00180         energy = (char1 & 0x03) << 8 | char2;
00181 
00182         if (count == 0)
00183           processBatt(energy);
00184         else
00185         {
00186           boost::lock_guard<boost::mutex> lock(array_mutex_);
00187 #ifdef DEBUG_
00188           std::cout << "DEBUG: Incrementing Bin: "
00189           << boost::lexical_cast<std::string>(energy) << " By amount: "
00190           << boost::lexical_cast<std::string>(count >> 2) << std::endl;
00191 #endif
00192           pulses_[energy] += (count >> 2);
00193         }
00194       }
00195       else
00196       {
00197         std::cout << "ERROR: Read error, dropping chars:"
00198             << (int) rx_buffer_.front();
00199         rx_buffer_.pop_front();
00200         while (rx_buffer_.front() != 0xff && rx_buffer_.size() > 0)
00201         {
00202           std::cout << ", " << (int) rx_buffer_.front();
00203           rx_buffer_.pop_front();
00204         }
00205         std::cout << std::endl;
00206       }
00207     }
00208   }
00209 
00214   void Interface::getSpectra(boost::array<unsigned int, 4096>* array) {
00215     boost::lock_guard<boost::mutex> lock(array_mutex_);
00216     *array = pulses_;
00217   }
00218 
00222   void Interface::clearSpectra() {
00223     boost::lock_guard<boost::mutex> lock(array_mutex_);
00224     pulses_.fill(0);
00225   }
00226 
00231   void Interface::processBatt(uint16_t input) {
00232     battV_ = (float) input * 12 / 1024;
00233 
00234 #ifdef DEBUG_
00235     std::cout << "DEBUG: Battery voltage processed: "
00236     << boost::lexical_cast<std::string>(battV_) << std::endl;
00237 #endif
00238   }
00239 
00245   bool Interface::checkComms() {
00246     stopAcquire();
00247     serial_->flush();
00248     tx_buffer_ << "U";
00249     transmit();
00250     std::string msg = serial_->read(max_line_length);
00251     boost::trim(msg);
00252     if (msg == "URSA2")
00253       return (true);
00254     else
00255       return (false);
00256   }
00257 
00258   void Interface::stopAcquire() {
00259     do
00260     {
00261       std::string ignored = serial_->read(128);
00262       tx_buffer_ << "R";
00263       transmit();
00264       usleep(500);
00265     }
00266     while (serial_->available());
00267     acquiring_ = false;
00268   }
00269 
00270   void Interface::startAcquire() {
00271     if (!acquiring_)
00272     {
00273       tx_buffer_ << "G";
00274       transmit();
00275       acquiring_ = true;
00276     }
00277     else
00278       std::cout << "WARNING: Already acquiring" << std::endl;
00279   }
00280 
00281   void Interface::startGM() {
00282     if (!acquiring_)
00283     {
00284       tx_buffer_ << "J";
00285       transmit();
00286       gmMode_ = true;
00287       startAcquire();
00288     }
00289     else
00290       std::cout << "WARNING: Already acquiring" << std::endl;
00291   }
00292 
00293   void Interface::stopGM() {
00294     if (acquiring_)
00295       stopAcquire();
00296     tx_buffer_ << "j";
00297     transmit();
00298     gmMode_ = false;
00299   }
00300 
00308   uint32_t Interface::requestCounts() {
00309     if (gmMode_ && acquiring_)
00310     {
00311       uint8_t temp_buffer[10];
00312       uint8_t count = 0;
00313       tx_buffer_ << "c";
00314       transmit();
00315       serial_->waitReadable();
00316       if (serial_->available() <= 4)
00317       {
00318         count = serial_->read(temp_buffer, 4);
00319         if (count == 4)
00320         {
00321           return (((uint32_t) temp_buffer[0] << 24)
00322               | ((uint32_t) temp_buffer[1] << 16)
00323               | ((uint32_t) temp_buffer[2] << 8) | ((uint32_t) temp_buffer[3]));
00324         }
00325       }
00326       std::cout << "ERROR: Did not receive correct number of bytes"
00327           << std::endl;
00328       return (0);
00329     }
00330     else
00331     {
00332       std::cout << "ERROR: Either not acquiring or not in GM mode."
00333           << std::endl;
00334       return (0);
00335     }
00336   }
00337 
00338   void Interface::stopVoltage() {
00339     tx_buffer_ << "v";
00340     transmit();
00341   }
00348   void Interface::requestBatt() {
00349     tx_buffer_ << "B";
00350     transmit();
00351     if (!acquiring_ || gmMode_)
00352     {
00353       uint8_t gm = (gmMode_ ? 1 : 0);
00354       serial_->waitReadable();
00355       if (serial_->available() <= (2 + gm))
00356       {
00357         uint8_t temp_buffer[3];
00358         uint8_t count = serial_->read(temp_buffer, 2 + gm);
00359         if (count == (2 + gm))
00360         {
00361           processBatt(
00362               ((uint16_t) temp_buffer[0 + gm] << 8)
00363                   | ((uint16_t) temp_buffer[1 + gm]));
00364           return;
00365         }
00366       }
00367       else
00368       {
00369         std::cout << "ERROR: Failed to process Batt. voltage." << std::endl;
00370       }
00371     }
00372   }
00373 
00374   float Interface::getBatt() {
00375     return (battV_);
00376   }
00377 
00378   void Interface::startASCII() {
00379     if (!acquiring_)
00380     {
00381       tx_buffer_ << "A";
00382       transmit();
00383     }
00384     else
00385       std::cout << "ERROR: Acquiring. Stop acquiring to switch ASCII mode."
00386           << std::endl;
00387   }
00388 
00389   void Interface::stopASCII() {
00390     if (!acquiring_)
00391     {
00392       tx_buffer_ << "N";
00393       transmit();
00394     }
00395     else
00396       std::cout << "ERROR: Acquiring. Stop acquiring to switch ASCII mode."
00397           << std::endl;
00398   }
00399 
00400   int Interface::requestSerialNumber() {
00401     if (!acquiring_)
00402     {
00403       tx_buffer_ << "@";
00404       transmit();
00405       usleep(50000);
00406       std::string msg = serial_->read(max_line_length);
00407       boost::trim(msg);
00408       std::cout << "INFO: The serial number is: " << msg << std::endl;
00409       return (boost::lexical_cast<int>(msg.c_str()));
00410     }
00411     else
00412     {
00413       std::cout << "ERROR: Acquiring. Stop acquiring to switch ASCII mode."
00414           << std::endl;
00415       return (-1);
00416     }
00417   }
00418 
00424   void Interface::requestMaxHV() {
00425     if (!acquiring_)
00426     {
00427       tx_buffer_ << "2";
00428       transmit();
00429       usleep(50000);
00430       std::string msg = serial_->read(max_line_length);
00431       boost::trim(msg);
00432       std::cout << "INFO: The max HV is: " << msg << std::endl;
00433     }
00434     else
00435       std::cout << "ERROR: Acquiring. Stop acquiring to request Max HV."
00436           << std::endl;
00437   }
00438 
00439 #ifdef ADMIN_
00440 
00443   void Interface::setSerialNumber(int serial)
00444   {
00445     if (!acquiring_ && serial >= 200000 && serial <= 299999)
00446     {
00447       tx_buffer_ << "#";
00448       transmit();
00449       tx_buffer_ << boost::lexical_cast<std::string>(serial);
00450       transmit();
00451       sleep(3);
00452     }
00453     else
00454     std::cout
00455     << "ERROR: Serial must be between 200000 and 299999 and the system must not be acquiring."
00456     << std::endl;
00457   }
00458 
00462   void Interface::setSmudgeFactor(int smudge)
00463   {
00464     if (!acquiring_ && smudge >= 0 && smudge <= 4)
00465     {
00466       tx_buffer_ << "X" << boost::lexical_cast<std::string>(smudge);
00467       transmit();
00468     }
00469     else
00470     std::cout
00471     << "ERROR: Smudge factor must be between 0 and 4 and the system must not be acquiring."
00472     << std::endl;
00473   }
00474 
00475   //This function must NOT be used
00476 //  void Interface::setMaxHV(int HV) {
00477 //    if (!acquiring_ && HV >= 0 && HV <= 10000)
00478 //    {
00479 //      tx_buffer_ << "???";  //character not actually known.
00480 //      transmit();
00481 //      tx_buffer_ << char(HV >> 8) << char(HV & 0xFF);
00482 //      transmit();
00483 //      sleep(3);
00484 //    }
00485 //    else
00486 //      std::cout << "ERROR: Acquiring. Stop acquiring to change max HV."
00487 //          << std::endl;
00488 //  }
00489 #endif
00490 
00498   void Interface::loadPrevSettings() {
00499     if (!acquiring_)
00500     {
00501       tx_buffer_ << "r";
00502       transmit();
00503       int seconds = 1;
00504       //This sets HV so we need to wait for ramp
00505       std::string msg = serial_->read(max_line_length);
00506       while (!serial_->waitReadable())
00507       {
00508         tx_buffer_ << "B";
00509         transmit();
00510         std::cout << "INFO: Ramping HV.  Approx. seconds elapsed: " << seconds
00511             << std::endl;
00512         seconds++;
00513       }
00514       msg = serial_->read(max_line_length);
00515     }
00516     else
00517       std::cout << "ERROR: Acquiring. Stop acquiring to load settings."
00518           << std::endl;
00519   }
00520 
00521   void Interface::setNoSave() {
00522     if (!acquiring_)
00523     {
00524       tx_buffer_ << "d";
00525       transmit();
00526     }
00527     else
00528       std::cout << "ERROR: Acquiring. Stop acquiring to disable EEPROM saving."
00529           << std::endl;
00530   }
00531 
00545   void Interface::setVoltage(int voltage) {
00546     if (!acquiring_ && voltage >= 0 && voltage <= 2000)
00547     {
00548 
00549       if (voltage == 0)
00550         setNoSave();
00551       uint16_t outVolts = 0;
00552       outVolts = round(double(voltage) / 2000 * 65532);
00553       tx_buffer_ << "V" << (uint8_t) (outVolts >> 8)
00554           << (uint8_t) (outVolts & 0xff);
00555       transmit();
00556       //calculate seconds for ramp then adjust for the loop taking 1.1 seconds
00557       int seconds = ((ramp_ * abs(voltage - voltage_) / 100) / 1.1) - 1;
00558       // blocking call to serial to wait for responsiveness
00559       std::string msg = serial_->read(max_line_length);
00560       while (!serial_->waitReadable())
00561       {
00562         std::cout << "INFO: Ramping HV to: " << voltage
00563             << " Approx. Seconds Remaining: " << seconds << std::endl;
00564         seconds--;
00565         tx_buffer_ << "B";
00566         transmit();
00567       }
00568       msg = serial_->read(max_line_length);
00569       voltage_ = voltage;
00570     }
00571     else
00572       std::cout
00573           << "ERROR: Voltage must be between 0 and 2000 volts and the system must not be acquiring"
00574           << std::endl;
00575   }
00576 
00585   void Interface::setGain(double gain) {
00586     if (!acquiring_)
00587     {
00588       char coarse;
00589       uint8_t fine;
00590       std::string coarse_str;
00591       if (gain < 2)
00592       {
00593         coarse = '0';
00594         fine = round((gain / 2) * 256 - 1);
00595         coarse_str = "2";
00596       }
00597       else if (gain < 4)
00598       {
00599         coarse = '1';
00600         fine = round((gain / 4) * 256 - 1);
00601         coarse_str = "4";
00602       }
00603       else if (gain < 15)
00604       {
00605         coarse = '2';
00606         fine = round((gain / 15) * 256 - 1);
00607         coarse_str = "15";
00608       }
00609       else if (gain < 35)
00610       {
00611         coarse = '3';
00612         fine = round((gain / 35) * 256 - 1);
00613         coarse_str = "35";
00614       }
00615       else if (gain < 125)
00616       {
00617         coarse = '4';
00618         fine = round((gain / 125) * 256 - 1);
00619         coarse_str = "125";
00620       }
00621       else if (gain < 250)
00622       {
00623         coarse = '5';
00624         fine = round((gain / 250) * 256 - 1);
00625         coarse_str = "250";
00626       }
00627       else
00628       {
00629         std::cout << "ERROR: Gain must be bellow 250x" << std::endl;
00630         return;
00631       }
00632 
00633       std::cout << "INFO: Setting coarse gain to: " << coarse_str << std::endl;
00634 
00635       double confirmGain = ((double(fine) + 1) / 256);
00636       std::cout << "INFO: Setting fine gain to: "
00637           << boost::lexical_cast<std::string>(confirmGain) << std::endl;
00638       tx_buffer_ << "C" << coarse << "F" << fine;
00639       transmit();
00640     }
00641     else
00642       std::cout << "ERROR: Acquiring. Stop acquiring to change gain."
00643           << std::endl;
00644   }
00645 
00655   void Interface::setInput(inputs input) {
00656     if (!acquiring_)
00657     {
00658       setVoltage(0);
00659       tx_buffer_ << "I" << boost::lexical_cast<std::string>(input);
00660       transmit();
00661     }
00662     else
00663       std::cout
00664           << "ERROR: Acquiring. Stop acquiring to switch inputs or polarity."
00665           << std::endl;
00666   }
00667 
00677   void Interface::setShapingTime(shaping_time time) {
00678     if (!acquiring_)
00679     {
00680       tx_buffer_ << "S" << boost::lexical_cast<std::string>(time);
00681       transmit();
00682     }
00683     else
00684       std::cout << "ERROR: Acquiring. Stop acquiring to change shaping time."
00685           << std::endl;
00686   }
00687 
00697   void Interface::setThresholdOffset(int mVolts) {
00698     if (!acquiring_ && mVolts >= 25 && mVolts <= 1023)
00699     {
00700       uint16_t min_offset = 50;
00701       uint16_t thresh = mVolts * 2;
00702       uint16_t offset = 0;
00703       if (mVolts > min_offset * 2)
00704       {
00705         offset = mVolts;  //offset = mV/2 *2
00706       }
00707       else
00708         offset = min_offset * 2;
00709 
00710       tx_buffer_ << "T" << (unsigned char) ((thresh >> 4) & 0xFF)
00711           << (unsigned char) (((thresh & 0x0F) << 4) | ((offset >> 8) & 0x0F))
00712           << (unsigned char) (offset & 0xFF);
00713       transmit();
00714     }
00715     else
00716       std::cout
00717           << "ERROR: Threshold must be between 25 and 1024 mV and the system must not be acquiring"
00718           << std::endl;
00719   }
00720 
00727   void Interface::setBitMode(int bits) {
00728     if (!acquiring_ && bits >= 8 && bits <= 12)
00729     {
00730       tx_buffer_ << "M" << boost::lexical_cast<std::string>(13 - bits);
00731       transmit();
00732     }
00733     else
00734       std::cout
00735           << "ERROR: Bits must be between 12 and 8 bits and the system must not be acquiring"
00736           << std::endl;
00737   }
00738 
00747   void Interface::setRamp(int seconds) {
00748     if (!acquiring_ && seconds >= 6 && seconds <= 219)
00749     {
00750       ramp_ = seconds;
00751       uint16_t ramp = round((seconds * 303.45) - 1197);
00752       if (ramp > 16383)
00753         ramp = 16838;
00754       tx_buffer_ << "P" << (uint8_t) (ramp >> 8) << (uint8_t) (ramp & 0xFF);
00755       transmit();
00756     }
00757     else
00758       std::cout
00759           << "ERROR: Ramp must be between 6 and 219 seconds and the system must not be acquiring"
00760           << std::endl;
00761   }
00762 
00763   void Interface::noRamp() {
00764     if (!acquiring_)
00765     {
00766       tx_buffer_ << "p";
00767       transmit();
00768     }
00769     else
00770       std::cout << "ERROR: Acquiring. Stop acquiring to disable ramping of HV."
00771           << std::endl;
00772   }
00773 
00774   void Interface::setAlarm0(bool enable) {
00775     tx_buffer_ << (enable ? "Z" : "z");
00776     transmit();
00777   }
00778 
00779   void Interface::setAlarm1(bool enable) {
00780     tx_buffer_ << (enable ? "W" : "w");
00781     transmit();
00782   }
00783 }


ursa_driver
Author(s): Mike Hosmar
autogenerated on Sat Jun 8 2019 20:57:48