From 77efa953ddbb1f90b1606e53ce90d0d04ebf6291 Mon Sep 17 00:00:00 2001 From: naheedsa <97088153+naheedsa@users.noreply.github.com> Date: Fri, 1 Mar 2024 07:39:45 +0300 Subject: [PATCH] Migrate CCD simulator (#2008) * Migrate CCD simulator * use get and set for values; also avoid using ENUM which has only one value * Minor change for Telescope Simulator - Avoid using a single ENUM --- drivers/ccd/ccd_simulator.cpp | 286 ++++++++-------- drivers/ccd/ccd_simulator.h | 392 +++++++++++----------- drivers/telescope/telescope_simulator.cpp | 4 +- drivers/telescope/telescope_simulator.h | 4 - 4 files changed, 342 insertions(+), 344 deletions(-) diff --git a/drivers/ccd/ccd_simulator.cpp b/drivers/ccd/ccd_simulator.cpp index 90a02e7f53..8ed366a8a2 100644 --- a/drivers/ccd/ccd_simulator.cpp +++ b/drivers/ccd/ccd_simulator.cpp @@ -53,26 +53,26 @@ CCDSim::CCDSim() : INDI::FilterInterface(this) bool CCDSim::setupParameters() { - SetCCDParams(SimulatorSettingsN[SIM_XRES].value, - SimulatorSettingsN[SIM_YRES].value, + SetCCDParams(SimulatorSettingsNP[SIM_XRES].getValue(), + SimulatorSettingsNP[SIM_YRES].getValue(), 16, - SimulatorSettingsN[SIM_XSIZE].value, - SimulatorSettingsN[SIM_YSIZE].value); - - m_MaxNoise = SimulatorSettingsN[SIM_NOISE].value; - m_SkyGlow = SimulatorSettingsN[SIM_SKYGLOW].value; - m_MaxVal = SimulatorSettingsN[SIM_MAXVAL].value; - m_Bias = OffsetN[0].value; - m_LimitingMag = SimulatorSettingsN[SIM_LIMITINGMAG].value; - m_SaturationMag = SimulatorSettingsN[SIM_SATURATION].value; + SimulatorSettingsNP[SIM_XSIZE].getValue(), + SimulatorSettingsNP[SIM_YSIZE].getValue()); + + m_MaxNoise = SimulatorSettingsNP[SIM_NOISE].getValue(); + m_SkyGlow = SimulatorSettingsNP[SIM_SKYGLOW].getValue(); + m_MaxVal = SimulatorSettingsNP[SIM_MAXVAL].getValue(); + m_Bias = OffsetNP[0].getValue(); + m_LimitingMag = SimulatorSettingsNP[SIM_LIMITINGMAG].getValue(); + m_SaturationMag = SimulatorSettingsNP[SIM_SATURATION].getValue(); // An oag is offset this much from center of scope position (arcminutes); - m_OAGOffset = SimulatorSettingsN[SIM_OAGOFFSET].value; - m_PolarError = SimulatorSettingsN[SIM_POLAR].value; - m_PolarDrift = SimulatorSettingsN[SIM_POLARDRIFT].value; - m_PEPeriod = SimulatorSettingsN[SIM_PE_PERIOD].value; - m_PEMax = SimulatorSettingsN[SIM_PE_MAX].value; - m_TimeFactor = SimulatorSettingsN[SIM_TIME_FACTOR].value; - RotatorAngle = SimulatorSettingsN[SIM_ROTATION].value; + m_OAGOffset = SimulatorSettingsNP[SIM_OAGOFFSET].getValue(); + m_PolarError = SimulatorSettingsNP[SIM_POLAR].getValue(); + m_PolarDrift = SimulatorSettingsNP[SIM_POLARDRIFT].getValue(); + m_PEPeriod = SimulatorSettingsNP[SIM_PE_PERIOD].getValue(); + m_PEMax = SimulatorSettingsNP[SIM_PE_MAX].getValue(); + m_TimeFactor = SimulatorSettingsNP[SIM_TIME_FACTOR].getValue(); + RotatorAngle = SimulatorSettingsNP[SIM_ROTATION].getValue(); uint32_t nbuf = PrimaryCCD.getXRes() * PrimaryCCD.getYRes() * PrimaryCCD.getBPP() / 8; PrimaryCCD.setFrameBufferSize(nbuf); @@ -115,49 +115,49 @@ bool CCDSim::initProperties() CaptureFormat format = {"INDI_MONO", "Mono", 16, true}; addCaptureFormat(format); - IUFillNumber(&SimulatorSettingsN[SIM_XRES], "SIM_XRES", "CCD X resolution", "%4.0f", 512, 8192, 512, 1280); - IUFillNumber(&SimulatorSettingsN[SIM_YRES], "SIM_YRES", "CCD Y resolution", "%4.0f", 512, 8192, 512, 1024); - IUFillNumber(&SimulatorSettingsN[SIM_XSIZE], "SIM_XSIZE", "CCD X Pixel Size", "%4.2f", 1, 30, 5, 5.2); - IUFillNumber(&SimulatorSettingsN[SIM_YSIZE], "SIM_YSIZE", "CCD Y Pixel Size", "%4.2f", 1, 30, 5, 5.2); - IUFillNumber(&SimulatorSettingsN[SIM_MAXVAL], "SIM_MAXVAL", "CCD Maximum ADU", "%4.0f", 255, 65000, 1000, 65000); - IUFillNumber(&SimulatorSettingsN[SIM_SATURATION], "SIM_SATURATION", "Saturation Mag", "%4.1f", 0, 20, 1, 1.0); - IUFillNumber(&SimulatorSettingsN[SIM_LIMITINGMAG], "SIM_LIMITINGMAG", "Limiting Mag", "%4.1f", 0, 20, 1, 17.0); - IUFillNumber(&SimulatorSettingsN[SIM_NOISE], "SIM_NOISE", "CCD Noise", "%4.0f", 0, 6000, 500, 10); - IUFillNumber(&SimulatorSettingsN[SIM_SKYGLOW], "SIM_SKYGLOW", "Sky Glow (magnitudes)", "%4.1f", 0, 6000, 500, 19.5); - IUFillNumber(&SimulatorSettingsN[SIM_OAGOFFSET], "SIM_OAGOFFSET", "Oag Offset (arcminutes)", "%4.1f", 0, 6000, 500, 0); - IUFillNumber(&SimulatorSettingsN[SIM_POLAR], "SIM_POLAR", "PAE (arcminutes)", "%4.1f", -600, 600, 100, 0); - IUFillNumber(&SimulatorSettingsN[SIM_POLARDRIFT], "SIM_POLARDRIFT", "PAE Drift (minutes)", "%4.1f", 0, 60, 5, 0); - IUFillNumber(&SimulatorSettingsN[SIM_PE_PERIOD], "SIM_PEPERIOD", "PE Period (seconds)", "%4.1f", 0, 60, 5, 0); - IUFillNumber(&SimulatorSettingsN[SIM_PE_MAX], "SIM_PEMAX", "PE Max (arcsec)", "%4.1f", 0, 6000, 500, 0); - IUFillNumber(&SimulatorSettingsN[SIM_TIME_FACTOR], "SIM_TIME_FACTOR", "Time Factor (x)", "%.2f", 0.01, 100, 10, 1); - IUFillNumber(&SimulatorSettingsN[SIM_ROTATION], "SIM_ROTATION", "CCD Rotation", "%.2f", 0, 360, 10, 0); - - IUFillNumberVector(&SimulatorSettingsNP, SimulatorSettingsN, SIM_N, getDeviceName(), "SIMULATOR_SETTINGS", - "Settings", SIMULATOR_TAB, IP_RW, 60, IPS_IDLE); + SimulatorSettingsNP[SIM_XRES].fill("SIM_XRES", "CCD X resolution", "%4.0f", 512, 8192, 512, 1280); + SimulatorSettingsNP[SIM_YRES].fill("SIM_YRES", "CCD Y resolution", "%4.0f", 512, 8192, 512, 1024); + SimulatorSettingsNP[SIM_XSIZE].fill("SIM_XSIZE", "CCD X Pixel Size", "%4.2f", 1, 30, 5, 5.2); + SimulatorSettingsNP[SIM_YSIZE].fill("SIM_YSIZE", "CCD Y Pixel Size", "%4.2f", 1, 30, 5, 5.2); + SimulatorSettingsNP[SIM_MAXVAL].fill("SIM_MAXVAL", "CCD Maximum ADU", "%4.0f", 255, 65000, 1000, 65000); + SimulatorSettingsNP[SIM_SATURATION].fill("SIM_SATURATION", "Saturation Mag", "%4.1f", 0, 20, 1, 1.0); + SimulatorSettingsNP[SIM_LIMITINGMAG].fill("SIM_LIMITINGMAG", "Limiting Mag", "%4.1f", 0, 20, 1, 17.0); + SimulatorSettingsNP[SIM_NOISE].fill("SIM_NOISE", "CCD Noise", "%4.0f", 0, 6000, 500, 10); + SimulatorSettingsNP[SIM_SKYGLOW].fill("SIM_SKYGLOW", "Sky Glow (magnitudes)", "%4.1f", 0, 6000, 500, 19.5); + SimulatorSettingsNP[SIM_OAGOFFSET].fill("SIM_OAGOFFSET", "Oag Offset (arcminutes)", "%4.1f", 0, 6000, 500, 0); + SimulatorSettingsNP[SIM_POLAR].fill("SIM_POLAR", "PAE (arcminutes)", "%4.1f", -600, 600, 100, 0); + SimulatorSettingsNP[SIM_POLARDRIFT].fill("SIM_POLARDRIFT", "PAE Drift (minutes)", "%4.1f", 0, 60, 5, 0); + SimulatorSettingsNP[SIM_PE_PERIOD].fill("SIM_PEPERIOD", "PE Period (seconds)", "%4.1f", 0, 60, 5, 0); + SimulatorSettingsNP[SIM_PE_MAX].fill("SIM_PEMAX", "PE Max (arcsec)", "%4.1f", 0, 6000, 500, 0); + SimulatorSettingsNP[SIM_TIME_FACTOR].fill("SIM_TIME_FACTOR", "Time Factor (x)", "%.2f", 0.01, 100, 10, 1); + SimulatorSettingsNP[SIM_ROTATION].fill("SIM_ROTATION", "CCD Rotation", "%.2f", 0, 360, 10, 0); + + SimulatorSettingsNP.fill(getDeviceName(), "SIMULATOR_SETTINGS", + "Settings", SIMULATOR_TAB, IP_RW, 60, IPS_IDLE); // RGB Simulation - IUFillSwitch(&SimulateBayerS[INDI_ENABLED], "INDI_ENABLED", "Enabled", ISS_OFF); - IUFillSwitch(&SimulateBayerS[INDI_DISABLED], "INDI_DISABLED", "Disabled", ISS_ON); - IUFillSwitchVector(&SimulateBayerSP, SimulateBayerS, 2, getDeviceName(), "SIMULATE_BAYER", "Bayer", SIMULATOR_TAB, IP_RW, - ISR_1OFMANY, 60, IPS_IDLE); + SimulateBayerSP[INDI_ENABLED].fill("INDI_ENABLED", "Enabled", ISS_OFF); + SimulateBayerSP[INDI_DISABLED].fill("INDI_DISABLED", "Disabled", ISS_ON); + SimulateBayerSP.fill(getDeviceName(), "SIMULATE_BAYER", "Bayer", SIMULATOR_TAB, IP_RW, + ISR_1OFMANY, 60, IPS_IDLE); // Simulate focusing - IUFillNumber(&FocusSimulationN[0], "SIM_FOCUS_POSITION", "Focus", "%.f", 0.0, 100000.0, 1.0, 36700.0); - IUFillNumber(&FocusSimulationN[1], "SIM_FOCUS_MAX", "Max. Position", "%.f", 0.0, 100000.0, 1.0, 100000.0); - IUFillNumber(&FocusSimulationN[2], "SIM_SEEING", "Seeing (arcsec)", "%4.2f", 0, 60, 0, 3.5); - IUFillNumberVector(&FocusSimulationNP, FocusSimulationN, 3, getDeviceName(), "SIM_FOCUSING", "Focus Simulation", - SIMULATOR_TAB, IP_RW, 60, IPS_IDLE); + FocusSimulationNP[SIM_FOCUS_POSITION].fill("SIM_FOCUS_POSITION", "Focus", "%.f", 0.0, 100000.0, 1.0, 36700.0); + FocusSimulationNP[SIM_FOCUS_MAX].fill("SIM_FOCUS_MAX", "Max. Position", "%.f", 0.0, 100000.0, 1.0, 100000.0); + FocusSimulationNP[SIM_SEEING].fill("SIM_SEEING", "Seeing (arcsec)", "%4.2f", 0, 60, 0, 3.5); + FocusSimulationNP.fill(getDeviceName(), "SIM_FOCUSING", "Focus Simulation", + SIMULATOR_TAB, IP_RW, 60, IPS_IDLE); // Simulate Crash - IUFillSwitch(&CrashS[0], "CRASH", "Crash driver", ISS_OFF); - IUFillSwitchVector(&CrashSP, CrashS, 1, getDeviceName(), "CCD_SIMULATE_CRASH", "Crash", SIMULATOR_TAB, IP_WO, - ISR_ATMOST1, 0, IPS_IDLE); + CrashSP[0].fill("CRASH", "Crash driver", ISS_OFF); + CrashSP.fill(getDeviceName(), "CCD_SIMULATE_CRASH", "Crash", SIMULATOR_TAB, IP_WO, + ISR_ATMOST1, 0, IPS_IDLE); // Periodic Error - IUFillNumber(&EqPEN[AXIS_RA], "RA_PE", "RA (hh:mm:ss)", "%010.6m", 0, 24, 0, 0); - IUFillNumber(&EqPEN[AXIS_DE], "DEC_PE", "DEC (dd:mm:ss)", "%010.6m", -90, 90, 0, 0); - IUFillNumberVector(&EqPENP, EqPEN, 2, getDeviceName(), "EQUATORIAL_PE", "EQ PE", SIMULATOR_TAB, IP_RW, 60, - IPS_IDLE); + EqPENP[AXIS_RA].fill("RA_PE", "RA (hh:mm:ss)", "%010.6m", 0, 24, 0, 0); + EqPENP[AXIS_DE].fill("DEC_PE", "DEC (dd:mm:ss)", "%010.6m", -90, 90, 0, 0); + EqPENP.fill(getDeviceName(), "EQUATORIAL_PE", "EQ PE", SIMULATOR_TAB, IP_RW, 60, + IPS_IDLE); // FWHM auto focuser = ActiveDeviceT[ACTIVE_FOCUSER].text ? ActiveDeviceT[ACTIVE_FOCUSER].text : ""; @@ -165,18 +165,18 @@ bool CCDSim::initProperties() IUFillNumberVector(&FWHMNP, FWHMN, 1, focuser, "FWHM", "FWHM", OPTIONS_TAB, IP_RO, 60, IPS_IDLE); // Cooler - IUFillSwitch(&CoolerS[INDI_ENABLED], "COOLER_ON", "ON", ISS_OFF); - IUFillSwitch(&CoolerS[INDI_DISABLED], "COOLER_OFF", "OFF", ISS_ON); - IUFillSwitchVector(&CoolerSP, CoolerS, 2, getDeviceName(), "CCD_COOLER", "Cooler", MAIN_CONTROL_TAB, IP_WO, - ISR_1OFMANY, 0, IPS_IDLE); + CoolerSP[INDI_ENABLED].fill("COOLER_ON", "ON", ISS_OFF); + CoolerSP[INDI_DISABLED].fill("COOLER_OFF", "OFF", ISS_ON); + CoolerSP.fill(getDeviceName(), "CCD_COOLER", "Cooler", MAIN_CONTROL_TAB, IP_WO, + ISR_1OFMANY, 0, IPS_IDLE); // Gain - IUFillNumber(&GainN[0], "GAIN", "value", "%.f", 0, 100, 10, 90); - IUFillNumberVector(&GainNP, GainN, 1, getDeviceName(), "CCD_GAIN", "Gain", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); + GainNP[0].fill("GAIN", "value", "%.f", 0, 100, 10, 90); + GainNP.fill(getDeviceName(), "CCD_GAIN", "Gain", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); // Offset - IUFillNumber(&OffsetN[0], "OFFSET", "value", "%.f", 0, 6000, 500, 0); - IUFillNumberVector(&OffsetNP, OffsetN, 1, getDeviceName(), "CCD_OFFSET", "Offset", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); + OffsetNP[0].fill("OFFSET", "value", "%.f", 0, 6000, 500, 0); + OffsetNP.fill(getDeviceName(), "CCD_OFFSET", "Offset", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE); // Directory to read images from. This is useful to test real images captured by camera // For each capture, one file is read (sorted by name) and is sent to client. @@ -262,11 +262,11 @@ void CCDSim::ISGetProperties(const char * dev) { INDI::CCD::ISGetProperties(dev); - defineProperty(&SimulatorSettingsNP); - defineProperty(&EqPENP); - defineProperty(&FocusSimulationNP); - defineProperty(&SimulateBayerSP); - defineProperty(&CrashSP); + defineProperty(SimulatorSettingsNP); + defineProperty(EqPENP); + defineProperty(FocusSimulationNP); + defineProperty(SimulateBayerSP); + defineProperty(CrashSP); } bool CCDSim::updateProperties() @@ -276,10 +276,10 @@ bool CCDSim::updateProperties() if (isConnected()) { if (HasCooler()) - defineProperty(&CoolerSP); + defineProperty(CoolerSP); - defineProperty(&GainNP); - defineProperty(&OffsetNP); + defineProperty(GainNP); + defineProperty(OffsetNP); defineProperty(DirectoryTP); defineProperty(DirectorySP); @@ -299,10 +299,10 @@ bool CCDSim::updateProperties() else { if (HasCooler()) - deleteProperty(CoolerSP.name); + deleteProperty(CoolerSP.getName()); - deleteProperty(GainNP.name); - deleteProperty(OffsetNP.name); + deleteProperty(GainNP.getName()); + deleteProperty(OffsetNP.getName()); deleteProperty(DirectoryTP); deleteProperty(DirectorySP); deleteProperty(ResolutionSP); @@ -323,10 +323,10 @@ int CCDSim::SetTemperature(double temperature) } auto isCooling = TemperatureRequest < temperature; - CoolerS[0].s = isCooling ? ISS_ON : ISS_OFF; - CoolerS[1].s = isCooling ? ISS_OFF : ISS_ON; - CoolerSP.s = isCooling ? IPS_BUSY : IPS_IDLE; - IDSetSwitch(&CoolerSP, nullptr); + CoolerSP[INDI_ENABLED].setState(isCooling ? ISS_ON : ISS_OFF); + CoolerSP[INDI_DISABLED].setState(isCooling ? ISS_OFF : ISS_ON); + CoolerSP.setState(isCooling ? IPS_BUSY : IPS_IDLE); + CoolerSP.apply(); return 0; } @@ -503,10 +503,10 @@ void CCDSim::TimerHit() // Above 20, cooler is off if (TemperatureN[0].value >= 20) { - CoolerS[0].s = ISS_OFF; - CoolerS[1].s = ISS_ON; - CoolerSP.s = IPS_IDLE; - IDSetSwitch(&CoolerSP, nullptr); + CoolerSP[INDI_ENABLED].setState(ISS_OFF); + CoolerSP[INDI_DISABLED].setState(ISS_ON); + CoolerSP.setState(IPS_IDLE); + CoolerSP.apply(); } } @@ -537,7 +537,7 @@ int CCDSim::DrawCcdFrame(INDI::CCDChip * targetChip) else exposure_time = ExposureRequest; - exposure_time *= (1 + sqrt(GainN[0].value)); + exposure_time *= (1 + sqrt(GainNP[0].getValue())); auto targetFocalLength = ScopeInfoNP[FocalLength].getValue() > 0 ? ScopeInfoNP[FocalLength].getValue() : snoopedFocalLength; @@ -1081,52 +1081,52 @@ bool CCDSim::ISNewNumber(const char * dev, const char * name, double values[], c if (dev != nullptr && strcmp(dev, getDeviceName()) == 0) { - if (!strcmp(name, GainNP.name)) + if (GainNP.isNameMatch(name)) { - IUUpdateNumber(&GainNP, values, names, n); - GainNP.s = IPS_OK; - IDSetNumber(&GainNP, nullptr); + GainNP.update(values, names, n); + GainNP.setState(IPS_OK); + GainNP.apply(); return true; } - if (!strcmp(name, OffsetNP.name)) + if (OffsetNP.isNameMatch(name)) { - IUUpdateNumber(&OffsetNP, values, names, n); - OffsetNP.s = IPS_OK; - IDSetNumber(&OffsetNP, nullptr); - m_Bias = OffsetN[0].value; + OffsetNP.update(values, names, n); + OffsetNP.setState(IPS_OK); + OffsetNP.apply(); + m_Bias = OffsetNP[0].getValue(); return true; } - else if (!strcmp(name, SimulatorSettingsNP.name)) + else if (SimulatorSettingsNP.isNameMatch(name)) { - IUUpdateNumber(&SimulatorSettingsNP, values, names, n); - SimulatorSettingsNP.s = IPS_OK; + SimulatorSettingsNP.update(values, names, n); + SimulatorSettingsNP.setState(IPS_OK); // Reset our parameters now setupParameters(); - IDSetNumber(&SimulatorSettingsNP, nullptr); - saveConfig(true, SimulatorSettingsNP.name); + SimulatorSettingsNP.apply(); + saveConfig(true, SimulatorSettingsNP.getName()); return true; } // Record PE EQ to simulate different position in the sky than actual mount coordinate // This can be useful to simulate Periodic Error or cone error or any arbitrary error. - else if (!strcmp(name, EqPENP.name)) + else if (EqPENP.isNameMatch(name)) { - IUUpdateNumber(&EqPENP, values, names, n); - EqPENP.s = IPS_OK; + EqPENP.update(values, names, n); + EqPENP.setState(IPS_OK); INDI::IEquatorialCoordinates epochPos { 0, 0 }, J2000Pos { 0, 0 }; - epochPos.rightascension = EqPEN[AXIS_RA].value; - epochPos.declination = EqPEN[AXIS_DE].value; + epochPos.rightascension = EqPENP[AXIS_RA].getValue(); + epochPos.declination = EqPENP[AXIS_DE].getValue(); - RA = EqPEN[AXIS_RA].value; - Dec = EqPEN[AXIS_DE].value; + RA = EqPENP[AXIS_RA].getValue(); + Dec = EqPENP[AXIS_DE].getValue(); INDI::ObservedToJ2000(&epochPos, ln_get_julian_from_sys(), &J2000Pos); currentRA = J2000Pos.rightascension; currentDE = J2000Pos.declination; usePE = true; - IDSetNumber(&EqPENP, nullptr); + EqPENP.apply(); return true; } else if (!strcmp(name, FilterSlotNP.name)) @@ -1134,12 +1134,12 @@ bool CCDSim::ISNewNumber(const char * dev, const char * name, double values[], c INDI::FilterInterface::processNumber(dev, name, values, names, n); return true; } - else if (!strcmp(name, FocusSimulationNP.name)) + else if (FocusSimulationNP.isNameMatch(name)) { // update focus simulation parameters - IUUpdateNumber(&FocusSimulationNP, values, names, n); - FocusSimulationNP.s = IPS_OK; - IDSetNumber(&FocusSimulationNP, nullptr); + FocusSimulationNP.update(values, names, n); + FocusSimulationNP.setState(IPS_OK); + FocusSimulationNP.apply(); } } @@ -1151,44 +1151,44 @@ bool CCDSim::ISNewSwitch(const char * dev, const char * name, ISState * states, if (dev != nullptr && strcmp(dev, getDeviceName()) == 0) { // Simulate RGB - if (!strcmp(name, SimulateBayerSP.name)) + if (SimulateBayerSP.isNameMatch(name)) { - IUUpdateSwitch(&SimulateBayerSP, states, names, n); - int index = IUFindOnSwitchIndex(&SimulateBayerSP); + SimulateBayerSP.update(states, names, n); + int index = SimulateBayerSP.findOnSwitchIndex(); if (index == -1) { - SimulateBayerSP.s = IPS_ALERT; + SimulateBayerSP.setState(IPS_ALERT); LOG_INFO("Cannot determine whether RGB simulation should be switched on or off."); - IDSetSwitch(&SimulateBayerSP, nullptr); + SimulateBayerSP.apply(); return false; } m_SimulateBayer = index == 0; setBayerEnabled(m_SimulateBayer); - SimulateBayerS[INDI_ENABLED].s = m_SimulateBayer ? ISS_ON : ISS_OFF; - SimulateBayerS[INDI_DISABLED].s = m_SimulateBayer ? ISS_OFF : ISS_ON; - SimulateBayerSP.s = IPS_OK; - IDSetSwitch(&SimulateBayerSP, nullptr); + SimulateBayerSP[INDI_ENABLED].setState(m_SimulateBayer ? ISS_ON : ISS_OFF); + SimulateBayerSP[INDI_DISABLED].setState(m_SimulateBayer ? ISS_OFF : ISS_ON); + SimulateBayerSP.setState(IPS_OK); + SimulateBayerSP.apply(); return true; } - else if (strcmp(name, CoolerSP.name) == 0) + else if (CoolerSP.isNameMatch(name)) { - IUUpdateSwitch(&CoolerSP, states, names, n); + CoolerSP.update(states, names, n); - if (CoolerS[0].s == ISS_ON) - CoolerSP.s = IPS_BUSY; + if (CoolerSP[INDI_ENABLED].getState() == ISS_ON) + CoolerSP.setState(IPS_BUSY); else { - CoolerSP.s = IPS_IDLE; + CoolerSP.setState(IPS_IDLE); m_TargetTemperature = 20; TemperatureNP.s = IPS_BUSY; m_TemperatureCheckTimer.start(); m_TemperatureElapsedTimer.start(); } - IDSetSwitch(&CoolerSP, nullptr); + CoolerSP.apply(); return true; } @@ -1210,7 +1210,7 @@ bool CCDSim::ISNewSwitch(const char * dev, const char * name, ISState * states, { m_RemainingFiles.clear(); DirectorySP.setState(IPS_OK); - setBayerEnabled(SimulateBayerS[INDI_ENABLED].s == ISS_ON); + setBayerEnabled(SimulateBayerSP[INDI_ENABLED].getState() == ISS_ON); LOG_INFO("Directory-based images are disabled."); } DirectorySP.apply(nullptr); @@ -1225,22 +1225,22 @@ bool CCDSim::ISNewSwitch(const char * dev, const char * name, ISState * states, int index = ResolutionSP.findOnSwitchIndex(); if (index >= 0 && index < static_cast(Resolutions.size())) { - SimulatorSettingsN[SIM_XRES].value = Resolutions[index].first; - SimulatorSettingsN[SIM_YRES].value = Resolutions[index].second; - SetCCDParams(SimulatorSettingsN[SIM_XRES].value, - SimulatorSettingsN[SIM_YRES].value, + SimulatorSettingsNP[SIM_XRES].setValue(Resolutions[index].first); + SimulatorSettingsNP[SIM_YRES].setValue(Resolutions[index].second); + SetCCDParams(SimulatorSettingsNP[SIM_XRES].getValue(), + SimulatorSettingsNP[SIM_YRES].getValue(), 16, - SimulatorSettingsN[SIM_XSIZE].value, - SimulatorSettingsN[SIM_YSIZE].value); - UpdateCCDFrame(0, 0, SimulatorSettingsN[SIM_XRES].value, SimulatorSettingsN[SIM_YRES].value); + SimulatorSettingsNP[SIM_XSIZE].getValue(), + SimulatorSettingsNP[SIM_YSIZE].getValue()); + UpdateCCDFrame(0, 0, SimulatorSettingsNP[SIM_XRES].getValue(), SimulatorSettingsNP[SIM_YRES].getValue()); uint32_t nbuf = PrimaryCCD.getXRes() * PrimaryCCD.getYRes() * PrimaryCCD.getBPP() / 8; PrimaryCCD.setFrameBufferSize(nbuf); - IDSetNumber(&SimulatorSettingsNP, nullptr); + SimulatorSettingsNP.apply(); } return true; } - else if (strcmp(name, CrashSP.name) == 0) + else if (CrashSP.isNameMatch(name)) { abort(); } @@ -1260,9 +1260,9 @@ bool CCDSim::watchDirectory() } struct dirent * dp; - std::string d_dir = std::string(DirectoryTP[0].text); + std::string d_dir = std::string(DirectoryTP[0].getText()); auto directory = DirectoryTP[0].getText(); - if (directory[strlen(directory) - 1] != '/') + if (directory[std::string(directory).length() - 1] != '/') d_dir += "/"; while ((dp = readdir(dirp)) != NULL) { @@ -1323,9 +1323,9 @@ bool CCDSim::ISSnoopDevice(XMLEle * root) FocuserPos = atol(pcdataXMLEle(ep)); // calculate FWHM - double focus = FocusSimulationN[0].value; - double max = FocusSimulationN[1].value; - double optimalFWHM = FocusSimulationN[2].value; + double focus = FocusSimulationNP[SIM_FOCUS_POSITION].getValue(); + double max = FocusSimulationNP[SIM_FOCUS_MAX].getValue(); + double optimalFWHM = FocusSimulationNP[SIM_SEEING].getValue(); // limit to +/- 10 double ticks = 20 * (FocuserPos - focus) / max; @@ -1387,11 +1387,11 @@ bool CCDSim::saveConfigItems(FILE * fp) INDI::FilterInterface::saveConfigItems(fp); // Save CCD Simulator Config - IUSaveConfigNumber(fp, &SimulatorSettingsNP); + SimulatorSettingsNP.save(fp); // Gain - IUSaveConfigNumber(fp, &GainNP); - IUSaveConfigNumber(fp, &OffsetNP); + GainNP.save(fp); + OffsetNP.save(fp); // Directory DirectoryTP.save(fp); @@ -1400,10 +1400,10 @@ bool CCDSim::saveConfigItems(FILE * fp) ResolutionSP.save(fp); // Bayer - IUSaveConfigSwitch(fp, &SimulateBayerSP); + SimulateBayerSP.save(fp); // Focus simulation - IUSaveConfigNumber(fp, &FocusSimulationNP); + FocusSimulationNP.save(fp); return true; } @@ -1531,7 +1531,7 @@ void CCDSim::addFITSKeywords(INDI::CCDChip *targetChip, std::vector &fitsKeyword) override; - virtual void activeDevicesUpdated() override; - virtual int SetTemperature(double temperature) override; - virtual bool UpdateCCDFrame(int x, int y, int w, int h) override; - virtual bool UpdateCCDBin(int hor, int ver) override; - virtual bool UpdateGuiderBin(int hor, int ver) override; - - virtual bool SetCaptureFormat(uint8_t index) override; - - virtual bool StartStreaming() override; - virtual bool StopStreaming() override; - - // Filter - bool SelectFilter(int) override; - int QueryFilter() override; - - protected: - - float CalcTimeLeft(timeval, float); - bool watchDirectory(); - bool loadNextImage(); - bool setupParameters(); - - // Turns on/off Bayer RGB simulation. - void setBayerEnabled(bool onOff); - - double flux(double magnitude) const; - - double TemperatureRequest { 0 }; - - float ExposureRequest { 0 }; - struct timeval ExpStart - { - 0, 0 - }; - - float GuideExposureRequest { 0 }; - struct timeval GuideExpStart - { - 0, 0 - }; - - int testvalue { 0 }; - bool ShowStarField { true }; - int m_Bias { 1500 }; - int m_MaxNoise { 20 }; - int m_MaxVal { 65000 }; - int maxpix { 0 }; - int minpix { 65000 }; - float m_SkyGlow { 40 }; - float m_LimitingMag { 11.5 }; - float m_SaturationMag { 2 }; - float seeing { 3.5 }; - float ImageScalex { 1.0 }; - float ImageScaley { 1.0 }; - // An oag is offset this much from center of scope position (arcminutes) - float m_OAGOffset { 0 }; - float m_RotationCW { 0 }; - float m_TimeFactor { 1 }; - - bool m_SimulateBayer { false }; - - // our zero point calcs used for drawing stars - //float k { 0 }; - //float z { 0 }; - - bool AbortGuideFrame { false }; - bool AbortPrimaryFrame { false }; - - /// Guide rate is 7 arcseconds per second - float GuideRate { 7 }; - - /// PEPeriod in minutes - float m_PEPeriod { 0 }; - // PE max in arcsecs - float m_PEMax { 0 }; - - double currentRA { 0 }; - double currentDE { 0 }; - bool usePE { false }; - time_t RunStart; - - float guideNSOffset {0}; - float guideWEOffset {0}; - - float m_PolarError { 0 }; - float m_PolarDrift { 0 }; - - double m_LastTemperature {0}; - - int streamPredicate {0}; - pthread_t primary_thread; - bool terminateThread; - - std::deque m_AllFiles, m_RemainingFiles; - - // And this lives in our simulator settings page - INumberVectorProperty SimulatorSettingsNP; - INumber SimulatorSettingsN[SIM_N]; - - ISwitchVectorProperty SimulateBayerSP; - ISwitch SimulateBayerS[2]; - - // We are going to snoop these from focuser - INumberVectorProperty FWHMNP; - INumber FWHMN[1]; - - // Focuser positions for focusing simulation - // FocuserPosition[0] is the position where the scope is in focus - // FocuserPosition[1] is the maximal position the focuser may move to (@see FOCUS_MAX in #indifocuserinterface.cpp) - // FocuserPosition[2] is the seeing (in arcsec) - // We need to have these values here, since we cannot snoop it from the focuser (the focuser does not - // publish these values) - INumberVectorProperty FocusSimulationNP; - INumber FocusSimulationN[3]; - - INumberVectorProperty EqPENP; - INumber EqPEN[2]; + enum + { + SIM_XRES, + SIM_YRES, + SIM_XSIZE, + SIM_YSIZE, + SIM_MAXVAL, + SIM_SATURATION, + SIM_LIMITINGMAG, + SIM_NOISE, + SIM_SKYGLOW, + SIM_OAGOFFSET, + SIM_POLAR, + SIM_POLARDRIFT, + SIM_PE_PERIOD, + SIM_PE_MAX, + SIM_TIME_FACTOR, + SIM_ROTATION, + SIM_N + }; + + CCDSim(); + virtual ~CCDSim() override = default; + + const char *getDefaultName() override; + + bool initProperties() override; + bool updateProperties() override; + + void ISGetProperties(const char *dev) override; + + 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; + virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override; + virtual bool ISSnoopDevice(XMLEle *root) override; + + static void *streamVideoHelper(void *context); + void *streamVideo(); + +protected: + + bool Connect() override; + bool Disconnect() override; + + bool StartExposure(float duration) override; + bool StartGuideExposure(float) override; + + bool AbortExposure() override; + bool AbortGuideExposure() override; + + void TimerHit() override; + + int DrawCcdFrame(INDI::CCDChip *targetChip); + + int DrawImageStar(INDI::CCDChip *targetChip, float, float, float, float ExposureTime); + int AddToPixel(INDI::CCDChip *targetChip, int, int, int); + + virtual IPState GuideNorth(uint32_t) override; + virtual IPState GuideSouth(uint32_t) override; + virtual IPState GuideEast(uint32_t) override; + virtual IPState GuideWest(uint32_t) override; + + virtual bool saveConfigItems(FILE *fp) override; + virtual void addFITSKeywords(INDI::CCDChip *targetChip, std::vector &fitsKeyword) override; + virtual void activeDevicesUpdated() override; + virtual int SetTemperature(double temperature) override; + virtual bool UpdateCCDFrame(int x, int y, int w, int h) override; + virtual bool UpdateCCDBin(int hor, int ver) override; + virtual bool UpdateGuiderBin(int hor, int ver) override; + + virtual bool SetCaptureFormat(uint8_t index) override; + + virtual bool StartStreaming() override; + virtual bool StopStreaming() override; + + // Filter + bool SelectFilter(int) override; + int QueryFilter() override; + +protected: + + float CalcTimeLeft(timeval, float); + bool watchDirectory(); + bool loadNextImage(); + bool setupParameters(); + + // Turns on/off Bayer RGB simulation. + void setBayerEnabled(bool onOff); + + double flux(double magnitude) const; + + double TemperatureRequest { 0 }; + + float ExposureRequest { 0 }; + struct timeval ExpStart + { + 0, 0 + }; + + float GuideExposureRequest { 0 }; + struct timeval GuideExpStart + { + 0, 0 + }; + + int testvalue { 0 }; + bool ShowStarField { true }; + int m_Bias { 1500 }; + int m_MaxNoise { 20 }; + int m_MaxVal { 65000 }; + int maxpix { 0 }; + int minpix { 65000 }; + float m_SkyGlow { 40 }; + float m_LimitingMag { 11.5 }; + float m_SaturationMag { 2 }; + float seeing { 3.5 }; + float ImageScalex { 1.0 }; + float ImageScaley { 1.0 }; + // An oag is offset this much from center of scope position (arcminutes) + float m_OAGOffset { 0 }; + float m_RotationCW { 0 }; + float m_TimeFactor { 1 }; - ISwitch CoolerS[2]; - ISwitchVectorProperty CoolerSP; + bool m_SimulateBayer { false }; - INumber GainN[1]; - INumberVectorProperty GainNP; + // our zero point calcs used for drawing stars + //float k { 0 }; + //float z { 0 }; - INumber OffsetN[1]; - INumberVectorProperty OffsetNP; + bool AbortGuideFrame { false }; + bool AbortPrimaryFrame { false }; - INDI::PropertyText DirectoryTP {1}; - INDI::PropertySwitch DirectorySP {2}; + /// Guide rate is 7 arcseconds per second + float GuideRate { 7 }; - ISwitchVectorProperty CrashSP; - ISwitch CrashS[1]; + /// PEPeriod in minutes + float m_PEPeriod { 0 }; + // PE max in arcsecs + float m_PEMax { 0 }; - INDI::PropertySwitch ResolutionSP {2}; - inline static const std::vector> Resolutions = + double currentRA { 0 }; + double currentDE { 0 }; + bool usePE { false }; + time_t RunStart; + + float guideNSOffset {0}; + float guideWEOffset {0}; + + float m_PolarError { 0 }; + float m_PolarDrift { 0 }; + + double m_LastTemperature {0}; + + int streamPredicate {0}; + pthread_t primary_thread; + bool terminateThread; + + std::deque m_AllFiles, m_RemainingFiles; + + // And this lives in our simulator settings page + INDI::PropertyNumber SimulatorSettingsNP {16}; + + INDI::PropertySwitch SimulateBayerSP {2}; + enum + { + INDI_ENABLED, + INDI_DISABLED + }; + // We are going to snoop these from focuser + INumberVectorProperty FWHMNP; + INumber FWHMN[1]; + + // Focuser positions for focusing simulation + // FocuserPosition[0] is the position where the scope is in focus + // FocuserPosition[1] is the maximal position the focuser may move to (@see FOCUS_MAX in #indifocuserinterface.cpp) + // FocuserPosition[2] is the seeing (in arcsec) + // We need to have these values here, since we cannot snoop it from the focuser (the focuser does not + // publish these values) + INDI::PropertyNumber FocusSimulationNP {3}; + enum + { + SIM_FOCUS_POSITION, + SIM_FOCUS_MAX, + SIM_SEEING + }; + + INDI::PropertyNumber EqPENP {2}; + + INDI::PropertySwitch CoolerSP {2}; + + INDI::PropertyNumber GainNP {1}; + + INDI::PropertyNumber OffsetNP {1}; + + INDI::PropertyText DirectoryTP {1}; + INDI::PropertySwitch DirectorySP {2}; + + INDI::PropertySwitch CrashSP {1}; + + INDI::PropertySwitch ResolutionSP {2}; + inline static const std::vector> Resolutions = { {1280, 1024}, {6000, 4000} }; - static const constexpr char* SIMULATOR_TAB = "Simulator Config"; + static const constexpr char* SIMULATOR_TAB = "Simulator Config"; }; diff --git a/drivers/telescope/telescope_simulator.cpp b/drivers/telescope/telescope_simulator.cpp index 629d608255..6fe3e26e4c 100644 --- a/drivers/telescope/telescope_simulator.cpp +++ b/drivers/telescope/telescope_simulator.cpp @@ -84,7 +84,7 @@ bool ScopeSim::initProperties() mountModelNP.fill(getDeviceName(), "MOUNT_MODEL", "Mount Model", "Simulation", IP_WO, 0, IPS_IDLE); - flipHourAngleNP[FLIP_HA].fill("FLIP_HA", "Hour Angle (deg)", "%g", -20, 20, 0.1, 0); + flipHourAngleNP[0].fill("FLIP_HA", "Hour Angle (deg)", "%g", -20, 20, 0.1, 0); flipHourAngleNP.fill(getDeviceName(), "FLIP_HA", "Flip Posn.", "Simulation", IP_WO, 0, IPS_IDLE); @@ -433,7 +433,7 @@ bool ScopeSim::ISNewNumber(const char *dev, const char *name, double values[], c flipHourAngleNP.update(values, names, n); flipHourAngleNP.setState(IPS_OK); flipHourAngleNP.apply(); - alignment.setFlipHourAngle(flipHourAngleNP[FLIP_HA].getValue()); + alignment.setFlipHourAngle(flipHourAngleNP[0].getValue()); return true; } #endif diff --git a/drivers/telescope/telescope_simulator.h b/drivers/telescope/telescope_simulator.h index a754219453..3eaeabd4f3 100644 --- a/drivers/telescope/telescope_simulator.h +++ b/drivers/telescope/telescope_simulator.h @@ -165,10 +165,6 @@ class ScopeSim : public INDI::Telescope, public INDI::GuiderInterface }; INDI::PropertyNumber flipHourAngleNP {1}; - enum - { - FLIP_HA - }; #endif