2023-03-06 11:33:04 +03:00

839 lines
21 KiB
C++

/*
* libapogee.cpp - libapogee C wrapper
*
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include "libapogee.h"
#include <Alta.h>
#include <AltaF.h>
#include <Ascent.h>
#include <Aspen.h>
#include <Quad.h>
#include <CameraInfo.h>
#include <FindDeviceUsb.h>
#include <FindDeviceEthernet.h>
#include <ApogeeFilterWheel.h>
#include <ApogeeCam.h>
/*
#if defined APOGEE_ASCENT
#define CCD Ascent
#elif defined APOGEE_ALTA
#define CCD Alta
#elif defined APOGEE_ALTAF
#define CCD AltaF
#elif defined APOGEE_ASPEN
#define CCD Aspen
#elif defined APOGEE_QUAD
#define CCD Quad
#else
#error "You must define camera type: APOGEE_ASCENT, APOGEE_ALTA, \
APOGEE_ALTAF, APOGEE_ASPEN or APOGEE_QUAD"
#endif
*/
// static class for CCD device
//static CCD *alta = NULL;
static ApogeeCam *alta = NULL;
static bool isethernet = false;
int ApnGlueIsEthernet(){
if(isethernet) return 1;
else return 0;
}
static std::string cam_msg_id = "";
void ApnGlueSetMsgId(char *str){
cam_msg_id = str;
}
// static variable with last error
CCDerr altaerr = ALTA_OK;
typedef struct{
std::string address;
uint16_t FirmwareRev;
uint16_t Id;
std::string deviceType;
std::string model;
} CamParams;
// last camera parameters
static CamParams par;
#define TRY altaerr=ALTA_OK; try
#ifdef EBUG
#define SHOWEX() do{std::cout << "ERROR! " << err.what() << std::endl;}while(0)
#define DBG(msg) do{std::cout << msg << std::endl;}while(0)
#else
#define SHOWEX()
#define DBG(msg)
#endif
#define CATCH(ERR) catch(std::exception & err){altaerr=ERR;SHOWEX();}catch(...){altaerr=ALTA_UNDEF;}
#define RETERR(ERR) do{altaerr=ERR; return altaerr;}while(0)
static void checkalta(){
if(!alta){
fprintf(stderr, "Bug! Alta used before open\n");
exit(1);
}
}
// Functions for getting camera parameters from discovery string
// first two functions are from apogee's library
std::vector<std::string> MakeTokens(const std::string &str, const std::string &separator){
std::vector<std::string> returnVector;
std::string::size_type start = 0;
std::string::size_type end = 0;
while((end = str.find(separator, start)) != std::string::npos){
returnVector.push_back (str.substr(start, end-start));
start = end + separator.size();
}
returnVector.push_back( str.substr(start) );
return returnVector;
}
std::string GetItemFromFindStr( const std::string & msg, const std::string & item ){
std::vector<std::string> params = MakeTokens(msg, "," );
std::vector<std::string>::iterator iter;
for(iter = params.begin(); iter != params.end(); ++iter){
if( std::string::npos != (*iter).find( item )){
std::string result = MakeTokens((*iter), "=" ).at(1);
return result;
}
}
// fprintf(stderr, "Bug! Can't find parameter in description string!\n");
// exit(1);
std::string noOp;
return noOp;
}
uint16_t readUI(const std::string & msg, const std::string & key){
std::string str = GetItemFromFindStr(msg, key);
unsigned int x;
if(sscanf(str.c_str(), "%x", &x) < 1){
fprintf(stderr, "Bug! Can't convert parameter from hex!\n");
exit(1);
}
return (uint16_t) x;
}
CamParams *getCamParams(std::string & msg){
std::string port = GetItemFromFindStr(msg, "port=");
par.address = GetItemFromFindStr(msg, "address=");
if(port.size()){ // there's an network device
par.address.append(":");
par.address.append(port);
}
par.FirmwareRev = readUI(msg, "firmwareRev=");
par.Id = readUI(msg, "id=");
par.deviceType = GetItemFromFindStr(msg, "deviceType=");
par.model = GetItemFromFindStr(msg, "model=");
return &par;
}
/*
static bool IsProperDevice(const std::string & msg){
std::string model = GetItemFromFindStr(msg, "model=");
std::string
#if defined APOGEE_ASCENT
cam("Ascent");
#elif defined APOGEE_ALTA
cam("Alta");
#elif defined APOGEE_ALTAF
cam("AltaF");
#elif defined APOGEE_ASPEN
cam("Aspen");
#elif defined APOGEE_QUAD
cam("Quad");
#else
return false;
#endif
return(0 == model.compare(0, cam.size(), cam) ? true : false );
}*/
static bool assignAlta(const std::string & msg){
std::string model = GetItemFromFindStr(msg, "model=");
if(model.compare(0,6,"Ascent")==0) alta = (Ascent*) new Ascent();
else if(model.compare(0,5,"AltaF")==0) alta = (AltaF*) new AltaF();
else if(model.compare(0,4,"Alta")==0) alta = (Alta*) new Alta();
else if(model.compare(0,5,"Aspen")==0) alta = (Aspen*) new Aspen();
else if(model.compare(0,4,"Quad")==0) alta = (Quad*) new Quad();
else return false;
return true;
}
/**
* return camera info
* Don't forget to call FREE!!!
* @param pid, vid - device PID and VID
*/
char *ApnGlueGetInfo(int *pid, int *vid){
if(!alta || isethernet) return NULL;
if(pid || vid){
uint16_t v = 1, p = 2, d = 3;
alta->GetUsbVendorInfo(v, p, d);
if(pid) *pid = p;
if(vid) *vid = v;
}
std::string str = alta->GetInfo();
char *writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0';
return writable;
}
std::string subnet = "";
/**
* Set subnet name to use network camera
*/
void ApnGlueSetSubnet(char *val){
subnet = std::string(val);
}
/**
* try to find USB device
* return pointer to CamParams of found device or NULL
*/
static CamParams *findUSB(){
FindDeviceUsb look4cam;
std::string msg = look4cam.Find();
// if(!IsProperDevice(msg)) // device not found
// return NULL;
std::cout << "Camera MSG_ID=" << msg << std::endl;
if(!assignAlta(msg)){
std::cerr << "Unknown camera!" << std::endl;
return NULL;
}
isethernet = false;
return getCamParams(msg);
}
/**
* try to find ethernet device
* return pointer to CamParams of found device or NULL
*/
static CamParams *findNET(){
if(subnet.size() == 0) return NULL; // subnet wasn't defined
FindDeviceEthernet look4cam;
DBG(subnet);
//clearenv(); // clear all proxy & other data
setenv("http_proxy", "", 1);
setenv("HTTP_PROXY", "", 1);
std::string msg = look4cam.Find(subnet);
// if(!IsProperDevice(msg)) // device not found
// return NULL;
std::cout << "Camera MSG_ID=" << msg << std::endl;
if(!assignAlta(msg)){
std::cerr << "Unknown camera!" << std::endl;
return NULL;
}
isethernet = true;
return getCamParams(msg);
}
/**
* Open camera device and assign it to variable <alta>
* IT DON'T WORK WITH MULTIPLE CAMERAS SIMULTANEOUSLY!
* @param id - camera identificator (number)
* @return 0 in case of success
*/
int ApnGlueOpen(_U_ unsigned int id){
bool found = false;
CamParams *campar = NULL;
std::string ioInterface;
TRY{
if(cam_msg_id.size()){ // user had set MSG param, try it
DBG("Try to find camera by given id");
//if(IsProperDevice(cam_msg_id) && (campar = getCamParams(cam_msg_id))){
if(assignAlta(cam_msg_id) && (campar = getCamParams(cam_msg_id))){
found = true;
if(GetItemFromFindStr(cam_msg_id, "interface=") == "ethernet"){
clearenv(); // clear all proxy & other data
isethernet = true;
}else
isethernet = false;
}else std::cerr << "Can't find camera with given ID" << std::endl;
}
if(!found && subnet.size()){ // there's an ability of network camera presence
DBG("Try to find network camera");
if((campar = findNET())){
found = true;
}else std::cerr << "Network camera not found, try USB" << std::endl;
}
if(!found){
DBG("Try to find USB camera");
if(!(campar = findUSB()))
RETERR(ALTA_NO_SUCH_DEVICE);
}
if(isethernet)
ioInterface = "ethernet";
else
ioInterface = "usb";
//alta = (CCD*) new CCD();
alta->OpenConnection(ioInterface, campar->address, campar->FirmwareRev, campar->Id);
alta->Init();
}CATCH(ALTA_NO_SUCH_DEVICE);
return(altaerr);
}
/**
* Close connection and destroy camera object
*/
void ApnGlueClose(){
if(!alta) return;
TRY{
alta->CloseConnection();
delete alta;
}CATCH(ALTA_CANT_CLOSE);
}
/**
* Camera sensor and model
* @param sensor, model (o) - dinamically allocated strings or NULL
*/
void ApnGlueGetName(char **sensor, char **camera){
checkalta();
TRY{
if(camera) *camera = (char *)alta->GetModel().c_str();
if(sensor) *sensor = (char *)alta->GetSensor().c_str();
}CATCH(ALTA_UNDEF);
}
/**
* Set fan speed
* @param speed: 0 - turn fan off; 1 - slowest, 3 - fastest
*/
void ApnGlueSetFan(int speed){
checkalta();
TRY{
Apg::FanMode mode = (Apg::FanMode)(speed % 4);
alta->SetFanMode(mode);
}CATCH(ALTA_BAD_FANSPD);
}
/**
* Get fan speed
* @return fan speed
*/
int ApnGlueGetFan(){
int mode = -1;
checkalta();
TRY{
mode = alta->GetFanMode();
}CATCH(ALTA_BAD_FANSPD);
return mode;
}
/**
* Set parameters for subsequent exposures.
* In case of error return -1 or altaerr with explanation in whynot[], else 0.
* Also return final image size in net binned pixels, allowing for overscan,
* binning etc.
* @param roiw, roih - image width & height in unbinned pixels
* @param osw, osh - (USED only their sign) width & height of saved overscan part (should be less than max OS)
* @param binw, binh - binning by X and Y
* @param roix, roiy - coordinate of image angle on CCD
* @param impixw, impixh (o) - size of output image (binned) or NULL
* @param whynot[] - error explanation or NULL
* @return In case of error return -1 or altaerr with explanation in whynot[], else 0.
*/
int ApnGlueSetExpGeom(int roiw, int roih, int osw, int osh, int binw,
int binh, int roix, int roiy, int *impixw, int *impixh, char whynot[]){
uint16_t maxw, maxh, maxtotw;
//uint16_t maxtoth;
checkalta();
TRY{
maxw = alta->GetMaxImgCols();
maxh = alta->GetMaxImgRows();
maxtotw = alta->GetTotalRows();
//maxtoth = alta->GetTotalCols();
if(binw < 1) binw = 1;
if(binh < 1) binh = 1;
if(roiw < 1 || roiw > (int)maxw) roiw = maxw;
if(roih < 1 || roih > (int)maxh) roih = maxh;
if(osw > 0 || osh > 0){
int maxosw = alta->GetNumOverscanCols();
//int maxosh = ApogeeCam::m_CamCfgData->m_MetaData.OverscanRows;
if (osw > maxosw){
if(whynot) sprintf (whynot, "Max overscan columns is %d", maxosw);
RETERR(ALTA_BAD_GEOMETRY);
}
/*if (osh > maxosh) {
sprintf (whynot, "Max overscan rows is %d", maxosh);
return (-1);
}*/
if (roix > 0 || roiw < maxw || roiy > 0 || roih < maxh) {
if(whynot) sprintf (whynot, "Can not overscan with windowing");
RETERR(ALTA_BAD_GEOMETRY);
}
roiw += osw;
//roih += osh;
if(roiw > (int)maxtotw) roiw = maxtotw;
//if(roih > (int)maxtoth) roih = maxtoth;
roiw = maxtotw;
//roih = maxtoth;
alta->SetDigitizeOverscan(true);
}else alta->SetDigitizeOverscan(false);
alta->SetRoiBinCol(binw);
alta->SetRoiBinRow(binh);
if(roix > 0 || roiy > 0){
if((roix + roiw > maxw) || (roiy + roih > maxh)){
if(whynot) sprintf (whynot, "Windowed image too large");
RETERR(ALTA_BAD_GEOMETRY);
}
alta->SetRoiStartCol(roix);
alta->SetRoiStartRow(roiy);
}else{
alta->SetRoiStartCol(0);
alta->SetRoiStartRow(0);
}
alta->SetRoiNumCols(roiw / binw);
alta->SetRoiNumRows(roih / binh);
if(impixw) *impixw = roiw / binw;
if(impixh) *impixh = roih / binh;
}CATCH(ALTA_BAD_GEOMETRY);
return altaerr;
}
/**
* Get pixel size
* @param pixX, pixY (o) - pixel size in mkm or NULL
*/
void ApnGlueGetGeom(double *pixX, double *pixY){
checkalta();
TRY{
if(pixX) *pixX = alta->GetPixelWidth();
if(pixY) *pixY = alta->GetPixelHeight();
}CATCH(ALTA_UNDEF);
}
/**
* Get extremal values
* @param exptime - exposition time (array: [min, max]) or NULL
* @param roiw, roih - ROI image size or NULL
* @param osw, osh - overscan size (used only osw) or NULL
* @param binw, binh - binning size or NULL
* @param shutter - shutter presence or NULL
* @param mintemp - minimal temperature or NULL
*/
void ApnGlueGetMaxValues(double *exptime, int *roiw, int *roih, int *osw,
_U_ int *osh, int *binw, int *binh, int *shutter, double *mintemp){
checkalta();
TRY{
if(exptime){
exptime[0] = alta->GetMinExposureTime();
exptime[1] = alta->GetMaxExposureTime();
}
if(roiw) *roiw = alta->GetMaxImgCols();
if(roih) *roih = alta->GetMaxImgRows();
if(osw) *osw = alta->GetNumOverscanCols();
if(binw) *binw = alta->GetMaxBinCols();
if(binh) *binh = alta->GetMaxBinRows();
if(shutter) *shutter = 1; // !!!TODO!!!
if(mintemp) *mintemp = -30.; // !!!TODO!!!
}CATCH(ALTA_UNDEF);
}
/**
* Get sensor temperature and cooler status
* @param Cp - current sensor temperature
* @return Cooler_Status value
*/
int ApnGlueGetTemp(double *Cp){
int status = -1;
checkalta();
TRY{
*Cp = alta->GetTempCcd();
status = alta->GetCoolerStatus();
}CATCH(ALTA_COOLER);
return status;
}
/**
* Get heatsink temperature (in degC)
* @return hot side of Peltier temperature value
*/
double ApnGlueGetHotTemp(){
checkalta();
double temp = 1000.;
TRY{
temp = alta->GetTempHeatsink();
}CATCH(ALTA_COOLER);
return temp;
}
/**
* Set CCD temperature (in degC)
* @param C - new temperature, !!! value C == 0, disables cooler !!!
* @return
*/
void ApnGlueSetTemp(double C){
checkalta();
TRY{
if (C == 0) {
alta->SetCooler(0);
} else {
alta->SetCooler(1);
alta->SetCoolerSetPoint(C);
}
}CATCH(ALTA_COOLER);
}
/* Get setpoint temperature; return 1 if cooler is on, 0 if cooler is off;
stat == 0 - clamp to setpoint, 1 - at setpoint*/
/**
* Get temperature setpoint
* @param temp (o) - temperature setpoint or NULL
* @param stat (o) - ==1 if cooler is at setpoint or NULL
* @return cooler status
*/
int ApnGlueReadSetPoint(double *temp, int *stat){
checkalta();
Apg::CoolerStatus S = Apg::CoolerStatus_Suspended;
TRY{
S = alta->GetCoolerStatus();
if(S == Apg::CoolerStatus_Off) return S;
if(stat) *stat = (S == Apg::CoolerStatus_AtSetPoint) ? 1:0;
if(temp) *temp = alta->GetCoolerSetPoint();
}CATCH(ALTA_COOLER);
return S;
}
/**
* Read shutter state
* @return 1 if shutter opened, 0 if closed
*/
int ApnGlueReadShutter(){
checkalta();
int state = 0;
TRY{
Apg::ShutterState shtr = alta->GetShutterState();
if(shtr == Apg::ShutterState_ForceOpen)
state = 1;
}CATCH(ALTA_SHTR);
return state;
}
/**
* Force open/close shutter
* @param flag - == 0 to close, != 0 to open
*/
void ApnGlueOpenShutter(int flag){
checkalta();
TRY{
Apg::ShutterState shtr = (flag) ? Apg::ShutterState_ForceOpen : Apg::ShutterState_ForceClosed;
alta->SetShutterState(shtr);
}CATCH(ALTA_SHTR);
}
/**
* Get ADC speed
* @return Adc_Speed value
*/
unsigned short ApnGlueGetSpeed(){
checkalta();
Apg::AdcSpeed spd = Apg::AdcSpeed_Unknown;
TRY{
spd = alta->GetCcdAdcSpeed();
}CATCH(ALTA_BADSPD);
return (unsigned short)spd;
}
/**
* Set ADC speed
* @param Sp - speed (Adc_Speed)
*/
void ApnGlueSetSpeed(unsigned short Sp){
checkalta();
TRY{
if(Sp != AdcSpeed_Normal && Sp != AdcSpeed_Fast && Sp != AdcSpeed_Video){
altaerr = ALTA_BADSPD;
return;
}
alta->SetCcdAdcSpeed((Apg::AdcSpeed)Sp);
}CATCH(ALTA_BADSPD);
}
/**
* Reset camera
*/
void ApnGlueReset(){
checkalta();
TRY{
alta->Reset();
}CATCH(ALTA_POWER);
}
/**
* Power down/resume - just a stub for backward compability
*/
int ApnGluePowerDown(){return -1;}
void ApnGluePowerResume(){}
/**
* Disable (flag!=1) or enable post expose flushing
* @param flag == 1 to disable post-flushing
*/
void ApnGlueDisablePostExpFlushing(int flag){
checkalta();
TRY{
alta->SetPostExposeFlushing(flag);
}CATCH(ALTA_UNDEF);
}
/**
* Set (flag!=0) or reset preexposure IR-flashing
* @param flag != 1 to enable pre-flash
* @return
*/
void ApnGluePreFlash(int flag){
checkalta();
TRY{
alta->SetPreFlash(flag);
}CATCH(ALTA_UNDEF);
}
/**
* Set ADC databits (16/12)
* !!!DEPRECATED!!! Use ApnGlueSetSpeed() instead!
* @param BitResolution - ADC resolution
*/
void ApnGlueSetDatabits(Apn_Resolution BitResolution){
checkalta();
TRY{
Adc_Speed sp = AdcSpeed_Normal;
if(BitResolution != Resolution_SixteenBit)
sp = AdcSpeed_Fast;
ApnGlueSetSpeed(sp);
}CATCH(ALTA_UNDEF);
}
/**
* Set camera mode
* @param CameraMode - one of camera mode
*/
void ApnGlueWriteCamMode(Apn_CameraMode CameraMode){
checkalta();
TRY{
alta->SetCameraMode((Apg::CameraMode)CameraMode);
}CATCH(ALTA_UNDEF);
}
/* start an exposure with the given duration (secs) and whether to open shutter.
* update *exptime with the actual exposure time (may have been bumped to min).
* return 0 if ok, else -1
*/
/**
* Start an exposure with the given duration (secs)
* Update *exptime with the actual exposure time
* @param exptime (i/o) - exposition time in secs
* @param shutter - shutter state (1 - object, 0 - dark)
* @return ALTA_OK if ok
*/
int ApnGlueStartExp(double *exptime, int shutter){
checkalta();
if(!exptime) return ALTA_EXPOSURE;
TRY{
double maxtime; // ,mintime
//mintime = alta->GetMinExposureTime();
maxtime = alta->GetMaxExposureTime();
if(*exptime > maxtime) *exptime = maxtime;
else if(*exptime < 0.) *exptime = 0.;
alta->SetImageCount(1);
alta->StartExposure(*exptime, shutter);
}CATCH(ALTA_EXPOSURE);
return altaerr;
}
/**
* Pause or resume timer
* @param flag - !=0 to pause, ==0 to resume
* @return
*/
void ApnGluePauseTimer(int flag){
checkalta();
TRY{
alta->PauseTimer(flag);
}CATCH(ALTA_EXPOSURE);
}
/**
* These two functions makes similar work: aborts exposition
* ApnGlueExpAbort() fully aborts it, whith sensor cleaning
* ApnGlueStopExposure() allows to read stored image
* @return ApnGlueStopExposure() returns value of altaerr
*/
void ApnGlueExpAbort(){
checkalta();
TRY{
alta->StopExposure(false);
}CATCH(ALTA_EXPOSURE);
}
int ApnGlueStopExposure(){
checkalta();
TRY{
alta->StopExposure(true);
}CATCH(ALTA_EXPOSURE);
return altaerr;
}
/**
* Check whether exposition is done
* @return 1 if exposition is over
*/
int ApnGlueExpDone(){
checkalta();
TRY{
Apg::Status st = alta->GetImagingStatus();
if(st == Apg::Status_ImageReady) return 1;
}CATCH(ALTA_EXPOSURE);
return 0;
}
/**
* read pixels from the camera into the given buffer of length nbuf.
* @param buf - image buffer
* @param nbuf - buf size
* @param whynot - error explanation or NULL
* @return ALTA_OK if OK
*/
int ApnGlueReadPixels(unsigned short *buf, int nbuf, char whynot[]){
checkalta();
if(!buf || nbuf < 1) RETERR(ALTA_GETIMAGE);
printf("READ\n");
TRY{
std::vector<uint16_t> v;
alta->GetImage(v);
if(nbuf < alta->GetRoiNumCols() * (int)alta->GetRoiNumRows() || nbuf < (int)v.size()){
if(whynot) sprintf(whynot, "Buffer size less than image size");
RETERR(ALTA_GETIMAGE);
}
std::copy(v.begin(), v.end(), buf);
}CATCH(ALTA_GETIMAGE);
printf("DONE\n");
return altaerr;
}
/*
******************************** FILTER WHEEL ********************************
*/
static ApogeeFilterWheel *wheel;
static void checkwheel();
/**
* Open and initialise filter wheel device
* @param id - number of wheel
* @param type - wheel type
* @return 0 if init OK, else return !0 and set altaerr
*/
int ApnGlueWheelOpen(_U_ unsigned int id, Apn_Filter type){
TRY{
FindDeviceUsb look4FilterWheel;
std::string msg = look4FilterWheel.Find();
DBG(msg);
if(msg == "<d></d>")
RETERR(ALTA_NO_SUCH_DEVICE);
std::string str = GetItemFromFindStr(msg, "deviceType=");
if(str.compare("filterWheel"))
RETERR(ALTA_NOTWHEEL);
wheel = (ApogeeFilterWheel*) new ApogeeFilterWheel();
std::string addr = GetItemFromFindStr(msg, "address=");
wheel->Init((ApogeeFilterWheel::Type)type, addr);
}CATCH(ALTA_NO_SUCH_DEVICE);
return 0;
}
/**
* Close filter device
*/
void ApnGlueWheelClose(){
TRY{
if(wheel) wheel->Close();
delete wheel;
}CATCH(ALTA_CANT_CLOSE);
}
/**
* Get current filter wheel status
* @param
* @return 0 if ready, 1 if moving or absent
*/
int ApnGlueWheelGetStatus(){
checkwheel();
TRY{
ApogeeFilterWheel::Status st = wheel->GetStatus();
if(st != ApogeeFilterWheel::READY) return 1;
}CATCH(ALTA_NOTWHEEL);
if(altaerr != ALTA_OK) return 1;
return 0;
}
/**
* Get maximum position number
* @return amount of positions or -1 if err
*/
int ApnGlueWheelGetMaxPos(){
uint16_t m = 0;
checkwheel();
TRY{
m = wheel->GetMaxPositions();
}CATCH(ALTA_NOTWHEEL);
if(altaerr != ALTA_OK) return -1;
return (int) m;
}
/**
* Set position
* @param pos - new position number (1..max)
* @return 0 on success or !0 in case of error
*/
int ApnGlueWheelSetPos(int pos){
checkwheel();
TRY{
if(pos < 1 || wheel->GetMaxPositions() < pos) RETERR(ALTA_BADWHEELPOS);
wheel->SetPosition((uint16_t) pos);
}CATCH(ALTA_BADWHEELPOS);
if(altaerr != ALTA_OK) return ALTA_BADWHEELPOS;
return 0;
}
/**
* Get current position (1..max)
* @return current position or -1 on error
*/
int ApnGlueWheelGetPos(){
uint16_t m = 0;
checkwheel();
TRY{
m = wheel->GetPosition();
}CATCH(ALTA_BADWHEELPOS);
if(altaerr != ALTA_OK) return -1;
return (int)m;
}
/**
* Check wheel
*/
static void checkwheel(){
if(!wheel){
fprintf(stderr, "Bug! Wheel used before open\n");
exit(1);
}
}