indiccd.cpp 53.6 KB
Newer Older
Jasem Mutlaq's avatar
Jasem Mutlaq committed
1 2 3 4 5 6 7 8 9
/*  INDI CCD
    Copyright (C) 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>

    This application is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
 */

10 11
#include <config-kstars.h>

Jasem Mutlaq's avatar
Jasem Mutlaq committed
12 13
#include <string.h>

Jasem Mutlaq's avatar
Jasem Mutlaq committed
14
#include <KMessageBox>
Jasem Mutlaq's avatar
Jasem Mutlaq committed
15
#include <QStatusBar>
16
#include <QImageReader>
17
#include <KNotifications/KNotification>
18

19
#include <basedevice.h>
Jasem Mutlaq's avatar
Jasem Mutlaq committed
20

Jasem Mutlaq's avatar
Jasem Mutlaq committed
21
#ifdef HAVE_CFITSIO
Jasem Mutlaq's avatar
Jasem Mutlaq committed
22 23
#include "fitsviewer/fitsviewer.h"
#include "fitsviewer/fitscommon.h"
24
#include "fitsviewer/fitsview.h"
25
#include "fitsviewer/fitsdata.h"
26 27
#endif

28 29 30 31
#ifdef HAVE_LIBRAW
#include <libraw/libraw.h>
#endif

Jasem Mutlaq's avatar
Jasem Mutlaq committed
32
#include "driverinfo.h"
Jasem Mutlaq's avatar
Jasem Mutlaq committed
33 34 35
#include "clientmanager.h"
#include "streamwg.h"
#include "indiccd.h"
36
#include "guimanager.h"
37
#include "kstarsdata.h"
Jasem Mutlaq's avatar
Jasem Mutlaq committed
38
#include "fov.h"
39
#include "kspaths.h"
Jasem Mutlaq's avatar
Jasem Mutlaq committed
40

41 42
#include <ekos/ekosmanager.h>

Jasem Mutlaq's avatar
Jasem Mutlaq committed
43 44
#include "Options.h"

45

Jasem Mutlaq's avatar
Jasem Mutlaq committed
46
const int MAX_FILENAME_LEN = 1024;
47
const QStringList RAWFormats = { "cr2", "crw", "nef", "raf", "dng", "arw" };
Jasem Mutlaq's avatar
Jasem Mutlaq committed
48 49 50 51

