Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sensor mode control for Player One cameras #815

Merged
merged 1 commit into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions debian/indi-playerone/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
indi-playerone (1.9) bionic; urgency=low

* Add sensor mode control for cameras that support it

-- Jarno Paananen <[email protected]> Thu, 20 Jul 2023 01:16:17 +0300

indi-playerone (1.8) bionic; urgency=low

* Update PlayerOneCamera SDK v3.4.0
Expand Down
2 changes: 1 addition & 1 deletion indi-playerone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ find_package(USB1 REQUIRED)
find_package(Threads REQUIRED)

set(PLAYERONE_VERSION_MAJOR 1)
set(PLAYERONE_VERSION_MINOR 8)
set(PLAYERONE_VERSION_MINOR 9)

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/indi_playerone.xml.cmake ${CMAKE_CURRENT_BINARY_DIR}/indi_playerone.xml)
Expand Down
132 changes: 91 additions & 41 deletions indi-playerone/playerone_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Copyright (C) 2018 Leonard Bottleman ([email protected])
Copyright (C) 2021 Pawel Soja ([email protected])
Copyright (C) 2021 Hiroshi Saito ([email protected])
Copyright (C) 2023 Jarno Paananen ([email protected])
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -75,15 +76,15 @@ void POABase::workerStreamVideo(const std::atomic_bool &isAbortToQuit)
while (!isAbortToQuit)
{
POABool pIsReady = POA_FALSE;
while (pIsReady == POA_FALSE)
{
//if (isAbortToQuit) //Triggered by external conditions
// break;

//usleep(ExposureRequest / 10);
POAImageReady(mCameraInfo.cameraID, &pIsReady);
}
while (pIsReady == POA_FALSE)
{
//if (isAbortToQuit) //Triggered by external conditions
// break;

//usleep(ExposureRequest / 10);
POAImageReady(mCameraInfo.cameraID, &pIsReady);
}

ret = POAGetImageData(mCameraInfo.cameraID, targetFrame, totalBytes, waitMS);
if (ret != POA_OK)
{
Expand All @@ -93,7 +94,7 @@ void POABase::workerStreamVideo(const std::atomic_bool &isAbortToQuit)
LOGF_ERROR("Failed to read video data (%s).", Helpers::toString(ret));
break;
}

usleep(100);
continue;
}
Expand Down Expand Up @@ -187,12 +188,12 @@ void POABase::workerExposure(const std::atomic_bool &isAbortToQuit, float durati
{
LOGF_ERROR("Failed to set exposure duration (%s).", Helpers::toString(ret));
}

// Try exposure for 3 times
// isDark is for mechanical shutter control
// However, PlayerOne Cameras doesn't have mechanical shutter
//POABool isDark = (PrimaryCCD.getFrameType() == INDI::CCDChip::DARK_FRAME) ? POA_TRUE : POA_FALSE;

for (int i = 0; i < 3; i++)
{
//ret = POAStartExposure(mCameraInfo.cameraID, isDark);
Expand Down Expand Up @@ -243,14 +244,14 @@ void POABase::workerExposure(const std::atomic_bool &isAbortToQuit, float durati
{
PrimaryCCD.setExposureLeft(timeLeft);
}

usleep(delay * 1000 * 1000);

POAErrors ret = POAGetCameraState(mCameraInfo.cameraID, &status);

if (isAbortToQuit)
return;

if (ret != POA_OK)
{
LOGF_DEBUG("Failed to get exposure status (%s)", Helpers::toString(ret));
Expand Down Expand Up @@ -280,7 +281,7 @@ void POABase::workerExposure(const std::atomic_bool &isAbortToQuit, float durati
PrimaryCCD.setExposureFailed();
return;
}

POAImageReady(mCameraInfo.cameraID, &pIsReady);
}
while (!pIsReady);
Expand Down Expand Up @@ -343,7 +344,7 @@ bool POABase::initProperties()
FlipSP[FLIP_HORIZONTAL].fill("FLIP_HORIZONTAL", "Horizontal", ISS_OFF);
FlipSP[FLIP_VERTICAL].fill("FLIP_VERTICAL", "Vertical", ISS_OFF);
FlipSP.fill(getDeviceName(), "FLIP", "Flip", CONTROL_TAB, IP_RW, ISR_NOFMANY, 60, IPS_IDLE);

VideoFormatSP.fill(getDeviceName(), "CCD_VIDEO_FORMAT", "Format", CONTROL_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);

BlinkNP[BLINK_COUNT ].fill("BLINK_COUNT", "Blinks before exposure", "%2.0f", 0, 100, 1.000, 0);
Expand All @@ -363,7 +364,7 @@ bool POABase::initProperties()

NicknameTP[0].fill("nickname", "nickname", mNickname);
NicknameTP.fill(getDeviceName(), "NICKNAME", "Nickname", INFO_TAB, IP_RW, 60, IPS_IDLE);

int maxBin = 1;

for (const auto &supportedBin : mCameraInfo.bins)
Expand Down Expand Up @@ -444,7 +445,7 @@ bool POABase::updateProperties()
defineProperty(ControlSP);
loadConfig(true, ControlSP.getName());
}

if (hasFlipControl())
{
defineProperty(FlipSP);
Expand Down Expand Up @@ -482,39 +483,48 @@ bool POABase::updateProperties()
defineProperty(SerialNumberTP);
defineProperty(NicknameTP);
}
if (!SensorModeSP.isEmpty())
{
defineProperty(SensorModeSP);
}
}
else
{
if (HasCooler())
{
deleteProperty(CoolerNP.getName());
deleteProperty(CoolerSP.getName());
deleteProperty(CoolerNP);
deleteProperty(CoolerSP);
}
else
deleteProperty(TemperatureNP.name);

if (!ControlNP.isEmpty())
deleteProperty(ControlNP.getName());
deleteProperty(ControlNP);

if (!ControlSP.isEmpty())
deleteProperty(ControlSP.getName());
deleteProperty(ControlSP);

if (hasFlipControl())
{
deleteProperty(FlipSP.getName());
deleteProperty(FlipSP);
}

if (!VideoFormatSP.isEmpty())
deleteProperty(VideoFormatSP.getName());
deleteProperty(VideoFormatSP);

deleteProperty(BlinkNP.getName());
deleteProperty(SDKVersionSP.getName());
deleteProperty(BlinkNP);
deleteProperty(SDKVersionSP);
if (!mSerialNumber.empty())
{
deleteProperty(SerialNumberTP.getName());
deleteProperty(NicknameTP.getName());
deleteProperty(SerialNumberTP);
deleteProperty(NicknameTP);
}
deleteProperty(ADCDepthNP);

if (!SensorModeSP.isEmpty())
{
deleteProperty(SensorModeSP);
}
deleteProperty(ADCDepthNP.getName());
}

return true;
Expand Down Expand Up @@ -581,8 +591,8 @@ bool POABase::Disconnect()
}

