Instrument Neutral Distributed Interface INDI  2.0.2
simpleccd.cpp
Go to the documentation of this file.
1 /*
2  INDI Developers Manual
3  Tutorial #3
4 
5  "Simple CCD Driver"
6 
7  We develop a simple CCD driver.
8 
9  Refer to README, which contains instruction on how to build this driver, and use it
10  with an INDI-compatible client.
11 
12 */
13 
23 #include "simpleccd.h"
24 
25 #include <memory>
26 
27 /* Macro shortcut to CCD temperature value */
28 #define currentCCDTemperature TemperatureN[0].value
29 
30 std::unique_ptr<SimpleCCD> simpleCCD(new SimpleCCD());
31 
32 /**************************************************************************************
33 ** Client is asking us to establish connection to the device
34 ***************************************************************************************/
36 {
37  IDMessage(getDeviceName(), "Simple CCD connected successfully!");
38 
39  // Let's set a timer that checks teleCCDs status every POLLMS milliseconds.
41  return true;
42 }
43 
44 /**************************************************************************************
45 ** Client is asking us to terminate connection to the device
46 ***************************************************************************************/
48 {
49  IDMessage(getDeviceName(), "Simple CCD disconnected successfully!");
50  return true;
51 }
52 
53 /**************************************************************************************
54 ** INDI is asking us for our default device name
55 ***************************************************************************************/
57 {
58  return "Simple CCD";
59 }
60 
61 /**************************************************************************************
62 ** INDI is asking us to init our properties.
63 ***************************************************************************************/
65 {
66  // Must init parent properties first!
68 
69  // We set the CCD capabilities
71  SetCCDCapability(cap);
72 
73  // Add Debug, Simulator, and Configuration controls
75 
77 
78  return true;
79 }
80 
81 /********************************************************************************************
82 ** INDI is asking us to update the properties because there is a change in CONNECTION status
83 ** This fucntion is called whenever the device is connected or disconnected.
84 *********************************************************************************************/
86 {
87  // Call parent update properties first
89 
90  if (isConnected())
91  {
92  // Let's get parameters now from CCD
93  setupParams();
94 
95  // Start the timer
97  }
98 
99  return true;
100 }
101 
102 /**************************************************************************************
103 ** Setting up CCD parameters
104 ***************************************************************************************/
105 void SimpleCCD::setupParams()
106 {
107  // Our CCD is an 8 bit CCD, 1280x1024 resolution, with 5.4um square pixels.
108  SetCCDParams(1280, 1024, 8, 5.4, 5.4);
109 
110  // Let's calculate how much memory we need for the primary CCD buffer
111  uint32_t nbuf = PrimaryCCD.getXRes() * PrimaryCCD.getYRes() * PrimaryCCD.getBPP() / 8;
113 }
114 
115 /**************************************************************************************
116 ** Client is asking us to start an exposure
117 ***************************************************************************************/
118 bool SimpleCCD::StartExposure(float duration)
119 {
120  ExposureRequest = duration;
121 
122  // Since we have only have one CCD with one chip, we set the exposure duration of the primary CCD
124 
125  ExposureTimer.start();
126  InExposure = true;
127 
128  // We're done
129  return true;
130 }
131 
132 /**************************************************************************************
133 ** Client is asking us to abort an exposure
134 ***************************************************************************************/
136 {
137  InExposure = false;
138  return true;
139 }
140 
141 /**************************************************************************************
142 ** Client is asking us to set a new temperature
143 ***************************************************************************************/
144 int SimpleCCD::SetTemperature(double temperature)
145 {
146  TemperatureRequest = temperature;
147 
148  // 0 means it will take a while to change the temperature
149  return 0;
150 }
151 
152 /**************************************************************************************
153 ** How much longer until exposure is done?
154 ***************************************************************************************/
155 float SimpleCCD::CalcTimeLeft()
156 {
157  return ExposureRequest - ExposureTimer.elapsed() / 1000.0;
158 }
159 
160 /**************************************************************************************
161 ** Main device loop. We check for exposure and temperature progress here
162 ***************************************************************************************/
164 {
165  if (!isConnected())
166  return; // No need to reset timer if we are not connected anymore
167 
168  if (InExposure)
169  {
170  double timeleft = CalcTimeLeft();
171 
172  // Less than a 0.1 second away from exposure completion
173  // This is an over simplified timing method, check CCDSimulator and simpleCCD for better timing checks
174  if (timeleft < 0.1)
175  {
176  /* We're done exposing */
177  IDMessage(getDeviceName(), "Exposure done, downloading image...");
178 
179  // Set exposure left to zero
181 
182  // We're no longer exposing...
183  InExposure = false;
184 
185  /* grab and save image */
186  grabImage();
187  }
188  else
189  // Just update time left in client
190  PrimaryCCD.setExposureLeft(timeleft);
191  }
192 
193  // TemperatureNP is defined in INDI::CCD
194  switch (TemperatureNP.s)
195  {
196  case IPS_IDLE:
197  case IPS_OK:
198  break;
199 
200  case IPS_BUSY:
201  /* If target temperature is higher, then increase current CCD temperature */
202  if (currentCCDTemperature < TemperatureRequest)
204  /* If target temperature is lower, then decrese current CCD temperature */
205  else if (currentCCDTemperature > TemperatureRequest)
207  /* If they're equal, stop updating */
208  else
209  {
211  IDSetNumber(&TemperatureNP, "Target temperature reached.");
212 
213  break;
214  }
215 
216  IDSetNumber(&TemperatureNP, nullptr);
217 
218  break;
219 
220  case IPS_ALERT:
221  break;
222  }
223 
225 }
226 
227 /**************************************************************************************
228 ** Create a random image and return it to client
229 ***************************************************************************************/
230 void SimpleCCD::grabImage()
231 {
232  // Let's get a pointer to the frame buffer
233  uint8_t *image = PrimaryCCD.getFrameBuffer();
234 
235  // Get width and height
236  int width = PrimaryCCD.getSubW() / PrimaryCCD.getBinX() * PrimaryCCD.getBPP() / 8;
237  int height = PrimaryCCD.getSubH() / PrimaryCCD.getBinY();
238 
239  // Fill buffer with random pattern
240  for (int i = 0; i < height; i++)
241  for (int j = 0; j < width; j++)
242  image[i * width + j] = rand() % 255;
243 
244  IDMessage(getDeviceName(), "Download complete.");
245 
246  // Let INDI::CCD know we're done filling the image buffer
248 }
bool isConnected() const
Definition: basedevice.cpp:520
const char * getDeviceName() const
Definition: basedevice.cpp:821
uint8_t * getFrameBuffer()
getFrameBuffer Get raw frame buffer of the CCD chip.
Definition: indiccdchip.h:209
void setExposureDuration(double duration)
setExposureDuration Set desired CCD frame exposure duration for next exposure. You must call this fun...
int getSubH() const
getSubH Get the height of the frame
Definition: indiccdchip.h:122
int getBPP() const
getBPP Get CCD Chip depth (bits per pixel).
Definition: indiccdchip.h:167
int getBinY() const
getBinY Get vertical binning of the CCD chip.
Definition: indiccdchip.h:140
int getXRes() const
getXRes Get the horizontal resolution in pixels of the CCD Chip.
Definition: indiccdchip.h:77
int getBinX() const
getBinX Get horizontal binning of the CCD chip.
Definition: indiccdchip.h:131
void setExposureLeft(double duration)
setExposureLeft Update exposure time left. Inform the client of the new exposure time left value.
int getSubW() const
getSubW Get the width of the frame
Definition: indiccdchip.h:113
void setFrameBufferSize(uint32_t nbuf, bool allocMem=true)
setFrameBufferSize Set desired frame buffer size. The function will allocate memory accordingly....
int getYRes() const
Get the vertical resolution in pixels of the CCD Chip.
Definition: indiccdchip.h:86
CCDChip PrimaryCCD
Definition: indiccd.h:629
@ CCD_CAN_SUBFRAME
Definition: indiccd.h:124
@ CCD_CAN_ABORT
Definition: indiccd.h:125
@ CCD_HAS_SHUTTER
Definition: indiccd.h:128
@ CCD_CAN_BIN
Definition: indiccd.h:123
@ CCD_HAS_COOLER
Definition: indiccd.h:129
virtual bool ExposureComplete(CCDChip *targetChip)
Uploads target Chip exposed buffer as FITS to the client. Dervied classes should class this function ...
Definition: indiccd.cpp:2228
virtual bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: indiccd.cpp:152
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: indiccd.cpp:528
void SetCCDCapability(uint32_t cap)
SetCCDCapability Set the CCD capabilities. Al fields must be initialized.
Definition: indiccd.cpp:138
INumberVectorProperty TemperatureNP
TemperatureNP Camera Temperature in Celcius.
Definition: indiccd.h:677
virtual void SetCCDParams(int x, int y, int bpp, float xf, float yf)
Setup CCD paramters for primary CCD. Child classes call this function to update CCD parameters.
Definition: indiccd.cpp:2742
void setDefaultPollingPeriod(uint32_t msec)
setDefaultPollingPeriod Change the default polling period to call TimerHit() function in the driver.
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
int64_t elapsed() const
Returns the number of milliseconds since this ElapsedTimer was last started.
void start()
Starts this timer. Once started, a timer value can be checked with elapsed().
int SetTemperature(double temperature) override
Set CCD temperature.
Definition: simpleccd.cpp:144
bool Disconnect() override
Disconnect from device.
Definition: simpleccd.cpp:47
bool AbortExposure() override
Abort ongoing exposure.
Definition: simpleccd.cpp:135
bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
Definition: simpleccd.cpp:85
bool initProperties() override
Initilize properties initial state and value. The child class must implement this function.
Definition: simpleccd.cpp:64
bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
Definition: simpleccd.cpp:35
const char * getDefaultName() override
Definition: simpleccd.cpp:56
bool StartExposure(float duration) override
Start exposing primary CCD chip.
Definition: simpleccd.cpp:118
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
Definition: simpleccd.cpp:163
@ IPS_BUSY
Definition: indiapi.h:163
@ IPS_ALERT
Definition: indiapi.h:164
@ IPS_IDLE
Definition: indiapi.h:161
@ IPS_OK
Definition: indiapi.h:162
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
Definition: indidriver.c:1211
void IDMessage(const char *dev, const char *fmt,...)
Definition: indidriver.c:960
#define currentCCDTemperature
Definition: simpleccd.cpp:28
std::unique_ptr< SimpleCCD > simpleCCD(new SimpleCCD())
Construct a basic INDI CCD device that simulates exposure & temperature settings. It also generates a...