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);
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
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();
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
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 #endif
00490
00498 void Interface::loadPrevSettings() {
00499 if (!acquiring_)
00500 {
00501 tx_buffer_ << "r";
00502 transmit();
00503 int seconds = 1;
00504
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
00557 int seconds = ((ramp_ * abs(voltage - voltage_) / 100) / 1.1) - 1;
00558
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;
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 }