LOG_INFO("Camera is offline.");


setConnected(false, IPS_IDLE);
return true;
}
Expand All @@ -608,6 +618,28 @@ void POABase::setupParams()
}
}

int modeCount = 0;
if (POA_OK == POAGetSensorModeCount(mCameraInfo.cameraID, &modeCount) && modeCount > 0)
{
SensorModeSP.resize(modeCount);
char propertyName[16] = {0};
for (int i = 0; i < modeCount; ++i)
{
POASensorModeInfo info;
POAGetSensorModeInfo(mCameraInfo.cameraID, i, &info);
snprintf(propertyName, sizeof(propertyName) - 1, "MODE_%d", i);
SensorModeSP[i].fill(propertyName, info.name, ISS_OFF);
}
SensorModeSP.fill(getDeviceName(), "SENSOR_MODE", "Sensor Mode", CONTROL_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);

int mode;
if (POA_OK == POAGetSensorMode(mCameraInfo.cameraID, &mode) && mode >= 0 && mode < modeCount - 1)
{
SensorModeSP[mode].setState(ISS_ON);
SensorModeSP.setState(IPS_OK);
}
}

// Set minimum POA_USB_BANDWIDTH_LIMIT on ARM
#ifdef LOW_USB_BANDWIDTH
for (int j = 0; j < piNumberOfControls; j++)
Expand Down Expand Up @@ -869,11 +901,11 @@ bool POABase::ISNewSwitch(const char *dev, const char *name, ISState *states, ch
{
if (FlipSP[FLIP_VERTICAL].getState() == ISS_ON)
{
flip = POA_FLIP_BOTH;
flip = POA_FLIP_BOTH;
}
else
{
flip = POA_FLIP_HORI;
flip = POA_FLIP_HORI;
}
}
else
Expand All @@ -883,7 +915,7 @@ bool POABase::ISNewSwitch(const char *dev, const char *name, ISState *states, ch
flip = POA_FLIP_VERT;
}
}

