From 6f994e8c0a8b65ae1af5777e936a8b0161bbfd28 Mon Sep 17 00:00:00 2001 From: POES-Weather Ltd Date: Tue, 25 Oct 2011 23:28:32 +0300 Subject: [PATCH] beta Jrk USB API --- POES-Decoder.pro | 20 +- rig/deprecated/jrk.cpp | 702 +++++++++++++++++++++++++++++++++++++++++ rig/deprecated/jrk.h | 103 ++++++ rig/jrk.cpp | 655 ++++++++++---------------------------- rig/jrk.h | 64 ++-- rig/jrk_protocol.h | 129 ++++++++ rig/jrkconfdialog.cpp | 31 +- rig/jrkconfdialog.h | 2 + rig/jrkconfdialog.ui | 96 +++--- rig/jrkusb.cpp | 278 ++++++++++++++++ rig/jrkusb.h | 88 ++++++ rig/rigdialog.cpp | 23 +- rig/rigdialog.ui | 199 +++++------- rig/rotor.cpp | 23 +- rig/rotor.h | 6 +- rig/usb/tusb.cpp | 194 ++++++++++++ rig/usb/tusb.h | 59 ++++ rig/usb/usbdevice.cpp | 236 ++++++++++++++ rig/usb/usbdevice.h | 70 ++++ utils/azeldialog.cpp | 7 + utils/azeldialog.h | 1 + utils/azeldialog.ui | 6 +- utils/utils.h | 4 + 23 files changed, 2254 insertions(+), 742 deletions(-) create mode 100644 rig/deprecated/jrk.cpp create mode 100644 rig/deprecated/jrk.h create mode 100644 rig/jrk_protocol.h create mode 100644 rig/jrkusb.cpp create mode 100644 rig/jrkusb.h create mode 100644 rig/usb/tusb.cpp create mode 100644 rig/usb/tusb.h create mode 100644 rig/usb/usbdevice.cpp create mode 100644 rig/usb/usbdevice.h diff --git a/POES-Decoder.pro b/POES-Decoder.pro index 552192f..d9fa86f 100644 --- a/POES-Decoder.pro +++ b/POES-Decoder.pro @@ -53,7 +53,10 @@ SOURCES += main.cpp \ satellite/property/satprop.cpp \ satellite/property/satpropdialog.cpp \ satellite/property/rgbconf.cpp \ - satellite/property/ndvi.cpp + satellite/property/ndvi.cpp \ + rig/usb/usbdevice.cpp \ + rig/usb/tusb.cpp \ + rig/jrkusb.cpp HEADERS += mainwindow.h \ decoder/hrptblock.h \ version.h \ @@ -110,7 +113,11 @@ HEADERS += mainwindow.h \ satellite/property/satprop.h \ satellite/property/satpropdialog.h \ satellite/property/rgbconf.h \ - satellite/property/ndvi.h + satellite/property/ndvi.h \ + rig/usb/usbdevice.h \ + rig/usb/tusb.h \ + rig/jrkusb.h \ + rig/jrk_protocol.h DEFINES += _CRT_SECURE_NO_WARNINGS FORMS += mainwindow.ui \ satellite/station/stationdialog.ui \ @@ -141,6 +148,7 @@ INCLUDEPATH += decoder \ satellite/property \ utils \ rig \ + rig/usb \ rig/qextserialport \ decoder/ljpeg \ tools \ @@ -167,6 +175,10 @@ unix { rig/OakHidBase.h INCLUDEPATH += /usr/local/include + # libusb + INCLUDEPATH += /usr/include + LIBS += -lusb + # DSP and FEC Library, http://www.ka9q.net/code/fec/ #DEFINES += HAVE_LIBFEC #LIBS += -L/usr/local/lib -lfec @@ -199,3 +211,7 @@ win32 { OTHER_FILES += + + + + diff --git a/rig/deprecated/jrk.cpp b/rig/deprecated/jrk.cpp new file mode 100644 index 0000000..c0ff5ce --- /dev/null +++ b/rig/deprecated/jrk.cpp @@ -0,0 +1,702 @@ +/* + HRPT-Decoder, a software for processing POES high resolution weather satellite imagery. + Copyright (C) 2010,2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ + +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +#include "rotor.h" +#include "qextserialport.h" +#include "utils.h" +#include "jrk.h" + +//--------------------------------------------------------------------------- +TJRK::TJRK(TRotor *_rotor) +{ + rotor = _rotor; + +#if defined(Q_OS_UNIX) || defined(Q_OS_MAC) + az_deviceId = "/dev/ttyACM0"; + el_deviceId = "/dev/ttyACM2"; +#else + az_deviceId = "COM6"; + el_deviceId = "COM8"; +#endif + + az_port = rotor->serialPort; + el_port = rotor->serialPort_2; + port = NULL; + + iobuff = (unsigned char *) rotor->iobuff; + + az_id = 11; + el_id = 11; + + current_az = 0; + current_el = 0; + flags = 0; + + el_min_fk = 0; + el_max_fk = 4095; + + az_min_fk = 0; + az_max_fk = 4095; +} + +//--------------------------------------------------------------------------- +TJRK::~TJRK(void) +{ + closeCOM(); +} + +//--------------------------------------------------------------------------- +void TJRK::writeSettings(QSettings *reg) +{ + reg->beginGroup("Jrk"); + + reg->setValue("AzDeviceId", az_deviceId); + reg->setValue("AzId", az_id); + reg->setValue("ElDeviceId", el_deviceId); + reg->setValue("ElId", el_id); + + reg->beginGroup("Feedback"); + reg->setValue("ElMinFk", el_min_fk); + reg->setValue("ElMaxFk", el_max_fk); + + reg->setValue("AzMinFk", az_min_fk); + reg->setValue("AzMaxFk", az_max_fk); + reg->endGroup(); + + reg->endGroup(); +} + +//--------------------------------------------------------------------------- +void TJRK::readSettings(QSettings *reg) +{ + reg->beginGroup("Jrk"); + +#if defined Q_OS_WIN + az_deviceId = reg->value("AzDeviceId", QString("COM6")).toString(); + el_deviceId = reg->value("ElDeviceId", QString("COM8")).toString(); +#else + az_deviceId = reg->value("AzDeviceId", QString("/dev/ttyACM0")).toString(); + el_deviceId = reg->value("ElDeviceId", QString("/dev/ttyACM2")).toString(); +#endif + + az_id = reg->value("AzId", 11).toInt(); + el_id = reg->value("ElId", 11).toInt(); + + reg->beginGroup("Feedback"); + el_min_fk = reg->value("ElMinFk", 0).toInt(); + el_max_fk = reg->value("ElMaxFk", 4095).toInt(); + + az_min_fk = reg->value("AzMinFk", 0).toInt(); + az_max_fk = reg->value("AzMaxFk", 4095).toInt(); + reg->endGroup(); + + reg->endGroup(); // Jrk +} + +//--------------------------------------------------------------------------- +bool TJRK::isCOMOpen(void) +{ + bool rc = true; + + if(az_id >= 0) + if(!az_port->isOpen()) + return false; + + if(el_id >= 0) + if(!el_port->isOpen()) + return false; + + return rc; +} + +//--------------------------------------------------------------------------- +bool TJRK::openCOM(void) +{ + bool rc; + + if(isCOMOpen()) + return true; + + if(iobuff == NULL || (flags & R_ROTOR_IOERR)) + return false; + + if(az_id >= 0) { + if(!open(az_port, az_deviceId)) + flags |= R_ROTOR_IOERR; + } + + if(el_id >= 0) { + if(!open(el_port, el_deviceId)) + flags |= R_ROTOR_IOERR; + } + + if(flags & R_ROTOR_IOERR) + rc = false; + else + rc = true; + + if(rc) { + clearErrors(); + + rc = readPosition(); + + if(rc) + qDebug("Az: %f El: %f", current_az, current_el); + } + + return rc; +} + +//--------------------------------------------------------------------------- +bool TJRK::open(QextSerialPort *port, QString portname) +{ + if(port->isOpen()) + return true; + + port->setPortName(portname); + + port->setBaudRate(BAUD115200); + port->setDataBits(DATA_8); + port->setParity(PAR_NONE); + port->setStopBits(STOP_1); + port->setFlowControl(FLOW_OFF); + port->setTimeout(500); + + return port->open(QIODevice::ReadWrite | QIODevice::Unbuffered); +} + +//--------------------------------------------------------------------------- +void TJRK::closeCOM(void) +{ + stop(); + + if(az_port->isOpen()) + az_port->close(); + + if(el_port->isOpen()) + el_port->close(); + + flags = 0; +} + +//--------------------------------------------------------------------------- +quint16 TJRK::readErrorHalting(unsigned char id) +{ + quint16 data = 0xffff; + + if(send3bytecommand(id, 0x33)) + readshort(&data); + + return data; +} + +//--------------------------------------------------------------------------- +quint16 TJRK::readErrorOccurred(unsigned char id) +{ + quint16 data = 0xffff; + + if(send3bytecommand(id, 0x35)) + readshort(&data); + + return data; +} + +//--------------------------------------------------------------------------- +QString TJRK::errorString(void) +{ + QString str; + + str = "Pololu Jrk Motor Contorol:\n\n"; + if(az_id < 0 && el_id < 0) { + str += "No motors enabled!"; + + return str; + } + + if(!isCOMOpen()) { + str += "Failed to open communication!\n"; + + if(az_id >= 0) + if(!az_port->isOpen()) + str += "Port: " + az_deviceId + "\n"; + + if(el_id >= 0) + if(!el_port->isOpen()) + str += "Port: " + el_deviceId + "\n"; + + return str; + } + + QStringList sl; + int i; + + if(az_id >= 0) { + str.sprintf("Jrk Port: %s Id: %d\n", az_deviceId.toStdString().c_str(), az_id); + + port = az_port; + errorStrings(&sl, az_id, readErrorOccurred(az_id)); + for(i=0; i= 0) { + str.sprintf("Jrk Port: %s Id: %d\n", el_deviceId.toStdString().c_str(), el_id); + + port = el_port; + errorStrings(&sl, el_id, readErrorOccurred(el_id)); + for(i=0; iclear(); + + str.sprintf("Port: %s Device: %d\n", port->portName().toStdString().c_str(), id); + sl->append(str); + + if(err == 0xffff) { + sl->append("Unknown error, read failed!"); + sl->append("\n"); + return; + } + + if(err & 0x0001) + sl->append("Awaiting command"); + if(err & 0x0002) + sl->append("No power"); + if(err & 0x0004) + sl->append("Motor driver error"); + if(err & 0x0008) + sl->append("Input invalid (Pulse Width Input Mode only)"); + if(err & 0x0010) + sl->append("Input disconnect"); + if(err & 0x0020) + sl->append("Feedback disconnect"); + if(err & 0x0040) + sl->append("Maximum current exceeded"); + if(err & 0x0080) + sl->append("Serial signal error"); + if(err & 0x0100) + sl->append("Serial overrun"); + if(err & 0x0200) + sl->append("Serial RX buffer full"); + if(err & 0x0400) + sl->append("Serial CRC error"); + if(err & 0x0800) + sl->append("Serial protocol error"); + if(err & 0x1000) + sl->append("Serial timeout error"); + if(err == 0x0000) + sl->append("No errors"); + + sl->append("\n"); +} + +//--------------------------------------------------------------------------- +void TJRK::clearErrors(void) +{ + clearError(true); + clearError(false); +} + +//--------------------------------------------------------------------------- +void TJRK::clearError(bool az) +{ + port = az ? az_port:el_port; + + readErrorHalting(az ? az_id:el_id); +} + +//--------------------------------------------------------------------------- +quint16 TJRK::readFeedback(bool az) +{ + quint16 data = 0xffff; + + port = az ? az_port:el_port; + + if(send3bytecommand(az ? az_id:el_id, 0xa5 & 0x7f)) + readshort(&data); + + return data; +} + +//--------------------------------------------------------------------------- +QString TJRK::status(bool az) +{ + QStringList sl; + QString str; + int i; + + port = az ? az_port:el_port; + + errorStrings(&sl, az ? az_id:el_id, readErrorOccurred(az ? az_id:el_id)); + for(i=0; iaz_max, rotor->az_min); + + if(!isCOMOpen()) + return false; + else if(az == current_az) + return true; + + port = az_port; + if(setTargetHiRes(az_id, degrees2target(az, rotor->az_max - rotor->az_min))) { + current_az = az; + + return true; + } + else + return false; +} + +//--------------------------------------------------------------------------- +bool TJRK::moveToEl(double el) +{ + el = ClipValue(el, rotor->el_max, rotor->el_min); + + if(!isCOMOpen()) + return false; + else if(el == current_el) + return true; + + port = el_port; + if(setTargetHiRes(el_id, degrees2target(el, rotor->el_max - rotor->el_min))) { + current_el = el; + + return true; + } + else + return false; +} + +//--------------------------------------------------------------------------- +bool TJRK::readPosition(void) +{ + current_az = 0; + current_el = 0; + + if(!isCOMOpen()) + return false; + + quint16 target; + int i = 0; + + if(az_id >= 0) { + port = az_port; + target = readTarget(az_id); + if(target != 0xffff) + current_az = target2degrees(target, rotor->az_max - rotor->az_min); + else + i |= 1; + } + + if(el_id >= 0) { + port = el_port; + target = readTarget(el_id); + if(target != 0xffff) + current_el = target2degrees(target, rotor->el_max - rotor->el_min); + else + i |= 2; + } + + qDebug("readPos Az: %g El: %g", current_az, current_el); + + return i ? false:true; +} + +//--------------------------------------------------------------------------- +void TJRK::stop(void) +{ + if(!isCOMOpen()) + return; + + if(az_id >= 0) { + port = az_port; + send3bytecommand(az_id, 0x7f); + } + + if(el_id >= 0) { + port = el_port; + send3bytecommand(el_id, 0x7f); + } +} + +//--------------------------------------------------------------------------- +// +// Protected functions +// +//--------------------------------------------------------------------------- +quint16 TJRK::readTarget(unsigned char id) +{ + quint16 data = 0xffff; + + delay(10); + if(port->isOpen() && send3bytecommand(id, 0xa3 & 0x7f)) + readshort(&data); + + return data; +} + +//--------------------------------------------------------------------------- +bool TJRK::setTargetHiRes(unsigned char id, quint16 target) +{ + if(target > 0x0fff || !port->isOpen()) + return false; + + target &= 0x0fff; + + iobuff[0] = (unsigned char) 0xaa; + iobuff[1] = id; + iobuff[2] = (unsigned char) (0x40 + (target & 0x1F)); + iobuff[3] = (unsigned char) ((target >> 5) & 0x7F); + + qDebug("set target %d hi res: 0x%02x%02x%02x%02x", target, iobuff[0], iobuff[1], iobuff[2], iobuff[3]); + + delay(10); + if(port->write((const char *) iobuff, 4) != 4) + return false; + else + return true; +} + +//--------------------------------------------------------------------------- +bool TJRK::setTargetLowRes(unsigned char id, int magnitude) +{ + if(!port->isOpen() || magnitude < -127 || magnitude > 127) + return false; + + iobuff[0] = 0xaa; + iobuff[1] = id; + iobuff[2] = magnitude < 0 ? 0x60:0x61; + iobuff[3] = (unsigned char) (magnitude < 0 ? -magnitude:magnitude); + + qDebug("set target low res: 0x%02x%02x%02x%02x", iobuff[0], iobuff[1], iobuff[2], iobuff[3]); + + delay(10); + if(port->write((const char *) iobuff, 4) != 4) + return false; + else + return true; +} + +//--------------------------------------------------------------------------- +#if 0 +quint16 TJRK::degrees2target(double degrees, bool azimuth) +{ + quint16 target; + double d_deg, d_target; + + if(azimuth) { + d_deg = rotor->az_max - rotor->az_min; + d_target = az_max_fk - az_min_fk; + + if(d_deg <= 0) + return az_min_fk; + } + else { + d_deg = rotor->el_max - rotor->el_min; + d_target = el_max_fk - el_min_fk; + + if(d_deg <= 0) + return el_min_fk; + } + + // 0...4095 = 0...max_degrees + target = (quint16) rint(((d_target * degrees) / d_deg)); + target += azimuth ? az_min_fk:el_min_fk; + + qDebug("degrees2target, target: %d degrees: %f", target, degrees); + + return (target & 0x0fff); +} +#else + +quint16 TJRK::degrees2target(double degrees, double max_degrees) +{ + quint16 target; + + degrees = ClipValue(degrees, max_degrees, 0); + + // 0...4095 = 0...max_degrees + target = (quint16) rint(((4095.0 * degrees) / max_degrees)); + + // qDebug("degrees2target, target: %d degrees: %f", target, degrees); + + return (target & 0x0fff); +} + +#endif + +#if 0 +//--------------------------------------------------------------------------- +double TJRK::target2degrees(quint16 target, bool azimuth) +{ + double degrees; + double d_deg, d_target; + + if(azimuth) { + d_deg = rotor->az_max - rotor->az_min; + d_target = az_max_fk - az_min_fk; + + if(d_target <= 0) + return rotor->az_min; + } + else { + d_deg = rotor->el_max - rotor->el_min; + d_target = el_max_fk - el_min_fk; + + if(d_target <= 0) + return rotor->el_min; + } + + degrees = (((double) target) * d_deg) / d_target; + degrees += azimuth ? rotor->az_min:rotor->el_min; + + qDebug("target2degrees, target: %d degrees: %f", target, degrees); + + return degrees; +} +#else +//--------------------------------------------------------------------------- +double TJRK::target2degrees(quint16 target, double max_degrees) +{ + double degrees; + + degrees = (((double) target) * max_degrees) / 4095.0; + + // qDebug("target2degrees, target: %d degrees: %f", target, degrees); + + return degrees; // ClipValue(degrees, max_degrees, 0); +} +#endif + +//--------------------------------------------------------------------------- +quint16 TJRK::magnitude2target(int magnitude, bool analog) +{ + quint16 rc = 2048; + + if(analog) + rc = 2048 + 16 * magnitude; + else + rc = 2048 + (600 / 127) * magnitude; + + return rc; +} + +//--------------------------------------------------------------------------- +int TJRK::target2magnitude(quint16 target, bool analog) +{ + int rc = 0; + + if(analog) + rc = (target - 2048) / 16; + else + rc = (target - 2048) * (127 / 600); + + return rc; +} + +//--------------------------------------------------------------------------- +bool TJRK::readshort(quint16 *data) +{ + int retrys = 10; + int i = 0; + + *data = 0xffff; + + if(!port->isOpen()) + return false; + + delay(10); + while(port->bytesAvailable() != 2) { + i++; + if(i >= retrys) + return false; + + delay(50); + } + + if(port->read((char *) iobuff, 2) != 2) + return false; + + *data = (iobuff[1] << 8) | iobuff[0]; + // qDebug("readshort data: 0x%02x", *data); + + return true; +} + +//--------------------------------------------------------------------------- +bool TJRK::send3bytecommand(unsigned char id, unsigned char cmd) +{ + if(!port->isOpen()) + return false; + + iobuff[0] = 0xaa; + iobuff[1] = id; + iobuff[2] = cmd; + + if(port->write((const char *) iobuff, 3) != 3) + return false; + + return true; +} diff --git a/rig/deprecated/jrk.h b/rig/deprecated/jrk.h new file mode 100644 index 0000000..b002387 --- /dev/null +++ b/rig/deprecated/jrk.h @@ -0,0 +1,103 @@ +/* + HRPT-Decoder, a software for processing POES high resolution weather satellite imagery. + Copyright (C) 2010,2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ + +//--------------------------------------------------------------------------- + +#ifndef JRK_H +#define JRK_H + +#include +#include +#include "qextserialport.h" + +#include "rig.h" + +class QextSerialPort; +class QDateTime; +class QSettings; + +//--------------------------------------------------------------------------- +class TJRK +{ +public: + TJRK(TRotor *_rotor); + ~TJRK(void); + + void writeSettings(QSettings *reg); + void readSettings(QSettings *reg); + + bool isCOMOpen(void); + bool openCOM(void); + void closeCOM(void); + + quint16 readErrorHalting(unsigned char id); + quint16 readErrorOccurred(unsigned char id); + void errorStrings(QStringList *sl, unsigned char id, quint16 err); + QString errorString(void); + + void clearError(bool az); + void clearErrors(void); + + void stop(void); + bool moveTo(double az, double el); + bool moveToAz(double az); + bool moveToEl(double el); + bool readPosition(void); + + QString az_deviceId, el_deviceId; + int az_id, el_id; + double current_az, current_el; // in degrees, 0-90 el 0-360 az + + int flags; + + // feedback parameters + int el_min_fk, el_max_fk; + int az_min_fk, az_max_fk; + + quint16 readFeedback(bool az); + QString status(bool az); + +protected: + bool open(QextSerialPort *port, QString portname); + + quint16 readTarget(unsigned char id); + bool setTargetHiRes(unsigned char id, quint16 target); + bool setTargetLowRes(unsigned char id, int magnitude); + + quint16 degrees2target(double degrees, double max_degrees); + //quint16 degrees2target(double degrees, bool azimuth); + double target2degrees(quint16 target, double max_degrees); + //double target2degrees(quint16 target, bool azimuth); + + quint16 magnitude2target(int magnitude, bool analog); + int target2magnitude(quint16 target, bool analog); + + bool send3bytecommand(unsigned char id, unsigned char cmd); + bool readshort(quint16 *data); + +private: + TRotor *rotor; + QextSerialPort *az_port, *el_port, *port; + unsigned char *iobuff; + +}; + +#endif // JRK_H diff --git a/rig/jrk.cpp b/rig/jrk.cpp index d40f70b..07c4b2a 100644 --- a/rig/jrk.cpp +++ b/rig/jrk.cpp @@ -28,47 +28,31 @@ #include #include "rotor.h" -#include "qextserialport.h" #include "utils.h" #include "jrk.h" +#include "tusb.h" +#include "jrkusb.h" //--------------------------------------------------------------------------- TJRK::TJRK(TRotor *_rotor) { rotor = _rotor; -#if defined(Q_OS_UNIX) || defined(Q_OS_MAC) - az_deviceId = "/dev/ttyACM0"; - el_deviceId = "/dev/ttyACM2"; -#else - az_deviceId = "COM6"; - el_deviceId = "COM8"; -#endif - - az_port = rotor->serialPort; - el_port = rotor->serialPort_2; - port = NULL; - - iobuff = (unsigned char *) rotor->iobuff; - - az_id = 11; - el_id = 11; - - current_az = 0; - current_el = 0; - flags = 0; - - el_min_fk = 0; - el_max_fk = 4095; + flags = 0; - az_min_fk = 0; - az_max_fk = 4095; + usb = new TUSB; + az_jrk = new TJrkUSB; + el_jrk = new TJrkUSB; } //--------------------------------------------------------------------------- TJRK::~TJRK(void) { - closeCOM(); + close(); + + delete az_jrk; + delete el_jrk; + delete usb; } //--------------------------------------------------------------------------- @@ -76,18 +60,11 @@ void TJRK::writeSettings(QSettings *reg) { reg->beginGroup("Jrk"); - reg->setValue("AzDeviceId", az_deviceId); - reg->setValue("AzId", az_id); - reg->setValue("ElDeviceId", el_deviceId); - reg->setValue("ElId", el_id); - - reg->beginGroup("Feedback"); - reg->setValue("ElMinFk", el_min_fk); - reg->setValue("ElMaxFk", el_max_fk); + reg->setValue("AzDeviceId", az_jrk->serialnumber()); + reg->setValue("ElDeviceId", el_jrk->serialnumber()); - reg->setValue("AzMinFk", az_min_fk); - reg->setValue("AzMaxFk", az_max_fk); - reg->endGroup(); + az_jrk->writeSettings(reg); + el_jrk->writeSettings(reg); reg->endGroup(); } @@ -95,609 +72,317 @@ void TJRK::writeSettings(QSettings *reg) //--------------------------------------------------------------------------- void TJRK::readSettings(QSettings *reg) { - reg->beginGroup("Jrk"); + if(rotor->rotor_type != RotorType_JRK) + return; -#if defined Q_OS_WIN - az_deviceId = reg->value("AzDeviceId", QString("COM6")).toString(); - el_deviceId = reg->value("ElDeviceId", QString("COM8")).toString(); -#else - az_deviceId = reg->value("AzDeviceId", QString("/dev/ttyACM0")).toString(); - el_deviceId = reg->value("ElDeviceId", QString("/dev/ttyACM2")).toString(); -#endif + if(!loadDevices()) + return; - az_id = reg->value("AzId", 11).toInt(); - el_id = reg->value("ElId", 11).toInt(); + reg->beginGroup("Jrk"); - reg->beginGroup("Feedback"); - el_min_fk = reg->value("ElMinFk", 0).toInt(); - el_max_fk = reg->value("ElMaxFk", 4095).toInt(); + az_jrk->setDevice(usb->get_device_by_sn(reg->value("AzDeviceId", "").toString())); + el_jrk->setDevice(usb->get_device_by_sn(reg->value("ElDeviceId", "").toString())); - az_min_fk = reg->value("AzMinFk", 0).toInt(); - az_max_fk = reg->value("AzMaxFk", 4095).toInt(); - reg->endGroup(); + az_jrk->readSettings(reg); + el_jrk->readSettings(reg); reg->endGroup(); // Jrk + + open(); } //--------------------------------------------------------------------------- -bool TJRK::isCOMOpen(void) +bool TJRK::isOpen(void) { - bool rc = true; - - if(az_id >= 0) - if(!az_port->isOpen()) - return false; - - if(el_id >= 0) - if(!el_port->isOpen()) - return false; - - return rc; + return (az_jrk->isOpen() || el_jrk->isOpen()) ? true:false; } //--------------------------------------------------------------------------- -bool TJRK::openCOM(void) +bool TJRK::loadDevices(void) { - bool rc; + if(usb->list_devices(JRK_VENDOR)) { + usb->conf_devices(-1); + usb->open_devices(); - if(isCOMOpen()) return true; - - if(iobuff == NULL || (flags & R_ROTOR_IOERR)) - return false; - - if(az_id >= 0) { - if(!open(az_port, az_deviceId)) - flags |= R_ROTOR_IOERR; - } - - if(el_id >= 0) { - if(!open(el_port, el_deviceId)) - flags |= R_ROTOR_IOERR; } - - if(flags & R_ROTOR_IOERR) - rc = false; else - rc = true; - - if(rc) { - clearErrors(); - - rc = readPosition(); - - if(rc) - qDebug("Az: %f El: %f", current_az, current_el); - } - - return rc; + return false; } //--------------------------------------------------------------------------- -bool TJRK::open(QextSerialPort *port, QString portname) +QStringList TJRK::deviceNames(void) { - if(port->isOpen()) - return true; - - port->setPortName(portname); + if(!usb->count_devices()) + loadDevices(); - port->setBaudRate(BAUD115200); - port->setDataBits(DATA_8); - port->setParity(PAR_NONE); - port->setStopBits(STOP_1); - port->setFlowControl(FLOW_OFF); - port->setTimeout(500); - - return port->open(QIODevice::ReadWrite | QIODevice::Unbuffered); + return usb->device_names("Disabled"); } //--------------------------------------------------------------------------- -void TJRK::closeCOM(void) +bool TJRK::setDevices(int az_index, int el_index) { - stop(); + az_jrk->setDevice(usb->get_device(az_index)); + el_jrk->setDevice(usb->get_device(el_index)); - if(az_port->isOpen()) - az_port->close(); + open(); - if(el_port->isOpen()) - el_port->close(); + return isOpen(); +} - flags = 0; +//--------------------------------------------------------------------------- +int TJRK::deviceIndex(bool az) +{ + return usb->device_index(az ? az_jrk->udev():el_jrk->udev()); } //--------------------------------------------------------------------------- -quint16 TJRK::readErrorHalting(unsigned char id) +bool TJRK::open(void) { - quint16 data = 0xffff; + if(!isOpen()) + return false; - if(send3bytecommand(id, 0x33)) - readshort(&data); + clearErrors(); - return data; + az_jrk->minPos(rotor->az_min); + az_jrk->maxPos(rotor->az_max); + el_jrk->minPos(rotor->el_min); + el_jrk->maxPos(rotor->el_max); + + bool rc = readPosition(); + + if(rc) + qDebug("Jrk Az: %f El: %f", az_jrk->currentPos(), el_jrk->currentPos()); + else + qDebug("Jrk ERROR: Position read failed!"); + + return rc; } //--------------------------------------------------------------------------- -quint16 TJRK::readErrorOccurred(unsigned char id) +void TJRK::close(void) { - quint16 data = 0xffff; - - if(send3bytecommand(id, 0x35)) - readshort(&data); - - return data; + stop(); + flags = 0; } //--------------------------------------------------------------------------- +// todo QString TJRK::errorString(void) { - QString str; + QString str, str2; str = "Pololu Jrk Motor Contorol:\n\n"; - if(az_id < 0 && el_id < 0) { + if(!isOpen()) { str += "No motors enabled!"; return str; } - if(!isCOMOpen()) { - str += "Failed to open communication!\n"; - - if(az_id >= 0) - if(!az_port->isOpen()) - str += "Port: " + az_deviceId + "\n"; - - if(el_id >= 0) - if(!el_port->isOpen()) - str += "Port: " + el_deviceId + "\n"; - - return str; - } - QStringList sl; int i; - if(az_id >= 0) { - str.sprintf("Jrk Port: %s Id: %d\n", az_deviceId.toStdString().c_str(), az_id); + str = ""; + if(az_jrk->isOpen()) { + str2.sprintf("Azimuth Jrk SN %s\n", az_jrk->serialnumber().toStdString().c_str()); + str += str2; - port = az_port; - errorStrings(&sl, az_id, readErrorOccurred(az_id)); + az_jrk->errorStr(&sl); for(i=0; i= 0) { - str.sprintf("Jrk Port: %s Id: %d\n", el_deviceId.toStdString().c_str(), el_id); + if(el_jrk->isOpen()) { + str2.sprintf("Elevation Jrk SN %s\n", el_jrk->serialnumber().toStdString().c_str()); + str += str2; - port = el_port; - errorStrings(&sl, el_id, readErrorOccurred(el_id)); + el_jrk->errorStr(&sl); for(i=0; iclear(); - - str.sprintf("Port: %s Device: %d\n", port->portName().toStdString().c_str(), id); - sl->append(str); - - if(err == 0xffff) { - sl->append("Unknown error, read failed!"); - sl->append("\n"); - return; - } - - if(err & 0x0001) - sl->append("Awaiting command"); - if(err & 0x0002) - sl->append("No power"); - if(err & 0x0004) - sl->append("Motor driver error"); - if(err & 0x0008) - sl->append("Input invalid (Pulse Width Input Mode only)"); - if(err & 0x0010) - sl->append("Input disconnect"); - if(err & 0x0020) - sl->append("Feedback disconnect"); - if(err & 0x0040) - sl->append("Maximum current exceeded"); - if(err & 0x0080) - sl->append("Serial signal error"); - if(err & 0x0100) - sl->append("Serial overrun"); - if(err & 0x0200) - sl->append("Serial RX buffer full"); - if(err & 0x0400) - sl->append("Serial CRC error"); - if(err & 0x0800) - sl->append("Serial protocol error"); - if(err & 0x1000) - sl->append("Serial timeout error"); - if(err == 0x0000) - sl->append("No errors"); - - sl->append("\n"); + return az ? az_jrk->minFeedback():el_jrk->minFeedback(); } //--------------------------------------------------------------------------- -void TJRK::clearErrors(void) +void TJRK::minFeedback(bool az, int fb) { - clearError(true); - clearError(false); -} - -//--------------------------------------------------------------------------- -void TJRK::clearError(bool az) -{ - port = az ? az_port:el_port; - - readErrorHalting(az ? az_id:el_id); + if(az) + az_jrk->minFeedback(fb & 0x0fff); + else + el_jrk->minFeedback(fb & 0x0fff); } //--------------------------------------------------------------------------- -quint16 TJRK::readFeedback(bool az) +int TJRK::maxFeedback(bool az) { - quint16 data = 0xffff; - - port = az ? az_port:el_port; - - if(send3bytecommand(az ? az_id:el_id, 0xa5 & 0x7f)) - readshort(&data); - - return data; + return az ? az_jrk->maxFeedback():el_jrk->maxFeedback(); } //--------------------------------------------------------------------------- -QString TJRK::status(bool az) +void TJRK::maxFeedback(bool az, int fb) { - QStringList sl; - QString str; - int i; - - port = az ? az_port:el_port; - - errorStrings(&sl, az ? az_id:el_id, readErrorOccurred(az ? az_id:el_id)); - for(i=0; imaxFeedback(fb & 0x0fff); + else + el_jrk->maxFeedback(fb & 0x0fff); } //--------------------------------------------------------------------------- -bool TJRK::moveTo(double az, double el) +void TJRK::clearErrors(void) { - if(!isCOMOpen()) - return false; - - // fixme - qDebug("\nMoveto Az: %g El: %g", az, el); - - port = az_port; - moveToAz(az); - - port = el_port; - moveToEl(el); - - // readPosition(); - - return true; + az_jrk->clearErrors(); + el_jrk->clearErrors(); } //--------------------------------------------------------------------------- -bool TJRK::moveToAz(double az) +void TJRK::clearError(bool az) { - az = ClipValue(az, rotor->az_max, rotor->az_min); - - if(!isCOMOpen()) - return false; - else if(az == current_az) - return true; + TJrkUSB *d = az ? az_jrk:el_jrk; - port = az_port; - if(setTargetHiRes(az_id, degrees2target(az, rotor->az_max - rotor->az_min))) { - current_az = az; - - return true; - } - else - return false; + d->clearErrors(); } //--------------------------------------------------------------------------- -bool TJRK::moveToEl(double el) +// mode & 1 = read +quint16 TJRK::readFeedback(bool az, int mode) { - el = ClipValue(el, rotor->el_max, rotor->el_min); - - if(!isCOMOpen()) - return false; - else if(el == current_el) - return true; + TJrkUSB *d = az ? az_jrk:el_jrk; - port = el_port; - if(setTargetHiRes(el_id, degrees2target(el, rotor->el_max - rotor->el_min))) { - current_el = el; - - return true; - } - else - return false; + return d->feedback(mode); } //--------------------------------------------------------------------------- -bool TJRK::readPosition(void) +QString TJRK::status(bool az) { - current_az = 0; - current_el = 0; - - if(!isCOMOpen()) - return false; - - quint16 target; - int i = 0; - - if(az_id >= 0) { - port = az_port; - target = readTarget(az_id); - if(target != 0xffff) - current_az = target2degrees(target, rotor->az_max - rotor->az_min); - else - i |= 1; - } + TJrkUSB *d = az ? az_jrk:el_jrk; + QStringList sl; + QString str, sn; - if(el_id >= 0) { - port = el_port; - target = readTarget(el_id); - if(target != 0xffff) - current_el = target2degrees(target, rotor->el_max - rotor->el_min); - else - i |= 2; - } + sn = az ? az_jrk->serialnumber():el_jrk->serialnumber(); + str.sprintf("%s Jrk SN %s\n", az ? "Azimuth":"Elevation", sn.toStdString().c_str()); - qDebug("readPos Az: %g El: %g", current_az, current_el); + d->errorStr(&sl); + for(int i=0; i= 0) { - port = az_port; - send3bytecommand(az_id, 0x7f); - } - - if(el_id >= 0) { - port = el_port; - send3bytecommand(el_id, 0x7f); - } + return az_jrk->readPos(mode); } //--------------------------------------------------------------------------- -// -// Protected functions -// -//--------------------------------------------------------------------------- -quint16 TJRK::readTarget(unsigned char id) +// mode & 1 = read +double TJRK::current_el(int mode) { - quint16 data = 0xffff; - - delay(10); - if(port->isOpen() && send3bytecommand(id, 0xa3 & 0x7f)) - readshort(&data); - - return data; + return el_jrk->readPos(mode); } //--------------------------------------------------------------------------- -bool TJRK::setTargetHiRes(unsigned char id, quint16 target) +void TJRK::setTarget(bool az, quint16 t) { - if(target > 0x0fff || !port->isOpen()) - return false; - - target &= 0x0fff; - - iobuff[0] = (unsigned char) 0xaa; - iobuff[1] = id; - iobuff[2] = (unsigned char) (0x40 + (target & 0x1F)); - iobuff[3] = (unsigned char) ((target >> 5) & 0x7F); - - qDebug("set target %d hi res: 0x%02x%02x%02x%02x", target, iobuff[0], iobuff[1], iobuff[2], iobuff[3]); - - delay(10); - if(port->write((const char *) iobuff, 4) != 4) - return false; + if(az) + az_jrk->setTarget(t); else - return true; + el_jrk->setTarget(t); } //--------------------------------------------------------------------------- -bool TJRK::setTargetLowRes(unsigned char id, int magnitude) +// move min_az and max_az values +void TJRK::adjustToAz(double az) { - if(!port->isOpen() || magnitude < -127 || magnitude > 127) - return false; - - iobuff[0] = 0xaa; - iobuff[1] = id; - iobuff[2] = magnitude < 0 ? 0x60:0x61; - iobuff[3] = (unsigned char) (magnitude < 0 ? -magnitude:magnitude); - - qDebug("set target low res: 0x%02x%02x%02x%02x", iobuff[0], iobuff[1], iobuff[2], iobuff[3]); - - delay(10); - if(port->write((const char *) iobuff, 4) != 4) - return false; - else - return true; -} - -//--------------------------------------------------------------------------- + az = az; #if 0 -quint16 TJRK::degrees2target(double degrees, bool azimuth) -{ - quint16 target; - double d_deg, d_target; - - if(azimuth) { - d_deg = rotor->az_max - rotor->az_min; - d_target = az_max_fk - az_min_fk; - - if(d_deg <= 0) - return az_min_fk; - } - else { - d_deg = rotor->el_max - rotor->el_min; - d_target = el_max_fk - el_min_fk; - - if(d_deg <= 0) - return el_min_fk; - } - - // 0...4095 = 0...max_degrees - target = (quint16) rint(((d_target * degrees) / d_deg)); - target += azimuth ? az_min_fk:el_min_fk; + if(!az_jrk->readVariables()) + return; - qDebug("degrees2target, target: %d degrees: %f", target, degrees); + double target = az_jrk->target(0); + double pos = current_az(0); + double delta = az - pos; +#endif - return (target & 0x0fff); } -#else -quint16 TJRK::degrees2target(double degrees, double max_degrees) +//--------------------------------------------------------------------------- +void TJRK::adjustToEl(double el) { - quint16 target; - - degrees = ClipValue(degrees, max_degrees, 0); - - // 0...4095 = 0...max_degrees - target = (quint16) rint(((4095.0 * degrees) / max_degrees)); - - // qDebug("degrees2target, target: %d degrees: %f", target, degrees); - - return (target & 0x0fff); + el = el; } -#endif - -#if 0 //--------------------------------------------------------------------------- -double TJRK::target2degrees(quint16 target, bool azimuth) +bool TJRK::moveTo(double az, double el) { - double degrees; - double d_deg, d_target; - - if(azimuth) { - d_deg = rotor->az_max - rotor->az_min; - d_target = az_max_fk - az_min_fk; - - if(d_target <= 0) - return rotor->az_min; - } - else { - d_deg = rotor->el_max - rotor->el_min; - d_target = el_max_fk - el_min_fk; - - if(d_target <= 0) - return rotor->el_min; - } - - degrees = (((double) target) * d_deg) / d_target; - degrees += azimuth ? rotor->az_min:rotor->el_min; - - qDebug("target2degrees, target: %d degrees: %f", target, degrees); + if(!isOpen()) + return false; - return degrees; -} -#else -//--------------------------------------------------------------------------- -double TJRK::target2degrees(quint16 target, double max_degrees) -{ - double degrees; + // fixme + qDebug("JRK Moveto Az: %g El: %g", az, el); - degrees = (((double) target) * max_degrees) / 4095.0; + az_jrk->moveTo(az); + el_jrk->moveTo(el); - // qDebug("target2degrees, target: %d degrees: %f", target, degrees); + // readPosition(); - return degrees; // ClipValue(degrees, max_degrees, 0); + return true; } -#endif //--------------------------------------------------------------------------- -quint16 TJRK::magnitude2target(int magnitude, bool analog) +bool TJRK::moveToAz(double az) { - quint16 rc = 2048; - - if(analog) - rc = 2048 + 16 * magnitude; - else - rc = 2048 + (600 / 127) * magnitude; + az_jrk->moveTo(az); - return rc; + return true; } //--------------------------------------------------------------------------- -int TJRK::target2magnitude(quint16 target, bool analog) +bool TJRK::moveToEl(double el) { - int rc = 0; + el_jrk->moveTo(el); - if(analog) - rc = (target - 2048) / 16; - else - rc = (target - 2048) * (127 / 600); - - return rc; + return true; } //--------------------------------------------------------------------------- -bool TJRK::readshort(quint16 *data) +bool TJRK::readPosition(void) { - int retrys = 10; - int i = 0; - - *data = 0xffff; - - if(!port->isOpen()) + if(!isOpen()) return false; - delay(10); - while(port->bytesAvailable() != 2) { - i++; - if(i >= retrys) - return false; - - delay(50); - } - - if(port->read((char *) iobuff, 2) != 2) - return false; + double az = az_jrk->readPos(); + double el = el_jrk->readPos(); - *data = (iobuff[1] << 8) | iobuff[0]; - // qDebug("readshort data: 0x%02x", *data); + qDebug("JRK readPos Az: %g El: %g", az, el); return true; } //--------------------------------------------------------------------------- -bool TJRK::send3bytecommand(unsigned char id, unsigned char cmd) +void TJRK::stop(void) { - if(!port->isOpen()) - return false; - - iobuff[0] = 0xaa; - iobuff[1] = id; - iobuff[2] = cmd; - - if(port->write((const char *) iobuff, 3) != 3) - return false; + if(!isOpen()) + return; - return true; + az_jrk->stop(); + el_jrk->stop(); } + +//--------------------------------------------------------------------------- +// +// Protected functions +// +//--------------------------------------------------------------------------- diff --git a/rig/jrk.h b/rig/jrk.h index b002387..fafcac0 100644 --- a/rig/jrk.h +++ b/rig/jrk.h @@ -26,14 +26,15 @@ #include #include -#include "qextserialport.h" #include "rig.h" -class QextSerialPort; class QDateTime; class QSettings; +class TJrkUSB; +class TUSB; + //--------------------------------------------------------------------------- class TJRK { @@ -44,14 +45,17 @@ class TJRK void writeSettings(QSettings *reg); void readSettings(QSettings *reg); - bool isCOMOpen(void); - bool openCOM(void); - void closeCOM(void); + bool isOpen(void); + bool setDevices(int az_index, int el_index); + bool loadDevices(void); + QStringList deviceNames(void); + int deviceIndex(bool az); + + bool open(void); + void close(void); - quint16 readErrorHalting(unsigned char id); - quint16 readErrorOccurred(unsigned char id); - void errorStrings(QStringList *sl, unsigned char id, quint16 err); QString errorString(void); + QString status(bool az); void clearError(bool az); void clearErrors(void); @@ -62,42 +66,26 @@ class TJRK bool moveToEl(double el); bool readPosition(void); - QString az_deviceId, el_deviceId; - int az_id, el_id; - double current_az, current_el; // in degrees, 0-90 el 0-360 az + double current_az(int mode = 1); + double current_el(int mode = 1); + void adjustToAz(double az); + void adjustToEl(double el); - int flags; + int minFeedback(bool az); + int maxFeedback(bool az); + void minFeedback(bool az, int fb); + void maxFeedback(bool az, int fb); - // feedback parameters - int el_min_fk, el_max_fk; - int az_min_fk, az_max_fk; - - quint16 readFeedback(bool az); - QString status(bool az); + quint16 readFeedback(bool az, int mode); + void setTarget(bool az, quint16 t); + int flags; protected: - bool open(QextSerialPort *port, QString portname); - - quint16 readTarget(unsigned char id); - bool setTargetHiRes(unsigned char id, quint16 target); - bool setTargetLowRes(unsigned char id, int magnitude); - - quint16 degrees2target(double degrees, double max_degrees); - //quint16 degrees2target(double degrees, bool azimuth); - double target2degrees(quint16 target, double max_degrees); - //double target2degrees(quint16 target, bool azimuth); - - quint16 magnitude2target(int magnitude, bool analog); - int target2magnitude(quint16 target, bool analog); - - bool send3bytecommand(unsigned char id, unsigned char cmd); - bool readshort(quint16 *data); private: - TRotor *rotor; - QextSerialPort *az_port, *el_port, *port; - unsigned char *iobuff; - + TRotor *rotor; + TJrkUSB *az_jrk, *el_jrk; + TUSB *usb; }; #endif // JRK_H diff --git a/rig/jrk_protocol.h b/rig/jrk_protocol.h new file mode 100644 index 0000000..cb7b05a --- /dev/null +++ b/rig/jrk_protocol.h @@ -0,0 +1,129 @@ +/* + POES-USRP, a software for recording and decoding POES high resolution weather satellite images. + Copyright (C) 2009-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ +//--------------------------------------------------------------------------- +#ifndef JRK_PROTOCOL_H +#define JRK_PROTOCOL_H + +#define JRK_IO_BUF_SIZE 64 +#define JRK_VENDOR 0x1ffb +#define JRK_12v12 0x0085 +#define JRK_21v3 0x0083 + +#define JRK_REQUEST_GET_TYPE 0xC0 +#define JRK_REQUEST_SET_TYPE 0x40 + +#define JRK_REQUEST_GET_PARAMETER 0x81 +#define JRK_REQUEST_SET_PARAMETER 0x82 +#define JRK_REQUEST_GET_VARIABLES 0x83 +#define JRK_REQUEST_SET_TARGET 0x84 +#define JRK_REQUEST_CLEAR_ERRORS 0x86 +#define JRK_REQUEST_MOTOR_OFF 0x87 +#define JRK_REQUEST_REINITIALIZE 0x90 + +typedef struct jrk_variables_t +{ + unsigned short input; // Offset 1 + unsigned short target; // Offset 3 + unsigned short feedback; // Offset 5 + unsigned short scaledFeedback; // Offset 7 + short errorSum; // Offset 9 + short dutyCycleTarget; // Offset 11 + short dutyCycle; // Offset 13 + unsigned char current; // Offset 15 + unsigned char pidPeriodExceeded; // Offset 16 + unsigned short pidPeriodCount; // Offset 17 + unsigned short errorFlagBits; // Offset 19 + unsigned short errorOccurredBits; // Offset 21 +} jrk_variables; + + +#define JRK_PARAMETER_INPUT_MODE 1 // 1 byte unsigned value. Valid values are INPUT_MODE_*. Init parameter. +#define JRK_PARAMETER_INPUT_MINIMUM 2 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_INPUT_MAXIMUM 6 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_OUTPUT_MINIMUM 8 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_OUTPUT_NEUTRAL 10 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_OUTPUT_MAXIMUM 12 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_INPUT_INVERT 16 // 1 bit boolean value +#define JRK_PARAMETER_INPUT_SCALING_DEGREE 17 // 1 bit boolean value +#define JRK_PARAMETER_INPUT_POWER_WITH_AUX 18 // 1 bit boolean value +#define JRK_PARAMETER_INPUT_ANALOG_SAMPLES_EXPONENT 20 // 1 byte unsigned value, 0-8 - averages together 4 * 2^x samples +#define JRK_PARAMETER_INPUT_DISCONNECT_MINIMUM 22 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_INPUT_DISCONNECT_MAXIMUM 24 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_INPUT_NEUTRAL_MAXIMUM 26 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_INPUT_NEUTRAL_MINIMUM 28 // 2 byte unsigned value (0-4095) + +#define JRK_PARAMETER_SERIAL_MODE 30 // 1 byte unsigned value. Valid values are SERIAL_MODE_*. MUST be SERIAL_MODE_USB_DUAL_PORT if INPUT_MODE!=INPUT_MODE_SERIAL. Init parameter. +#define JRK_PARAMETER_SERIAL_FIXED_BAUD_RATE 31 // 2-byte unsigned value; 0 means autodetect. Init parameter. +#define JRK_PARAMETER_SERIAL_TIMEOUT 34 // 2-byte unsigned value +#define JRK_PARAMETER_SERIAL_ENABLE_CRC 36 // 1 bit boolean value +#define JRK_PARAMETER_SERIAL_NEVER_SUSPEND 37 // 1 bit boolean value +#define JRK_PARAMETER_SERIAL_DEVICE_NUMBER 38 // 1 byte unsigned value, 0-127 + +#define JRK_PARAMETER_FEEDBACK_MODE 50 // 1 byte unsigned value. Valid values are FEEDBACK_MODE_*. Init parameter. +#define JRK_PARAMETER_FEEDBACK_MINIMUM 51 // 2 byte unsigned value +#define JRK_PARAMETER_FEEDBACK_MAXIMUM 53 // 2 byte unsigned value +#define JRK_PARAMETER_FEEDBACK_INVERT 55 // 1 bit boolean value +#define JRK_PARAMETER_FEEDBACK_POWER_WITH_AUX 57 // 1 bit boolean value +#define JRK_PARAMETER_FEEDBACK_DEAD_ZONE 58 // 1 byte unsigned value +#define JRK_PARAMETER_FEEDBACK_ANALOG_SAMPLES_EXPONENT 59 // 1 byte unsigned value, 0-8 - averages together 4 * 2^x samples +#define JRK_PARAMETER_FEEDBACK_DISCONNECT_MINIMUM 61 // 2 byte unsigned value (0-4095) +#define JRK_PARAMETER_FEEDBACK_DISCONNECT_MAXIMUM 63 // 2 byte unsigned value (0-4095) + +#define JRK_PARAMETER_PROPORTIONAL_MULTIPLIER 70 // 2 byte unsigned value (0-1023) +#define JRK_PARAMETER_PROPORTIONAL_EXPONENT 72 // 1 byte unsigned value (0-15) +#define JRK_PARAMETER_INTEGRAL_MULTIPLIER 73 // 2 byte unsigned value (0-1023) +#define JRK_PARAMETER_INTEGRAL_EXPONENT 75 // 1 byte unsigned value (0-15) +#define JRK_PARAMETER_DERIVATIVE_MULTIPLIER 76 // 2 byte unsigned value (0-1023) +#define JRK_PARAMETER_DERIVATIVE_EXPONENT 78 // 1 byte unsigned value (0-15) +#define JRK_PARAMETER_PID_PERIOD 79 // 2 byte unsigned value +#define JRK_PARAMETER_PID_INTEGRAL_LIMIT 81 // 2 byte unsigned value +#define JRK_PARAMETER_PID_RESET_INTEGRAL 84 // 1 bit boolean value + +#define JRK_PARAMETER_MOTOR_PWM_FREQUENCY 100 // 1 byte unsigned value. Valid values are 0 = 20kHz, 1 = 5kHz. Init parameter. +#define JRK_PARAMETER_MOTOR_INVERT 101 // 1 bit boolean value + +// WARNING: The EEPROM initialization assumes the 5 parameters below are consecutive! +#define JRK_PARAMETER_MOTOR_MAX_DUTY_CYCLE_WHILE_FEEDBACK_OUT_OF_RANGE 102 // 2 byte unsigned value (0-600) +#define JRK_PARAMETER_MOTOR_MAX_ACCELERATION_FORWARD 104 // 2 byte unsigned value (1-600) +#define JRK_PARAMETER_MOTOR_MAX_ACCELERATION_REVERSE 106 // 2 byte unsigned value (1-600) +#define JRK_PARAMETER_MOTOR_MAX_DUTY_CYCLE_FORWARD 108 // 2 byte unsigned value (0-600) +#define JRK_PARAMETER_MOTOR_MAX_DUTY_CYCLE_REVERSE 110 // 2 byte unsigned value (0-600) +// WARNING: The EEPROM initialization assumes the 5 parameters above are consecutive! + +// WARNING: The EEPROM initialization assumes the 2 parameters below are consecutive! +#define JRK_PARAMETER_MOTOR_MAX_CURRENT_FORWARD 112 // 1 byte unsigned value (units of current_calibration_forward) +#define JRK_PARAMETER_MOTOR_MAX_CURRENT_REVERSE 113 // 1 byte unsigned value (units of current_calibration_reverse) +// WARNING: The EEPROM initialization assumes the 2 parameters above are consecutive! + +// WARNING: The EEPROM initialization assumes the 2 parameters below are consecutive! +#define JRK_PARAMETER_MOTOR_CURRENT_CALIBRATION_FORWARD 114 // 1 byte unsigned value (units of mA) +#define JRK_PARAMETER_MOTOR_CURRENT_CALIBRATION_REVERSE 115 // 1 byte unsigned value (units of mA) +// WARNING: The EEPROM initialization assumes the 2 parameters above are consecutive! + +#define JRK_PARAMETER_MOTOR_BRAKE_DURATION_FORWARD 116 // 1 byte unsigned value (units of 5 ms) +#define JRK_PARAMETER_MOTOR_BRAKE_DURATION_REVERSE 117 // 1 byte unsigned value (units of 5 ms) +#define JRK_PARAMETER_MOTOR_COAST_WHEN_OFF 118 // 1 bit boolean value (coast=1, brake=0) + +#define JRK_PARAMETER_ERROR_ENABLE 130 // 2 byte unsigned value. See below for the meanings of the bits. +#define JRK_PARAMETER_ERROR_LATCH 132 // 2 byte unsigned value. See below for the meanings of the bits. + + +#endif // JRK_PROTOCOL_H diff --git a/rig/jrkconfdialog.cpp b/rig/jrkconfdialog.cpp index 1073ec3..70e9ab5 100644 --- a/rig/jrkconfdialog.cpp +++ b/rig/jrkconfdialog.cpp @@ -42,9 +42,9 @@ JrkConfDialog::JrkConfDialog(TRotor *rotor_, bool azimuth_, QWidget *parent) : ui->minDegrees->setMaximum(azimuth ? 360:180); ui->maxDegrees->setMaximum(azimuth ? 360:180); - ui->minFeedback->setValue(azimuth ? jrk->az_min_fk:jrk->el_min_fk); + ui->minFeedback->setValue(jrk->minFeedback(azimuth)); ui->minDegrees->setValue(azimuth ? rotor->az_min:rotor->el_min); - ui->maxFeedback->setValue(azimuth ? jrk->az_max_fk:jrk->el_max_fk); + ui->maxFeedback->setValue(jrk->maxFeedback(azimuth)); ui->maxDegrees->setValue(azimuth ? rotor->az_max:rotor->el_max); } @@ -66,23 +66,18 @@ void JrkConfDialog::on_jrkStatusButton_clicked() void JrkConfDialog::on_buttonBox_accepted() { double *min_deg, *max_deg; - int *min_fk, *max_fk; if(azimuth) { - min_fk = &jrk->az_min_fk; - max_fk = &jrk->az_max_fk; min_deg = &rotor->az_min; max_deg = &rotor->az_max; } else { - min_fk = &jrk->el_min_fk; - max_fk = &jrk->el_max_fk; min_deg = &rotor->el_min; max_deg = &rotor->el_max; } - *min_fk = ui->minFeedback->value(); - *max_fk = ui->maxFeedback->value(); + jrk->minFeedback(azimuth, ui->minFeedback->value()); + jrk->maxFeedback(azimuth, ui->maxFeedback->value()); *min_deg = ui->minDegrees->value(); *max_deg = ui->maxDegrees->value(); } @@ -90,7 +85,7 @@ void JrkConfDialog::on_buttonBox_accepted() //--------------------------------------------------------------------------- void JrkConfDialog::on_readMinFeedbackButton_clicked() { - quint16 data = jrk->readFeedback(azimuth); + quint16 data = jrk->readFeedback(azimuth, 1); if(data == 0xffff) on_jrkStatusButton_clicked(); @@ -101,10 +96,22 @@ void JrkConfDialog::on_readMinFeedbackButton_clicked() //--------------------------------------------------------------------------- void JrkConfDialog::on_readMaxFeedbackButton_clicked() { - quint16 data = jrk->readFeedback(azimuth); + quint16 data = jrk->readFeedback(azimuth, 1); if(data == 0xffff) on_jrkStatusButton_clicked(); else - ui->maxFeedback->setValue((int)jrk->readFeedback(azimuth)); + ui->maxFeedback->setValue((int) data); +} + +//--------------------------------------------------------------------------- +void JrkConfDialog::on_movetoMinBtn_clicked() +{ + jrk->setTarget(azimuth, 0); +} + +//--------------------------------------------------------------------------- +void JrkConfDialog::on_movetoMaxBtn_clicked() +{ + jrk->setTarget(azimuth, 4095); } diff --git a/rig/jrkconfdialog.h b/rig/jrkconfdialog.h index bcddc66..7748c7c 100644 --- a/rig/jrkconfdialog.h +++ b/rig/jrkconfdialog.h @@ -53,6 +53,8 @@ private slots: void on_readMinFeedbackButton_clicked(); void on_buttonBox_accepted(); void on_jrkStatusButton_clicked(); + void on_movetoMinBtn_clicked(); + void on_movetoMaxBtn_clicked(); }; #endif // JRKCONFDIALOG_H diff --git a/rig/jrkconfdialog.ui b/rig/jrkconfdialog.ui index 3dba8cd..2c4c53f 100644 --- a/rig/jrkconfdialog.ui +++ b/rig/jrkconfdialog.ui @@ -13,13 +13,13 @@ Dialog - + 10 10 - 471 - 151 + 485 + 169 @@ -38,31 +38,14 @@ 10 - - - - Min feedback - - - - + 4095 - - - - => - - - Qt::AlignCenter - - - - + 3 @@ -72,28 +55,14 @@ - - - - Degrees - - - - + Read - - - - Max feedback - - - - + 4095 @@ -103,17 +72,7 @@ - - - - => - - - Qt::AlignCenter - - - - + 3 @@ -126,14 +85,14 @@ - + Read - + Qt::Horizontal @@ -143,7 +102,7 @@ - + Qt::Vertical @@ -156,18 +115,45 @@ - + Jrk Status - - + + + + Feedback + + + Qt::AlignCenter + + + + + Degrees + + Qt::AlignCenter + + + + + + + Move to Min + + + + + + + Move to Max + diff --git a/rig/jrkusb.cpp b/rig/jrkusb.cpp new file mode 100644 index 0000000..d7e0948 --- /dev/null +++ b/rig/jrkusb.cpp @@ -0,0 +1,278 @@ +/* + POES-USRP, a software for recording and decoding POES high resolution weather satellite images. + Copyright (C) 2009-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ +//--------------------------------------------------------------------------- +#include +#include +#include +#include + +#include "jrkusb.h" +#include "usbdevice.h" +#include "utils.h" + +//--------------------------------------------------------------------------- +TJrkUSB::TJrkUSB(void) +{ + jrk = NULL; + + current_deg = 0; + min_deg = 0; + max_deg = 360; + min_fb = 0; + max_fb = 4095; + + iobuff = (unsigned char *) malloc(JRK_IO_BUF_SIZE + 1); + memset(&vars, 0, sizeof(jrk_variables_t)); +} + +//--------------------------------------------------------------------------- +TJrkUSB::~TJrkUSB(void) +{ + free(iobuff); +} + +//--------------------------------------------------------------------------- +bool TJrkUSB::setDevice(TUSBDevice *usbdev) +{ + jrk = usbdev; + sn_ = ""; + + if(!isOpen() || !readVariables()) + return false; + + sn_ = jrk->serialnumber(); + +#if 0 + min_fb = jrk->control_read_u16(JRK_REQUEST_GET_TYPE, JRK_REQUEST_GET_PARAMETER, 0, JRK_PARAMETER_FEEDBACK_MINIMUM); + max_fb = jrk->control_read_u16(JRK_REQUEST_GET_TYPE, JRK_REQUEST_GET_PARAMETER, 0, JRK_PARAMETER_FEEDBACK_MAXIMUM); +#endif + + current_deg = feedbackToPos(vars.feedback); + + return true; +} + +//--------------------------------------------------------------------------- +bool TJrkUSB::isOpen(void) +{ + return (jrk && jrk->isOpen()) ? true:false; +} + +//--------------------------------------------------------------------------- +void TJrkUSB::readSettings(QSettings *reg) +{ + if(!isOpen() || sn_.isEmpty()) + return; + + reg->beginGroup(sn_); + + max_fb = reg->value("MaxFeedback", "4095").toInt(); + min_fb = reg->value("MinFeedback", "0").toInt(); + +#if 0 + max_deg = reg->value("MaxDegrees", "360").toDouble(); + min_deg = reg->value("MinDegrees", "0").toDouble(); +#endif + + reg->endGroup(); +} + +//--------------------------------------------------------------------------- +void TJrkUSB::writeSettings(QSettings *reg) +{ + if(!isOpen() || sn_.isEmpty()) + return; + + reg->beginGroup(sn_); + + reg->setValue("MaxFeedback", max_fb); + reg->setValue("MinFeedback", min_fb); + +#if 0 + reg->setValue("MaxDegrees", max_deg); + reg->setValue("MinDegrees", min_deg); +#endif + + reg->endGroup(); +} + +//--------------------------------------------------------------------------- +bool TJrkUSB::readVariables(void) +{ + bool rc = false; + + if(isOpen()) + if(jrk->control_transfer(JRK_REQUEST_GET_TYPE, JRK_REQUEST_GET_VARIABLES, 0, 0, (char *)iobuff, sizeof(jrk_variables_t))) + rc = true; + + if(rc) + vars = *(jrk_variables *) iobuff; + + return rc; +} + +//--------------------------------------------------------------------------- +void TJrkUSB::stop(void) +{ + if(isOpen()) + jrk->control_write(JRK_REQUEST_SET_TYPE, JRK_REQUEST_MOTOR_OFF, 0, 0); +} + +//--------------------------------------------------------------------------- +void TJrkUSB::clearErrors(void) +{ + if(isOpen()) + jrk->control_write(JRK_REQUEST_SET_TYPE, JRK_REQUEST_CLEAR_ERRORS, 0, 0); +} + +//--------------------------------------------------------------------------- +void TJrkUSB::errorStr(QStringList *sl) +{ + sl->clear(); + + if(!readVariables()) { + sl->append("Fatal Error: Unable to read variables"); + return; + } + + unsigned short err = vars.errorFlagBits | vars.errorOccurredBits; + + if(err & 0x0001) + sl->append("Awaiting command"); + if(err & 0x0002) + sl->append("No power"); + if(err & 0x0004) + sl->append("Motor driver error"); + if(err & 0x0008) + sl->append("Input invalid (Pulse Width Input Mode only)"); + if(err & 0x0010) + sl->append("Input disconnect"); + if(err & 0x0020) + sl->append("Feedback disconnect"); + if(err & 0x0040) + sl->append("Maximum current exceeded"); + if(err & 0x0080) + sl->append("Serial signal error"); + if(err & 0x0100) + sl->append("Serial overrun"); + if(err & 0x0200) + sl->append("Serial RX buffer full"); + if(err & 0x0400) + sl->append("Serial CRC error"); + if(err & 0x0800) + sl->append("Serial protocol error"); + if(err & 0x1000) + sl->append("Serial timeout error"); +} + +//--------------------------------------------------------------------------- +void TJrkUSB::moveTo(double deg) +{ + double delta = fabs(currentPos() - deg); + + if(isOpen() && delta >= 0.01) + if(setTarget(posToTarget(deg))) + current_deg = deg; +} + +//--------------------------------------------------------------------------- +// mode & 1 = read variables +double TJrkUSB::readPos(int mode) +{ + if(mode & 1) + readVariables(); + + current_deg = feedbackToPos(vars.feedback); + + return current_deg; +} + +//--------------------------------------------------------------------------- +bool TJrkUSB::setTarget(unsigned short target) +{ + if(isOpen()) + if(jrk->control_write(JRK_REQUEST_SET_TYPE, + JRK_REQUEST_SET_TARGET, + (target & 0x0fff), 0)) + return true; + + return false; +} + +//--------------------------------------------------------------------------- +// mode & 1 = read variables +unsigned short TJrkUSB::target(int mode) +{ + if(mode & 1) + readVariables(); + + return vars.target; +} + +//--------------------------------------------------------------------------- +// mode & 1 = read variables +unsigned short TJrkUSB::feedback(int mode) +{ + if(mode & 1) + readVariables(); + + return vars.feedback; +} + +//--------------------------------------------------------------------------- +double TJrkUSB::feedbackToPos(int feedback) +{ + double d_deg = max_deg - min_deg; + double d_fb = max_fb - min_fb; + double pos = 0; + + if(d_fb > 0 && d_deg > 0 && feedback >= 0 && feedback <= 4095) + pos = min_deg + (d_deg / d_fb) * ((double) (feedback - min_fb)); + + return pos; +} + +//--------------------------------------------------------------------------- +unsigned short TJrkUSB::posToTarget(double deg) +{ + double t, d; + unsigned short u16; + + if(deg < min_deg) + deg = min_deg; + if(deg > max_deg) + deg = max_deg; + + if(deg >= max_deg) + u16 = 4095; + else if(deg <= min_deg) + u16 = 0; + else { + d = max_deg - min_deg; + if(d <= 0) + return 0; + + t = (4095.0 / d) * deg; + u16 = rint(t); + } + + return u16; +} diff --git a/rig/jrkusb.h b/rig/jrkusb.h new file mode 100644 index 0000000..1c03060 --- /dev/null +++ b/rig/jrkusb.h @@ -0,0 +1,88 @@ +/* + POES-USRP, a software for recording and decoding POES high resolution weather satellite images. + Copyright (C) 2009-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ +//--------------------------------------------------------------------------- +#ifndef JRKUSB_H +#define JRKUSB_H + +#include +#include + +#include "jrk_protocol.h" +//--------------------------------------------------------------------------- + +class TUSBDevice; +class QSettings; + +//--------------------------------------------------------------------------- +class TJrkUSB +{ +public: + TJrkUSB(void); + ~TJrkUSB(void); + + bool setDevice(TUSBDevice *usbdev); + bool isOpen(void); + + void readSettings(QSettings *reg); + void writeSettings(QSettings *reg); + + bool setTarget(unsigned short target); + unsigned short target(int mode = 0); + unsigned short feedback(int mode = 0); + + QString serialnumber(void) { return sn_; } + void stop(void); + void clearErrors(void); + void errorStr(QStringList *sl); + + double maxPos(void) { return max_deg; } + void maxPos(double deg) { max_deg = deg; } + double minPos(void) { return min_deg; } + void minPos(double deg) { min_deg = deg; } + + unsigned short maxFeedback(void) { return max_fb; } + unsigned short minFeedback(void) { return min_fb; } + void maxFeedback(unsigned short fb) { max_fb = fb; } + void minFeedback(unsigned short fb) { min_fb = fb; } + + double currentPos(void) { return current_deg; } + double readPos(int mode = 0); + void moveTo(double deg); + bool readVariables(void); + + TUSBDevice *udev(void) { return jrk; } + +protected: + double feedbackToPos(int feedback); + unsigned short posToTarget(double deg); + +private: + TUSBDevice *jrk; + jrk_variables vars; + unsigned char *iobuff; + QString sn_; + double current_deg, max_deg, min_deg; + unsigned short min_fb, max_fb; + + +}; + +#endif // JRKUSB_H diff --git a/rig/rigdialog.cpp b/rig/rigdialog.cpp index caa91f7..3b6d5ff 100644 --- a/rig/rigdialog.cpp +++ b/rig/rigdialog.cpp @@ -124,10 +124,19 @@ RigDialog::RigDialog(QWidget *parent) : m_ui->spidPorted->setText(rig->rotor->spid->deviceId); // Pololu Jrk settings + QStringList sl = rig->rotor->jrk->deviceNames(); + m_ui->jrkAzCb->addItems(sl); + m_ui->jrkAzCb->setCurrentIndex(rig->rotor->jrk->deviceIndex(true) + 1); + m_ui->jrkElCb->addItems(sl); + m_ui->jrkElCb->setCurrentIndex(rig->rotor->jrk->deviceIndex(false) + 1); + + +#if 0 m_ui->jrkAzPortEd->setText(rig->rotor->jrk->az_deviceId); m_ui->jrkAzIdEd->setValue(rig->rotor->jrk->az_id); m_ui->jrkElPortEd->setText(rig->rotor->jrk->el_deviceId); m_ui->jrkElIdEd->setValue(rig->rotor->jrk->el_id); +#endif #if 0 // Oak USB @@ -396,6 +405,7 @@ void RigDialog::on_rotorZeroPosBtn_clicked() dlg->setlimits(rig->rotor->az_min, rig->rotor->az_max, true); dlg->setlimits(rig->rotor->el_min, rig->rotor->el_max, false); + dlg->setAzEl(rig->rotor->getAzimuth(), rig->rotor->getElevation()); if(dlg->exec()) { flags |= (256 | 2); @@ -539,10 +549,8 @@ void RigDialog::applyRotorSettings(void) rig->rotor->stepper->rotor_el_ratio = m_ui->elRatiospinBox->value(); // jrk settings - rig->rotor->jrk->az_deviceId = m_ui->jrkAzPortEd->text(); - rig->rotor->jrk->az_id = m_ui->jrkAzIdEd->value(); - rig->rotor->jrk->el_deviceId = m_ui->jrkElPortEd->text(); - rig->rotor->jrk->el_id = m_ui->jrkElIdEd->value(); + rig->rotor->jrk->setDevices(m_ui->jrkAzCb->currentIndex() - 1, + m_ui->jrkElCb->currentIndex() - 1); if(rig->rotor->rotor_type == RotorType_Stepper) { m_ui->az_spinBox->setSingleStep((360.0 / (double) rig->rotor->stepper->rotor_spr_az) / ((double) rig->rotor->stepper->rotor_az_ratio)); @@ -698,16 +706,9 @@ void RigDialog::on_calibrateJrkElButton_clicked() //--------------------------------------------------------------------------- void RigDialog::calibrateJrk(bool azimuth) { - int id; - rig->rotor->closePort(); applyRotorSettings(); - id = azimuth ? rig->rotor->jrk->az_id:rig->rotor->jrk->el_id; - - if(id < 0) - return; - if(!rig->rotor->openPort()) { QMessageBox::critical(this, "Error: Communication failure!", rig->rotor->getErrorString()); return; diff --git a/rig/rigdialog.ui b/rig/rigdialog.ui index 8c8e17b..64eef89 100644 --- a/rig/rigdialog.ui +++ b/rig/rigdialog.ui @@ -532,7 +532,7 @@ - 0 + 1 @@ -548,7 +548,7 @@ - 0 + 1 @@ -807,7 +807,7 @@ Miscellaneous - + 10 @@ -837,7 +837,7 @@ true - Wobble antenna + Conical scan @@ -898,7 +898,7 @@ true - Wobble + Test @@ -1031,6 +1031,77 @@ + + + Jrk Motor Control + + + + + 12 + 10 + 411 + 189 + + + + + + + Azimuth + + + + + + + Elevation + + + + + + + true + + + Calibrate... + + + + + + + true + + + Calibrate... + + + + + + + Clear errors + + + + + + + Status + + + + + + + + + + + + Monstrum X-Y @@ -1113,124 +1184,6 @@ - - - Jrk Motor Control - - - - - 12 - 10 - 411 - 189 - - - - - - - Azimuth port: - - - - - - - - - - Id: - - - - - - - -1 - - - 255 - - - 11 - - - - - - - Elevation port: - - - - - - - - - - Id: - - - - - - - -1 - - - 255 - - - 12 - - - - - - - Enter Id = -1 to disable a motor - - - - - - - false - - - Calibrate... - - - - - - - false - - - Calibrate... - - - - - - - Clear errors - - - - - - - Status - - - - - - Stepper diff --git a/rig/rotor.cpp b/rig/rotor.cpp index 0d9f127..792ac77 100644 --- a/rig/rotor.cpp +++ b/rig/rotor.cpp @@ -30,8 +30,6 @@ #define SER_IO_BUFF_SIZE 128 -static const double RTD = 180.0 / M_PI; -static const double DTR = M_PI / 180.0; //--------------------------------------------------------------------------- TRotor::TRotor(TRig *_rig) @@ -202,7 +200,7 @@ bool TRotor::openPort(void) case RotorType_Stepper: return stepper->openLPT(); case RotorType_GS232B: return gs232b->openCOM(); case RotorType_SPID: return spid->openCOM(); - case RotorType_JRK: return jrk->openCOM(); + case RotorType_JRK: return jrk->open(); case RotorType_Monstrum: return monster->openCOM(); default: @@ -216,7 +214,7 @@ void TRotor::closePort(void) stepper->closeLPT(); gs232b->closeCOM(); spid->closeCOM(); - jrk->closeCOM(); + jrk->close(); monster->closeCOM(); } @@ -228,7 +226,7 @@ bool TRotor::isPortOpen(void) case RotorType_Stepper: return stepper->isLPTOpen(); case RotorType_GS232B: return gs232b->isCOMOpen(); case RotorType_SPID: return spid->isCOMOpen(); - case RotorType_JRK: return jrk->isCOMOpen(); + case RotorType_JRK: return jrk->isOpen(); case RotorType_Monstrum: return monster->isCOMOpen(); default: @@ -355,7 +353,7 @@ double TRotor::getAzimuth(void) case RotorType_Stepper: return stepper->current_az; case RotorType_GS232B: return gs232b->current_az; case RotorType_SPID: return spid->current_az; - case RotorType_JRK: return jrk->current_az; + case RotorType_JRK: return jrk->current_az(1); case RotorType_Monstrum: return monster->current_x; default: @@ -371,7 +369,7 @@ double TRotor::getElevation(void) case RotorType_Stepper: return stepper->current_el; case RotorType_GS232B: return gs232b->current_el; case RotorType_SPID: return spid->current_el; - case RotorType_JRK: return jrk->current_el; + case RotorType_JRK: return jrk->current_el(1); case RotorType_Monstrum: return monster->current_y; default: @@ -382,8 +380,13 @@ double TRotor::getElevation(void) //--------------------------------------------------------------------------- void TRotor::setAzimuth(double az) { - if(rotor_type == RotorType_Stepper) - stepper->current_az = az; + switch(rotor_type) + { + case RotorType_Stepper: stepper->current_az = az; break; + case RotorType_JRK: jrk->adjustToAz(az); break; + + default: {} + } } //--------------------------------------------------------------------------- @@ -471,7 +474,7 @@ void TRotor::XYtoAzEl(double X, double Y, double *az, double *el) double tanX, tanX2, sinY2, sinY, A, B; tanX = tan(X * DTR); - tanX2 = tanX * tanX; //tanX2 = tanX^2 or tanX * tanX + tanX2 = tanX * tanX; sinY = sin(Y * DTR); sinY2 = sinY * sinY; diff --git a/rig/rotor.h b/rig/rotor.h index 5494c14..bfbc774 100644 --- a/rig/rotor.h +++ b/rig/rotor.h @@ -30,7 +30,7 @@ #define R_ROTOR_ENABLE 16 // rotor is enabled #define R_ROTOR_CCW 32 // direction is counter clock wise #define R_ROTOR_PARK 64 // parking is enabled -#define R_ROTOR_WOBBLE 128 // wobble antenna in circles +#define R_ROTOR_WOBBLE 128 // conical scan //--------------------------------------------------------------------------- @@ -53,14 +53,14 @@ typedef enum TRotorType_t RotorType_GS232B, RotorType_SPID, RotorType_JRK, - RotorType_Monstrum, + RotorType_Monstrum } TRotorType_t; //--------------------------------------------------------------------------- typedef enum TCommType_t { Comm_Default, - Comm_Network, + Comm_Network } TCommType; //--------------------------------------------------------------------------- diff --git a/rig/usb/tusb.cpp b/rig/usb/tusb.cpp new file mode 100644 index 0000000..4e42c17 --- /dev/null +++ b/rig/usb/tusb.cpp @@ -0,0 +1,194 @@ +/* + POES-Weather Ltd Sensor Benchmark, a software for testing different sensors used to align antennas. + Copyright (C) 2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ +//--------------------------------------------------------------------------- + +#include +#include "tusb.h" +#include "usbdevice.h" + +//--------------------------------------------------------------------------- +TUSB::TUSB(void) +{ + + +} + +//--------------------------------------------------------------------------- +TUSB::~TUSB(void) +{ + clearlist(); +} + +//--------------------------------------------------------------------------- +void TUSB::clearlist(void) +{ + vector::iterator i = usblist.begin(); + + for(; i < usblist.end(); i++) + delete *i; + + usblist.clear(); +} + +//--------------------------------------------------------------------------- +int TUSB::count_devices(void) +{ + return usblist.size(); +} + +//--------------------------------------------------------------------------- +int TUSB::list_devices(u_int16_t vendor) +{ + struct usb_bus *bus; + struct usb_device *dev; + + qDebug ("Scanning for devices with VendorId = 0x%04x...", vendor); + + clearlist(); + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + for(bus = usb_get_busses(); bus; bus = bus->next) { + for(dev = bus->devices; dev; dev = dev->next) { + if(dev->descriptor.idVendor == vendor) + { + qDebug ("Device found!"); + usblist.push_back(new TUSBDevice(dev)); + } + } + } + + return usblist.size(); +} + +//--------------------------------------------------------------------------- +// must be called before open. bConfigurationValue in usb_config_descriptor +void TUSB::conf_devices(int conf) +{ + vector::iterator i; + TUSBDevice *d; + + for(i=usblist.begin(); iconfiguration(conf); + } +} + +//--------------------------------------------------------------------------- +void TUSB::open_devices(void) +{ + vector::iterator i; + TUSBDevice *d; + + for(i=usblist.begin(); iopen(); + } +} + +//--------------------------------------------------------------------------- +// index is zero based +TUSBDevice *TUSB::get_device(int index) +{ + TUSBDevice *d = NULL; + + if(index >= 0 && index < (signed) usblist.size()) + d = (TUSBDevice *) usblist.at((unsigned) index); + + return d; +} + +//--------------------------------------------------------------------------- +TUSBDevice *TUSB::get_device_by_sn(QString serialnr) +{ + if(serialnr.isEmpty()) + return NULL; + + vector::iterator i; + TUSBDevice *d; + QString sn; + + for(i=usblist.begin(); iserialnumber(); + if(sn == serialnr) + return d; + } + + return NULL; +} + +//--------------------------------------------------------------------------- +int TUSB::device_index(TUSBDevice *dev) +{ + vector::iterator i; + TUSBDevice *d; + int index = 0; + + for(i=usblist.begin(); i::iterator i; + TUSBDevice *d; + QStringList sl; + QString prod, sn, str; + + if(!firstItem.isEmpty()) + sl.append(firstItem); + + for(i=usblist.begin(); iproduct(); + sn = d->serialnumber(); + + if(!prod.isEmpty()) + str = prod; + + if(!sn.isEmpty()) { + if(!str.isEmpty()) + str += " SN "; + + str += sn; + } + + if(str.isEmpty()) + str = d->shortname(); + + sl.append(str); + } + + return sl; +} + +//--------------------------------------------------------------------------- diff --git a/rig/usb/tusb.h b/rig/usb/tusb.h new file mode 100644 index 0000000..418c02c --- /dev/null +++ b/rig/usb/tusb.h @@ -0,0 +1,59 @@ +/* + POES-Weather Ltd Sensor Benchmark, a software for testing different sensors used to align antennas. + Copyright (C) 2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ +//--------------------------------------------------------------------------- +#ifndef USB_H +#define USB_H + +#include +#include + +class QStringList; +class TUSBDevice; + +using namespace std; + +//--------------------------------------------------------------------------- +class TUSB +{ +public: + TUSB(void); + ~TUSB(void); + + int count_devices(void); + int list_devices(u_int16_t vendor); + void open_devices(void); + void conf_devices(int conf); + int device_index(TUSBDevice *dev); + + TUSBDevice *get_device(int index); + TUSBDevice *get_device_by_sn(QString serialnr); + + QStringList device_names(QString firstItem = ""); + +protected: + void clearlist(void); + +private: + vector usblist; + +}; + +#endif // USB_H diff --git a/rig/usb/usbdevice.cpp b/rig/usb/usbdevice.cpp new file mode 100644 index 0000000..d357236 --- /dev/null +++ b/rig/usb/usbdevice.cpp @@ -0,0 +1,236 @@ +/* + POES-USRP, a software for recording and decoding POES high resolution weather satellite images. + Copyright (C) 2009-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ +//--------------------------------------------------------------------------- +#include + +#include "usbdevice.h" + +static const int USB_DEFAULT_INTERFACE = 0; +static const int USB_DEFAULT_CONFIGURATION = 1; +static const int USB_DEFAULT_TIMEOUT_MS = 5000; + +//--------------------------------------------------------------------------- +TUSBDevice::TUSBDevice() +{ + zero(); +} + +//--------------------------------------------------------------------------- +TUSBDevice::TUSBDevice(struct usb_device *usbdev) +{ + zero(); + + dev = usbdev; + //open(); +} + +//--------------------------------------------------------------------------- +TUSBDevice::~TUSBDevice(void) +{ + close(); +} + +//--------------------------------------------------------------------------- +void TUSBDevice::zero(void) +{ + dev = NULL; + handle = NULL; + isopen_ = false; + + // use lsusb -vd vendor:[product] to find out... + interface_ = USB_DEFAULT_INTERFACE; + configuration_ = USB_DEFAULT_CONFIGURATION; + timeoutms_ = USB_DEFAULT_TIMEOUT_MS; +} + +//--------------------------------------------------------------------------- +bool TUSBDevice::open(void) +{ + if(isopen_) + return true; + + if(dev == NULL) + return false; + + usb_init(); + handle = usb_open(dev); + + if(handle == NULL) { + qDebug("Error: %s [%s:%d]", usb_strerror(), __FILE__, __LINE__); + return false; + } + + if(usb_detach_kernel_driver_np(handle, interface()) < 0) + qDebug("Info: %s [%s:%d]", usb_strerror(), __FILE__, __LINE__); + + if(configuration() >= 0) + if(usb_set_configuration(handle, configuration()) < 0) { + qDebug("Error: %s [%s:%d]", usb_strerror(), __FILE__, __LINE__); + + close(); + return false; + } + + if(usb_claim_interface(handle, interface()) < 0) { + qDebug("Error: %s [%s:%d]", usb_strerror(), __FILE__, __LINE__); + + close(); + return false; + } + + isopen_ = true; + + return isopen_; +} + +//--------------------------------------------------------------------------- +void TUSBDevice::close(void) +{ + if(isopen_) + usb_release_interface(handle, interface()); + + if(handle) + usb_close(handle); + + handle = NULL; + isopen_ = false; +} + +//--------------------------------------------------------------------------- +bool TUSBDevice::control_transfer(int requesttype, int request, int value, int index, char *bytes, int size) +{ + if(!handle) { + qDebug("Error: No handle [%s:%d]", __FILE__, __LINE__); + return false; + } + + if(usb_control_msg(handle, requesttype, request, value, index, bytes, size, timeoutms()) < 0) { + qDebug("Error: %s [%s:%d]", usb_strerror(), __FILE__, __LINE__); + + return false; + } + + return true; +} + +//--------------------------------------------------------------------------- +bool TUSBDevice::control_write(int requesttype, int request, int value, int index) +{ + return control_transfer(requesttype, request, value, index, NULL, 0); +} + +//--------------------------------------------------------------------------- +unsigned char TUSBDevice::control_read_u8(int requesttype, int request, int value, int index) +{ + unsigned char byte; + unsigned char rc = 0x00; + + if(control_transfer(requesttype, request, value, index, (char *) &byte, 1)) + rc = byte; + + qDebug("control_read_u8: 0x%02x [%s:%d]", rc, __FILE__, __LINE__); + + return rc; +} + +//--------------------------------------------------------------------------- +unsigned short TUSBDevice::control_read_u16(int requesttype, int request, int value, int index) +{ + unsigned char bytes[2]; + unsigned short rc = 0x0000; + + if(control_transfer(requesttype, request, value, index, (char *)bytes, 2)) + rc = (bytes[1] << 8) | bytes[0]; + + qDebug("control_read_u16: 0x%04x [%s:%d]", rc, __FILE__, __LINE__); + + return rc; +} + +//--------------------------------------------------------------------------- +QString TUSBDevice::manufacturer(void) +{ + if(!handle) + return ""; + + if(dev->descriptor.iManufacturer == 0) + return ""; + + char buf[256]; + if(usb_get_string_simple(handle, dev->descriptor.iManufacturer, buf, sizeof(buf)) < 0) { + qDebug("Error: %s [%s:%d]", usb_strerror(), __FILE__, __LINE__); + return ""; + } + else + return buf; +} + +//--------------------------------------------------------------------------- +QString TUSBDevice::product(void) +{ + if(!handle) + return ""; + + if(dev->descriptor.iProduct == 0) + return ""; + + char buf[256]; + if(usb_get_string_simple(handle, dev->descriptor.iProduct, buf, sizeof(buf)) < 0) { + qDebug("Error: %s [%s:%d]", usb_strerror(), __FILE__, __LINE__); + return ""; + } + else + return buf; +} + +//--------------------------------------------------------------------------- +QString TUSBDevice::serialnumber(void) +{ + if(!handle) + return ""; + + if(dev->descriptor.iSerialNumber == 0) + return ""; + + char buf[32]; + if(usb_get_string_simple(handle, dev->descriptor.iSerialNumber, buf, sizeof(buf)) < 0) { + qDebug("Error: %s [%s:%d]", usb_strerror(), __FILE__, __LINE__); + return ""; + } + else + return buf; +} + +//--------------------------------------------------------------------------- +QString TUSBDevice::shortname(void) +{ + if(!handle) + return ""; + + QString str; + + str.sprintf("%04X:%04X", dev->descriptor.idVendor, dev->descriptor.idProduct); + + return str; +} + +//--------------------------------------------------------------------------- + diff --git a/rig/usb/usbdevice.h b/rig/usb/usbdevice.h new file mode 100644 index 0000000..a264802 --- /dev/null +++ b/rig/usb/usbdevice.h @@ -0,0 +1,70 @@ +/* + POES-Weather Ltd Sensor Benchmark, a software for testing different sensors used to align antennas. + Copyright (C) 2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Email: + Web: +*/ +//--------------------------------------------------------------------------- +#ifndef USBDEVICE_H +#define USBDEVICE_H + +#include +#include + +class TUSBDevice +{ +public: + TUSBDevice(void); + TUSBDevice(struct usb_device *usbdev); + ~TUSBDevice(void); + + void configuration(int conf) { configuration_ = conf; } + int configuration(void) { return configuration_; } + void interface(int i) { interface_ = i; } + int interface(void) { return interface_; } + void timeoutms(int ms) { timeoutms_ = ms; } + int timeoutms(void) { return timeoutms_; } + + bool open(void); + bool isOpen(void) { return isopen_; } + void close(void); + + bool control_transfer(int requesttype, int request, int value, int index, char *bytes, int size); + bool control_write(int requesttype, int request, int value, int index); + + unsigned char control_read_u8(int requesttype, int request, int value, int index); + unsigned short control_read_u16(int requesttype, int request, int value, int index); + + + QString manufacturer(void); + QString product(void); + QString serialnumber(void); + QString shortname(void); + + + +protected: + void zero(void); + +private: + struct usb_device *dev; + usb_dev_handle *handle; + int configuration_, interface_, timeoutms_; + bool isopen_; +}; + +#endif // USBDEVICE_H diff --git a/utils/azeldialog.cpp b/utils/azeldialog.cpp index f8e0148..67f3cc0 100644 --- a/utils/azeldialog.cpp +++ b/utils/azeldialog.cpp @@ -38,6 +38,13 @@ AzElDialog::~AzElDialog() delete ui; } +//--------------------------------------------------------------------------- +void AzElDialog::setAzEl(double Az, double El) +{ + ui->azSB->setValue(Az); + ui->elSB->setValue(El); +} + //--------------------------------------------------------------------------- void AzElDialog::on_AzElDialog_accepted() { diff --git a/utils/azeldialog.h b/utils/azeldialog.h index 5d084ab..db9ecf0 100644 --- a/utils/azeldialog.h +++ b/utils/azeldialog.h @@ -41,6 +41,7 @@ class AzElDialog : public QDialog double azimuth(void); void azimuth(double az); void setlimits(double min_value, double max_value, bool az); + void setAzEl(double Az, double El); double elevation(void); void elevation(double el); diff --git a/utils/azeldialog.ui b/utils/azeldialog.ui index 862f97c..7f191cd 100644 --- a/utils/azeldialog.ui +++ b/utils/azeldialog.ui @@ -11,15 +11,15 @@ - Apply Rotor Position + Rotor is now pointing at - + 21 40 341 - 91 + 113 diff --git a/utils/utils.h b/utils/utils.h index 26d87d9..0c92f11 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -47,6 +47,10 @@ class QListWidgetItem; # define MIN(a, b) (a < b ? a:b) #endif +static const double RTD = 180.0 / M_PI; +static const double DTR = M_PI / 180.0; + + double GetStartTime(QDateTime utc, int mode=0); char *ReplaceChar(const char *buff, char *ret, const char tofind, const char newchar); bool SameDate(QDateTime dt1, QDateTime dt2);