Instrument Neutral Distributed Interface INDI  1.9.2
indiccdchip.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2019 Jasem Mutlaq. All rights reserved.
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 *******************************************************************************/
18 #include "indiccdchip.h"
19 #include "indidevapi.h"
20 #include "locale_compat.h"
21 
22 #include <cstring>
23 #include <ctime>
24 
25 namespace INDI
26 {
27 
29 {
30  strncpy(ImageExtention, "fits", MAXINDIBLOBFMT);
31 }
32 
34 {
35  delete [] RawFrame;
36  delete[] BinFrame;
37 }
38 
39 void CCDChip::setFrameType(CCD_FRAME type)
40 {
41  FrameType = type;
42 }
43 
44 void CCDChip::setResolution(uint32_t x, uint32_t y)
45 {
46  XRes = x;
47  YRes = y;
48 
49  ImagePixelSizeN[0].value = x;
50  ImagePixelSizeN[1].value = y;
51 
52  IDSetNumber(&ImagePixelSizeNP, nullptr);
53 
54  ImageFrameN[FRAME_X].min = 0;
55  ImageFrameN[FRAME_X].max = x - 1;
56  ImageFrameN[FRAME_Y].min = 0;
57  ImageFrameN[FRAME_Y].max = y - 1;
58 
59  ImageFrameN[FRAME_W].min = 1;
60  ImageFrameN[FRAME_W].max = x;
61  ImageFrameN[FRAME_H].min = 1;
62  ImageFrameN[FRAME_H].max = y;
63  IUUpdateMinMax(&ImageFrameNP);
64 }
65 
66 void CCDChip::setFrame(uint32_t subx, uint32_t suby, uint32_t subw, uint32_t subh)
67 {
68  SubX = subx;
69  SubY = suby;
70  SubW = subw;
71  SubH = subh;
72 
73  ImageFrameN[FRAME_X].value = SubX;
74  ImageFrameN[FRAME_Y].value = SubY;
75  ImageFrameN[FRAME_W].value = SubW;
76  ImageFrameN[FRAME_H].value = SubH;
77 
78  IDSetNumber(&ImageFrameNP, nullptr);
79 }
80 
81 void CCDChip::setBin(uint8_t hor, uint8_t ver)
82 {
83  BinX = hor;
84  BinY = ver;
85 
86  ImageBinN[BIN_W].value = BinX;
87  ImageBinN[BIN_H].value = BinY;
88 
89  IDSetNumber(&ImageBinNP, nullptr);
90 }
91 
92 void CCDChip::setMinMaxStep(const char *property, const char *element, double min, double max, double step,
93  bool sendToClient)
94 {
95  INumberVectorProperty *nvp = nullptr;
96 
97  if (!strcmp(property, ImageExposureNP.name))
98  nvp = &ImageExposureNP;
99  else if (!strcmp(property, ImageFrameNP.name))
100  nvp = &ImageFrameNP;
101  else if (!strcmp(property, ImageBinNP.name))
102  nvp = &ImageBinNP;
103  else if (!strcmp(property, ImagePixelSizeNP.name))
104  nvp = &ImagePixelSizeNP;
105  // else if (!strcmp(property, RapidGuideDataNP.name))
106  // nvp = &RapidGuideDataNP;
107  else
108  return;
109 
110  INumber *np = IUFindNumber(nvp, element);
111  if (np)
112  {
113  np->min = min;
114  np->max = max;
115  np->step = step;
116 
117  if (sendToClient)
118  IUUpdateMinMax(nvp);
119  }
120 }
121 
122 void CCDChip::setPixelSize(double x, double y)
123 {
124  PixelSizeX = x;
125  PixelSizeY = y;
126 
127  ImagePixelSizeN[2].value = x;
128  ImagePixelSizeN[3].value = x;
129  ImagePixelSizeN[4].value = y;
130 
131  IDSetNumber(&ImagePixelSizeNP, nullptr);
132 }
133 
134 void CCDChip::setBPP(uint8_t bbp)
135 {
136  BitsPerPixel = bbp;
137 
138  ImagePixelSizeN[5].value = BitsPerPixel;
139 
140  IDSetNumber(&ImagePixelSizeNP, nullptr);
141 }
142 
143 void CCDChip::setFrameBufferSize(uint32_t nbuf, bool allocMem)
144 {
145  if (nbuf == RawFrameSize)
146  return;
147 
148  RawFrameSize = nbuf;
149 
150  if (allocMem == false)
151  return;
152 
153  delete [] RawFrame;
154  RawFrame = new uint8_t[nbuf];
155 
156  if (BinFrame)
157  {
158  delete [] BinFrame;
159  BinFrame = new uint8_t[nbuf];
160  }
161 }
162 
163 void CCDChip::setExposureLeft(double duration)
164 {
165  ImageExposureNP.s = IPS_BUSY;
166  ImageExposureN[0].value = duration;
167 
168  IDSetNumber(&ImageExposureNP, nullptr);
169 }
170 
171 void CCDChip::setExposureDuration(double duration)
172 {
173  ExposureDuration = duration;
174  gettimeofday(&StartExposureTime, nullptr);
175 }
176 
177 const char *CCDChip::getFrameTypeName(CCD_FRAME fType)
178 {
179  return FrameTypeS[fType].name;
180 }
181 
182 const char *CCDChip::getExposureStartTime()
183 {
184  static char ts[32];
185 
186  char iso8601[32] = {0};
187  struct tm *tp = nullptr;
188 
189  // Get exposure startup timestamp
190  time_t t = static_cast<time_t>(StartExposureTime.tv_sec);
191 
192  // Get UTC timestamp
193  tp = gmtime(&t);
194 
195  // Format it in ISO8601 format
196  strftime(iso8601, sizeof(iso8601), "%Y-%m-%dT%H:%M:%S", tp);
197 
198  // Add millisecond
199  snprintf(ts, 32, "%s.%03d", iso8601, static_cast<int>(StartExposureTime.tv_usec / 1000.0));
200 
201  return (ts);
202 }
203 
204 //void CCDChip::setInterlaced(bool intr)
205 //{
206 // Interlaced = intr;
207 //}
208 
210 {
211  ImageExposureNP.s = IPS_ALERT;
212  IDSetNumber(&ImageExposureNP, nullptr);
213 }
214 
215 int CCDChip::getNAxis() const
216 {
217  return NAxis;
218 }
219 
220 void CCDChip::setNAxis(int value)
221 {
222  NAxis = value;
223 }
224 
225 void CCDChip::setImageExtension(const char *ext)
226 {
227  strncpy(ImageExtention, ext, MAXINDIBLOBFMT);
228 }
229 
230 void CCDChip::binFrame()
231 {
232  if (BinX == 1)
233  return;
234 
235  // Jasem: Keep full frame shadow in memory to enhance performance and just swap frame pointers after operation is complete
236  if (BinFrame == nullptr)
237  BinFrame = new uint8_t[RawFrameSize];
238 
239  memset(BinFrame, 0, RawFrameSize);
240 
241  switch (getBPP())
242  {
243  case 8:
244  {
245  uint8_t *bin_buf = BinFrame;
246  // Try to average pixels since in 8bit they get saturated pretty quickly
247  double factor = (BinX * BinX) / 2;
248  double accumulator = 0;
249 
250  for (uint32_t i = 0; i < SubH; i += BinX)
251  for (uint32_t j = 0; j < SubW; j += BinX)
252  {
253  accumulator = 0;
254  for (int k = 0; k < BinX; k++)
255  {
256  for (int l = 0; l < BinX; l++)
257  {
258  accumulator += *(RawFrame + j + (i + k) * SubW + l);
259  }
260  }
261 
262  accumulator /= factor;
263  if (accumulator > UINT8_MAX)
264  *bin_buf = UINT8_MAX;
265  else
266  *bin_buf += static_cast<uint8_t>(accumulator);
267  bin_buf++;
268  }
269  }
270  break;
271 
272  case 16:
273  {
274  uint16_t *bin_buf = reinterpret_cast<uint16_t *>(BinFrame);
275  uint16_t *RawFrame16 = reinterpret_cast<uint16_t *>(RawFrame);
276  uint16_t val;
277  for (uint32_t i = 0; i < SubH; i += BinX)
278  for (uint32_t j = 0; j < SubW; j += BinX)
279  {
280  for (int k = 0; k < BinX; k++)
281  {
282  for (int l = 0; l < BinX; l++)
283  {
284  val = *(RawFrame16 + j + (i + k) * SubW + l);
285  if (val + *bin_buf > UINT16_MAX)
286  *bin_buf = UINT16_MAX;
287  else
288  *bin_buf += val;
289  }
290  }
291  bin_buf++;
292  }
293  }
294  break;
295 
296  default:
297  return;
298  }
299 
300  // Swap frame pointers
301  uint8_t *rawFramePointer = RawFrame;
302  RawFrame = BinFrame;
303  // We just memset it next time we use it
304  BinFrame = rawFramePointer;
305 }
306 
307 }
INDI::CCDChip::setFrameBufferSize
void setFrameBufferSize(uint32_t nbuf, bool allocMem=true)
setFrameBufferSize Set desired frame buffer size. The function will allocate memory accordingly....
Definition: indiccdchip.cpp:159
INDI::CCDChip::getFrameTypeName
const char * getFrameTypeName(CCD_FRAME fType)
getFrameTypeName returns CCD Frame type name
Definition: indiccdchip.cpp:193
INDI::CCDChip::setBin
void setBin(uint8_t hor, uint8_t ver)
setBin Set CCD Chip binnig
Definition: indiccdchip.cpp:97
indiccdchip.h
IUUpdateMinMax
void IUUpdateMinMax(const INumberVectorProperty *nvp)
Function to update the min and max elements of a number in the client.
Definition: indidriver.c:1849
_INumberVectorProperty::s
IPState s
Definition: indiapi.h:332
min
double min(void)
locale_compat.h
INDI::CCDChip::setFrameType
void setFrameType(CCD_FRAME type)
setFrameType Set desired frame type for next exposure.
Definition: indiccdchip.cpp:55
IPS_ALERT
@ IPS_ALERT
Definition: indiapi.h:163
INumber
One number descriptor.
MAXINDIBLOBFMT
#define MAXINDIBLOBFMT
Definition: indiapi.h:195
INDI::CCDChip::FRAME_X
@ FRAME_X
Definition: indiccdchip.h:71
INDI::CCDChip::setExposureDuration
void setExposureDuration(double duration)
setExposureDuration Set desired CCD frame exposure duration for next exposure. You must call this fun...
Definition: indiccdchip.cpp:187
INDI::CCDChip::setExposureLeft
void setExposureLeft(double duration)
setExposureLeft Update exposure time left. Inform the client of the new exposure time left value.
Definition: indiccdchip.cpp:179
max
double max(void)
INDI::CCDChip::setBPP
void setBPP(uint8_t bpp)
setBPP Set depth of CCD chip.
Definition: indiccdchip.cpp:150
INDI::CCDChip::setExposureFailed
void setExposureFailed()
setExposureFailed Alert the client that the exposure failed.
Definition: indiccdchip.cpp:225
INDI::CCDChip::BIN_H
@ BIN_H
Definition: indiccdchip.h:72
type
__le16 type
Definition: pwc-ioctl.h:2
_INumberVectorProperty
Number vector property descriptor.
Definition: indiapi.h:317
indidevapi.h
Interface to the reference INDI C API device implementation on the Device Driver side.
INDI::CCDChip::FRAME_W
@ FRAME_W
Definition: indiccdchip.h:71
IPS_BUSY
@ IPS_BUSY
Definition: indiapi.h:162
INDI::CCDChip::CCDChip
CCDChip()
Definition: indiccdchip.cpp:44
INDI::CCDChip::getExposureStartTime
const char * getExposureStartTime()
getExposureStartTime
Definition: indiccdchip.cpp:198
_INumberVectorProperty::name
char name[MAXINDINAME]
Definition: indiapi.h:322
INDI::CCDChip::getBPP
int getBPP() const
getBPP Get CCD Chip depth (bits per pixel).
Definition: indiccdchip.h:177
INDI::CCDChip::setImageExtension
void setImageExtension(const char *ext)
setImageExtension Set image exntension
Definition: indiccdchip.cpp:241
IUFindNumber
INumber * IUFindNumber(const INumberVectorProperty *nvp, const char *name)
Find an INumber member in a number text property.
Definition: indicom.c:1351
INDI::CCDChip::setFrame
void setFrame(uint32_t subx, uint32_t suby, uint32_t subw, uint32_t subh)
setFrame Set desired frame resolutoin for an exposure.
Definition: indiccdchip.cpp:82
INDI::CCDChip::FRAME_Y
@ FRAME_Y
Definition: indiccdchip.h:71
INDI::CCDChip::setPixelSize
void setPixelSize(double x, double y)
setPixelSize Set CCD Chip pixel size
Definition: indiccdchip.cpp:138
INDI::CCDChip::getNAxis
int getNAxis() const
Definition: indiccdchip.cpp:231
INDI::CCDChip::setNAxis
void setNAxis(int value)
setNAxis Set FITS number of axis
Definition: indiccdchip.cpp:236
INDI
Namespace to encapsulate INDI client, drivers, and mediator classes.
Definition: AlignmentSubsystemForClients.cpp:11
INDI::CCDChip::~CCDChip
~CCDChip()
Definition: indiccdchip.cpp:49
INDI::CCDChip::setMinMaxStep
void setMinMaxStep(const char *property, const char *element, double min, double max, double step, bool sendToClient=true)
setMinMaxStep for a number property element
Definition: indiccdchip.cpp:108
INDI::CCDChip::binFrame
void binFrame()
binFrame Perform softwre binning on the CCD frame. Only use this function if hardware binning is not ...
Definition: indiccdchip.cpp:246
INDI::CCDChip::BIN_W
@ BIN_W
Definition: indiccdchip.h:72
IDSetNumber
void void void IDSetNumber(const INumberVectorProperty *n, const char *msg,...) ATTRIBUTE_FORMAT_PRINTF(2
Tell client to update an existing number vector property.
INDI::CCDChip::FRAME_H
@ FRAME_H
Definition: indiccdchip.h:71
INDI::CCDChip::setResolution
void setResolution(uint32_t x, uint32_t y)
setResolution set CCD Chip resolution
Definition: indiccdchip.cpp:60