POAConfigValue confVal; // confValue will be ignored by POASetConfig()
POAErrors ret = POASetConfig(mCameraInfo.cameraID, flip, confVal, POA_FALSE);
if (ret != POA_OK)
Expand All @@ -896,14 +928,14 @@ bool POABase::ISNewSwitch(const char *dev, const char *name, ISState *states, ch

// Compensate bayer pattern (effective for RAW data format)
char bayer[5];
POABayerCompensationByFlip(flip, bayer);
POABayerCompensationByFlip(flip, bayer);
IUSaveText(&BayerT[2], bayer);

FlipSP.setState(IPS_OK);
FlipSP.apply();
return true;
}

/* Cooler */
if (CoolerSP.isNameMatch(name))
{
Expand Down Expand Up @@ -950,6 +982,21 @@ bool POABase::ISNewSwitch(const char *dev, const char *name, ISState *states, ch
}
return true;
}

if (SensorModeSP.isNameMatch(name))
{
if (SensorModeSP.update(states, names, n) == false)
{
SensorModeSP.setState(IPS_ALERT);
SensorModeSP.apply();
return true;
}

int mode = SensorModeSP.findOnSwitchIndex();
SensorModeSP.setState(POASetSensorMode(mCameraInfo.cameraID, mode) == POA_OK ? IPS_OK : IPS_ALERT);
SensorModeSP.apply();
return true;
}
}

return INDI::CCD::ISNewSwitch(dev, name, states, names, n);
Expand Down Expand Up @@ -1438,7 +1485,7 @@ void POABase::createControls(int piNumberOfControls)
}

LOGF_DEBUG("Control #%d: name (%s), Descp (%s), Min (%ld), Max (%ld), Default Value (%ld), isSupportAuto (%s), "
"isWritale (%s) ",
"isWritable (%s) ",
i, cap.szConfName, cap.szDescription, cap.minValue.intValue, cap.maxValue.intValue,
cap.defaultValue.intValue, cap.isSupportAuto ? "True" : "False",
cap.isWritable ? "True" : "False");
Expand Down Expand Up @@ -1595,10 +1642,13 @@ bool POABase::saveConfigItems(FILE *fp)

if (hasFlipControl())
FlipSP.save(fp);

if (!VideoFormatSP.isEmpty())
VideoFormatSP.save(fp);

if (!SensorModeSP.isEmpty())
SensorModeSP.save(fp);

BlinkNP.save(fp);

return true;
Expand Down Expand Up @@ -1657,7 +1707,7 @@ POAErrors POABase::POAPulseGuideOff(int cameraID, POAConfig dir)
POAErrors POABase::POABayerCompensationByFlip(POAConfig flip, char *dest)
{
const char *src = getBayerString();

switch (flip)
{
case POA_FLIP_NONE:
Expand All @@ -1675,6 +1725,6 @@ POAErrors POABase::POABayerCompensationByFlip(POAConfig flip, char *dest)
default:
return POA_ERROR_INVALID_ARGU;
}

return POA_OK;
}
10 changes: 6 additions & 4 deletions indi-playerone/playerone_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class POABase : public INDI::CCD
virtual bool AbortExposure() override;

protected:

virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override;
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override;

Expand All @@ -77,7 +77,7 @@ class POABase : public INDI::CCD
virtual bool saveConfigItems(FILE *fp) override;

virtual bool SetCaptureFormat(uint8_t index) override;

/** Get the current Bayer string used */
const char *getBayerString() const;

Expand Down Expand Up @@ -146,18 +146,20 @@ class POABase : public INDI::CCD
INDI::PropertySwitch ControlSP {0};
INDI::PropertySwitch VideoFormatSP {0};

INDI::PropertyNumber ADCDepthNP {1};
INDI::PropertyNumber ADCDepthNP {1};
INDI::PropertyText SDKVersionSP {1};
INDI::PropertyText SerialNumberTP {1};
INDI::PropertyText NicknameTP {1};

INDI::PropertySwitch SensorModeSP {0};

INDI::PropertyNumber BlinkNP {2};
enum
{
BLINK_COUNT,
BLINK_DURATION
};

INDI::PropertySwitch FlipSP {2};
enum
{
Expand Down