LCOV - code coverage report
Current view: top level - apps/modalFilter - modalFilter.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 408 0
Test Date: 2026-01-03 21:03:39 Functions: 0.0 % 59 0

            Line data    Source code
       1              : /** \file modalFilter.hpp
       2              :  * \brief The MagAO-X modal filter header file
       3              :  *
       4              :  * \ingroup modalFilter_files
       5              :  */
       6              : 
       7              : #ifndef modalFilter_hpp
       8              : #define modalFilter_hpp
       9              : 
      10              : #include <mutex>
      11              : #include <shared_mutex>
      12              : 
      13              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      14              : #include "../../magaox_git_version.h"
      15              : 
      16              : #include <mx/sigproc/circularBuffer.hpp>
      17              : 
      18              : /** \defgroup modalFilter
      19              :  * \brief The MagAO-X application to perform modal filtering
      20              :  *
      21              :  * <a href="../handbook/operating/software/apps/modalFilter.html">Application Documentation</a>
      22              :  *
      23              :  * \ingroup apps
      24              :  *
      25              :  */
      26              : 
      27              : /** \defgroup modalFilter_files
      28              :  * \ingroup modalFilter
      29              :  */
      30              : 
      31              : namespace MagAOX
      32              : {
      33              : namespace app
      34              : {
      35              : 
      36              : struct gainFactShmimT
      37              : {
      38            0 :     static std::string configSection()
      39              :     {
      40            0 :         return "gainFactShmim";
      41              :     };
      42              : 
      43            0 :     static std::string indiPrefix()
      44              :     {
      45            0 :         return "gainFact";
      46              :     };
      47              : };
      48              : 
      49              : struct multFactShmimT
      50              : {
      51            0 :     static std::string configSection()
      52              :     {
      53            0 :         return "multFactShmim";
      54              :     };
      55              : 
      56            0 :     static std::string indiPrefix()
      57              :     {
      58            0 :         return "multFact";
      59              :     };
      60              : };
      61              : 
      62              : struct pcGainFactShmimT
      63              : {
      64            0 :     static std::string configSection()
      65              :     {
      66            0 :         return "pcGainFactShmim";
      67              :     };
      68              : 
      69            0 :     static std::string indiPrefix()
      70              :     {
      71            0 :         return "pcGainFact";
      72              :     };
      73              : };
      74              : 
      75              : struct pcMultFactShmimT
      76              : {
      77            0 :     static std::string configSection()
      78              :     {
      79            0 :         return "pcMultFactShmim";
      80              :     };
      81              : 
      82            0 :     static std::string indiPrefix()
      83              :     {
      84            0 :         return "pcMultFact";
      85              :     };
      86              : };
      87              : 
      88              : struct acoeffShmimT
      89              : {
      90            0 :     static std::string configSection()
      91              :     {
      92            0 :         return "acoeffShmim";
      93              :     };
      94              : 
      95            0 :     static std::string indiPrefix()
      96              :     {
      97            0 :         return "acoeff";
      98              :     };
      99              : };
     100              : 
     101              : struct bcoeffShmimT
     102              : {
     103            0 :     static std::string configSection()
     104              :     {
     105            0 :         return "bcoeffShmim";
     106              :     };
     107              : 
     108            0 :     static std::string indiPrefix()
     109              :     {
     110            0 :         return "bcoeff";
     111              :     };
     112              : };
     113              : 
     114              : struct modevalShmimT
     115              : {
     116            0 :     static std::string configSection()
     117              :     {
     118            0 :         return "modevalShmim";
     119              :     };
     120              : 
     121            0 :     static std::string indiPrefix()
     122              :     {
     123            0 :         return "modeval";
     124              :     };
     125              : };
     126              : 
     127              : /// The MagAO-X modal filter
     128              : /**
     129              :  * \ingroup modalFilter
     130              :  */
     131              : class modalFilter : public MagAOXApp<true>,
     132              :                     dev::shmimMonitor<modalFilter, gainFactShmimT>,
     133              :                     dev::shmimMonitor<modalFilter, multFactShmimT>,
     134              :                     dev::shmimMonitor<modalFilter, pcGainFactShmimT>,
     135              :                     dev::shmimMonitor<modalFilter, pcMultFactShmimT>,
     136              :                     dev::shmimMonitor<modalFilter, acoeffShmimT>,
     137              :                     dev::shmimMonitor<modalFilter, bcoeffShmimT>,
     138              :                     dev::shmimMonitor<modalFilter, modevalShmimT>,
     139              :                     dev::frameGrabber<modalFilter>,
     140              :                     dev::telemeter<modalFilter>
     141              : {
     142              : 
     143              :     // Give the test harness access.
     144              :     friend class modalFilter_test;
     145              : 
     146              :     friend class dev::shmimMonitor<modalFilter, gainFactShmimT>;
     147              :     friend class dev::shmimMonitor<modalFilter, multFactShmimT>;
     148              :     friend class dev::shmimMonitor<modalFilter, pcGainFactShmimT>;
     149              :     friend class dev::shmimMonitor<modalFilter, pcMultFactShmimT>;
     150              :     friend class dev::shmimMonitor<modalFilter, acoeffShmimT>;
     151              :     friend class dev::shmimMonitor<modalFilter, bcoeffShmimT>;
     152              :     friend class dev::shmimMonitor<modalFilter, modevalShmimT>;
     153              :     friend class dev::frameGrabber<modalFilter>;
     154              :     friend class dev::telemeter<modalFilter>;
     155              : 
     156              :     typedef dev::shmimMonitor<modalFilter, gainFactShmimT>   gainFactShmimMonitorT;
     157              :     typedef dev::shmimMonitor<modalFilter, multFactShmimT>   multFactShmimMonitorT;
     158              :     typedef dev::shmimMonitor<modalFilter, pcGainFactShmimT> pcGainFactShmimMonitorT;
     159              :     typedef dev::shmimMonitor<modalFilter, pcMultFactShmimT> pcMultFactShmimMonitorT;
     160              :     typedef dev::shmimMonitor<modalFilter, acoeffShmimT>     acoeffShmimMonitorT;
     161              :     typedef dev::shmimMonitor<modalFilter, bcoeffShmimT>     bcoeffShmimMonitorT;
     162              :     typedef dev::shmimMonitor<modalFilter, modevalShmimT>    modevalShmimMonitorT;
     163              :     typedef dev::frameGrabber<modalFilter>                   frameGrabberT;
     164              :     typedef dev::telemeter<modalFilter>                      telemeterT;
     165              : 
     166              :     static constexpr bool c_frameGrabber_flippable = false; /**< app:dev config to tell framegrabber these images
     167              :                                                                  can not be flipped*/
     168              : 
     169              :   protected:
     170              :     /** \name Configurable Parameters
     171              :      *@{
     172              :      */
     173              : 
     174              :     std::string m_fpsDevice;               ///< Device name for getting fps to set circular buffer length.
     175              :     std::string m_fpsProperty{ "fps" };    ///< Property name for getting fps to set circular buffer length.
     176              :     std::string m_fpsElement{ "current" }; ///< Element name for getting fps to set circular buffer length.
     177              : 
     178              :     float m_fpsTol{ 0 }; ///< The tolerance for detecting a change in FPS.
     179              : 
     180              :     int m_loopNum{ 1 }; ///< The number of the loop. Used to set shmim names, as in aolN_mgainfact.  Default is 1.
     181              : 
     182              :     std::string m_loopName{ "ho" }; ///< The name of the loop control INDI device name. Defalt is "ho".
     183              : 
     184              :     int32_t m_modevalCBLength{ 1000 }; ///< The length of the modeval circular buffers.  Default is 1000 entries.
     185              : 
     186              :     ///@}
     187              : 
     188              :     float m_fps{ 0 };
     189              : 
     190              :     bool m_loop{ false };
     191              : 
     192              :     float m_gain{ 0 };
     193              : 
     194              :     float m_mc{ 1 };
     195              : 
     196              :     bool m_pcOn{ false };
     197              : 
     198              :     float m_pcGain{ 0 };
     199              : 
     200              :     float m_pcMc{ 1 };
     201              : 
     202              :     std::vector<float> m_gainfacts;
     203              : 
     204              :     std::vector<float> m_multfacts;
     205              : 
     206              :     std::vector<float> m_pcGainfacts;
     207              : 
     208              :     std::vector<float> m_pcMultfacts;
     209              : 
     210              :     std::vector<int> m_Na;
     211              : 
     212              :     std::vector<int> m_Nb;
     213              : 
     214              :     eigenImage<float> m_as;
     215              : 
     216              :     eigenImage<float> m_bs;
     217              : 
     218              :     uint32_t m_modevalSz{ 0 };
     219              : 
     220              :     mx::sigproc::circularBufferIndex<std::vector<float>, int32_t> m_modevalWFS;
     221              : 
     222              :     mx::sigproc::circularBufferIndex<std::vector<float>, int32_t> m_modevalDM;
     223              : 
     224              :     sem_t m_filtSem; ///< Semaphore used to signal that fresh modevals are waiting to be filtered
     225              : 
     226              :     bool m_sizesMatch{ false }; ///< Flag indicating that all sizes are consistent
     227              : 
     228              :     bool m_pcSizesMatch{ false }; ///< Flag indicating that all sizes are consistent
     229              : 
     230              :     std::shared_mutex m_filtMutex; ///< Mutex for locking access to filter parameters
     231              : 
     232              :     timespec m_atime; ///< The acq time of the WFS modevals
     233              :   public:
     234              :     /// Default c'tor.
     235              :     modalFilter();
     236              : 
     237              :     /// D'tor, declared and defined for noexcept.
     238            0 :     ~modalFilter() noexcept
     239            0 :     {
     240            0 :     }
     241              : 
     242              :     virtual void setupConfig();
     243              : 
     244              :     /// Implementation of loadConfig logic, separated for testing.
     245              :     /** This is called by loadConfig().
     246              :      */
     247              :     int loadConfigImpl( mx::app::appConfigurator &_config /**< [in] an application configuration
     248              :                                                                     from which to load values*/ );
     249              : 
     250              :     virtual void loadConfig();
     251              : 
     252              :     /// Startup function
     253              :     /**
     254              :      *
     255              :      */
     256              :     virtual int appStartup();
     257              : 
     258              :     /// Implementation of the FSM for modalFilter.
     259              :     /**
     260              :      * \returns 0 on no critical error
     261              :      * \returns -1 on an error requiring shutdown
     262              :      */
     263              :     virtual int appLogic();
     264              : 
     265              :     /// Shutdown the app.
     266              :     /**
     267              :      *
     268              :      */
     269              :     virtual int appShutdown();
     270              : 
     271              :     int allocate( const gainFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     272              :     );
     273              : 
     274              :     int processImage( void *curr_src,        ///< [in] pointer to the start of the current frame
     275              :                       const gainFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     276              :     );
     277              : 
     278              :     int allocate( const multFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     279              :     );
     280              : 
     281              :     int processImage( void *curr_src,        ///< [in] pointer to the start of the current frame
     282              :                       const multFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     283              :     );
     284              : 
     285              :     int allocate( const pcGainFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     286              :     );
     287              : 
     288              :     int processImage( void *curr_src,          ///< [in] pointer to the start of the current frame
     289              :                       const pcGainFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     290              :     );
     291              : 
     292              :     int allocate( const pcMultFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     293              :     );
     294              : 
     295              :     int processImage( void *curr_src,          ///< [in] pointer to the start of the current frame
     296              :                       const pcMultFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     297              :     );
     298              : 
     299              :     int allocate( const acoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     300              :     );
     301              : 
     302              :     int processImage( void *curr_src,      ///< [in] pointer to the start of the current frame
     303              :                       const acoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     304              :     );
     305              : 
     306              :     int allocate( const bcoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     307              :     );
     308              : 
     309              :     int processImage( void *curr_src,      ///< [in] pointer to the start of the current frame
     310              :                       const bcoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     311              :     );
     312              : 
     313              :     int allocate( const modevalShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     314              :     );
     315              : 
     316              :     int processImage( void *curr_src,       ///< [in] pointer to the start of the current frame
     317              :                       const modevalShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     318              :     );
     319              : 
     320              :     /** \name frameGrabber interface
     321              :      * @{
     322              :      */
     323              : 
     324              :     /// Implementation of the framegrabber configureAcquisition interface
     325              :     /**
     326              :      *
     327              :      * \returns 0 on success
     328              :      * \returns -1 on error
     329              :      */
     330              :     int configureAcquisition();
     331              : 
     332              :     /// Implementation of the frameGrabber fps interface
     333              :     /** Just returns the value of m_fps
     334              :      */
     335              :     float fps();
     336              : 
     337              :     /// Implementation of the framegrabber startAcquisition interface
     338              :     /**
     339              :      *
     340              :      * \returns 0 on success
     341              :      * \returns -1 on error
     342              :      */
     343              :     int startAcquisition();
     344              : 
     345              :     /// Implementation of the framegrabber acquireAndCheckValid interface
     346              :     /**
     347              :      *
     348              :      * \returns 0 on success
     349              :      * \returns -1 on error
     350              :      */
     351              :     int acquireAndCheckValid();
     352              : 
     353              :     /// Implementation of the framegrabber loadImageIntoStream interface
     354              :     /**
     355              :      *
     356              :      * \returns 0 on success
     357              :      * \returns -1 on error
     358              :      */
     359              :     int loadImageIntoStream( void *dest /**< [in] */ );
     360              : 
     361              :     /// Implementation of the framegrabber reconfig interface
     362              :     /**
     363              :      * \returns 0 on success
     364              :      * \returns -1 on error
     365              :      */
     366              :     int reconfig();
     367              : 
     368              :     ///@}
     369              : 
     370              :     void checkSizes();
     371              : 
     372              :     /** \name Telemeter Interface
     373              :      *
     374              :      * @{
     375              :      */
     376              :     int checkRecordTimes();
     377              : 
     378              :     int recordTelem( const telem_fgtimings * );
     379              : 
     380              :     ///@}
     381              : 
     382              :     /** \name INDI
     383              :      * @{
     384              :      */
     385              : 
     386              :     pcf::IndiProperty m_indiP_fpsSource;
     387              : 
     388              :     pcf::IndiProperty m_indiP_loop;
     389              : 
     390              :     pcf::IndiProperty m_indiP_gain;
     391              : 
     392              :     pcf::IndiProperty m_indiP_mult;
     393              : 
     394              :     pcf::IndiProperty m_indiP_pcGain;
     395              : 
     396              :     pcf::IndiProperty m_indiP_pcMult;
     397              : 
     398              :     pcf::IndiProperty m_indiP_pcOn;
     399              : 
     400            0 :     INDI_SETCALLBACK_DECL( modalFilter, m_indiP_fpsSource );
     401              : 
     402            0 :     INDI_NEWCALLBACK_DECL( modalFilter, m_indiP_loop );
     403              : 
     404            0 :     INDI_NEWCALLBACK_DECL( modalFilter, m_indiP_gain );
     405              : 
     406            0 :     INDI_NEWCALLBACK_DECL( modalFilter, m_indiP_mult );
     407              : 
     408            0 :     INDI_NEWCALLBACK_DECL( modalFilter, m_indiP_pcGain );
     409              : 
     410            0 :     INDI_NEWCALLBACK_DECL( modalFilter, m_indiP_pcMult );
     411              : 
     412            0 :     INDI_NEWCALLBACK_DECL( modalFilter, m_indiP_pcOn );
     413              : 
     414              :     ///@}
     415              : };
     416              : 
     417            0 : modalFilter::modalFilter() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
     418              : {
     419              : 
     420            0 :     gainFactShmimMonitorT::m_getExistingFirst   = true;
     421            0 :     multFactShmimMonitorT::m_getExistingFirst   = true;
     422            0 :     pcGainFactShmimMonitorT::m_getExistingFirst = true;
     423            0 :     pcMultFactShmimMonitorT::m_getExistingFirst = true;
     424            0 :     acoeffShmimMonitorT::m_getExistingFirst     = true;
     425            0 :     bcoeffShmimMonitorT::m_getExistingFirst     = true;
     426            0 :     modevalShmimMonitorT::m_getExistingFirst    = true;
     427            0 :     return;
     428            0 : }
     429              : 
     430            0 : void modalFilter::setupConfig()
     431              : {
     432            0 :     config.add( "circBuff.fpsDevice",
     433              :                 "",
     434              :                 "circBuff.fpsDevice",
     435              :                 argType::Required,
     436              :                 "circBuff",
     437              :                 "fpsDevice",
     438              :                 false,
     439              :                 "string",
     440              :                 "Device name for getting fps to set circular buffer length." );
     441            0 :     config.add( "circBuff.fpsProperty",
     442              :                 "",
     443              :                 "circBuff.fpsProperty",
     444              :                 argType::Required,
     445              :                 "circBuff",
     446              :                 "fpsProperty",
     447              :                 false,
     448              :                 "string",
     449              :                 "Property name for getting fps to set circular buffer length. Default is 'fps'." );
     450            0 :     config.add( "circBuff.fpsElement",
     451              :                 "",
     452              :                 "circBuff.fpsElement",
     453              :                 argType::Required,
     454              :                 "circBuff",
     455              :                 "fpsElement",
     456              :                 false,
     457              :                 "string",
     458              :                 "Property name for getting fps to set circular buffer length. Default is 'current'." );
     459            0 :     config.add( "circBuff.fpsTol",
     460              :                 "",
     461              :                 "circBuff.fpsTol",
     462              :                 argType::Required,
     463              :                 "circBuff",
     464              :                 "fpsTol",
     465              :                 false,
     466              :                 "float",
     467              :                 "Tolerance for detecting a change in FPS.  Default is 0." );
     468              : 
     469            0 :     config.add( "loop.number",
     470              :                 "",
     471              :                 "loop.number",
     472              :                 argType::Required,
     473              :                 "loop",
     474              :                 "number",
     475              :                 false,
     476              :                 "int",
     477              :                 "The number of the loop. Used to set shmim names, as in aolN_mgainfact.  Default is 1." );
     478              : 
     479            0 :     config.add( "loop.name",
     480              :                 "",
     481              :                 "loop.name",
     482              :                 argType::Required,
     483              :                 "loop",
     484              :                 "name",
     485              :                 false,
     486              :                 "string",
     487              :                 "The name of the loop control INDI device name. Default is \"ho\"." );
     488              : 
     489            0 :     SHMIMMONITORT_SETUP_CONFIG( gainFactShmimMonitorT, config );
     490            0 :     SHMIMMONITORT_SETUP_CONFIG( multFactShmimMonitorT, config );
     491            0 :     SHMIMMONITORT_SETUP_CONFIG( pcGainFactShmimMonitorT, config );
     492            0 :     SHMIMMONITORT_SETUP_CONFIG( pcMultFactShmimMonitorT, config );
     493            0 :     SHMIMMONITORT_SETUP_CONFIG( acoeffShmimMonitorT, config );
     494            0 :     SHMIMMONITORT_SETUP_CONFIG( bcoeffShmimMonitorT, config );
     495            0 :     SHMIMMONITORT_SETUP_CONFIG( modevalShmimMonitorT, config );
     496            0 :     FRAMEGRABBER_SETUP_CONFIG( config );
     497            0 :     TELEMETER_SETUP_CONFIG( config );
     498              : }
     499              : 
     500            0 : int modalFilter::loadConfigImpl( mx::app::appConfigurator &_config )
     501              : {
     502            0 :     _config( m_fpsDevice, "circBuff.fpsDevice" );
     503            0 :     _config( m_fpsProperty, "circBuff.fpsProperty" );
     504            0 :     _config( m_fpsElement, "circBuff.fpsElement" );
     505            0 :     _config( m_fpsTol, "circBuff.fpsTol" );
     506              : 
     507            0 :     _config( m_loopNum, "loop.number" );
     508            0 :     _config( m_loopName, "loop.name" );
     509              : 
     510              :     char shmim[1024];
     511              : 
     512            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_mgainfact", m_loopNum );
     513            0 :     gainFactShmimMonitorT::m_shmimName = shmim;
     514            0 :     SHMIMMONITORT_LOAD_CONFIG( gainFactShmimMonitorT, _config );
     515              : 
     516            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_mmultfact", m_loopNum );
     517            0 :     multFactShmimMonitorT::m_shmimName = shmim;
     518            0 :     SHMIMMONITORT_LOAD_CONFIG( multFactShmimMonitorT, _config );
     519              : 
     520            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_mpcgainfact", m_loopNum );
     521            0 :     pcGainFactShmimMonitorT::m_shmimName = shmim;
     522            0 :     SHMIMMONITORT_LOAD_CONFIG( pcGainFactShmimMonitorT, _config );
     523              : 
     524            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_mpcmultfact", m_loopNum );
     525            0 :     pcMultFactShmimMonitorT::m_shmimName = shmim;
     526            0 :     SHMIMMONITORT_LOAD_CONFIG( pcMultFactShmimMonitorT, _config );
     527              : 
     528            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_acoeff", m_loopNum );
     529            0 :     acoeffShmimMonitorT::m_shmimName = shmim;
     530            0 :     SHMIMMONITORT_LOAD_CONFIG( acoeffShmimMonitorT, _config );
     531              : 
     532            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_bcoeff", m_loopNum );
     533            0 :     bcoeffShmimMonitorT::m_shmimName = shmim;
     534            0 :     SHMIMMONITORT_LOAD_CONFIG( bcoeffShmimMonitorT, _config );
     535              : 
     536            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_modevalWFS", m_loopNum );
     537            0 :     modevalShmimMonitorT::m_shmimName = shmim;
     538            0 :     SHMIMMONITORT_LOAD_CONFIG( modevalShmimMonitorT, _config );
     539              : 
     540            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_modevalDM", m_loopNum );
     541            0 :     frameGrabberT::m_shmimName = shmim;
     542            0 :     FRAMEGRABBER_LOAD_CONFIG( _config );
     543              : 
     544            0 :     TELEMETER_LOAD_CONFIG( _config );
     545              : 
     546            0 :     return 0;
     547              : }
     548              : 
     549            0 : void modalFilter::loadConfig()
     550              : {
     551            0 :     loadConfigImpl( config );
     552            0 : }
     553              : 
     554            0 : int modalFilter::appStartup()
     555              : {
     556              : 
     557            0 :     if( sem_init( &m_filtSem, 0, 0 ) < 0 )
     558              :     {
     559            0 :         return log<software_critical, -1>( { __FILE__, __LINE__, errno, 0, "Initializing filter semaphore" } );
     560              :     }
     561              : 
     562            0 :     SHMIMMONITORT_APP_STARTUP( gainFactShmimMonitorT );
     563            0 :     SHMIMMONITORT_APP_STARTUP( multFactShmimMonitorT );
     564            0 :     SHMIMMONITORT_APP_STARTUP( pcGainFactShmimMonitorT );
     565            0 :     SHMIMMONITORT_APP_STARTUP( pcMultFactShmimMonitorT );
     566            0 :     SHMIMMONITORT_APP_STARTUP( acoeffShmimMonitorT );
     567            0 :     SHMIMMONITORT_APP_STARTUP( bcoeffShmimMonitorT );
     568            0 :     SHMIMMONITORT_APP_STARTUP( modevalShmimMonitorT );
     569            0 :     FRAMEGRABBER_APP_STARTUP;
     570            0 :     TELEMETER_APP_STARTUP;
     571              : 
     572            0 :     if( m_fpsDevice == "" )
     573              :     {
     574            0 :         return log<software_critical, -1>(
     575            0 :             { __FILE__, __LINE__, "FPS source is not configurated (circBuff.fpsDevice)" } );
     576              :     }
     577              : 
     578            0 :     REG_INDI_SETPROP( m_indiP_fpsSource, m_fpsDevice, m_fpsProperty );
     579              : 
     580            0 :     CREATE_REG_INDI_NEW_TOGGLESWITCH( m_indiP_loop, "loop_state" );
     581            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_gain, "loop_gain", 0, 1, 0.01, "%0.01f", "Gain", "Loop" );
     582            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_mult, "loop_multcoeff", 0, 1, 0.01, "%0.01f", "Mult. Coeff.", "Loop" );
     583            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_pcGain, "loop_pcgain", 0, 1, 0.01, "%0.01f", "PC Gain", "Loop" );
     584            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_pcMult, "loop_pcmultcoeff", 0, 1, 0.01, "%0.01f", "PC Mult. Coeff.", "Loop" );
     585              : 
     586            0 :     CREATE_REG_INDI_NEW_TOGGLESWITCH( m_indiP_pcOn, "loop_pcon" );
     587              : 
     588            0 :     state( stateCodes::OPERATING );
     589              : 
     590            0 :     return 0;
     591              : }
     592              : 
     593            0 : int modalFilter::appLogic()
     594              : {
     595            0 :     SHMIMMONITORT_APP_LOGIC( gainFactShmimMonitorT );
     596            0 :     SHMIMMONITORT_APP_LOGIC( multFactShmimMonitorT );
     597            0 :     SHMIMMONITORT_APP_LOGIC( pcGainFactShmimMonitorT );
     598            0 :     SHMIMMONITORT_APP_LOGIC( pcMultFactShmimMonitorT );
     599            0 :     SHMIMMONITORT_APP_LOGIC( acoeffShmimMonitorT );
     600            0 :     SHMIMMONITORT_APP_LOGIC( bcoeffShmimMonitorT );
     601            0 :     SHMIMMONITORT_APP_LOGIC( modevalShmimMonitorT );
     602            0 :     FRAMEGRABBER_APP_LOGIC;
     603            0 :     TELEMETER_APP_LOGIC;
     604              : 
     605            0 :     SHMIMMONITORT_UPDATE_INDI( gainFactShmimMonitorT );
     606            0 :     SHMIMMONITORT_UPDATE_INDI( multFactShmimMonitorT );
     607            0 :     SHMIMMONITORT_UPDATE_INDI( pcGainFactShmimMonitorT );
     608            0 :     SHMIMMONITORT_UPDATE_INDI( pcMultFactShmimMonitorT );
     609            0 :     SHMIMMONITORT_UPDATE_INDI( acoeffShmimMonitorT );
     610            0 :     SHMIMMONITORT_UPDATE_INDI( bcoeffShmimMonitorT );
     611            0 :     SHMIMMONITORT_UPDATE_INDI( modevalShmimMonitorT );
     612            0 :     FRAMEGRABBER_UPDATE_INDI;
     613              : 
     614            0 :     if( m_loop )
     615              :     {
     616            0 :         updateSwitchIfChanged( m_indiP_loop, "toggle", pcf::IndiElement::On, INDI_OK );
     617              :     }
     618              :     else
     619              :     {
     620            0 :         updateSwitchIfChanged( m_indiP_loop, "toggle", pcf::IndiElement::Off, INDI_IDLE );
     621              :     }
     622              : 
     623            0 :     if( m_pcOn )
     624              :     {
     625            0 :         updateSwitchIfChanged( m_indiP_pcOn, "toggle", pcf::IndiElement::On, INDI_OK );
     626              :     }
     627              :     else
     628              :     {
     629            0 :         updateSwitchIfChanged( m_indiP_pcOn, "toggle", pcf::IndiElement::Off, INDI_IDLE );
     630              :     }
     631              : 
     632            0 :     updatesIfChanged<float>( m_indiP_gain, { "current", "target" }, { m_gain, m_gain } );
     633            0 :     updatesIfChanged<float>( m_indiP_mult, { "current", "target" }, { m_mc, m_mc } );
     634              : 
     635            0 :     updatesIfChanged<float>( m_indiP_pcGain, { "current", "target" }, { m_pcGain, m_pcGain } );
     636            0 :     updatesIfChanged<float>( m_indiP_pcMult, { "current", "target" }, { m_pcMc, m_pcMc } );
     637              : 
     638            0 :     return 0;
     639              : }
     640              : 
     641            0 : int modalFilter::appShutdown()
     642              : {
     643            0 :     SHMIMMONITORT_APP_SHUTDOWN( gainFactShmimMonitorT );
     644            0 :     SHMIMMONITORT_APP_SHUTDOWN( multFactShmimMonitorT );
     645            0 :     SHMIMMONITORT_APP_SHUTDOWN( pcGainFactShmimMonitorT );
     646            0 :     SHMIMMONITORT_APP_SHUTDOWN( pcMultFactShmimMonitorT );
     647            0 :     SHMIMMONITORT_APP_SHUTDOWN( acoeffShmimMonitorT );
     648            0 :     SHMIMMONITORT_APP_SHUTDOWN( bcoeffShmimMonitorT );
     649            0 :     SHMIMMONITORT_APP_SHUTDOWN( modevalShmimMonitorT );
     650            0 :     FRAMEGRABBER_APP_SHUTDOWN;
     651            0 :     TELEMETER_APP_SHUTDOWN;
     652              : 
     653            0 :     return 0;
     654              : }
     655              : 
     656            0 : int modalFilter::allocate( const gainFactShmimT &dummy )
     657              : {
     658              :     static_cast<void>( dummy );
     659              : 
     660            0 :     if( gainFactShmimMonitorT::m_height != 1 )
     661              :     {
     662            0 :         return log<software_error, -1>( { __FILE__, __LINE__, "got gainFacts with height not 1" } );
     663              :     }
     664              : 
     665              :     // If there's a size change we have to lock
     666            0 :     if( gainFactShmimMonitorT::m_width != m_gainfacts.size() )
     667              :     {
     668            0 :         std::shared_lock<std::shared_mutex> lock( m_filtMutex );
     669              : 
     670            0 :         m_gainfacts.resize( gainFactShmimMonitorT::m_width );
     671              : 
     672            0 :         checkSizes();
     673            0 :     }
     674              : 
     675            0 :     return 0;
     676              : }
     677              : 
     678            0 : int modalFilter::processImage( void *curr_src, const gainFactShmimT &dummy )
     679              : {
     680              :     static_cast<void>( dummy );
     681              : 
     682              :     // We just update without a lock.  Size change handled in allocate.
     683            0 :     for( uint32_t n = 0; n < gainFactShmimMonitorT::m_width; ++n )
     684              :     {
     685            0 :         m_gainfacts[n] = reinterpret_cast<float *>( curr_src )[n];
     686              :     }
     687              : 
     688            0 :     return 0;
     689              : }
     690              : 
     691            0 : int modalFilter::allocate( const multFactShmimT &dummy )
     692              : {
     693              :     static_cast<void>( dummy );
     694              : 
     695            0 :     if( multFactShmimMonitorT::m_height != 1 )
     696              :     {
     697            0 :         return log<software_error, -1>( { __FILE__, __LINE__, "got multFacts with height not 1" } );
     698              :     }
     699              : 
     700              :     // If there's a size change we have to lock
     701            0 :     if( multFactShmimMonitorT::m_width != m_multfacts.size() )
     702              :     {
     703            0 :         std::shared_lock<std::shared_mutex> lock( m_filtMutex );
     704              : 
     705            0 :         m_multfacts.resize( multFactShmimMonitorT::m_width );
     706              : 
     707            0 :         checkSizes();
     708            0 :     }
     709              : 
     710            0 :     return 0;
     711              : }
     712              : 
     713            0 : int modalFilter::processImage( void *curr_src, const multFactShmimT &dummy )
     714              : {
     715              :     static_cast<void>( dummy );
     716              : 
     717              :     // We just update without a lock.  Size change handled in allocate.
     718            0 :     for( uint32_t n = 0; n < multFactShmimMonitorT::m_width; ++n )
     719              :     {
     720            0 :         m_multfacts[n] = reinterpret_cast<float *>( curr_src )[n];
     721              :     }
     722              : 
     723            0 :     return 0;
     724              : }
     725              : 
     726            0 : int modalFilter::allocate( const pcGainFactShmimT &dummy )
     727              : {
     728              :     static_cast<void>( dummy );
     729              : 
     730            0 :     if( pcGainFactShmimMonitorT::m_height != 1 )
     731              :     {
     732            0 :         return log<software_error, -1>( { __FILE__, __LINE__, "got pcGainFacts with height not 1" } );
     733              :     }
     734              : 
     735              :     // If there's a size change we have to lock
     736            0 :     if( pcGainFactShmimMonitorT::m_width != m_pcGainfacts.size() )
     737              :     {
     738            0 :         std::shared_lock<std::shared_mutex> lock( m_filtMutex );
     739              : 
     740            0 :         m_pcGainfacts.resize( pcGainFactShmimMonitorT::m_width );
     741              : 
     742            0 :         checkSizes();
     743            0 :     }
     744              : 
     745            0 :     return 0;
     746              : }
     747              : 
     748            0 : int modalFilter::processImage( void *curr_src, const pcGainFactShmimT &dummy )
     749              : {
     750              :     static_cast<void>( dummy );
     751              : 
     752              :     // We just update without a lock.  Size change handled in allocate.
     753            0 :     for( uint32_t n = 0; n < pcGainFactShmimMonitorT::m_width; ++n )
     754              :     {
     755            0 :         m_pcGainfacts[n] = reinterpret_cast<float *>( curr_src )[n];
     756              :     }
     757              : 
     758            0 :     return 0;
     759              : }
     760              : 
     761            0 : int modalFilter::allocate( const pcMultFactShmimT &dummy )
     762              : {
     763              :     static_cast<void>( dummy );
     764              : 
     765            0 :     if( pcMultFactShmimMonitorT::m_height != 1 )
     766              :     {
     767            0 :         return log<software_error, -1>( { __FILE__, __LINE__, "got pcMultFacts with height not 1" } );
     768              :     }
     769              : 
     770              :     // If there's a size change we have to lock
     771            0 :     if( pcMultFactShmimMonitorT::m_width != m_pcMultfacts.size() )
     772              :     {
     773            0 :         std::shared_lock<std::shared_mutex> lock( m_filtMutex );
     774              : 
     775            0 :         m_pcMultfacts.resize( pcMultFactShmimMonitorT::m_width );
     776              : 
     777            0 :         checkSizes();
     778            0 :     }
     779              : 
     780            0 :     return 0;
     781              : }
     782              : 
     783            0 : int modalFilter::processImage( void *curr_src, const pcMultFactShmimT &dummy )
     784              : {
     785              :     static_cast<void>( dummy );
     786              : 
     787              :     // We just update without a lock.  Size change handled in allocate.
     788            0 :     for( uint32_t n = 0; n < pcMultFactShmimMonitorT::m_width; ++n )
     789              :     {
     790            0 :         m_pcMultfacts[n] = reinterpret_cast<float *>( curr_src )[n];
     791              :     }
     792              : 
     793            0 :     return 0;
     794              : }
     795              : 
     796            0 : int modalFilter::allocate( const acoeffShmimT &dummy )
     797              : {
     798              :     static_cast<void>( dummy );
     799              : 
     800            0 :     uint32_t w = acoeffShmimMonitorT::m_width;
     801            0 :     uint32_t h = acoeffShmimMonitorT::m_height;
     802              : 
     803              :     // If there's a size change we lock
     804            0 :     if( w - 1 != m_as.rows() || h != m_as.cols() || h != m_Na.size() )
     805              :     {
     806            0 :         std::shared_lock<std::shared_mutex> lock( m_filtMutex );
     807              : 
     808            0 :         m_Na.resize( h );
     809            0 :         m_as.resize( w - 1, h );
     810              : 
     811            0 :         checkSizes();
     812            0 :     }
     813              : 
     814            0 :     return 0;
     815              : }
     816              : 
     817            0 : int modalFilter::processImage( void *curr_src, const acoeffShmimT &dummy )
     818              : {
     819              :     static_cast<void>( dummy );
     820              : 
     821            0 :     uint32_t w = acoeffShmimMonitorT::m_width;
     822            0 :     uint32_t h = acoeffShmimMonitorT::m_height;
     823              : 
     824            0 :     eigenMap<float> ac( reinterpret_cast<float *>( curr_src ), w, h );
     825              : 
     826            0 :     for( uint32_t cc = 0; cc < h; ++cc )
     827              :     {
     828            0 :         m_Na[cc] = ac( 0, cc );
     829            0 :         for( uint32_t rr = 1; rr < w; ++rr )
     830              :         {
     831            0 :             m_as( rr - 1, cc ) = ac( rr, cc );
     832              :         }
     833              :     }
     834              : 
     835            0 :     std::cerr << "Got pc a-coeffs.  Mode 0 has " << m_Na[0] << '\n';
     836              : 
     837            0 :     return 0;
     838              : }
     839              : 
     840            0 : int modalFilter::allocate( const bcoeffShmimT &dummy )
     841              : {
     842              :     static_cast<void>( dummy );
     843              : 
     844            0 :     uint32_t w = bcoeffShmimMonitorT::m_width;
     845            0 :     uint32_t h = bcoeffShmimMonitorT::m_height;
     846              : 
     847              :     // If there's a size change we lock
     848            0 :     if( w - 1 != m_bs.rows() || h != m_bs.cols() || h != m_Nb.size() )
     849              :     {
     850            0 :         std::shared_lock<std::shared_mutex> lock( m_filtMutex );
     851              : 
     852            0 :         m_Nb.resize( h );
     853            0 :         m_bs.resize( w - 1, h );
     854              : 
     855            0 :         checkSizes();
     856            0 :     }
     857              : 
     858            0 :     std::cerr << "Got pc b-coeffs.  Mode 0 has " << m_Nb[0] << '\n';
     859              : 
     860            0 :     return 0;
     861              : }
     862              : 
     863            0 : int modalFilter::processImage( void *curr_src, const bcoeffShmimT &dummy )
     864              : {
     865              :     static_cast<void>( dummy );
     866              : 
     867            0 :     uint32_t w = bcoeffShmimMonitorT::m_width;
     868            0 :     uint32_t h = bcoeffShmimMonitorT::m_height;
     869              : 
     870            0 :     eigenMap<float> bc( reinterpret_cast<float *>( curr_src ), w, h );
     871              : 
     872            0 :     for( uint32_t cc = 0; cc < h; ++cc )
     873              :     {
     874            0 :         m_Nb[cc] = bc( 0, cc );
     875            0 :         for( uint32_t rr = 1; rr < w; ++rr )
     876              :         {
     877            0 :             m_bs( rr - 1, cc ) = bc( rr, cc );
     878              :         }
     879              :     }
     880            0 :     return 0;
     881              : }
     882              : 
     883            0 : int modalFilter::allocate( const modevalShmimT &dummy )
     884              : {
     885              :     static_cast<void>( dummy );
     886              : 
     887            0 :     if( modevalShmimMonitorT::m_height != 1 )
     888              :     {
     889            0 :         return log<software_error, -1>( { __FILE__, __LINE__, "got modevals with height not 1" } );
     890              :     }
     891              : 
     892            0 :     if( modevalShmimMonitorT::m_width != m_modevalSz ) // This invalidates the whole c.b.
     893              :     {
     894            0 :         std::shared_lock<std::shared_mutex> lock( m_filtMutex );
     895              : 
     896            0 :         m_modevalSz = modevalShmimMonitorT::m_width;
     897            0 :         m_modevalWFS.maxEntries( m_modevalCBLength );
     898            0 :         m_modevalDM.maxEntries( m_modevalCBLength );
     899              : 
     900            0 :         checkSizes();
     901            0 :     }
     902              : 
     903            0 :     std::cerr << "Allocated modevals: " << modevalShmimMonitorT::m_width << " x " << modevalShmimMonitorT::m_height
     904            0 :               << '\n';
     905            0 :     return 0;
     906              : }
     907              : 
     908            0 : int modalFilter::processImage( void *curr_src, const modevalShmimT &dummy )
     909              : {
     910              :     static_cast<void>( dummy );
     911              : 
     912            0 :     clock_gettime( CLOCK_ISIO, &m_atime );
     913              : 
     914            0 :     float *F = reinterpret_cast<float *>( curr_src );
     915              : 
     916            0 :     m_modevalWFS.nextEntry( std::vector<float>( F, F + m_modevalSz ) );
     917              : 
     918              :     // Now tell the writer to get going
     919            0 :     if( sem_post( &m_filtSem ) < 0 )
     920              :     {
     921            0 :         return log<software_critical, -1>( { __FILE__, __LINE__, errno, 0, "Error posting to filter semaphore" } );
     922              :     }
     923              : 
     924            0 :     return 0;
     925              : }
     926              : 
     927            0 : int modalFilter::configureAcquisition()
     928              : {
     929              : 
     930            0 :     while( ( modevalShmimMonitorT::m_width < 1 || modevalShmimMonitorT::m_height != 1 ) && !m_shutdown )
     931              :     {
     932            0 :         sleep( 1 );
     933              :     }
     934              : 
     935            0 :     frameGrabberT::m_width    = modevalShmimMonitorT::m_width;
     936            0 :     frameGrabberT::m_height   = modevalShmimMonitorT::m_height;
     937            0 :     frameGrabberT::m_dataType = _DATATYPE_FLOAT;
     938              : 
     939            0 :     return 0;
     940              : }
     941              : 
     942            0 : float modalFilter::fps()
     943              : {
     944            0 :     return m_fps;
     945              : }
     946              : 
     947            0 : int modalFilter::startAcquisition()
     948              : {
     949            0 :     return 0;
     950              : }
     951              : 
     952            0 : int modalFilter::acquireAndCheckValid()
     953              : {
     954              :     timespec ts;
     955              : 
     956            0 :     XWC_SEM_WAIT_TS( ts, 1, 0 );
     957              : 
     958            0 :     if( sem_timedwait( &m_filtSem, &ts ) != 0 )
     959              :     {
     960              :         /* Check for why we timed out */
     961              :         /* EINTER probably indicates time to shutdown, loop will exit if m_shutdown is set */
     962              :         /* ETIMEDOUT just means keep waiting */
     963            0 :         if( errno == EINTR || errno == ETIMEDOUT )
     964              :         {
     965            0 :             return 1;
     966              :         }
     967              : 
     968              :         /*Otherwise, report an error.*/
     969            0 :         return log<software_error, -1>( { __FILE__, __LINE__, errno, "sem_timedwait" } );
     970              :     }
     971              :     else
     972              :     {
     973            0 :         std::unique_lock<std::shared_mutex> lock( m_filtMutex ); // gotta be the only one
     974              : 
     975            0 :         if( !m_sizesMatch )
     976              :         {
     977            0 :             return 1;
     978              :         }
     979              : 
     980            0 :         m_modevalDM.nextEntry();               // move to the next entry without modifying what is there
     981            0 :         m_modevalDM[-1].resize( m_modevalSz ); // needed while growing, no-op once grown
     982            0 :         if( !m_loop )
     983              :         {
     984            0 :             for( uint32_t mode = 0; mode < m_modevalSz; ++mode )
     985              :             {
     986            0 :                 m_modevalDM[-1][mode] = 0;
     987              :             }
     988            0 :             return 1; // we update the cbuff but we don't push to the DM
     989              :         }
     990              :         else
     991              :         {
     992            0 :             if( !m_pcOn )
     993              :             {
     994            0 :                 for( uint32_t mode = 0; mode < m_modevalSz; ++mode )
     995              :                 {
     996              :                     // index [0] is 1the latest entry in the circular buffer
     997            0 :                     m_modevalDM[-1][mode] = -1.0 * m_gain * m_gainfacts[mode] * m_modevalWFS[-1][mode] +
     998            0 :                                             m_mc * m_multfacts[mode] * m_modevalDM[-2][mode];
     999              :                 }
    1000              :             }
    1001              :             else
    1002              :             {
    1003            0 :                 for( uint32_t mode = 0; mode < m_modevalSz; ++mode )
    1004              :                 {
    1005            0 :                     float a = 0;
    1006            0 :                     float b = 0;
    1007            0 :                     for(int c = 0; c < m_Na[mode]; ++c)
    1008              :                     {
    1009            0 :                         a += m_as(c,mode)*m_modevalWFS[-1-c][mode];
    1010              :                     }
    1011              : 
    1012            0 :                     for(int c = 0; c < m_Nb[mode]; ++c)
    1013              :                     {
    1014            0 :                         b += m_bs(c,mode)*m_modevalDM[-2-c][mode];
    1015              :                     }
    1016              : 
    1017            0 :                     a = m_modevalWFS[-1][mode];
    1018            0 :                     b = m_modevalDM[-2][mode];
    1019            0 :                     m_modevalDM[-1][mode] = -1.0 * m_pcGain * m_pcGainfacts[mode] * a +
    1020            0 :                                             m_pcMc * m_pcMultfacts[mode] * b;
    1021              :                 }
    1022              :             }
    1023              : 
    1024            0 :             frameGrabberT::m_currImageTimestamp = m_atime;
    1025              :         }
    1026            0 :     }
    1027              : 
    1028            0 :     return 0;
    1029              : }
    1030              : 
    1031            0 : int modalFilter::loadImageIntoStream( void *dest )
    1032              : {
    1033              : 
    1034            0 :     memcpy( dest, m_modevalDM[-1].data(), m_modevalDM[-1].size() * sizeof( float ) );
    1035              : 
    1036            0 :     return 0;
    1037              : }
    1038              : 
    1039            0 : int modalFilter::reconfig()
    1040              : {
    1041            0 :     return 0;
    1042              : }
    1043              : 
    1044            0 : void modalFilter::checkSizes()
    1045              : {
    1046            0 :     m_sizesMatch   = true;
    1047            0 :     m_pcSizesMatch = true;
    1048              : 
    1049            0 :     if( m_gainfacts.size() != m_modevalSz )
    1050              :     {
    1051            0 :         m_sizesMatch = false;
    1052              :     }
    1053              : 
    1054            0 :     if( m_multfacts.size() != m_modevalSz )
    1055              :     {
    1056            0 :         m_sizesMatch = false;
    1057              :     }
    1058              : 
    1059            0 :     if( static_cast<size_t>( m_as.cols() ) != m_modevalSz )
    1060              :     {
    1061            0 :         m_pcSizesMatch = false;
    1062              :     }
    1063              : 
    1064            0 :     if( static_cast<size_t>( m_bs.cols() ) != m_modevalSz )
    1065              :     {
    1066            0 :         m_pcSizesMatch = false;
    1067              :     }
    1068              : 
    1069            0 :     if( m_modevalWFS.size() != m_modevalCBLength )
    1070              :     {
    1071            0 :         m_pcSizesMatch = false;
    1072              :     }
    1073              : 
    1074            0 :     if( m_modevalDM.size() != m_modevalCBLength )
    1075              :     {
    1076            0 :         m_pcSizesMatch = false;
    1077              :     }
    1078            0 : }
    1079              : 
    1080            0 : int modalFilter::checkRecordTimes()
    1081              : {
    1082            0 :     return telemeterT::checkRecordTimes( telem_fgtimings() );
    1083              : }
    1084              : 
    1085            0 : int modalFilter::recordTelem( const telem_fgtimings * )
    1086              : {
    1087            0 :     return recordFGTimings( true );
    1088              : }
    1089              : 
    1090            0 : INDI_SETCALLBACK_DEFN( modalFilter, m_indiP_fpsSource )( const pcf::IndiProperty &ipRecv )
    1091              : {
    1092            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_fpsSource, ipRecv );
    1093              : 
    1094            0 :     if( ipRecv.find( m_fpsElement ) != true ) // this isn't valid
    1095              :     {
    1096            0 :         log<software_error>( { __FILE__, __LINE__, "No current property in fps source." } );
    1097            0 :         return 0;
    1098              :     }
    1099              : 
    1100            0 :     std::lock_guard<std::mutex> guard( m_indiMutex );
    1101              : 
    1102            0 :     float fps = ipRecv[m_fpsElement].get<float>();
    1103              : 
    1104            0 :     if( fabs( fps - m_fps ) > m_fpsTol )
    1105              :     {
    1106            0 :         m_fps = fps;
    1107            0 :         log<text_log>( "set fps to " + std::to_string( m_fps ), logPrio::LOG_NOTICE );
    1108            0 :         frameGrabberT::m_reconfig = true;
    1109              :     }
    1110              : 
    1111            0 :     return 0;
    1112              : 
    1113            0 : } // INDI_SETCALLBACK_DEFN(modalFilter, m_indiP_fpsSource)
    1114              : 
    1115            0 : INDI_NEWCALLBACK_DEFN( modalFilter, m_indiP_loop )( const pcf::IndiProperty &ipRecv )
    1116              : {
    1117            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_loop, ipRecv );
    1118              : 
    1119            0 :     if( ipRecv.find( "toggle" ) )
    1120              :     {
    1121            0 :         if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
    1122              :         {
    1123            0 :             if( !m_loop )
    1124              :             {
    1125            0 :                 log<loop_closed>();
    1126              :             }
    1127            0 :             m_loop = true;
    1128              :         }
    1129              :         else
    1130              :         {
    1131            0 :             if( m_loop )
    1132              :             {
    1133            0 :                 log<loop_open>();
    1134              :             }
    1135            0 :             m_loop = false;
    1136              :         }
    1137              :     }
    1138              : 
    1139            0 :     return 0;
    1140              : }
    1141              : 
    1142            0 : INDI_NEWCALLBACK_DEFN( modalFilter, m_indiP_gain )( const pcf::IndiProperty &ipRecv )
    1143              : {
    1144            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_gain, ipRecv );
    1145              : 
    1146              :     float target;
    1147            0 :     if( indiTargetUpdate( m_indiP_gain, target, ipRecv, true ) < 0 )
    1148              :     {
    1149            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1150            0 :         return -1;
    1151              :     }
    1152              : 
    1153            0 :     m_gain = target;
    1154              : 
    1155            0 :     std::cerr << "Got global gain: " << m_gain << '\n';
    1156              : 
    1157            0 :     return 0;
    1158              : }
    1159              : 
    1160            0 : INDI_NEWCALLBACK_DEFN( modalFilter, m_indiP_mult )( const pcf::IndiProperty &ipRecv )
    1161              : {
    1162            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_mult, ipRecv );
    1163              : 
    1164              :     float target;
    1165            0 :     if( indiTargetUpdate( m_indiP_mult, target, ipRecv, true ) < 0 )
    1166              :     {
    1167            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1168            0 :         return -1;
    1169              :     }
    1170              : 
    1171            0 :     m_mc = target;
    1172              : 
    1173            0 :     std::cerr << "Got global mc: " << m_mc << '\n';
    1174              : 
    1175            0 :     return 0;
    1176              : }
    1177              : 
    1178            0 : INDI_NEWCALLBACK_DEFN( modalFilter, m_indiP_pcGain )( const pcf::IndiProperty &ipRecv )
    1179              : {
    1180            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_pcGain, ipRecv );
    1181              : 
    1182              :     float target;
    1183            0 :     if( indiTargetUpdate( m_indiP_pcGain, target, ipRecv, true ) < 0 )
    1184              :     {
    1185            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1186            0 :         return -1;
    1187              :     }
    1188              : 
    1189            0 :     m_pcGain = target;
    1190              : 
    1191            0 :     std::cerr << "Got global pc gain: " << m_pcGain << '\n';
    1192            0 :     return 0;
    1193              : }
    1194              : 
    1195            0 : INDI_NEWCALLBACK_DEFN( modalFilter, m_indiP_pcMult )( const pcf::IndiProperty &ipRecv )
    1196              : {
    1197            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_pcMult, ipRecv );
    1198              : 
    1199              :     float target;
    1200            0 :     if( indiTargetUpdate( m_indiP_pcMult, target, ipRecv, true ) < 0 )
    1201              :     {
    1202            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1203            0 :         return -1;
    1204              :     }
    1205              : 
    1206            0 :     m_pcMc = target;
    1207              : 
    1208            0 :     std::cerr << "Got global pc mc: " << m_mc << '\n';
    1209              : 
    1210            0 :     return 0;
    1211              : }
    1212              : 
    1213            0 : INDI_NEWCALLBACK_DEFN( modalFilter, m_indiP_pcOn )( const pcf::IndiProperty &ipRecv )
    1214              : {
    1215            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_pcOn, ipRecv );
    1216              : 
    1217            0 :     if( ipRecv.find( "toggle" ) )
    1218              :     {
    1219            0 :         if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
    1220              :         {
    1221              : 
    1222            0 :             m_pcOn = true;
    1223              :         }
    1224              :         else
    1225              :         {
    1226            0 :             m_pcOn = false;
    1227              :         }
    1228              :     }
    1229              : 
    1230            0 :     return 0;
    1231              : }
    1232              : 
    1233              : } // namespace app
    1234              : } // namespace MagAOX
    1235              : 
    1236              : #endif // modalFilter_hpp
        

Generated by: LCOV version 2.0-1