API
 
Loading...
Searching...
No Matches
mcp3008Ctrl.hpp
Go to the documentation of this file.
1/** \file mcp3008Ctrl.hpp
2 * \brief The MagAO-X MCP3008 Controller header file
3 *
4 * \ingroup mcp3008Ctrl_files
5 */
6
7#ifndef mcp3008Ctrl_hpp
8#define mcp3008Ctrl_hpp
9
10#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
11#include "../../magaox_git_version.h"
12#include "dependencies/MCP3008.h" // Included for adc.connect()
13
14/** \defgroup mcp3008Ctrl
15 * \brief The MagAO-X application to readout a MCP3008 A/D on a raspberry Pi.
16 *
17 * <a href="../handbook/operating/software/apps/XXXXXX.html">Application Documentation</a>
18 *
19 * \ingroup apps
20 *
21 */
22
23/** \defgroup mcp3008Ctrl_files
24 * \ingroup mcp3008Ctrl
25 */
26
27namespace MagAOX
28{
29namespace app
30{
31
32/// The MagAO-X MCP3008 Controller
33/**
34 * \ingroup mcp3008Ctrl
35 */
36class mcp3008Ctrl : public MagAOXApp<true>, public dev::frameGrabber<mcp3008Ctrl>, public dev::telemeter<mcp3008Ctrl>
37{
38
39 // Give the test harness access.
40 friend class mcp3008Ctrl_test;
41 friend class dev::frameGrabber<mcp3008Ctrl>;
42 friend class dev::telemeter<mcp3008Ctrl>;
43
46
48
49 static constexpr bool c_frameGrabber_flippable = false; /**< app:dev config to tell framegrabber these images
50 can not be flipped*/
51
52 protected:
53 /** \name Configurable Parameters
54 *@{
55 */
56
57 int m_numChannels{ 8 }; ///< The number of channels being read out.
58
59 std::string m_fpsDevice; ///< Device name for getting fps to set circular buffer length.
60 std::string m_fpsProperty{ "fps" }; ///< Property name for getting fps to set circular buffer length.
61 std::string m_fpsElement{ "current" }; ///< Element name for getting fps to set circular buffer length.
62
63 float m_fpsTol{ 0 }; ///< The tolerance for detecting a change in FPS.
64
65 ///@}
66
67 // Creating INDI property for desired fps
68 pcf::IndiProperty m_indiP_fps;
70 float m_fps{ 2000 }; ///< The target FPS
71
72 pcf::IndiProperty m_indiP_fpsSource;
74
75 float m_trigger{ 1e9f / m_fps }; ///< The trigger time to readout. Adjusts to match desired FPS.
76 float m_gain{ .1 }; // Gain used to adjust trigger to keep at correct fps
77 float nano_sec_target{ 1e9f / m_fps };
78
80
81 std::chrono::time_point<std::chrono::high_resolution_clock> m_time_start;
82
83 std::vector<uint16_t> m_values; ///< The values read out from the chip
84
85 public:
86 /// Default c'tor.
88
89 /// D'tor, declared and defined for noexcept.
93
94 virtual void setupConfig();
95
96 /// Implementation of loadConfig logic, separated for testing.
97 /** This is called by loadConfig().
98 */
100 mx::app::appConfigurator &_config /**< [in] an application configuration
101 from which to load values*/ );
102
103 virtual void loadConfig();
104
105 /// Startup function
106 /**
107 *
108 */
109 virtual int appStartup();
110
111 /// Implementation of the FSM for mcp3008Ctrl.
112 /**
113 * \returns 0 on no critical error
114 * \returns -1 on an error requiring shutdown
115 */
116 virtual int appLogic();
117
118 /// Shutdown the app.
119 /**
120 *
121 */
122 virtual int appShutdown();
123
124 /// Implementation of the framegrabber configureAcquisition interface
125 /**
126 *
127 * \returns 0 on success
128 * \returns -1 on error
129 */
131
132 /// Implementation of the frameGrabber fps interface
133 /** Just returns the value of m_fps
134 */
135 float fps();
136
137 /// Implementation of the framegrabber startAcquisition interface
138 /**
139 *
140 * \returns 0 on success
141 * \returns -1 on error
142 */
143 int startAcquisition();
144
145 /// Implementation of the framegrabber acquireAndCheckValid interface
146 /**
147 *
148 * \returns 0 on success
149 * \returns -1 on error
150 */
152
153 /// Implementation of the framegrabber loadImageIntoStream interface
154 /**
155 *
156 * \returns 0 on success
157 * \returns -1 on error
158 */
159 int loadImageIntoStream( void *dest /**< [in] */ );
160
161 /// Implementation of the framegrabber reconfig interface
162 /**
163 * \returns 0 on success
164 * \returns -1 on error
165 */
166 int reconfig();
167
168 ///@}
169
170 /** \name Telemeter Interface
171 *
172 * @{
173 */
174 int checkRecordTimes();
175
176 int recordTelem( const telem_fgtimings * );
177};
178
179mcp3008Ctrl::mcp3008Ctrl() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
180{
181 return;
182}
183
185{
187 TELEMETER_SETUP_CONFIG( config );
188
189 config.add( "fps.device",
190 "",
191 "fps.device",
192 argType::Required,
193 "fps",
194 "device",
195 false,
196 "string",
197 "Device name for getting fps to set circular buffer length." );
198
199 config.add( "fps.property",
200 "",
201 "fps.property",
202 argType::Required,
203 "fps",
204 "property",
205 false,
206 "string",
207 "Property name for getting fps to set circular buffer length. Default is 'fps'." );
208
209 config.add( "fps.element",
210 "",
211 "fps.element",
212 argType::Required,
213 "fps",
214 "element",
215 false,
216 "string",
217 "Property name for getting fps to set circular buffer length. Default is 'current'." );
218
219 config.add( "fps.tol",
220 "",
221 "fps.tol",
222 argType::Required,
223 "fps",
224 "tol",
225 false,
226 "float",
227 "Tolerance for detecting a change in FPS. Default is 0." );
228
229 config.add( "accel.numChannels",
230 "",
231 "accel.numChannels",
232 argType::Required,
233 "accel",
234 "numChannels",
235 false,
236 "int",
237 "Setting the number of channels needed to readout accelerometers" );
238}
239
240int mcp3008Ctrl::loadConfigImpl( mx::app::appConfigurator &_config )
241{
242
245
246 _config( m_fpsDevice, "fps.device" );
247 _config( m_fpsProperty, "fps.property" );
248 _config( m_fpsElement, "fps.element" );
249 _config( m_fpsTol, "fps.tol" );
250
251 _config( m_numChannels, "accel.numChannels" ); // making number of mcp3008 channels we read out configurable
252
253 return 0;
254}
255
257{
258 loadConfigImpl( config );
259}
260
262{
265
266 // INDI prop for user to set fps
267 CREATE_REG_INDI_NEW_NUMBERF( m_indiP_fps, "fps", 0, 10000, 1, "%d", "", "" );
268 m_indiP_fps["current"].setValue( m_fps );
269 m_indiP_fps["target"].setValue( m_fps );
270
271 if( m_fpsDevice != "" )
272 {
274 }
275
276 {
277 // Get the maximum privileges available
278 elevatedPrivileges elPriv( this );
279
280 m_adc.connect();
281 }
282
284 return 0;
285}
286
288{
291
293
294 updatesIfChanged<float>( m_indiP_fps, { "current", "target" }, { m_fps, m_fps } );
295
296 return 0;
297}
298
306
308{
309 /** \todo @PARKER do anything needed to setup the MPC3008*/
310
311 m_values.resize( m_numChannels );
312
314 m_height = 1;
316
317 return 0;
318}
319
321{
322 return m_fps;
323}
324
326{
327 /** \todo @PARKER Do anything needed to start the MPC3008 reading out ... probably nothing*/
328
329 m_time_start = std::chrono::high_resolution_clock::now();
330
331 return 0;
332}
333
335{
336 while( !m_shutdown && !m_reconfig )
337 {
338 // Get current time
339 auto now = std::chrono::high_resolution_clock::now();
340 auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>( now - m_time_start );
341
342 // Read every 500 microseconds
343 if( elapsed.count() >= m_trigger ) /** \todo @PARKER make m_trigger adjust */
344 {
345 m_time_start = now; // Reset start time
346
347 for( int i = 0; i < m_numChannels; ++i )
348 {
349 m_values[i] = m_adc.read( i );
350 }
351
353
354 return 0;
355 }
356 else
357 {
358 mx::sys::nanoSleep( 10000 );
359 }
360 }
361
362 return 0;
363}
364
366{
367 memcpy( dest, m_values.data(), m_values.size() * sizeof( uint16_t ) );
368 return 0;
369}
370
372{
373 return 0;
374}
375
380
382{
383 return recordFGTimings( true );
384}
385
386// Testing for user to select star number
387INDI_NEWCALLBACK_DEFN( mcp3008Ctrl, m_indiP_fps )( const pcf::IndiProperty &ipRecv )
388{
389 if( ipRecv.getName() != m_indiP_fps.getName() )
390 {
391 log<software_error>( { __FILE__, __LINE__, "wrong INDI property received." } );
392 return -1;
393 }
394
395 float target;
396
397 if( indiTargetUpdate( m_indiP_fps, target, ipRecv, true ) < 0 )
398 {
399 log<software_error>( { __FILE__, __LINE__ } );
400 return -1;
401 }
402
403 m_fps = target;
404 m_trigger = 1e9f / m_fps; // Update trigger value based off new fps
405 nano_sec_target = 1e9f / m_fps;
406
407 log<text_log>( "set fps = " + std::to_string( m_fps ));
408 return 0;
409}
410
411INDI_SETCALLBACK_DEFN( mcp3008Ctrl, m_indiP_fpsSource )( const pcf::IndiProperty &ipRecv )
412{
413 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_fpsSource, ipRecv );
414
415 if( ipRecv.find( m_fpsElement ) != true ) // this isn't valid
416 {
417 log<software_error>( { __FILE__, __LINE__, "No current property in fps source." } );
418 return 0;
419 }
420
421 float target = ipRecv[m_fpsElement].get<float>();
422
423 m_fps = target;
424 m_trigger = 1e9f / m_fps; // Update trigger value based off new fps
425 nano_sec_target = 1e9f / m_fps;
426
427 log<text_log>( "set fps from " + m_fpsDevice + " = " + std::to_string( m_fps ));
428 return 0;
429
430} // INDI_SETCALLBACK_DEFN(mcp3008Ctrl, m_indiP_fpsSource)
431
432} // namespace app
433} // namespace MagAOX
434
435#endif // mcp3008Ctrl_hpp
unsigned short read(const std::uint8_t channel, const Mode m=Mode::SINGLE) const
Definition MCP3008.cpp:65
The base-class for MagAO-X applications.
Definition MagAOXApp.hpp:73
stateCodes::stateCodeT state()
Get the current state code.
int m_shutdown
Flag to signal it's time to shutdown. When not 0, the main loop exits.
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
uint32_t m_width
The width of the image, once deinterlaced etc.
uint8_t m_dataType
The ImageStreamIO type code.
bool m_reconfig
Flag to set if a camera reconfiguration requires a framegrabber reset.
uint32_t m_height
The height of the image, once deinterlaced etc.
The MagAO-X MCP3008 Controller.
INDI_SETCALLBACK_DECL(mcp3008Ctrl, m_indiP_fpsSource)
std::string m_fpsElement
Element name for getting fps to set circular buffer length.
MCP3008Lib::MCP3008 m_adc
virtual int appLogic()
Implementation of the FSM for mcp3008Ctrl.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
friend class mcp3008Ctrl_test
mcp3008Ctrl()
Default c'tor.
std::string m_fpsProperty
Property name for getting fps to set circular buffer length.
INDI_NEWCALLBACK_DECL(mcp3008Ctrl, m_indiP_fps)
std::string m_fpsDevice
Device name for getting fps to set circular buffer length.
virtual int appShutdown()
Shutdown the app.
static constexpr bool c_frameGrabber_flippable
int acquireAndCheckValid()
Implementation of the framegrabber acquireAndCheckValid interface.
dev::telemeter< mcp3008Ctrl > telemeterT
dev::frameGrabber< mcp3008Ctrl > frameGrabberT
int recordTelem(const telem_fgtimings *)
float m_trigger
The trigger time to readout. Adjusts to match desired FPS.
float m_fpsTol
The tolerance for detecting a change in FPS.
std::vector< uint16_t > m_values
The values read out from the chip.
int loadImageIntoStream(void *dest)
Implementation of the framegrabber loadImageIntoStream interface.
int startAcquisition()
Implementation of the framegrabber startAcquisition interface.
MCP3008Lib::MCP3008 adc
std::chrono::time_point< std::chrono::high_resolution_clock > m_time_start
pcf::IndiProperty m_indiP_fps
virtual int appStartup()
Startup function.
float m_fps
The target FPS.
~mcp3008Ctrl() noexcept
D'tor, declared and defined for noexcept.
int configureAcquisition()
Implementation of the framegrabber configureAcquisition interface.
int reconfig()
Implementation of the framegrabber reconfig interface.
float fps()
Implementation of the frameGrabber fps interface.
pcf::IndiProperty m_indiP_fpsSource
int m_numChannels
The number of channels being read out.
#define FRAMEGRABBER_SETUP_CONFIG(cfig)
Call frameGrabberT::setupConfig with error checking for frameGrabber.
#define FRAMEGRABBER_APP_LOGIC
Call frameGrabberT::appLogic with error checking for frameGrabber.
#define FRAMEGRABBER_APP_SHUTDOWN
Call frameGrabberT::appShutdown with error checking for frameGrabber.
#define FRAMEGRABBER_UPDATE_INDI
Call frameGrabberT::updateINDI with error checking for frameGrabber.
#define FRAMEGRABBER_LOAD_CONFIG(cfig)
Call frameGrabberT::loadConfig with error checking for frameGrabber.
#define FRAMEGRABBER_APP_STARTUP
Call frameGrabberT::appStartup with error checking for frameGrabber.
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define CREATE_REG_INDI_NEW_NUMBERF(prop, name, min, max, step, format, label, group)
Create and register a NEW INDI property as a standard number as float, using the standard callback na...
#define INDI_SETCALLBACK_DEFN(class, prop)
Define the callback for a set property request.
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
@ OPERATING
The device is operating, other than homing.
#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2)
Standard check for matching INDI properties in a callback.
const pcf::IndiProperty & ipRecv
Definition dm.hpp:26
A device base class which saves telemetry.
Definition telemeter.hpp:69
Log entry recording framegrabber timings.
#define TELEMETER_APP_LOGIC
Call telemeter::appLogic with error checking.
#define TELEMETER_LOAD_CONFIG(cfig)
Call telemeter::loadConfig with error checking.
#define TELEMETER_APP_STARTUP
Call telemeter::appStartup with error checking.
#define TELEMETER_SETUP_CONFIG(cfig)
Call telemeter::setupConfig with error checking.
#define TELEMETER_APP_SHUTDOWN
Call telemeter::appShutdown with error checking.