bool Camera_QHY::Connect(const wxString& camId) { if (QHYSDKInit()) { wxMessageBox(_("Failed to initialize QHY SDK")); return true; } int num_cams = ScanQHYCCD(); std::vector<std::string> camids; for (int i = 0; i < num_cams; i++) { char camid[32] = ""; GetQHYCCDId(i, camid); bool st4 = false; qhyccd_handle *h = OpenQHYCCD(camid); if (h) { uint32_t ret = IsQHYCCDControlAvailable(h, CONTROL_ST4PORT); if (ret == QHYCCD_SUCCESS) st4 = true; //CloseQHYCCD(h); // CloseQHYCCD() would proform a reset, so the other software that use QHY camera would be impacted. // Do not call this,would not cause memory leak.The SDk has already process this. } Debug.Write(wxString::Format("QHY cam [%d] %s avail %s st4 %s\n", i, camid, h ? "Yes" : "No", st4 ? "Yes" : "No")); if (st4) camids.push_back(camid); } if (camids.size() == 0) { wxMessageBox(_("No compatible QHY cameras found")); return true; } std::string camid; if (camids.size() > 1) { wxArrayString names; int n = 1; for (auto it = camids.begin(); it != camids.end(); ++it, ++n) names.Add(wxString::Format("%d: %s", n, *it)); int i = wxGetSingleChoiceIndex(_("Select QHY camera"), _("Camera choice"), names); if (i == -1) return true; camid = camids[i]; } else camid = camids[0]; char *s = new char[camid.length() + 1]; memcpy(s, camid.c_str(), camid.length() + 1); m_camhandle = OpenQHYCCD(s); delete[] s; Name = camid; if (!m_camhandle) { wxMessageBox(_("Failed to connect to camera")); return true; } // before calling InitQHYCCD() we must call SetQHYCCDStreamMode(camhandle, 0 or 1) // 0: single frame mode // 1: live frame mode uint32_t ret = SetQHYCCDStreamMode(m_camhandle, 0); if (ret != QHYCCD_SUCCESS) { CloseQHYCCD(m_camhandle); m_camhandle = 0; wxMessageBox(_("SetQHYCCDStreamMode failed")); return true; } ret = InitQHYCCD(m_camhandle); if (ret != QHYCCD_SUCCESS) { CloseQHYCCD(m_camhandle); m_camhandle = 0; wxMessageBox(_("Init camera failed")); return true; } ret = GetQHYCCDParamMinMaxStep(m_camhandle, CONTROL_GAIN, &m_gainMin, &m_gainMax, &m_gainStep); if (ret != QHYCCD_SUCCESS) { CloseQHYCCD(m_camhandle); m_camhandle = 0; wxMessageBox(_("Failed to get gain range")); return true; } double chipw, chiph, pixelw, pixelh; uint32_t imagew, imageh, bpp; ret = GetQHYCCDChipInfo(m_camhandle, &chipw, &chiph, &imagew, &imageh, &pixelw, &pixelh, &bpp); if (ret != QHYCCD_SUCCESS) { CloseQHYCCD(m_camhandle); m_camhandle = 0; wxMessageBox(_("Failed to get camera chip info")); return true; } int bayer = IsQHYCCDControlAvailable(m_camhandle, CAM_COLOR); Debug.Write(wxString::Format("QHY: cam reports bayer type %d\n", bayer)); Color = false; switch ((BAYER_ID)bayer) { case BAYER_GB: case BAYER_GR: case BAYER_BG: case BAYER_RG: Color = true; } // check bin modes CONTROL_ID modes[] = { CAM_BIN2X2MODE, CAM_BIN3X3MODE, CAM_BIN4X4MODE, }; int bin[] = { 2, 3, 4, }; int maxBin = 1; for (int i = 0; i < WXSIZEOF(modes); i++) { ret = IsQHYCCDControlAvailable(m_camhandle, modes[i]); #if 0 // FIXME- IsQHYCCDControlAvailable is supposed to return QHYCCD_ERROR_NOTSUPPORT for a // bin mode that is not supported, but in fact it returns QHYCCD_ERROR, so we cannot // distinguish "not supported" from "error". if (ret != QHYCCD_SUCCESS && ret != QHYCCD_ERROR_NOTSUPPORT) { CloseQHYCCD(m_camhandle); m_camhandle = 0; wxMessageBox(_("Failed to get camera bin info")); return true; } #endif if (ret == QHYCCD_SUCCESS) maxBin = bin[i]; else break; } Debug.Write(wxString::Format("QHY: max binning = %d\n", maxBin)); MaxBinning = maxBin; if (Binning > MaxBinning) Binning = MaxBinning; Debug.Write(wxString::Format("QHY: call SetQHYCCDBinMode bin = %d\n", Binning)); ret = SetQHYCCDBinMode(m_camhandle, Binning, Binning); if (ret != QHYCCD_SUCCESS) { CloseQHYCCD(m_camhandle); m_camhandle = 0; wxMessageBox(_("Failed to set camera binning")); return true; } m_curBin = Binning; m_maxSize = wxSize(imagew, imageh); FullSize = wxSize(imagew / Binning, imageh / Binning); delete[] RawBuffer; size_t size = GetQHYCCDMemLength(m_camhandle); RawBuffer = new unsigned char[size]; m_devicePixelSize = sqrt(pixelw * pixelh); m_curGain = -1; m_curExposure = -1; m_roi = wxRect(0, 0, FullSize.GetWidth(), FullSize.GetHeight()); // binned coordinates Debug.Write(wxString::Format("QHY: call SetQHYCCDResolution roi = %d,%d\n", m_roi.width, m_roi.height)); ret = SetQHYCCDResolution(m_camhandle, 0, 0, m_roi.GetWidth(), m_roi.GetHeight()); if (ret != QHYCCD_SUCCESS) { CloseQHYCCD(m_camhandle); m_camhandle = 0; wxMessageBox(_("Init camera failed")); return true; } Debug.Write(wxString::Format("QHY: connect done\n")); Connected = true; return false; }
bool QHYCCD::updateProperties() { double min=0, max=0, step=0; // This must be executed BEFORE INDI::CCD::updateProperties() // Since Primary CCD Exposure will be defined in there so we have to get its limits now { // Exposure limits in microseconds int ret = GetQHYCCDParamMinMaxStep(camhandle, CONTROL_EXPOSURE, &min, &max, &step); if (ret == QHYCCD_SUCCESS) PrimaryCCD.setMinMaxStep("CCD_EXPOSURE", "CCD_EXPOSURE_VALUE", min/1e6, max/1e6, step/1e6, false); else PrimaryCCD.setMinMaxStep("CCD_EXPOSURE", "CCD_EXPOSURE_VALUE", 0.001, 3600, 1, false); DEBUGF(INDI::Logger::DBG_DEBUG, "Exposure. Min: %g Max: %g Step %g", min, max, step); } // Define parent class properties INDI::CCD::updateProperties(); if (isConnected()) { if (HasCooler()) { defineSwitch(&CoolerSP); defineNumber(&CoolerNP); temperatureID = IEAddTimer(POLLMS, QHYCCD::updateTemperatureHelper, this); } if (HasUSBSpeed) { if (sim) { SpeedN[0].min = 1; SpeedN[0].max = 5; SpeedN[0].step = 1; SpeedN[0].value = 1; } else { int ret = GetQHYCCDParamMinMaxStep(camhandle, CONTROL_SPEED, &min, &max, &step); if (ret == QHYCCD_SUCCESS) { SpeedN[0].min = min; SpeedN[0].max = max; SpeedN[0].step = step; } SpeedN[0].value = GetQHYCCDParam(camhandle, CONTROL_SPEED); DEBUGF(INDI::Logger::DBG_DEBUG, "USB Speed. Value: %g Min: %g Max: %g Step %g", SpeedN[0].value, SpeedN[0].min, SpeedN[0].max, SpeedN[0].step); } defineNumber(&SpeedNP); } if (HasGain) { if (sim) { GainN[0].min = 0; GainN[0].max = 100; GainN[0].step = 10; GainN[0].value = 50; } else { int ret = GetQHYCCDParamMinMaxStep(camhandle, CONTROL_GAIN, &min, &max, &step); if (ret == QHYCCD_SUCCESS) { GainN[0].min = min; GainN[0].max = max; GainN[0].step = step; } GainN[0].value = GetQHYCCDParam(camhandle, CONTROL_GAIN); DEBUGF(INDI::Logger::DBG_DEBUG, "Gain. Value: %g Min: %g Max: %g Step %g", GainN[0].value, GainN[0].min, GainN[0].max, GainN[0].step); } defineNumber(&GainNP); } if (HasOffset) { if (sim) { OffsetN[0].min = 1; OffsetN[0].max = 10; OffsetN[0].step = 1; OffsetN[0].value = 1; } else { int ret = GetQHYCCDParamMinMaxStep(camhandle, CONTROL_OFFSET, &min, &max, &step); if (ret == QHYCCD_SUCCESS) { OffsetN[0].min = min; OffsetN[0].max = max; OffsetN[0].step = step; } OffsetN[0].value = GetQHYCCDParam(camhandle, CONTROL_OFFSET); DEBUGF(INDI::Logger::DBG_DEBUG, "Offset. Value: %g Min: %g Max: %g Step %g", OffsetN[0].value, OffsetN[0].min, OffsetN[0].max, OffsetN[0].step); } //Define the Offset defineNumber(&OffsetNP); } if (HasFilters) { INDI::FilterInterface::updateProperties(); } if (HasUSBTraffic) { if (sim) { USBTrafficN[0].min = 1; USBTrafficN[0].max = 100; USBTrafficN[0].step = 5; USBTrafficN[0].value = 20; } else { int ret = GetQHYCCDParamMinMaxStep(camhandle, CONTROL_USBTRAFFIC, &min, &max, &step); if (ret == QHYCCD_SUCCESS) { USBTrafficN[0].min = min; USBTrafficN[0].max = max; USBTrafficN[0].step = step; } USBTrafficN[0].value = GetQHYCCDParam(camhandle, CONTROL_USBTRAFFIC); DEBUGF(INDI::Logger::DBG_DEBUG, "USB Traffic. Value: %g Min: %g Max: %g Step %g", USBTrafficN[0].value, USBTrafficN[0].min, USBTrafficN[0].max, USBTrafficN[0].step); } defineNumber(&USBTrafficNP); } // Let's get parameters now from CCD setupParams(); //timerID = SetTimer(POLLMS); } else { if (HasCooler()) { deleteProperty(CoolerSP.name); deleteProperty(CoolerNP.name); } if (HasUSBSpeed) { deleteProperty(SpeedNP.name); } if (HasGain) { deleteProperty(GainNP.name); } if (HasOffset) { deleteProperty(OffsetNP.name); } if (HasFilters) { INDI::FilterInterface::updateProperties(); } if (HasUSBTraffic) deleteProperty(USBTrafficNP.name); RemoveTimer(timerID); } return true; }
bool QHYCCD::updateProperties() { INDI::CCD::updateProperties(); double min,max,step; if (isConnected()) { if (HasCooler()) { defineSwitch(&CoolerSP); defineNumber(&CoolerNP); temperatureID = IEAddTimer(POLLMS, QHYCCD::updateTemperatureHelper, this); } if(HasUSBSpeed) { if (sim) { SpeedN[0].min = 1; SpeedN[0].max = 5; SpeedN[0].step = 1; SpeedN[0].value = 1; } else { int ret = GetQHYCCDParamMinMaxStep(camhandle,CONTROL_SPEED,&min,&max,&step); if(ret == QHYCCD_SUCCESS) { SpeedN[0].min = min; SpeedN[0].max = max; SpeedN[0].step = step; } SpeedN[0].value = GetQHYCCDParam(camhandle,CONTROL_SPEED); DEBUGF(INDI::Logger::DBG_DEBUG, "USB Speed. Value: %g Min: %g Max: %g Step %g", SpeedN[0].value, SpeedN[0].min, SpeedN[0].max, SpeedN[0].step); } defineNumber(&SpeedNP); } if(HasGain) { if (sim) { GainN[0].min = 0; GainN[0].max = 100; GainN[0].step = 10; GainN[0].value = 50; } else { int ret = GetQHYCCDParamMinMaxStep(camhandle,CONTROL_GAIN,&min,&max,&step); if(ret == QHYCCD_SUCCESS) { GainN[0].min = min; GainN[0].max = max; GainN[0].step = step; } GainN[0].value = GetQHYCCDParam(camhandle,CONTROL_GAIN); DEBUGF(INDI::Logger::DBG_DEBUG, "Gain. Value: %g Min: %g Max: %g Step %g", GainN[0].value, GainN[0].min, GainN[0].max, GainN[0].step); } defineNumber(&GainNP); } if(HasOffset) { if (sim) { OffsetN[0].min = 1; OffsetN[0].max = 10; OffsetN[0].step = 1; OffsetN[0].value = 1; } else { int ret = GetQHYCCDParamMinMaxStep(camhandle,CONTROL_OFFSET,&min,&max,&step); if(ret == QHYCCD_SUCCESS) { OffsetN[0].min = min; OffsetN[0].max = max; OffsetN[0].step = step; } OffsetN[0].value = GetQHYCCDParam(camhandle,CONTROL_OFFSET); DEBUGF(INDI::Logger::DBG_DEBUG, "Offset. Value: %g Min: %g Max: %g Step %g", OffsetN[0].value, OffsetN[0].min, OffsetN[0].max, OffsetN[0].step); } //Define the Offset defineNumber(&OffsetNP); } if(HasFilters) { //Define the Filter Slot and name properties defineNumber(&FilterSlotNP); GetFilterNames(FILTER_TAB); defineText(FilterNameTP); } if (HasUSBTraffic) { if (sim) { USBTrafficN[0].min = 1; USBTrafficN[0].max = 100; USBTrafficN[0].step = 5; USBTrafficN[0].value = 20; } else { int ret = GetQHYCCDParamMinMaxStep(camhandle,CONTROL_USBTRAFFIC,&min,&max,&step); if(ret == QHYCCD_SUCCESS) { USBTrafficN[0].min = min; USBTrafficN[0].max = max; USBTrafficN[0].step = step; } USBTrafficN[0].value = GetQHYCCDParam(camhandle,CONTROL_USBTRAFFIC); DEBUGF(INDI::Logger::DBG_DEBUG, "USB Traffic. Value: %g Min: %g Max: %g Step %g", USBTrafficN[0].value, USBTrafficN[0].min, USBTrafficN[0].max, USBTrafficN[0].step); } defineNumber(&USBTrafficNP); } // Let's get parameters now from CCD setupParams(); //timerID = SetTimer(POLLMS); } else { if (HasCooler()) { deleteProperty(CoolerSP.name); deleteProperty(CoolerNP.name); } if(HasUSBSpeed) { deleteProperty(SpeedNP.name); } if(HasGain) { deleteProperty(GainNP.name); } if(HasOffset) { deleteProperty(OffsetNP.name); } if(HasFilters) { deleteProperty(FilterSlotNP.name); deleteProperty(FilterNameTP->name); } if (HasUSBTraffic) deleteProperty(USBTrafficNP.name); RemoveTimer(timerID); } return true; }