bool QHYCCD::UpdateCCDBin(int hor, int ver) { int ret = QHYCCD_ERROR; if (hor != ver) { DEBUG(INDI::Logger::DBG_ERROR, "Invalid binning mode. Asymmetrical binning not supported."); return false; } if (hor == 3) { DEBUG(INDI::Logger::DBG_ERROR, "Invalid binning mode. Only 1x1, 2x2, and 4x4 binning modes supported."); return false; } if (hor > 1 && GetCCDCapability() & CCD_HAS_BAYER) { DEBUG(INDI::Logger::DBG_ERROR, "Binning not supported for color CCDs."); return false; } //PrimaryCCD.setBin(hor,ver); //camxbin = hor; //camybin = ver; //return UpdateCCDFrame(PrimaryCCD.getSubX(), PrimaryCCD.getSubY(), PrimaryCCD.getSubW(), PrimaryCCD.getSubH()); if(hor == 1 && ver == 1) { ret = IsQHYCCDControlAvailable(camhandle,CAM_BIN1X1MODE); } else if(hor == 2 && ver == 2) { ret = IsQHYCCDControlAvailable(camhandle,CAM_BIN2X2MODE); } else if(hor == 3 && ver == 3) { ret = IsQHYCCDControlAvailable(camhandle,CAM_BIN3X3MODE); } else if(hor == 4 && ver == 4) { ret = IsQHYCCDControlAvailable(camhandle,CAM_BIN4X4MODE); } if(ret == QHYCCD_SUCCESS) { PrimaryCCD.setBin(hor,ver); camxbin = hor; camybin = ver; return UpdateCCDFrame(PrimaryCCD.getSubX(), PrimaryCCD.getSubY(), PrimaryCCD.getSubW(), PrimaryCCD.getSubH()); } DEBUGF(INDI::Logger::DBG_ERROR, "SetBin mode failed. Invalid bin requested %dx%d",hor,ver); return false; }
bool QHYCCD::UpdateCCDBin(int hor, int ver) { int ret = QHYCCD_ERROR; if (hor != ver) { DEBUG(INDI::Logger::DBG_ERROR, "Invalid binning mode. Asymmetrical binning not supported."); return false; } if (hor == 3) { DEBUG(INDI::Logger::DBG_ERROR, "Invalid binning mode. Only 1x1, 2x2, and 4x4 binning modes supported."); return false; } if (hor > 1 && GetCCDCapability() & CCD_HAS_BAYER) { DEBUG(INDI::Logger::DBG_ERROR, "Binning not supported for color CCDs."); return false; } if (useSoftBin) ret = QHYCCD_SUCCESS; else if (hor == 1 && ver == 1) { ret = IsQHYCCDControlAvailable(camhandle, CAM_BIN1X1MODE); } else if (hor == 2 && ver == 2) { ret = IsQHYCCDControlAvailable(camhandle, CAM_BIN2X2MODE); } else if (hor == 3 && ver == 3) { ret = IsQHYCCDControlAvailable(camhandle, CAM_BIN3X3MODE); } else if (hor == 4 && ver == 4) { ret = IsQHYCCDControlAvailable(camhandle, CAM_BIN4X4MODE); } // Binning ALWAYS succeeds if (ret != QHYCCD_SUCCESS) { useSoftBin = true; } // We always use software binning so QHY binning is always at 1x1 camxbin = 1; camybin = 1; PrimaryCCD.setBin(hor, ver); return UpdateCCDFrame(PrimaryCCD.getSubX(), PrimaryCCD.getSubY(), PrimaryCCD.getSubW(), PrimaryCCD.getSubH()); }
bool QHYCCD::Connect() { unsigned int ret = 0; uint32_t cap; sim = isSimulation(); if (sim) { cap = CCD_CAN_SUBFRAME | CCD_CAN_ABORT | CCD_CAN_BIN | CCD_HAS_COOLER | CCD_HAS_ST4_PORT; SetCCDCapability(cap); HasUSBTraffic = true; HasUSBSpeed = true; HasGain = true; HasOffset = true; HasFilters = true; return true; } // Query the current CCD cameras. This method makes the driver more robust and // it fixes a crash with the new QHC SDK when the INDI driver reopens the same camera // with OpenQHYCCD() without a ScanQHYCCD() call before. // 2017-12-15 JM: No this method ReleaseQHYCCDResource which ends up clearing handles for multiple // cameras /*std::vector<std::string> devices = GetDevicesIDs(); // The CCD device is not available anymore if (std::find(devices.begin(), devices.end(), std::string(camid)) == devices.end()) { DEBUGF(INDI::Logger::DBG_ERROR, "Error: Camera %s is not connected", camid); return false; }*/ camhandle = OpenQHYCCD(camid); if (camhandle != NULL) { DEBUGF(INDI::Logger::DBG_SESSION, "Connected to %s.", camid); cap = CCD_CAN_ABORT | CCD_CAN_SUBFRAME | CCD_HAS_STREAMING; // Disable the stream mode before connecting ret = SetQHYCCDStreamMode(camhandle, 0); if (ret != QHYCCD_SUCCESS) { DEBUGF(INDI::Logger::DBG_ERROR, "Error: Can not disable stream mode (%d)", ret); } ret = InitQHYCCD(camhandle); if (ret != QHYCCD_SUCCESS) { DEBUGF(INDI::Logger::DBG_ERROR, "Error: Init Camera failed (%d)", ret); return false; } ret = IsQHYCCDControlAvailable(camhandle, CAM_MECHANICALSHUTTER); if (ret == QHYCCD_SUCCESS) { cap |= CCD_HAS_SHUTTER; } DEBUGF(INDI::Logger::DBG_DEBUG, "Shutter Control: %s", cap & CCD_HAS_SHUTTER ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle, CONTROL_COOLER); if (ret == QHYCCD_SUCCESS) { cap |= CCD_HAS_COOLER; } DEBUGF(INDI::Logger::DBG_DEBUG, "Cooler Control: %s", cap & CCD_HAS_COOLER ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle, CONTROL_ST4PORT); if (ret == QHYCCD_SUCCESS) { cap |= CCD_HAS_ST4_PORT; } DEBUGF(INDI::Logger::DBG_DEBUG, "Guider Port Control: %s", cap & CCD_HAS_ST4_PORT ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle, CONTROL_SPEED); if (ret == QHYCCD_SUCCESS) { HasUSBSpeed = true; // Force a certain speed on initialization of QHY5PII-C: // CONTROL_SPEED = 2 - Fastest, but the camera gets stuck with long exposure times. // CONTROL_SPEED = 1 - This is safe with the current driver. // CONTROL_SPEED = 0 - This is safe, but slower than 1. if (isQHY5PIIC()) SetQHYCCDParam(camhandle, CONTROL_SPEED, 1); } DEBUGF(INDI::Logger::DBG_DEBUG, "USB Speed Control: %s", HasUSBSpeed ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle, CONTROL_GAIN); if (ret == QHYCCD_SUCCESS) { HasGain = true; } DEBUGF(INDI::Logger::DBG_DEBUG, "Gain Control: %s", HasGain ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle, CONTROL_OFFSET); if (ret == QHYCCD_SUCCESS) { HasOffset = true; } DEBUGF(INDI::Logger::DBG_DEBUG, "Offset Control: %s", HasOffset ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle, CONTROL_CFWPORT); if (ret == QHYCCD_SUCCESS) { HasFilters = true; } DEBUGF(INDI::Logger::DBG_DEBUG, "Has Filters: %s", HasFilters ? "True" : "False"); // Using software binning cap |= CCD_CAN_BIN; camxbin = 1; camybin = 1; // Always use INDI software binning //useSoftBin = true; ret = IsQHYCCDControlAvailable(camhandle,CAM_BIN1X1MODE); if(ret == QHYCCD_SUCCESS) { camxbin = 1; camybin = 1; } DEBUGF(INDI::Logger::DBG_DEBUG, "Bin 1x1: %s", (ret == QHYCCD_SUCCESS) ? "True" : "False"); ret &= IsQHYCCDControlAvailable(camhandle,CAM_BIN2X2MODE); ret &= IsQHYCCDControlAvailable(camhandle,CAM_BIN3X3MODE); ret &= IsQHYCCDControlAvailable(camhandle,CAM_BIN4X4MODE); // Only use software binning if NOT supported by hardware //useSoftBin = !(ret == QHYCCD_SUCCESS); DEBUGF(INDI::Logger::DBG_DEBUG, "Binning Control: %s", cap & CCD_CAN_BIN ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle, CONTROL_USBTRAFFIC); if (ret == QHYCCD_SUCCESS) { HasUSBTraffic = true; // Force the USB traffic value to 30 on initialization of QHY5PII-C otherwise // the camera has poor transfer speed. if (isQHY5PIIC()) SetQHYCCDParam(camhandle, CONTROL_USBTRAFFIC, 30); } DEBUGF(INDI::Logger::DBG_DEBUG, "USB Traffic Control: %s", HasUSBTraffic ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle, CAM_COLOR); //if(ret != QHYCCD_ERROR && ret != QHYCCD_ERROR_NOTSUPPORT) if (ret != QHYCCD_ERROR) { if (ret == BAYER_GB) IUSaveText(&BayerT[2], "GBRG"); else if (ret == BAYER_GR) IUSaveText(&BayerT[2], "GRBG"); else if (ret == BAYER_BG) IUSaveText(&BayerT[2], "BGGR"); else IUSaveText(&BayerT[2], "RGGB"); DEBUGF(INDI::Logger::DBG_DEBUG, "Color CCD: %s", BayerT[2].text); cap |= CCD_HAS_BAYER; } SetCCDCapability(cap); terminateThread = false; pthread_create(&primary_thread, NULL, &streamVideoHelper, this); return true; } DEBUGF(INDI::Logger::DBG_ERROR, "Connecting to CCD failed (%s)", camid); return false; }
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::Connect() { sim = isSimulation(); int ret; uint32_t cap; if (sim) { cap = CCD_CAN_SUBFRAME | CCD_CAN_ABORT | CCD_CAN_BIN | CCD_HAS_COOLER | CCD_HAS_ST4_PORT; SetCCDCapability(cap); HasUSBTraffic = true; HasUSBSpeed = true; HasGain = true; HasOffset = true; HasFilters = true; return true; } camhandle = OpenQHYCCD(camid); if(camhandle != NULL) { DEBUGF(INDI::Logger::DBG_SESSION, "Connected to %s.",camid); #ifdef OSX_EMBEDED_MODE cap = CCD_CAN_ABORT | CCD_CAN_SUBFRAME; #else cap = CCD_CAN_ABORT | CCD_CAN_SUBFRAME | CCD_HAS_STREAMING; #endif ret = InitQHYCCD(camhandle); if(ret != QHYCCD_SUCCESS) { DEBUGF(INDI::Logger::DBG_ERROR, "Error: Init Camera failed (%d)", ret); return false; } ret = IsQHYCCDControlAvailable(camhandle,CAM_MECHANICALSHUTTER); if(ret == QHYCCD_SUCCESS) { cap |= CCD_HAS_SHUTTER; } DEBUGF(INDI::Logger::DBG_DEBUG, "Shutter Control: %s", cap & CCD_HAS_SHUTTER ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle,CONTROL_COOLER); if(ret == QHYCCD_SUCCESS) { cap |= CCD_HAS_COOLER; } DEBUGF(INDI::Logger::DBG_DEBUG, "Cooler Control: %s", cap & CCD_HAS_COOLER ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle,CONTROL_ST4PORT); if(ret == QHYCCD_SUCCESS) { cap |= CCD_HAS_ST4_PORT; } DEBUGF(INDI::Logger::DBG_DEBUG, "Guider Port Control: %s", cap & CCD_HAS_ST4_PORT ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle,CONTROL_SPEED); if(ret == QHYCCD_SUCCESS) { HasUSBSpeed = true; } DEBUGF(INDI::Logger::DBG_DEBUG, "USB Speed Control: %s", HasUSBSpeed ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle,CONTROL_GAIN); if(ret == QHYCCD_SUCCESS) { HasGain = true; } DEBUGF(INDI::Logger::DBG_DEBUG, "Gain Control: %s", HasGain ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle,CONTROL_OFFSET); if(ret == QHYCCD_SUCCESS) { HasOffset = true; } DEBUGF(INDI::Logger::DBG_DEBUG, "Offset Control: %s", HasOffset ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle,CONTROL_CFWPORT); if(ret == QHYCCD_SUCCESS) { HasFilters = true; } DEBUGF(INDI::Logger::DBG_DEBUG, "Has Filters: %s", HasFilters ? "True" : "False"); // Using software binning cap |= CCD_CAN_BIN; camxbin = 1; camybin = 1; ret = IsQHYCCDControlAvailable(camhandle,CAM_BIN1X1MODE); if(ret == QHYCCD_SUCCESS) { camxbin = 1; camybin = 1; } DEBUGF(INDI::Logger::DBG_DEBUG, "Bin 1x1: %s", (ret == QHYCCD_SUCCESS) ? "True" : "False"); ret &= IsQHYCCDControlAvailable(camhandle,CAM_BIN2X2MODE); ret &= IsQHYCCDControlAvailable(camhandle,CAM_BIN3X3MODE); ret &= IsQHYCCDControlAvailable(camhandle,CAM_BIN4X4MODE); if(ret == QHYCCD_SUCCESS) { cap |= CCD_CAN_BIN; } DEBUGF(INDI::Logger::DBG_DEBUG, "Binning Control: %s", cap & CCD_CAN_BIN ? "True" : "False"); ret= IsQHYCCDControlAvailable(camhandle, CONTROL_USBTRAFFIC); if (ret == QHYCCD_SUCCESS) { HasUSBTraffic = true; } DEBUGF(INDI::Logger::DBG_DEBUG, "USB Traffic Control: %s", HasUSBTraffic ? "True" : "False"); ret = IsQHYCCDControlAvailable(camhandle,CAM_COLOR); //if(ret != QHYCCD_ERROR && ret != QHYCCD_ERROR_NOTSUPPORT) if(ret != QHYCCD_ERROR) { if(ret == BAYER_GB) IUSaveText(&BayerT[2], "GBGR"); else if (ret == BAYER_GR) IUSaveText(&BayerT[2], "GRGB"); else if (ret == BAYER_BG) IUSaveText(&BayerT[2], "BGGR"); else IUSaveText(&BayerT[2], "RGGB"); DEBUGF(INDI::Logger::DBG_DEBUG, "Color CCD: %s", BayerT[2].text); cap |= CCD_HAS_BAYER; } SetCCDCapability(cap); #ifndef OSX_EMBEDED_MODE pthread_create( &primary_thread, NULL, &streamVideoHelper, this); #endif return true; } DEBUGF(INDI::Logger::DBG_ERROR, "Connecting to CCD failed (%s)",camid); return false; }