Kstars

indicamerachip.cpp
1/*
2 SPDX-FileCopyrightText: 2022 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "indicamerachip.h"
8#include "indicamera.h"
9
10#include "Options.h"
11
12#include "indi_debug.h"
13
14namespace ISD
15{
16
17CameraChip::CameraChip(ISD::Camera *camera, ChipType type): m_Camera(camera), m_Type(type) {}
18
19FITSView *CameraChip::getImageView(FITSMode imageType)
20{
21 switch (imageType)
22 {
23 case FITS_NORMAL:
24 return normalImage;
25
26 case FITS_FOCUS:
27 return focusImage;
28
29 case FITS_GUIDE:
30 return guideImage;
31
32 case FITS_CALIBRATE:
33 return calibrationImage;
34
35 case FITS_ALIGN:
36 return alignImage;
37
38 default:
39 break;
40 }
41
42 return nullptr;
43}
44
45void CameraChip::setImageView(FITSView *image, FITSMode imageType)
46{
47 switch (imageType)
48 {
49 case FITS_NORMAL:
50 normalImage = image;
51 break;
52
53 case FITS_FOCUS:
54 focusImage = image;
55 break;
56
57 case FITS_GUIDE:
58 guideImage = image;
59 break;
60
61 case FITS_CALIBRATE:
62 calibrationImage = image;
63 break;
64
65 case FITS_ALIGN:
66 alignImage = image;
67 break;
68
69 default:
70 break;
71 }
72
73 if (image)
74 imageData = image->imageData();
75}
76
77bool CameraChip::getFrameMinMax(int *minX, int *maxX, int *minY, int *maxY, int *minW, int *maxW, int *minH, int *maxH)
78{
79 INumberVectorProperty *frameProp = nullptr;
80
81 switch (m_Type)
82 {
83 case PRIMARY_CCD:
84 frameProp = m_Camera->getNumber("CCD_FRAME");
85 break;
86
87 case GUIDE_CCD:
88 frameProp = m_Camera->getNumber("GUIDER_FRAME");
89 break;
90 }
91
92 if (frameProp == nullptr)
93 return false;
94
95 INumber *arg = IUFindNumber(frameProp, "X");
96
97 if (arg == nullptr)
98 return false;
99
100 if (minX)
101 *minX = arg->min;
102 if (maxX)
103 *maxX = arg->max;
104
105 arg = IUFindNumber(frameProp, "Y");
106
107 if (arg == nullptr)
108 return false;
109
110 if (minY)
111 *minY = arg->min;
112 if (maxY)
113 *maxY = arg->max;
114
115 arg = IUFindNumber(frameProp, "WIDTH");
116
117 if (arg == nullptr)
118 return false;
119
120 if (minW)
121 *minW = arg->min;
122 if (maxW)
123 *maxW = arg->max;
124
125 arg = IUFindNumber(frameProp, "HEIGHT");
126
127 if (arg == nullptr)
128 return false;
129
130 if (minH)
131 *minH = arg->min;
132 if (maxH)
133 *maxH = arg->max;
134
135 return true;
136}
137
138bool CameraChip::setImageInfo(uint16_t width, uint16_t height, double pixelX, double pixelY, uint8_t bitdepth)
139{
140 INumberVectorProperty *ccdInfoProp = nullptr;
141
142 switch (m_Type)
143 {
144 case PRIMARY_CCD:
145 ccdInfoProp = m_Camera->getNumber("CCD_INFO");
146 break;
147
148 case GUIDE_CCD:
149 ccdInfoProp = m_Camera->getNumber("GUIDER_INFO");
150 break;
151 }
152
153 if (ccdInfoProp == nullptr)
154 return false;
155
156 ccdInfoProp->np[0].value = width;
157 ccdInfoProp->np[1].value = height;
158 ccdInfoProp->np[2].value = std::hypotf(pixelX, pixelY);
159 ccdInfoProp->np[3].value = pixelX;
160 ccdInfoProp->np[4].value = pixelY;
161 ccdInfoProp->np[5].value = bitdepth;
162
163 m_Camera->sendNewProperty(ccdInfoProp);
164
165 return true;
166}
167
168bool CameraChip::getImageInfo(uint16_t &width, uint16_t &height, double &pixelX, double &pixelY, uint8_t &bitdepth)
169{
170 INumberVectorProperty *ccdInfoProp = nullptr;
171
172 switch (m_Type)
173 {
174 case PRIMARY_CCD:
175 ccdInfoProp = m_Camera->getNumber("CCD_INFO");
176 break;
177
178 case GUIDE_CCD:
179 ccdInfoProp = m_Camera->getNumber("GUIDER_INFO");
180 break;
181 }
182
183 if (ccdInfoProp == nullptr)
184 return false;
185
186 width = ccdInfoProp->np[0].value;
187 height = ccdInfoProp->np[1].value;
188 pixelX = ccdInfoProp->np[2].value;
189 pixelY = ccdInfoProp->np[3].value;
190 bitdepth = ccdInfoProp->np[5].value;
191
192 return true;
193}
194
195bool CameraChip::getBayerInfo(uint16_t &offsetX, uint16_t &offsetY, QString &pattern)
196{
197 ITextVectorProperty * bayerTP = m_Camera->getText("CCD_CFA");
198 if (!bayerTP)
199 return false;
200
201 offsetX = QString(bayerTP->tp[0].text).toInt();
202 offsetY = QString(bayerTP->tp[1].text).toInt();
203 pattern = QString(bayerTP->tp[2].text);
204
205 return true;
206}
207
208bool CameraChip::getFrame(int *x, int *y, int *w, int *h)
209{
210 INumberVectorProperty *frameProp = nullptr;
211
212 switch (m_Type)
213 {
214 case PRIMARY_CCD:
215 frameProp = m_Camera->getNumber("CCD_FRAME");
216 break;
217
218 case GUIDE_CCD:
219 frameProp = m_Camera->getNumber("GUIDER_FRAME");
220 break;
221 }
222
223 if (frameProp == nullptr)
224 return false;
225
226 INumber *arg = IUFindNumber(frameProp, "X");
227
228 if (arg == nullptr)
229 return false;
230
231 *x = arg->value;
232
233 arg = IUFindNumber(frameProp, "Y");
234 if (arg == nullptr)
235 return false;
236
237 *y = arg->value;
238
239 arg = IUFindNumber(frameProp, "WIDTH");
240 if (arg == nullptr)
241 return false;
242
243 *w = arg->value;
244
245 arg = IUFindNumber(frameProp, "HEIGHT");
246 if (arg == nullptr)
247 return false;
248
249 *h = arg->value;
250
251 return true;
252}
253
254bool CameraChip::resetFrame()
255{
256 INumberVectorProperty *frameProp = nullptr;
257
258 switch (m_Type)
259 {
260 case PRIMARY_CCD:
261 frameProp = m_Camera->getNumber("CCD_FRAME");
262 break;
263
264 case GUIDE_CCD:
265 frameProp = m_Camera->getNumber("GUIDER_FRAME");
266 break;
267 }
268
269 if (frameProp == nullptr)
270 return false;
271
272 INumber *xarg = IUFindNumber(frameProp, "X");
273 INumber *yarg = IUFindNumber(frameProp, "Y");
274 INumber *warg = IUFindNumber(frameProp, "WIDTH");
275 INumber *harg = IUFindNumber(frameProp, "HEIGHT");
276
277 if (xarg && yarg && warg && harg)
278 {
279 if (!std::fabs(xarg->value - xarg->min) &&
280 !std::fabs(yarg->value - yarg->min) &&
281 !std::fabs(warg->value - warg->max) &&
282 !std::fabs(harg->value - harg->max))
283 return false;
284
285 xarg->value = xarg->min;
286 yarg->value = yarg->min;
287 warg->value = warg->max;
288 harg->value = harg->max;
289
290 m_Camera->sendNewProperty(frameProp);
291 return true;
292 }
293
294 return false;
295}
296
297bool CameraChip::setFrame(int x, int y, int w, int h, bool force)
298{
299 INumberVectorProperty *frameProp = nullptr;
300
301 switch (m_Type)
302 {
303 case PRIMARY_CCD:
304 frameProp = m_Camera->getNumber("CCD_FRAME");
305 break;
306
307 case GUIDE_CCD:
308 frameProp = m_Camera->getNumber("GUIDER_FRAME");
309 break;
310 }
311
312 if (frameProp == nullptr)
313 return false;
314
315 INumber *xarg = IUFindNumber(frameProp, "X");
316 INumber *yarg = IUFindNumber(frameProp, "Y");
317 INumber *warg = IUFindNumber(frameProp, "WIDTH");
318 INumber *harg = IUFindNumber(frameProp, "HEIGHT");
319
320 if (xarg && yarg && warg && harg)
321 {
322 if (!force &&
323 !std::fabs(xarg->value - x) &&
324 !std::fabs(yarg->value - y) &&
325 !std::fabs(warg->value - w) &&
326 !std::fabs(harg->value - h))
327 return true;
328
329 xarg->value = x;
330 yarg->value = y;
331 warg->value = w;
332 harg->value = h;
333
334 m_Camera->sendNewProperty(frameProp);
335 return true;
336 }
337
338 return false;
339}
340
341bool CameraChip::capture(double exposure)
342{
343 //qCDebug(KSTARS_INDI) << "IndiCCD: capture()" << (type==PRIMARY_CCD?"CCD":"Guide");
344 INumberVectorProperty *expProp = nullptr;
345
346 switch (m_Type)
347 {
348 case PRIMARY_CCD:
349 expProp = m_Camera->getNumber("CCD_EXPOSURE");
350 break;
351
352 case GUIDE_CCD:
353 expProp = m_Camera->getNumber("GUIDER_EXPOSURE");
354 break;
355 }
356
357 if (expProp == nullptr)
358 return false;
359
360 // If we have exposure presets, let's limit the exposure value
361 // to the preset values if it falls within their range of max/min
362 if (Options::forceDSLRPresets())
363 {
364 QMap<QString, double> exposurePresets = m_Camera->getExposurePresets();
365 if (!exposurePresets.isEmpty())
366 {
367 double min, max;
368 QPair<double, double> minmax = m_Camera->getExposurePresetsMinMax();
369 min = minmax.first;
370 max = minmax.second;
371 if (exposure > min && exposure < max)
372 {
373 double diff = 1e6;
374 double closestMatch = exposure;
375 for (const auto &oneValue : exposurePresets.values())
376 {
377 double newDiff = std::fabs(exposure - oneValue);
378 if (newDiff < diff)
379 {
380 closestMatch = oneValue;
381 diff = newDiff;
382 }
383 }
384
385 qCDebug(KSTARS_INDI) << "Requested exposure" << exposure << "closes match is" << closestMatch;
386 exposure = closestMatch;
387 }
388 }
389 }
390
391 // clone the INumberVectorProperty, to avoid modifications to the same
392 // property from two threads
393 INumber n;
394 strcpy(n.name, expProp->np[0].name);
395 n.value = exposure;
396
397 std::unique_ptr<INumberVectorProperty> newExpProp(new INumberVectorProperty());
398 strncpy(newExpProp->device, expProp->device, MAXINDIDEVICE);
399 strncpy(newExpProp->name, expProp->name, MAXINDINAME);
400 strncpy(newExpProp->label, expProp->label, MAXINDILABEL);
401 newExpProp->np = &n;
402 newExpProp->nnp = 1;
403
404 m_Camera->sendNewProperty(newExpProp.get());
405
406 return true;
407}
408
409bool CameraChip::abortExposure()
410{
411 if (!m_Camera) return false;
412 ISwitchVectorProperty *abortProp = nullptr;
413
414 switch (m_Type)
415 {
416 case PRIMARY_CCD:
417 abortProp = m_Camera->getSwitch("CCD_ABORT_EXPOSURE");
418 break;
419
420 case GUIDE_CCD:
421 abortProp = m_Camera->getSwitch("GUIDER_ABORT_EXPOSURE");
422 break;
423 }
424
425 if (abortProp == nullptr)
426 return false;
427
428 ISwitch *abort = IUFindSwitch(abortProp, "ABORT");
429
430 if (abort == nullptr)
431 return false;
432
433 abort->s = ISS_ON;
434
435 m_Camera->sendNewProperty(abortProp);
436
437 return true;
438}
439bool CameraChip::canBin() const
440{
441 return CanBin && m_Camera->getEncodingFormat() != QLatin1String("Native");
442}
443
444void CameraChip::setCanBin(bool value)
445{
446 CanBin = value;
447}
448
449bool CameraChip::canSubframe() const
450{
451 return CanSubframe && m_Camera->getEncodingFormat() != QLatin1String("Native");
452}
453
454void CameraChip::setCanSubframe(bool value)
455{
456 CanSubframe = value;
457}
458bool CameraChip::canAbort() const
459{
460 return CanAbort;
461}
462
463void CameraChip::setCanAbort(bool value)
464{
465 CanAbort = value;
466}
467
468const QSharedPointer<FITSData> &CameraChip::getImageData() const
469{
470 return imageData;
471}
472
473int CameraChip::getISOIndex() const
474{
475 auto isoProp = m_Camera->getSwitch("CCD_ISO");
476
477 if (!isoProp)
478 return -1;
479
480 return isoProp->findOnSwitchIndex();
481}
482
483bool CameraChip::getISOValue(QString &value) const
484{
485 auto index = getISOIndex();
486 auto list = getISOList();
487 if (!list.isEmpty() && index >= 0 && index < list.count())
488 {
489 value = list[index];
490 return true;
491 }
492
493 return false;
494}
495
496bool CameraChip::setISOIndex(int value)
497{
498 auto isoProp = m_Camera->getSwitch("CCD_ISO");
499
500 if (!isoProp)
501 return false;
502
503 isoProp->reset();
504 isoProp->at(value)->setState(ISS_ON);
505
506 m_Camera->sendNewProperty(isoProp);
507
508 return true;
509}
510
511QStringList CameraChip::getISOList() const
512{
513 QStringList isoList;
514
515 auto isoProp = m_Camera->getSwitch("CCD_ISO");
516
517 if (!isoProp)
518 return isoList;
519
520 for (const auto &it : *isoProp)
521 isoList << it.getLabel();
522
523 return isoList;
524}
525
526bool CameraChip::isCapturing()
527{
528 if (!m_Camera) return false;
529 INumberVectorProperty *expProp = nullptr;
530
531 switch (m_Type)
532 {
533 case PRIMARY_CCD:
534 expProp = m_Camera->getNumber("CCD_EXPOSURE");
535 break;
536
537 case GUIDE_CCD:
538 expProp = m_Camera->getNumber("GUIDER_EXPOSURE");
539 break;
540 }
541
542 if (expProp == nullptr)
543 return false;
544
545 return (expProp->s == IPS_BUSY);
546}
547
548bool CameraChip::setFrameType(const QString &name)
549{
550 CCDFrameType fType = FRAME_LIGHT;
551
552 if (name == "FRAME_LIGHT" || name == "Light")
553 fType = FRAME_LIGHT;
554 else if (name == "FRAME_DARK" || name == "Dark")
555 fType = FRAME_DARK;
556 else if (name == "FRAME_BIAS" || name == "Bias")
557 fType = FRAME_BIAS;
558 else if (name == "FRAME_FLAT" || name == "Flat")
559 fType = FRAME_FLAT;
560 else
561 {
562 qCWarning(KSTARS_INDI) << name << " frame type is unknown." ;
563 return false;
564 }
565
566 return setFrameType(fType);
567}
568
569bool CameraChip::setFrameType(CCDFrameType fType)
570{
571 ISwitchVectorProperty *frameProp = nullptr;
572
573 if (m_Type == PRIMARY_CCD)
574 frameProp = m_Camera->getSwitch("CCD_FRAME_TYPE");
575 else
576 frameProp = m_Camera->getSwitch("GUIDER_FRAME_TYPE");
577 if (frameProp == nullptr)
578 return false;
579
580 ISwitch *ccdFrame = nullptr;
581
582 if (fType == FRAME_LIGHT)
583 ccdFrame = IUFindSwitch(frameProp, "FRAME_LIGHT");
584 else if (fType == FRAME_DARK)
585 ccdFrame = IUFindSwitch(frameProp, "FRAME_DARK");
586 else if (fType == FRAME_BIAS)
587 ccdFrame = IUFindSwitch(frameProp, "FRAME_BIAS");
588 else if (fType == FRAME_FLAT)
589 ccdFrame = IUFindSwitch(frameProp, "FRAME_FLAT");
590
591 if (ccdFrame == nullptr)
592 return false;
593
594 if (ccdFrame->s == ISS_ON)
595 return true;
596
597 if (fType != FRAME_LIGHT)
598 captureMode = FITS_CALIBRATE;
599
600 IUResetSwitch(frameProp);
601 ccdFrame->s = ISS_ON;
602
603 m_Camera->sendNewProperty(frameProp);
604
605 return true;
606}
607
608CCDFrameType CameraChip::getFrameType()
609{
610 CCDFrameType fType = FRAME_LIGHT;
611 ISwitchVectorProperty *frameProp = nullptr;
612
613 if (m_Type == PRIMARY_CCD)
614 frameProp = m_Camera->getSwitch("CCD_FRAME_TYPE");
615 else
616 frameProp = m_Camera->getSwitch("GUIDER_FRAME_TYPE");
617
618 if (frameProp == nullptr)
619 return fType;
620
621 ISwitch *ccdFrame = nullptr;
622
623 ccdFrame = IUFindOnSwitch(frameProp);
624
625 if (ccdFrame == nullptr)
626 {
627 qCWarning(KSTARS_INDI) << "ISD:CCD Cannot find active frame in CCD!";
628 return fType;
629 }
630
631 if (!strcmp(ccdFrame->name, "FRAME_LIGHT"))
632 fType = FRAME_LIGHT;
633 else if (!strcmp(ccdFrame->name, "FRAME_DARK"))
634 fType = FRAME_DARK;
635 else if (!strcmp(ccdFrame->name, "FRAME_FLAT"))
636 fType = FRAME_FLAT;
637 else if (!strcmp(ccdFrame->name, "FRAME_BIAS"))
638 fType = FRAME_BIAS;
639
640 return fType;
641}
642
643bool CameraChip::setBinning(CCDBinType binType)
644{
645 switch (binType)
646 {
647 case SINGLE_BIN:
648 return setBinning(1, 1);
649 case DOUBLE_BIN:
650 return setBinning(2, 2);
651 case TRIPLE_BIN:
652 return setBinning(3, 3);
653 case QUADRAPLE_BIN:
654 return setBinning(4, 4);
655 }
656
657 return false;
658}
659
660CCDBinType CameraChip::getBinning()
661{
662 CCDBinType binType = SINGLE_BIN;
663 INumberVectorProperty *binProp = nullptr;
664
665 switch (m_Type)
666 {
667 case PRIMARY_CCD:
668 binProp = m_Camera->getNumber("CCD_BINNING");
669 break;
670
671 case GUIDE_CCD:
672 binProp = m_Camera->getNumber("GUIDER_BINNING");
673 break;
674 }
675
676 if (binProp == nullptr)
677 return binType;
678
679 INumber *horBin = nullptr, *verBin = nullptr;
680
681 horBin = IUFindNumber(binProp, "HOR_BIN");
682 verBin = IUFindNumber(binProp, "VER_BIN");
683
684 if (!horBin || !verBin)
685 return binType;
686
687 switch (static_cast<int>(horBin->value))
688 {
689 case 2:
690 binType = DOUBLE_BIN;
691 break;
692
693 case 3:
694 binType = TRIPLE_BIN;
695 break;
696
697 case 4:
698 binType = QUADRAPLE_BIN;
699 break;
700
701 default:
702 break;
703 }
704
705 return binType;
706}
707
708bool CameraChip::getBinning(int *bin_x, int *bin_y)
709{
710 INumberVectorProperty *binProp = nullptr;
711 *bin_x = *bin_y = 1;
712
713 switch (m_Type)
714 {
715 case PRIMARY_CCD:
716 binProp = m_Camera->getNumber("CCD_BINNING");
717 break;
718
719 case GUIDE_CCD:
720 binProp = m_Camera->getNumber("GUIDER_BINNING");
721 break;
722 }
723
724 if (binProp == nullptr)
725 return false;
726
727 INumber *horBin = nullptr, *verBin = nullptr;
728
729 horBin = IUFindNumber(binProp, "HOR_BIN");
730 verBin = IUFindNumber(binProp, "VER_BIN");
731
732 if (!horBin || !verBin)
733 return false;
734
735 *bin_x = horBin->value;
736 *bin_y = verBin->value;
737
738 return true;
739}
740
741bool CameraChip::getMaxBin(int *max_xbin, int *max_ybin)
742{
743 if (!max_xbin || !max_ybin)
744 return false;
745
746 INumberVectorProperty *binProp = nullptr;
747
748 *max_xbin = *max_ybin = 1;
749
750 switch (m_Type)
751 {
752 case PRIMARY_CCD:
753 binProp = m_Camera->getNumber("CCD_BINNING");
754 break;
755
756 case GUIDE_CCD:
757 binProp = m_Camera->getNumber("GUIDER_BINNING");
758 break;
759 }
760
761 if (binProp == nullptr)
762 return false;
763
764 INumber *horBin = nullptr, *verBin = nullptr;
765
766 horBin = IUFindNumber(binProp, "HOR_BIN");
767 verBin = IUFindNumber(binProp, "VER_BIN");
768
769 if (!horBin || !verBin)
770 return false;
771
772 *max_xbin = horBin->max;
773 *max_ybin = verBin->max;
774
775 return true;
776}
777
778bool CameraChip::setBinning(int bin_x, int bin_y)
779{
780 INumberVectorProperty *binProp = nullptr;
781
782 switch (m_Type)
783 {
784 case PRIMARY_CCD:
785 binProp = m_Camera->getNumber("CCD_BINNING");
786 break;
787
788 case GUIDE_CCD:
789 binProp = m_Camera->getNumber("GUIDER_BINNING");
790 break;
791 }
792
793 if (binProp == nullptr)
794 return false;
795
796 INumber *horBin = IUFindNumber(binProp, "HOR_BIN");
797 INumber *verBin = IUFindNumber(binProp, "VER_BIN");
798
799 if (!horBin || !verBin)
800 return false;
801
802 if (!std::fabs(horBin->value - bin_x) && !std::fabs(verBin->value - bin_y))
803 return true;
804
805 if (bin_x > horBin->max || bin_y > verBin->max)
806 return false;
807
808 horBin->value = bin_x;
809 verBin->value = bin_y;
810
811 m_Camera->sendNewProperty(binProp);
812
813 return true;
814}
815
816}
Camera class controls an INDI Camera device.
Definition indicamera.h:45
ISD is a collection of INDI Standard Devices.
QString name(GameStandardAction id)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
qsizetype count() const const
bool isEmpty() const const
bool isEmpty() const const
QList< T > values() const const
int toInt(bool *ok, int base) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:43 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.