namespace ISD
{

Jasem Mutlaq's avatar
Jasem Mutlaq committed
52
CCDChip::CCDChip(ISD::CCD *ccd, ChipType cType)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
53
{
Jasem Mutlaq's avatar
Jasem Mutlaq committed
54 55 56
    baseDevice    = ccd->getBaseDevice();
    clientManager = ccd->getDriverInfo()->getClientManager();
    parentCCD     = ccd;
57
    type          = cType;
58
    batchMode     = false;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
59
    displayFITS   = true;
60 61 62
    CanBin        = false;
    CanSubframe   = false;
    CanAbort      = false;
63
    imageData     = NULL;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
64

65 66
    captureMode   = FITS_NORMAL;
    captureFilter = FITS_NONE;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
67

68
    //fx=fy=fw=fh=0;
69

70
    normalImage = focusImage = guideImage = calibrationImage = NULL;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
71 72
}

73
FITSView * CCDChip::getImageView(FITSMode imageType)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
74
{
75
    switch (imageType)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
76
    {
77 78 79
    case FITS_NORMAL:
        return normalImage;
        break;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
80

81 82 83
    case FITS_FOCUS:
        return focusImage;
        break;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
84

85 86 87
    case FITS_GUIDE:
        return guideImage;
        break;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
88

89 90 91
    case FITS_CALIBRATE:
        return calibrationImage;
        break;
92

93 94 95 96
    case FITS_ALIGN:
        return alignImage;
        break;

97
    default:
98
        break;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
99 100
    }

101
    return NULL;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
102

103
}
Jasem Mutlaq's avatar
Jasem Mutlaq committed
104

105
void CCDChip::setImageView(FITSView *image, FITSMode imageType)
106 107
{
    switch (imageType)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
108
    {
109 110 111
    case FITS_NORMAL:
        normalImage = image;
        break;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
112

113 114 115
    case FITS_FOCUS:
        focusImage = image;
        break;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
116

117 118 119
    case FITS_GUIDE:
        guideImage = image;
        break;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
120

121 122
    case FITS_CALIBRATE:
        calibrationImage = image;
123 124
        break;

125
    case FITS_ALIGN:
126
        alignImage = image;        
127
        break;
128

129
    default:
130
        break;
131
    }
Jasem Mutlaq's avatar
Jasem Mutlaq committed
132

133 134
    if (image)
        imageData = image->getImageData();
Jasem Mutlaq's avatar
Jasem Mutlaq committed
135 136
}

137 138 139 140 141 142
bool CCDChip::getFrameMinMax(int *minX, int *maxX, int *minY, int *maxY, int *minW, int *maxW, int *minH, int *maxH)
{
    INumberVectorProperty *frameProp = NULL;

    switch (type)
    {
143
    case PRIMARY_CCD:
144 145 146
        frameProp = baseDevice->getNumber("CCD_FRAME");
        break;

147
    case GUIDE_CCD:
148 149 150 151 152 153 154 155 156 157 158 159
        frameProp = baseDevice->getNumber("GUIDER_FRAME");
        break;

    }

    if (frameProp == NULL)
        return false;

    INumber *arg = IUFindNumber(frameProp, "X");
    if (arg == NULL)
        return false;

160 161
    if (minX) *minX = arg->min;
    if (maxX) *maxX = arg->max;
162 163 164 165 166 167


    arg = IUFindNumber(frameProp, "Y");
    if (arg == NULL)
        return false;

168 169
    if (minY) *minY = arg->min;
    if (maxY) *maxY = arg->max;
170 171 172 173 174

    arg = IUFindNumber(frameProp, "WIDTH");
    if (arg == NULL)
        return false;

175 176
    if (minW) *minW = arg->min;
    if (maxW) *maxW = arg->max;
177 178 179 180 181 182


    arg = IUFindNumber(frameProp, "HEIGHT");
    if (arg == NULL)
        return false;

183 184
    if (minH) *minH = arg->min;
    if (maxH) *maxH = arg->max;
185 186 187 188 189

    return true;

}

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
bool CCDChip::getPixelSize(double & x, double & y)
{
    INumberVectorProperty *ccdInfoProp = NULL;

    switch (type)
    {
    case PRIMARY_CCD:
        ccdInfoProp = baseDevice->getNumber("CCD_INFO");
        break;

    case GUIDE_CCD:
        ccdInfoProp = baseDevice->getNumber("GUIDER_INFO");
        break;

    }

    if (ccdInfoProp == NULL)
        return false;

    INumber *pixelX = IUFindNumber(ccdInfoProp, "CCD_PIXEL_SIZE_X");
    INumber *pixelY = IUFindNumber(ccdInfoProp, "CCD_PIXEL_SIZE_Y");

    if (pixelX == NULL || pixelY == NULL)
        return false;

    x = pixelX->value;
    y = pixelY->value;

    return true;
}

221
bool CCDChip::getFrame(int *x, int *y, int *w, int *h)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
222 223
{

Jasem Mutlaq's avatar
Jasem Mutlaq committed
224 225 226 227
    INumberVectorProperty *frameProp = NULL;

    switch (type)
    {
228
    case PRIMARY_CCD:
Jasem Mutlaq's avatar
Jasem Mutlaq committed
229 230 231
        frameProp = baseDevice->getNumber("CCD_FRAME");
        break;

232
    case GUIDE_CCD:
Jasem Mutlaq's avatar
Jasem Mutlaq committed
233
        frameProp = baseDevice->getNumber("GUIDER_FRAME");
Jasem Mutlaq's avatar
Jasem Mutlaq committed
234 235 236
        break;

    }
Jasem Mutlaq's avatar
Jasem Mutlaq committed
237 238 239 240 241 242 243 244 245 246

    if (frameProp == NULL)
        return false;

    INumber *arg = IUFindNumber(frameProp, "X");
    if (arg == NULL)
        return false;

    *x = arg->value;

247

Jasem Mutlaq's avatar
Jasem Mutlaq committed
248 249 250 251 252 253
    arg = IUFindNumber(frameProp, "Y");
    if (arg == NULL)
        return false;

    *y = arg->value;

254

Jasem Mutlaq's avatar
Jasem Mutlaq committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    arg = IUFindNumber(frameProp, "WIDTH");
    if (arg == NULL)
        return false;

    *w = arg->value;

    arg = IUFindNumber(frameProp, "HEIGHT");
    if (arg == NULL)
        return false;

    *h = arg->value;

    return true;

}

271
bool CCDChip::resetFrame()
272 273 274 275 276
{
    INumberVectorProperty *frameProp = NULL;

    switch (type)
    {
277
    case PRIMARY_CCD:
278 279 280
        frameProp = baseDevice->getNumber("CCD_FRAME");
        break;

281
    case GUIDE_CCD:
282 283 284 285 286 287
        frameProp = baseDevice->getNumber("GUIDER_FRAME");
        break;

    }

    if (frameProp == NULL)
288
        return false;
289 290 291 292 293 294 295 296 297

    INumber *xarg = IUFindNumber(frameProp, "X");
    INumber *yarg = IUFindNumber(frameProp, "Y");
    INumber *warg = IUFindNumber(frameProp, "WIDTH");
    INumber *harg = IUFindNumber(frameProp, "HEIGHT");

    if (xarg && yarg && warg && harg)
    {
        if (xarg->value == xarg->min && yarg->value == yarg->min && warg->value == warg->max && harg->value == harg->max)
298
            return false;
299 300 301 302 303 304 305

        xarg->value = xarg->min;
        yarg->value = yarg->min;
        warg->value = warg->max;
        harg->value = harg->max;

        clientManager->sendNewNumber(frameProp);
306
        return true;
307 308 309
    }


310
    return false;
311 312
}

313
bool CCDChip::setFrame(int x, int y, int w, int h)
314
{
Jasem Mutlaq's avatar
Jasem Mutlaq committed
315 316 317 318
    INumberVectorProperty *frameProp = NULL;

    switch (type)
    {
319
    case PRIMARY_CCD:
Jasem Mutlaq's avatar
Jasem Mutlaq committed
320 321 322
        frameProp = baseDevice->getNumber("CCD_FRAME");
        break;

323
    case GUIDE_CCD:
Jasem Mutlaq's avatar
Jasem Mutlaq committed
324
        frameProp = baseDevice->getNumber("GUIDER_FRAME");
Jasem Mutlaq's avatar
Jasem Mutlaq committed
325 326 327
        break;

    }
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354

    if (frameProp == NULL)
        return false;

    INumber *xarg = IUFindNumber(frameProp, "X");
    INumber *yarg = IUFindNumber(frameProp, "Y");
    INumber *warg = IUFindNumber(frameProp, "WIDTH");
    INumber *harg = IUFindNumber(frameProp, "HEIGHT");

    if (xarg && yarg && warg && harg)
    {
        if (xarg->value == x && yarg->value == y && warg->value == w && harg->value == h)
            return true;

        xarg->value = x;
        yarg->value = y;
        warg->value = w;
        harg->value = h;

        clientManager->sendNewNumber(frameProp);
        return true;
    }

    return false;

}

355
bool CCDChip::capture(double exposure)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
356
{
Jasem Mutlaq's avatar
Jasem Mutlaq committed
357 358 359 360
    INumberVectorProperty *expProp = NULL;

    switch (type)
    {
361
    case PRIMARY_CCD:
Jasem Mutlaq's avatar
Jasem Mutlaq committed
362
        expProp = baseDevice->getNumber("CCD_EXPOSURE");
Jasem Mutlaq's avatar
Jasem Mutlaq committed
363 364
        break;

365
    case GUIDE_CCD:
Jasem Mutlaq's avatar
Jasem Mutlaq committed
366
        expProp = baseDevice->getNumber("GUIDER_EXPOSURE");
Jasem Mutlaq's avatar
Jasem Mutlaq committed
367 368 369 370
        break;

    }

Jasem Mutlaq's avatar
Jasem Mutlaq committed
371 372 373 374 375 376 377 378 379 380
    if (expProp == NULL)
        return false;

    expProp->np[0].value = exposure;

    clientManager->sendNewNumber(expProp);

    return true;
}

381 382 383 384 385 386
bool CCDChip::abortExposure()
{
    ISwitchVectorProperty *abortProp = NULL;

    switch (type)
    {
387
    case PRIMARY_CCD:
388 389 390
        abortProp = baseDevice->getSwitch("CCD_ABORT_EXPOSURE");
        break;

391
    case GUIDE_CCD:
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
        abortProp = baseDevice->getSwitch("GUIDER_ABORT_EXPOSURE");
        break;

    }

    if (abortProp == NULL)
        return false;

    ISwitch *abort = IUFindSwitch(abortProp, "ABORT");

    if (abort == NULL)
        return false;

    abort->s = ISS_ON;

407
    //captureMode = FITS_NORMAL;
408

409 410 411 412
    clientManager->sendNewSwitch(abortProp);

    return true;
}
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
bool CCDChip::canBin() const
{
    return CanBin;
}

void CCDChip::setCanBin(bool value)
{
    CanBin = value;
}
bool CCDChip::canSubframe() const
{
    return CanSubframe;
}

void CCDChip::setCanSubframe(bool value)
{
    CanSubframe = value;
}
bool CCDChip::canAbort() const
{
    return CanAbort;
}

436
/*bool CCDChip::getFocusFrame(int *x, int *y, int *w, int *h)
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
{
    *x = fx;
    *y = fy;
    *w = fw;
    *h = fh;

    return true;
}

bool CCDChip::setFocusFrame(int x, int y, int w, int h)
{
    fx=x;
    fy=y;
    fw=w;
    fh=h;

    return true;
454
}*/
455

456 457 458 459
void CCDChip::setCanAbort(bool value)
{
    CanAbort = value;
}
460

461
FITSData *CCDChip::getImageData() const
462 463 464
{
    return imageData;
}
465

466
void CCDChip::setImageData(FITSData *value)
467 468 469
{
    imageData = value;
}
Jasem Mutlaq's avatar
Jasem Mutlaq committed
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
int CCDChip::getISOIndex() const
{
    ISwitchVectorProperty *isoProp = baseDevice->getSwitch("CCD_ISO");
    if (isoProp == NULL)
        return -1;

    return IUFindOnSwitchIndex(isoProp);
}

bool CCDChip::setISOIndex(int value)
{
    ISwitchVectorProperty *isoProp = baseDevice->getSwitch("CCD_ISO");
    if (isoProp == NULL)
        return false;

    IUResetSwitch(isoProp);
    isoProp->sp[value].s = ISS_ON;

    clientManager->sendNewSwitch(isoProp);

    return true;
}

QStringList CCDChip::getISOList() const
{
495
    QStringList isoList;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
496

497 498 499
    ISwitchVectorProperty *isoProp = baseDevice->getSwitch("CCD_ISO");
    if (isoProp == NULL)
        return isoList;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
500

501 502
    for (int i=0; i < isoProp->nsp; i++)
        isoList << isoProp->sp[i].label;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
503 504 505

    return isoList;
}
506

507 508 509
bool CCDChip::isCapturing()
{
    INumberVectorProperty *expProp = NULL;
510

511 512
    switch (type)
    {
513
    case PRIMARY_CCD:
514 515 516
        expProp = baseDevice->getNumber("CCD_EXPOSURE");
        break;

517
    case GUIDE_CCD:
518 519 520 521 522 523 524 525 526 527 528
        expProp = baseDevice->getNumber("GUIDER_EXPOSURE");
        break;

    }

    if (expProp == NULL)
        return false;

    return (expProp->s == IPS_BUSY);
}

529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
bool CCDChip::setFrameType(const QString & name)
{
    CCDFrameType fType = FRAME_LIGHT;

    if (name == "FRAME_LIGHT" || name == "Light")
        fType = FRAME_LIGHT;
    else if (name == "FRAME_DARK" || name == "Dark")
        fType = FRAME_DARK;
    else if (name == "FRAME_BIAS" || name == "Bias")
        fType = FRAME_BIAS;
    else if (name == "FRAME_FLAT" || name == "Flat")
        fType = FRAME_FLAT;
    else
    {
        qDebug() << name << " frame type is unknown." << endl;
        return false;
    }

    return setFrameType(fType);

}

551
bool CCDChip::setFrameType(CCDFrameType fType)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
552
{
553
    ISwitchVectorProperty *frameProp = NULL;
554

555 556 557
    if (type == PRIMARY_CCD)
        frameProp = baseDevice->getSwitch("CCD_FRAME_TYPE");
    else
558
        frameProp = baseDevice->getSwitch("GUIDER_FRAME_TYPE");
Jasem Mutlaq's avatar
Jasem Mutlaq committed
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
    if (frameProp == NULL)
        return false;

    ISwitch *ccdFrame = NULL;

    if (fType == FRAME_LIGHT)
        ccdFrame = IUFindSwitch(frameProp, "FRAME_LIGHT");
    else if (fType == FRAME_DARK)
        ccdFrame = IUFindSwitch(frameProp, "FRAME_DARK");
    else if (fType == FRAME_BIAS)
        ccdFrame = IUFindSwitch(frameProp, "FRAME_BIAS");
    else if (fType == FRAME_FLAT)
        ccdFrame = IUFindSwitch(frameProp, "FRAME_FLAT");

    if (ccdFrame == NULL)
        return false;

    if (ccdFrame->s == ISS_ON)
        return true;

579 580 581
    if (fType != FRAME_LIGHT)
        captureMode = FITS_CALIBRATE;

Jasem Mutlaq's avatar
Jasem Mutlaq committed
582 583 584 585 586 587 588 589
    IUResetSwitch(frameProp);
    ccdFrame->s = ISS_ON;

    clientManager->sendNewSwitch(frameProp);

    return true;
}

590 591 592 593
CCDFrameType CCDChip::getFrameType()
{

    CCDFrameType fType = FRAME_LIGHT;
594
    ISwitchVectorProperty *frameProp = NULL;
595

596 597 598
    if (type == PRIMARY_CCD)
        frameProp = baseDevice->getSwitch("CCD_FRAME_TYPE");
    else
599
        frameProp = baseDevice->getSwitch("GUIDER_FRAME_TYPE");
600 601 602 603 604 605 606 607 608 609

    if (frameProp == NULL)
        return fType;

    ISwitch *ccdFrame = NULL;

    ccdFrame = IUFindOnSwitch(frameProp);

    if (ccdFrame == NULL)
    {
610
        qDebug() << "ISD:CCD Cannot find active frame in CCD!" << endl;
611 612 613 614 615 616
        return fType;
    }

    if (!strcmp(ccdFrame->name, "FRAME_LIGHT"))
        fType = FRAME_LIGHT;
    else if (!strcmp(ccdFrame->name, "FRAME_DARK"))
617
        fType = FRAME_DARK;
618
    else if (!strcmp(ccdFrame->name, "FRAME_FLAT"))
619
        fType = FRAME_FLAT;
620
    else if (!strcmp(ccdFrame->name, "FRAME_BIAS"))
621
        fType = FRAME_BIAS;
622 623 624 625 626

    return fType;

}

627
bool CCDChip::setBinning(CCDBinType binType)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
628
{
629

Jasem Mutlaq's avatar
Jasem Mutlaq committed
630 631
    switch (binType)
    {
632 633 634 635 636 637 638 639 640 641 642 643
    case SINGLE_BIN:
        return setBinning(1,1);
        break;
    case DOUBLE_BIN:
        return setBinning(2,2);
        break;
    case TRIPLE_BIN:
        return setBinning(3,3);
        break;
    case QUADRAPLE_BIN:
        return setBinning(4,4);
        break;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
644 645 646 647 648
    }

    return false;
}

649
CCDBinType CCDChip::getBinning()
650 651
{
    CCDBinType binType = SINGLE_BIN;
652
    INumberVectorProperty *binProp=NULL;
653

654 655
    switch (type)
    {
656
    case PRIMARY_CCD:
657 658 659
        binProp = baseDevice->getNumber("CCD_BINNING");
        break;

660
    case GUIDE_CCD:
661
        binProp = baseDevice->getNumber("GUIDER_BINNING");
662 663
        break;
    }
664

665 666 667 668 669 670 671 672 673 674 675 676 677
    if (binProp == NULL)
        return binType;

    INumber *horBin = NULL, *verBin=NULL;

    horBin = IUFindNumber(binProp, "HOR_BIN");
    verBin = IUFindNumber(binProp, "VER_BIN");

    if (!horBin || !verBin)
        return binType;

    switch ( (int) horBin->value)
    {
678 679 680
    case 2:
        binType = DOUBLE_BIN;
        break;
681

682 683 684
    case 3:
        binType = TRIPLE_BIN;
        break;
685

686 687 688
    case 4:
        binType = QUADRAPLE_BIN;
        break;
689

690
    default:
691 692 693 694 695 696 697 698
        break;

    }

    return binType;

}

699
bool CCDChip::getBinning(int *bin_x, int *bin_y)
700
{
701
    INumberVectorProperty *binProp=NULL;
702
    *bin_x=*bin_y=1;
703 704 705

    switch (type)
    {
706
    case PRIMARY_CCD:
707 708 709
        binProp = baseDevice->getNumber("CCD_BINNING");
        break;

710
    case GUIDE_CCD:
711
        binProp = baseDevice->getNumber("GUIDER_BINNING");
712 713 714
        break;
    }

715

716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
    if (binProp == NULL)
        return false;

    INumber *horBin = NULL, *verBin=NULL;

    horBin = IUFindNumber(binProp, "HOR_BIN");
    verBin = IUFindNumber(binProp, "VER_BIN");

    if (!horBin || !verBin)
        return false;

    *bin_x = horBin->value;
    *bin_y = verBin->value;

    return true;
}
732

733 734 735 736 737 738 739 740
bool CCDChip::getMaxBin(int *max_xbin, int *max_ybin)
{

    INumberVectorProperty *binProp=NULL;
    *max_xbin=*max_ybin=1;

    switch (type)
    {
741
    case PRIMARY_CCD:
742 743 744
        binProp = baseDevice->getNumber("CCD_BINNING");
        break;

745
    case GUIDE_CCD:
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
        binProp = baseDevice->getNumber("GUIDER_BINNING");
        break;
    }


    if (binProp == NULL)
        return false;

    INumber *horBin = NULL, *verBin=NULL;

    horBin = IUFindNumber(binProp, "HOR_BIN");
    verBin = IUFindNumber(binProp, "VER_BIN");

    if (!horBin || !verBin)
        return false;

    *max_xbin = horBin->max;
    *max_ybin = verBin->max;

    return true;
}

768
bool CCDChip::setBinning(int bin_x, int bin_y)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
769
{
770

771
    INumberVectorProperty *binProp=NULL;
772 773 774

    switch (type)
    {
775
    case PRIMARY_CCD:
776 777 778
        binProp = baseDevice->getNumber("CCD_BINNING");
        break;

779
    case GUIDE_CCD:
780
        binProp = baseDevice->getNumber("GUIDER_BINNING");
781 782 783
        break;
    }

Jasem Mutlaq's avatar
Jasem Mutlaq committed
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
    if (binProp == NULL)
        return false;

    INumber *horBin = NULL, *verBin=NULL;

    horBin = IUFindNumber(binProp, "HOR_BIN");
    verBin = IUFindNumber(binProp, "VER_BIN");

    if (!horBin || !verBin)
        return false;

    if (horBin->value == bin_x && verBin->value == bin_y)
        return true;

    if (bin_x > horBin->max || bin_y > verBin->max)
        return false;

    horBin->value = bin_x;
    verBin->value = bin_y;

    clientManager->sendNewNumber(binProp);

    return true;

}

810 811 812 813 814 815

CCD::CCD(GDInterface *iPtr) : DeviceDecorator(iPtr)
{
    dType = KSTARS_CCD;
    ISOMode   = true;
    HasGuideHead = false;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
816
    HasCooler    = false;
817
    HasCoolerControl = false;
818
    HasVideoStream = false;
819 820 821
    fv          = NULL;
    streamWindow      = NULL;
    ST4Driver = NULL;
822
    nextSequenceID  = 0 ;
823

Jasem Mutlaq's avatar
Jasem Mutlaq committed
824
    primaryChip = new CCDChip(this, CCDChip::PRIMARY_CCD);
825

826
    normalTabID = calibrationTabID = focusTabID = guideTabID = alignTabID = -1;
827 828
    guideChip   = NULL;

829
    transferFormat = FORMAT_FITS;
830 831 832 833
}

CCD::~CCD()
{
Jasem Mutlaq's avatar
Jasem Mutlaq committed
834
#ifdef HAVE_CFITSIO
835
    delete (fv);
836
#endif
837 838
    delete (primaryChip);
    delete (guideChip);
839
    delete (streamWindow);
840 841 842 843
}

void CCD::registerProperty(INDI::Property *prop)
{
Jasem Mutlaq's avatar
Jasem Mutlaq committed
844
    if (!strcmp(prop->getName(), "GUIDER_EXPOSURE"))
845 846
    {
        HasGuideHead = true;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
847
        guideChip = new CCDChip(this, CCDChip::GUIDE_CCD);
848
    }
849 850 851 852
    else if (!strcmp(prop->getName(), "CCD_FRAME_TYPE"))
    {
        ISwitchVectorProperty *ccdFrame = prop->getSwitch();

853 854
        primaryChip->clearFrameTypes();

855 856 857
        for (int i=0; i < ccdFrame->nsp; i++)
            primaryChip->addFrameLabel(ccdFrame->sp[i].label);
    }
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
    else if (!strcmp(prop->getName(), "CCD_FRAME"))
    {
        INumberVectorProperty *np = prop->getNumber();
        if (np && np->p != IP_RO)
            primaryChip->setCanSubframe(true);
    }
    else if (!strcmp(prop->getName(), "GUIDER_FRAME"))
    {
        INumberVectorProperty *np = prop->getNumber();
        if (np && np->p != IP_RO)
            guideChip->setCanSubframe(true);
    }
    else if (!strcmp(prop->getName(), "CCD_BINNING"))
    {
        INumberVectorProperty *np = prop->getNumber();
        if (np && np->p != IP_RO)
            primaryChip->setCanBin(true);
    }
    else if (!strcmp(prop->getName(), "GUIDER_BINNING"))
    {
        INumberVectorProperty *np = prop->getNumber();
        if (np && np->p != IP_RO)
            guideChip->setCanBin(true);
    }
    else if (!strcmp(prop->getName(), "CCD_ABORT_EXPOSURE"))
    {
        ISwitchVectorProperty *sp = prop->getSwitch();
        if (sp && sp->p != IP_RO)
            primaryChip->setCanAbort(true);
    }
    else if (!strcmp(prop->getName(), "GUIDER_ABORT_EXPOSURE"))
    {
        ISwitchVectorProperty *sp = prop->getSwitch();
        if (sp && sp->p != IP_RO)
            guideChip->setCanAbort(true);
    }
Jasem Mutlaq's avatar
Jasem Mutlaq committed
894 895 896 897 898 899 900
    else if (!strcmp(prop->getName(), "CCD_TEMPERATURE"))
    {
        INumberVectorProperty *np = prop->getNumber();
        HasCooler = true;
        if (np)
            emit newTemperatureValue(np->np[0].value);
    }
901 902 903 904 905
    else if (!strcmp(prop->getName(), "CCD_COOLER"))
    {
        // Can turn cooling on/off
        HasCoolerControl = true;
    }
906 907 908 909 910
    else if (!strcmp(prop->getName(), "CCD_VIDEO_STREAM"))
    {
        // Has Video Stream
        HasVideoStream = true;
    }
911 912 913 914 915 916 917 918 919 920 921 922
    else if (!strcmp(prop->getName(), "CCD_TRANSFER_FORMAT"))
    {
        ISwitchVectorProperty *sp = prop->getSwitch();
        if (sp)
        {
            ISwitch *format = IUFindSwitch(sp, "FORMAT_NATIVE");
            if (format && format->s == ISS_ON)
                transferFormat = FORMAT_NATIVE;
            else
                transferFormat = FORMAT_FITS;
        }
    }
923 924 925 926 927 928 929 930 931 932 933

    DeviceDecorator::registerProperty(prop);
}

void CCD::processLight(ILightVectorProperty *lvp)
{
    DeviceDecorator::processLight(lvp);
}

void CCD::processNumber(INumberVectorProperty *nvp)
{
Jasem Mutlaq's avatar
Jasem Mutlaq committed
934
    if (!strcmp(nvp->name, "CCD_EXPOSURE"))
935
    {
936 937
        INumber *np = IUFindNumber(nvp, "CCD_EXPOSURE_VALUE");
        if (np)
938
            emit newExposureValue(primaryChip, np->value, nvp->s);
Jasem Mutlaq's avatar
Jasem Mutlaq committed
939 940 941 942 943 944

        return;
    }

    if (!strcmp(nvp->name, "CCD_TEMPERATURE"))
    {
945
        HasCooler = true;
Jasem Mutlaq's avatar
Jasem Mutlaq committed
946
        INumber *np = IUFindNumber(nvp, "CCD_TEMPERATURE_VALUE");
947 948
        if (np)
            emit newTemperatureValue(np->value);
Jasem Mutlaq's avatar
Jasem Mutlaq committed
949

950
        return;
951 952
    }

Jasem Mutlaq's avatar
Jasem Mutlaq committed
953
    if (!strcmp(nvp->name, "GUIDER_EXPOSURE"))
954
    {
955 956
        INumber *np = IUFindNumber(nvp, "GUIDER_EXPOSURE_VALUE");
        if (np)
957
            emit newExposureValue(guideChip, np->value, nvp->s);
958
        return;
959 960
    }

961 962 963 964
    if (!strcmp(nvp->name, "CCD_RAPID_GUIDE_DATA"))
    {
        double dx=-1,dy=-1,fit=-1;
        INumber *np=NULL;
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985

        if (nvp->s == IPS_ALERT)
        {
            emit newGuideStarData(primaryChip, -1, -1, -1);
        }
        else
        {
            np = IUFindNumber(nvp, "GUIDESTAR_X");
            if (np)
                dx = np->value;
            np = IUFindNumber(nvp, "GUIDESTAR_Y");
            if (np)
                dy = np->value;
            np = IUFindNumber(nvp, "GUIDESTAR_FIT");
            if (np)
                fit = np->value;

            if (dx >= 0 && dy >= 0 && fit >= 0)
                emit newGuideStarData(primaryChip, dx, dy, fit);
        }

986 987
        return;

988 989 990 991 992 993 994
    }

    if (!strcmp(nvp->name, "GUIDER_RAPID_GUIDE_DATA"))
    {
        double dx=-1,dy=-1,fit=-1;
        INumber *np=NULL;

995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
        if (nvp->s == IPS_ALERT)
        {
            emit newGuideStarData(guideChip, -1, -1, -1);

        }
        else
        {
            np = IUFindNumber(nvp, "GUIDESTAR_X");
            if (np)
                dx = np->value;
            np = IUFindNumber(nvp, "GUIDESTAR_Y");
            if (np)
                dy = np->value;
            np = IUFindNumber(nvp, "GUIDESTAR_FIT");
            if (np)
                fit = np->value;
1011

1012 1013 1014 1015
            if (dx >= 0 && dy >= 0 && fit >= 0)
                emit newGuideStarData(guideChip, dx, dy, fit);
        }

1016 1017
        return;

1018
    }
1019

1020 1021 1022 1023 1024
    DeviceDecorator::processNumber(nvp);
}

void CCD::processSwitch(ISwitchVectorProperty *svp)
{
1025 1026 1027 1028
    if (!strcmp(svp->name, "CCD_COOLER"))
    {
        // Can turn cooling on/off
        HasCoolerControl = true;
1029
        return;
1030 1031
    }

1032
    if (QString(svp->name).endsWith("VIDEO_STREAM"))
1033
    {
1034 1035
        HasVideoStream = true;

1036
        if (streamWindow == NULL && svp->sp[0].s == ISS_ON)
1037
        {
1038
            streamWindow = new StreamWG(this);
1039

1040 1041 1042 1043
            // Only use CCD dimensions if we are receing raw stream and not stream of images (i.e. mjpeg..etc)
            IBLOBVectorProperty *rawBP = baseDevice->getBLOB("CCD1");
            if (rawBP)
            {
1044 1045
                int x,y,w,h;
                int binx, biny;
1046

1047 1048 1049 1050
                primaryChip->getFrame(&x, &y, &w, &h);
                primaryChip->getBinning(&binx, &biny);
                streamW = w / binx;
                streamH = h / biny;
1051

1052 1053
                rawBP->bp[0].aux0 = &(streamW);
                rawBP->bp[0].aux1 = &(streamH);
1054

1055
                if (streamWindow->getStreamWidth() != streamW || streamWindow->getStreamHeight() != streamH)
1056
                    streamWindow->setSize(streamW, streamH);
1057
            }
1058

1059 1060
        }

1061 1062
        if (streamWindow)
        {
1063 1064
            connect(streamWindow, SIGNAL(hidden()), this, SLOT(StreamWindowHidden()), Qt::UniqueConnection);

1065 1066
            streamWindow->enableStream(svp->sp[0].s == ISS_ON);
            emit videoStreamToggled(svp->sp[0].s == ISS_ON);
1067
        }
1068

1069 1070
        emit switchUpdated(svp);

1071 1072 1073
        return;
    }