Instrument Neutral Distributed Interface INDI 2.2.5
simple_receiver.cpp
Go to the documentation of this file.
1/*
2 INDI Developers Manual
3 Tutorial #3
4
5 "Simple Receiver Driver"
6
7 We develop a simple Receiver 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 "simple_receiver.h"
24
25#include <memory>
26
27/* Macro shortcut to Receiver temperature value */
28#define currentReceiverTemperature TemperatureN[0].value
29
30std::unique_ptr<SimpleReceiver> simpleReceiver(new SimpleReceiver());
31
32/**************************************************************************************
33** Client is asking us to establish connection to the device
34***************************************************************************************/
36{
37 LOG_INFO("Simple Receiver connected successfully!");
38
39 // Let's set a timer that checks teleReceivers status every POLLMS milliseconds.
41
42 return true;
43}
44
45/**************************************************************************************
46** Client is asking us to terminate connection to the device
47***************************************************************************************/
49{
50 LOG_INFO("Simple Receiver disconnected successfully!");
51 return true;
52}
53
54/**************************************************************************************
55** INDI is asking us for our default device name
56***************************************************************************************/
58{
59 return "Simple Receiver";
60}
61
62/**************************************************************************************
63** INDI is asking us to init our properties.
64***************************************************************************************/
66{
67 // Must init parent properties first!
69
70 // We set the Receiver capabilities
72 SetCapability(cap);
73
74 // Add Debug, Simulator, and Configuration controls
76
78
79 return true;
80}
81
82/********************************************************************************************
83** INDI is asking us to update the properties because there is a change in CONNECTION status
84** This function is called whenever the device is connected or disconnected.
85*********************************************************************************************/
87{
88 // Call parent update properties first
90
91 if (isConnected())
92 {
93 // Let's get parameters now from Receiver
94 setupParams();
95
96 // Start the timer
98 }
99
100 return true;
101}
102
103/**************************************************************************************
104** Client is updating capture settings
105***************************************************************************************/
106bool SimpleReceiver::paramsUpdated(float sr, float freq, float bps, float bw, float gain)
107{
108 INDI_UNUSED(bps);
109 INDI_UNUSED(freq);
110 INDI_UNUSED(sr);
111 INDI_UNUSED(bw);
112 INDI_UNUSED(gain);
113 return true;
114}
115
116/**************************************************************************************
117** Setting up Receiver parameters
118***************************************************************************************/
119void SimpleReceiver::setupParams()
120{
121 // Our Receiver is an 8 bit Receiver, 100MHz frequency 1MHz samplerate.
122 setFrequency(1000000.0);
123 setSampleRate(100000000.0);
124 setBPS(16);
125 setBandwidth(0.0);
126 setGain(25.0);
127}
128
129/**************************************************************************************
130** Client is asking us to start an exposure
131***************************************************************************************/
133{
134 IntegrationRequest = duration;
135
136 // Since we have only have one Receiver with one chip, we set the exposure duration of the primary Receiver
137 setIntegrationTime(duration);
138
139 gettimeofday(&CapStart, nullptr);
140
141 InIntegration = true;
142
143 // We're done
144 return true;
145}
146
147/**************************************************************************************
148** Client is asking us to abort an exposure
149***************************************************************************************/
151{
152 InIntegration = false;
153 return true;
154}
155
156/**************************************************************************************
157** Client is asking us to set a new temperature
158***************************************************************************************/
160{
161 TemperatureRequest = temperature;
162
163 // 0 means it will take a while to change the temperature
164 return 0;
165}
166
167/**************************************************************************************
168** How much longer until exposure is done?
169***************************************************************************************/
170float SimpleReceiver::CalcTimeLeft()
171{
172 double timesince;
173 double timeleft;
174 struct timeval now
175 {
176 0, 0
177 };
178
179 gettimeofday(&now, nullptr);
180
181 timesince = (double)(now.tv_sec * 1000.0 + now.tv_usec / 1000) -
182 (double)(CapStart.tv_sec * 1000.0 + CapStart.tv_usec / 1000);
183 timesince = timesince / 1000;
184
185 timeleft = IntegrationRequest - timesince;
186 return timeleft;
187}
188
189/**************************************************************************************
190** Main device loop. We check for exposure and temperature progress here
191***************************************************************************************/
193{
194 long timeleft;
195
196 if (!isConnected())
197 return; // No need to reset timer if we are not connected anymore
198
199 if (InIntegration)
200 {
201 timeleft = CalcTimeLeft();
202
203 // Less than a 0.1 second away from exposure completion
204 // This is an over simplified timing method, check ReceiverSimulator and simpleReceiver for better timing checks
205 if (timeleft < 0.1)
206 {
207 /* We're done exposing */
208 LOG_INFO("Integration done, downloading image...");
209
210 // Set exposure left to zero
212
213 // We're no longer exposing...
214 InIntegration = false;
215
216 /* grab and save image */
217 grabFrame();
218 }
219 else
220 // Just update time left in client
221 setIntegrationLeft(timeleft);
222 }
223
224 // TemperatureNP is defined in INDI::Receiver
225 switch (TemperatureNP.s)
226 {
227 case IPS_IDLE:
228 case IPS_OK:
229 break;
230
231 case IPS_BUSY:
232 /* If target temperature is higher, then increase current Receiver temperature */
233 if (currentReceiverTemperature < TemperatureRequest)
235 /* If target temperature is lower, then decrease current Receiver temperature */
236 else if (currentReceiverTemperature > TemperatureRequest)
238 /* If they're equal, stop updating */
239 else
240 {
242 LOG_INFO("Target temperature reached.");
243 IDSetNumber(&TemperatureNP, nullptr);
244
245 break;
246 }
247
248 IDSetNumber(&TemperatureNP, nullptr);
249
250 break;
251
252 case IPS_ALERT:
253 break;
254 }
255
257}
258
259/**************************************************************************************
260** Create a random image and return it to client
261***************************************************************************************/
262void SimpleReceiver::grabFrame()
263{
264 // Set length of continuum
265 int len = getSampleRate() * getIntegrationTime() * getBPS() / 8;
266 setBufferSize(len);
267
268 // Let's get a pointer to the frame buffer
269 uint8_t *continuum = getBuffer();
270
271 // Fill buffer with random pattern
272 for (int i = 0; i < len; i++)
273 continuum[i] = rand() % 255;
274
275 LOG_INFO("Download complete.");
276
277 // Let INDI::Receiver know we're done filling the image buffer
279}
double temperature
bool isConnected() const
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.
void setGain(double gain)
setGain Set gain of Receiver device.
virtual bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
void setBandwidth(double bandwidth)
setBandwidth Set bandwidth of Receiver device.
void setBPS(int BPS)
setBPS Set the bits per sample.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
void setFrequency(double freq)
setFrequency Set the frequency observed.
double getSampleRate()
getSampleRate Get requested sample rate for the sensor in Hz.
void setSampleRate(double sr)
setSampleRate Set depth of Receiver device.
void SetCapability(uint32_t cap)
SetCapability Set the Sensor capabilities. Al fields must be initialized.
void setBufferSize(int nbuf, bool allocMem=true)
setBufferSize Set desired buffer size. The function will allocate memory accordingly....
void setIntegrationLeft(double duration)
setIntegrationLeft Update Integration time left. Inform the client of the new Integration time left v...
void setIntegrationTime(double duration)
setIntegrationTime Set desired Sensor frame Integration duration for next Integration....
INumberVectorProperty TemperatureNP
virtual bool IntegrationComplete()
Uploads target Device exposed buffer as FITS to the client. Derived classes should class this functio...
uint8_t * getBuffer()
getBuffer Get continuum buffer of the stream of the Sensor device.
int getBPS() const
getBPS Get Sensor depth (bits per sample).
double getIntegrationTime() const
getIntegrationTime Get requested Integration duration for the Sensor device in seconds.
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
bool StartIntegration(double duration) override
Start integration from the Sensor device.
bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
bool Disconnect() override
Disconnect from device.
const char * getDefaultName() override
int SetTemperature(double temperature) override
Set Sensor temperature.
bool paramsUpdated(float sr, float freq, float bps, float bw, float gain)
bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
bool AbortIntegration() override
Abort ongoing Integration.
@ IPS_BUSY
Definition indiapi.h:161
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
#define INDI_UNUSED(x)
Definition indidevapi.h:132
void IDSetNumber(const INumberVectorProperty *nvp, const char *fmt,...)
#define LOG_INFO(txt)
Definition indilogger.h:74
std::unique_ptr< SimpleReceiver > simpleReceiver(new SimpleReceiver())
#define currentReceiverTemperature