#ifndef NFM_BASE_H
#define NFM_BASE_H

    #include <stdint.h>
    #include <stddef.h>
    #include <stdbool.h>

    #include "app/nfm/nfm_base_ECalUnit.h"

    typedef struct TEcalHeader            sEcalHeader_t;
    typedef struct TEcalHeaderCRC         sEcalHeaderCRC_t;
    typedef struct TEcalDataHeader        sEcalDataHeader_t;
    typedef struct TEcalDataHeaderCRC     sEcalDataHeaderCRC_t;
    typedef struct TEcalTCompHeader       sEcalTCompHeader_t;
    typedef struct TEcalTCompHeaderCRC    sEcalTCompHeaderCRC_t;
    typedef struct TEcalSegment           sEcalSegmentUnaligned_t;
    
    typedef struct TableTHeader           sTableHeader_t;
    typedef struct TableTHeaderCRC        sTableHeaderCRC_t;
    
    typedef struct TablePoint             sTableTablePoint_t;
    
    
    typedef struct // ==TEcalSegment
    {
        double  Fstart;    // aligned access for 'double'
        double  Fstop;     // aligned access for 'double'
        int16_t Points;    
    } 
    // sEcalSegmentAligned_t: contains the same fields as a 'TEcalSegment',
    // but with aligned access for 'double'-typed fields.
    // Note: is used to store data inside the application, must not be used
    // to cast the buffer with data that read from the memory, use
    // sEcalSegmentUnaligned_t instead
    sEcalSegmentAligned_t; 

    typedef sEcalSegmentAligned_t         sEcalSegment_t;
    
    typedef struct TEcalTableHeader       sEcalChrzTableHeader_t;    
    typedef struct TEcalPoint24           sEcalChrzTablePoint_t;
    typedef struct TEcalThermMagnHeader   sEcalTCompTableMagnHeader_t;
    typedef struct TEcalThermMagnPoint    sEcalTCompTableMagnPoint_t;
    typedef struct TEcalThermPhaseHeader  sEcalTCompTablePhaseHeader_t;
    typedef struct TEcalThermPhasePoint   sEcalTCompTablePhasePoint_t;
    
    // enum физических портов прибора
    typedef enum
    {
        eNFMPort_1 = 1,
        eNFMPort_2 = 2
    }
    eNFMPorts_t;
    
    typedef enum {
      ePort_1 = 0,
      ePort_2,
      ePort_3,
      ePort_4,
      ePort_5,
      ePort_6,
      ePort_7,
      ePort_8,
      ePort_9,
      ePort_10,
      ePort_11,
      ePort_12,

      ePort_Unknown = 255,
    }
    ePorts_t;
    
    typedef enum {
      eTerminatePortState = 0,           // All ports are shutdown
      eUnknownPortState = 255,
    }
    sDefaultPortStates_t;
    
    typedef enum {
      eTrigState_Rising = 0,           // Rising
      eTrigState_Falling,              // Falling
      
      eKeyState_UnknownTrig = 255,
    }
    eSBTrigState_t;

    #ifndef DEVICE_FIRMWARE_VERSION
    #define DEVICE_FIRMWARE_VERSION "2.0/02"
    #endif
    
    // eCharacterization_t:
    // Type of characterization table
    // Related objects: @aChrzDesc
    typedef enum
    {
        /* DO NOT CHANGE VALUES ! */
        eChFactory = 0,   // factory table, by default
        eChUser1   = 1,   // user table #1
        eChUser2   = 2,   // user table #2
        eChUser3   = 3,   // user table #3
        
        eCh_MAX    = 4
    }
    eChrz_t;
    
    typedef enum
    {
        eChValues = 0,    // User table plan
        
        eChValues_MAX = 2 // User table max
    }
    eChunks_t;
    
    // Type of scale of characterization table
    typedef enum
    {
        eChScale_undefined,
        eChScaleLinear,    // Linear frequency scale
        eChScaleSegment,   // Segment frequency scale    
        
    }
    eChrzScaleType_t;
    
    // Type of connector type
    typedef enum
    {
       eCon_N50_M,     // "Type-N50 -M-"
       eCon_N50_F,     // "Type-N50 -F-"
       eCon_3dot5mm_M, // "3.5mm -M-"
       eCon_3dot5mm_F, // "3.5mm -F-"
       eCon_2dot4mm_M, // "2.4mm -M-"
       eCon_2dot4mm_F, // "2.4mm -F-"
       eCon_N75_M,     // "Type-N75 -M-"
       eCon_N75_F,     // "Type-N75 -F-" 
       eCon_F_M,       // "Type-F -M-"
       eCon_F_F,       // "Type-F -F-" 
       eCon_7_16_M,    // "7/16 -M-"
       eCon_7_16_F,    // "7/16 -F-"  
       eCon_APC_7      // "APC-7"  
    }
    eConnectorType_t;
    
    typedef enum
    {
       ePortId_A,
       ePortId_B,
       ePortId_C,
       ePortId_D,
       
       ePortId_MAX
    }
    ePortId_t;
    
    typedef enum
    {
       ePortComb_UNDEFINED,
         
       ePortComb_A,
       ePortComb_B,
       ePortComb_C,
       ePortComb_D,
       ePortComb_AB,
       ePortComb_AC,
       ePortComb_AD,
       ePortComb_BC,
       ePortComb_BD,
       ePortComb_CD,
       ePortComb_CHECK,
       
       ePortComb_MAX,      
       
       ePortComb_BA = ePortComb_AB,
       ePortComb_CA = ePortComb_AC,
       ePortComb_CB = ePortComb_BC,       
       ePortComb_DA = ePortComb_AD,
       ePortComb_DB = ePortComb_BD,
       ePortComb_DC = ePortComb_CD,
       
       ePortComb_MIN_SINGLE_XPort = ePortComb_A,
       ePortComb_MAX_SINGLE_XPort = ePortComb_D, // maximum supported
       ePortComb_MIN_SINGLE_2Port = ePortComb_A,
       ePortComb_MAX_SINGLE_2Port = ePortComb_B,
       ePortComb_MIN_SINGLE_4Port = ePortComb_A,
       ePortComb_MAX_SINGLE_4Port = ePortComb_D,
       ePortComb_MIN_THRU_XPort   = ePortComb_AB,
       ePortComb_MAX_THRU_XPort   = ePortComb_CD, // maximum supported
       ePortComb_MIN_THRU_2Port   = ePortComb_AB,
       ePortComb_MAX_THRU_2Port   = ePortComb_AB,
       ePortComb_MIN_THRU_4Port   = ePortComb_AB,
       ePortComb_MAX_THRU_4Port   = ePortComb_CD, 
       
       ePortComb_MIN = ePortComb_A,
    }
    ePortComb_t;
    
    typedef enum  // Do not forget to update 'NFMCheckPortStateAvailable' and 'NFM_ROM_GetChrzTableIndex' routines
    { 
       ePortStateId_UNDEFINED,
                            // Port State:
       ePortStateId_Short,  // shorted port: A, B, C, D
       ePortStateId_Open,   // opened port: A, B, C, D
       ePortStateId_Load ,  // loaded port: A, B, C, D     
       ePortStateId_Load2,  // loaded (2) port: A, B, C, D
       ePortStateId_Open2,  // opened (2) port: A, B, C, D
       //-------------------------------------------------
       ePortStateId_S11,    // | Quard matrix of S-param  ^ } available for CHECK and THRU
       ePortStateId_S21,    // | S11, S12, S21, S22       ^ } available for CHECK and THRU
       ePortStateId_S12,    // | for combination of       ^ } available for CHECK and THRU
       ePortStateId_S22,    // | two ports or four ports  ^ } available for CHECK and THRU
       //-------------------------------------------------
       ePortStateId_S13,    // | 16-matrix of S-param     ^ } available for CHECK only
       ePortStateId_S14,    // | S11 - S44                ^ } available for CHECK only
       ePortStateId_S23,    // | for combination of       ^ } available for CHECK only
       ePortStateId_S24,    // | four ports only          ^ } available for CHECK only
       ePortStateId_S31,    // | available for CHECK only ^ } available for CHECK only
       ePortStateId_S32,    // |                          ^ } available for CHECK only
       ePortStateId_S33,    // |                          ^ } available for CHECK only
       ePortStateId_S34,    // |                          ^ } available for CHECK only
       ePortStateId_S41,    // |                          ^ } available for CHECK only
       ePortStateId_S42,    // |                          ^ } available for CHECK only
       ePortStateId_S43,    // |                          ^ } available for CHECK only
       ePortStateId_S44,    // |                          ^ } available for CHECK only
       //-------------------------------------------------
       ePortStateId_MAX,  
       
       // ePortStateId_MIN_SINGLE...ePortStateId_MAX_SINGLE
       // Available states for Single Port Combination (A,B,C,D)
       ePortStateId_MIN_SINGLE_XPort = ePortStateId_Short,  // 
       ePortStateId_MAX_SINGLE_XPort = ePortStateId_Open2,  // maximum supported
       ePortStateId_MIN_SINGLE_2Port = ePortStateId_Short,  // 
       ePortStateId_MAX_SINGLE_2Port = ePortStateId_Open2,  // 
       ePortStateId_MIN_SINGLE_4Port = ePortStateId_Short,  // 
       ePortStateId_MAX_SINGLE_4Port = ePortStateId_Open2,  //
       
       // ePortStateId_MIN_THRU...ePortStateId_MAX_THRU
       // Available states for Pair Port Combination (AB,AC,AD,BC,BD,CD)
       ePortStateId_MIN_THRU_XPort   = ePortStateId_S11,    //
       ePortStateId_MAX_THRU_XPort   = ePortStateId_S22,    // maximum supported
       ePortStateId_MIN_THRU_2Port   = ePortStateId_S11,    //
       ePortStateId_MAX_THRU_2Port   = ePortStateId_S22,    //
       ePortStateId_MIN_THRU_4Port   = ePortStateId_S11,    //
       ePortStateId_MAX_THRU_4Port   = ePortStateId_S22,    //
       
       // ePortStateId_MIN_CHECK...ePortStateId_MAX_CHECK
       // Available states for Quard Port Combination (CHECK)
       ePortStateId_MIN_CHECK_XPort  = ePortStateId_S11,    //
       ePortStateId_MAX_CHECK_XPort  = ePortStateId_S44,    // maximum supported
       ePortStateId_MIN_CHECK_2Port  = ePortStateId_S11,    //
       ePortStateId_MAX_CHECK_2Port  = ePortStateId_S22,    //
       ePortStateId_MIN_CHECK_4Port  = ePortStateId_S11,    //
       ePortStateId_MAX_CHECK_4Port  = ePortStateId_S44,    //

       ePortStateId_MIN = ePortStateId_Short,
    }
    ePortStateId_t;
    
    // sNFMChrzPoint_t:
    //
    typedef struct
    {
       double magn;
       double phase;
    }
    sNFMChrzPoint_t;
    
    // sNFMTCompMagnPoint_t:
    //
    typedef struct
    {
       double magn;       
    }
    sNFMTCompMagnPoint_t;
    
    // sNFMTCompPhasePoint_t:
    //
    typedef struct
    {
       double phase;       
    }
    sNFMTCompPhasePoint_t;
    
    typedef struct
    {                
        uint8_t port1;  // Device port1 switch state
        uint8_t port2;  // Device port2 switch state
    }sSWTablePoint_t; 
    
    // sNFMGetPoints_t
    // Control structure to retieve the data points of
    // characterization array or thermocompensation array
    typedef struct
    {
       struct
       {         
       size_t            nStartPoint;  // Starting point
       size_t            nCount;       // Amount of points
       sNFMChrzPoint_t * pDataArray;   // Pointer to the buffer to store chrz points
       }
       in;
       
       struct
       {  
       size_t TableAddress;   // memory address of the table
       size_t nPoints;        // whole number of points in the table
       int16_t min;           // "Minimum value": for scaling the values, see TEcalTableHeader
       int16_t max;           // "Maximum value": for scaling the values, see TEcalTableHeader       
       }
       out;
       
       struct
       {
       unsigned int errCode;  // error code, see @ERR_NFMGETPOINTS_* macros
       }
       svc;
    }
    sNFMGetPoints_t;

    // xNFMGetFreqPoints_t
    // Control structure to retieve the frequency points
    typedef struct
    {
       const void * private[14];
    }
    xNFMGetFreqPoints_t;

    // sNFMGetPointsSimplified_t
    // Control structure to retieve the data points
    typedef struct
    {
       const void * private[9];
    }
    xNFMGetPointsSimplified_t;
    
    typedef struct
    {
       const void * private[9];
    }
    xSWGetTablePoints_t;

    // @eNFMGetPointError_t
    // Result code of following routines:
    // - @NFMGetScaleFreqs_Begin
    // - @NFMGetScaleFreqs_Continue
    typedef enum
    {
        eNFMGetPointError_DataError = -2,     // can't get/process data (crc invalid?)
        eNFMGetPointError_InvalidValue = -1,  // invalid input parameters
        eNFMGetPointError_Success = 0,        // success code
        eNFMGetPointError_OutOfBuffer = 1,    // warning code
        eNFMGetPointError_Limit = 2,          // warning code
    }
    eNFMGetPointError_t;

    #define ERR_NFMGETPOINTS_NOERR      0    // no error
    #define ERR_NFMGETPOINTS_INVAL      1    // invalid parameter or argument
    #define ERR_NFMGETPOINTS_INVHDR     2    // invalid data header (chrz or tcomp)
    #define ERR_NFMGETPOINTS_INVTBL     3    // invalid data table (corrupted/invalid crc)
    #define ERR_NFMGETPOINTS_IO         4    // i/o error

    typedef enum
    {
       eNFM_IfaceUSBVendor,
       eNFM_IfaceUSBTMC
    }
    eNFMUSBInterface_t;

    typedef struct
    {
       uint16_t settingsVersion;              // Device settings version (for compatible)
       uint8_t rawBytes[8];                   // Device current USB protocol
       uint16_t tempCoeff;                    // Device temperature coefficient
       uint8_t reserved[48];                  // Reserved bytes
    }
    sNFMSettingsBlock_t;
    
    typedef struct
    {
        sNFMSettingsBlock_t settings;
        uint32_t CRCValue;
    }sNFMSettingsBlockCrc_t;

    typedef struct
    {
        struct
        {
            const char *           manufacturerId;         // Device Manufacturer Id
            const char *           firmwareId;             // Firmware ID
            const char *           modelName;              // SWB Model name
            const char *           serialNumber;           // serial number
            
            uint16_t allowedInputPorts;
            uint16_t allowedOutputPorts;
            uint16_t defaultInputState;
            
            uint16_t *              inputPortStates;       // Current input port states
            uint16_t                deviceId;              // device id
            bool                    isServiceMode;         // is device in service mode
        }
        properties;
        
        struct
        { 
            struct
            {
                  bool (* getInterface)( eNFMUSBInterface_t * pCurrentIface );
                  bool (* setInterface)( eNFMUSBInterface_t activateInterface );
            }
            usbInterface;
            
            struct
            {
                uint16_t (* getPortState)( uint16_t portNumber );
                bool     (* setPortState)( uint16_t portNumber, uint16_t portState );
            }portMethods;
            
            // Get device serial number in string format
            size_t (* getDeviceSerial)( char * buffer, size_t size );
            
            // Get device manufacturer ID in string format
            size_t (* getDeviceManufacturer)( char * buffer, size_t size );

            // Check if the specified port state is available for current configuration
            bool   (* checkPortStateAvailable)( ePortStateId_t portState );

            // Check if the specified port combination is available for current configuration
            bool   (* checkPortCombinationAvailable)( ePortComb_t portComb );

            // Get model name (description)
            size_t (* getModelName)(  char * buffer, size_t size );           
            
            // Checks the characterization table parameters for compatibility
            bool (* checkTableParams)( ePortComb_t portComb, ePortStateId_t portState );
                
                
            struct
            {
            // // MEM:TABL:DATA?
            // // Reads the data points of the characterization table
            // size_t (* getPoints)( eChrz_t tableId, ePortComb_t portComb, ePortStateId_t portState,
            //                       sNFMGetPoints_t * pCtl ); # replaced with @getPoints_Init/@getPoints_Next

                // MEM:TABL:DATA?
                // Prepares the context before reading the data points of the characterization table
                // Parameters:
                // @sectorId - bank id, characterization bank;
                // @portComb - port combination to request (NFM path);
                // @portState - port state to request (S-parameter);
                // @pDataBuffer - output data buffer;
                // @szDataBuffer - output data buffer capacity;
                // @xCtl - the control context to initialize;
                // Returns: 0 in case error, or number of points in case success.
                size_t (* getPoints_Init)( eChrz_t sectorId, ePortComb_t portComb, ePortStateId_t portState,
                                           sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer,
                                           xNFMGetPointsSimplified_t * xCtl );
                // MEM:TABL:DATA?
                // @getPoints_Next
                // Uses already prepared context and reads the data points of the characterization 
                // table to the top of specified buffer (see @getPoints_Init).
                // This method is designed to replace the obsolete @NFMGetPoints.
                // Parameters:
                // @xCtl - control context prepared by previous NFMGetPoints_Begin call
                // @pnPointsRetrieve - IN/OUT; IN: specifies a number of points to retrieve; OUT: stores the value of actually read points;
                //
                // Returns:
                // - eNFMGetPointError_DataError: error, can not load data;
                // - eNFMGetPointError_InvalidValue: error, invalid parameters;
                // - eNFMGetPointError_Success: success, all the points from the table have been read;
                // - eNFMGetPointError_OutOfBuffer: warning, points have been read, but it is required to continue because user buffer ran out;
                // - eNFMGetPointError_Limit: warning, points have been read, but the caller specified less points to read than actually available;
                int32_t (* getPoints_Next)( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve );
                
                // Reads amount of points in the characterization table
                size_t (* getPointsCount)( eChrz_t tableId );

                // MEM:TABL:POIN?
                // Reads amount of points in the characterization table
                bool (* getPointsCountSafe)( eChrz_t tableId, int16_t * count );
                
                // MEM:TABL:DATE?
                // Reads the date of characterization table
                bool (* getDate)( eChrz_t tableId, char * buffer, size_t size, size_t * bytes );
                
                // MEM:TABL:TIME?
                // Reads the time of characterization table
                bool (* getTime)( eChrz_t tableId, char * buffer, size_t size, size_t * bytes );
                
                // MEM:TABL:FREQ:TYPE?
                // Reads the type of the frequency scale of data characterization table
                bool (* getScaleType)( eChrz_t tableId, eChrzScaleType_t * pType );
                
                // MEM:TABL:FREQ:SEGM:DATA?
                // Reads the scale segment of data characterization table 
                // Pass NULL in @pSegment to retrieve amount of segments in return value
                size_t (* getScaleSegment)( eChrz_t tableId, sEcalSegment_t * pSegment, size_t nSegmentId );
                
                // MEM:TABL:FREQ:DATA?
                // @getScaleFreqs_Init
                // Prepares a retrieving context for calling the @getScaleFreqs_Next routine.
                // Initializes such values as:
                // - a number of starting point to retrive
                // - a buffer to retrieve the values to
                // - characterization table (unit) identifier (@tableId)
                // Parameters:
                // @tableId - characterization table to operate with;
                // @nStartPoint - starting point to begin retrieving from (default = 0);
                // @nStartSegment - starting segment to begin retrieving from (default = 0);
                // @pFreqArray - a floating point values buffer to store data to;
                // @BufferCapacity - receiving buffer capacity [@pFreqArray]
                // @xCtl - a control structure to intialize; use this structure to call @getScaleFreqs_Next. 
                //
                // Returns: integer result (see @eNFMGetPointError_t):
                // - eNFMGetPointError_DataError: error, can not load data;
                // - eNFMGetPointError_InvalidValue: error, invalid parameters;
                // - eNFMGetPointError_Success: success, all the points from all the segments have been read;
                int32_t (* getScaleFreqs_Init)( eChrz_t tableId, double * pFreqArray, size_t BufferCapacity, xNFMGetFreqPoints_t * xCtl );

                // MEM:TABL:FREQ:DATA?
                // @getScaleFreqs_Next
                // Related SCPI command: 'MEM:TABL:FREQ:DATA?'
                // Reads the frequencies of data characterization table's points (either for Linear and Segment scale)
                // and stores it into the buffer specified by calling @getScaleFreqs_Init
                // Note: the points are stored to the top of the specified buffer each call.
                //
                // Parameters:
                // @xCtl - retrieve context, must be initialized by @NFMGetScaleFreqs_Begin
                // @pnPointsRetrieve - IN/OUT; IN: specifies a number of points to retrieve; OUT: stores the value of actually read points;
                //
                // !!! Attention: user shall control the @pFreqArray buffer range itself when calling @getScaleFreqs_Init
                // !!! and guarantee, that it has enough room to recevie specified number of points [@nPointsRetrieve].
                //
                // Returns:
                // - eNFMGetPointError_DataError: error, can not load data;
                // - eNFMGetPointError_InvalidValue: error, invalid parameters;
                // - eNFMGetPointError_Success: success, all the points from all the segments have been read;
                // - eNFMGetPointError_OutOfBuffer: warning, points have been read, but it is required to continue because user buffer ran out;
                // - eNFMGetPointError_Limit: warning, points have been read, but the caller specified less points to read than actually available;
                int32_t (* getScaleFreqs_Next)( xNFMGetFreqPoints_t * xCtl, size_t * pnPointsRetrieve );
                
                // MEM:TABL:FREQ:STAR?
                // Reads the start frequency of the characterization table
                bool (* getStartFreq)( eChrz_t tableId, double * pStartFreq );
                
                // MEM:TABL:FREQ:STOP?
                // Reads the stop frequency of the characterization table
                bool (* getStopFreq)( eChrz_t tableId, double * pStopFreq );
                
                // MEM:TABL:TEMP?
                // Reads the characterization temperature of characterization table
                bool (* getChrzTemp)( eChrz_t tableId, double * pTemperature );
                
                // MEM:TABL:CONN?
                // Reads the connector type of the NFM
                bool (* getConnectorType)( ePortId_t portId, char * buffer, size_t size, size_t * bytes );
                
                // MEM:TABL:ADAP?
                // Reads the adapter description of the NFM connector
                bool (* getAdapterDesc)( eChrz_t tableId, ePortId_t portId, char * buffer, size_t size, size_t * bytes );
                
                // MEM:TABL:ANAL? ( =ANALyzer)
                // Reads the analyzer type
                bool (* getAnalyzer)( eChrz_t tableId, char * buffer, size_t size, size_t * bytes );
                
                // MEM:TABL:PLAC?
                // Reads the place where the characterization had been created
                bool (* getPlace)( eChrz_t tableId, char * buffer, size_t size, size_t * bytes );
                
                // MEM:TABL:OPER?
                // Reads the the characterization operator's name
                bool (* getOperator)( eChrz_t tableId, char * buffer, size_t size, size_t * bytes );
                
            }
            xCharacterization;
            
            struct
            {
                // TABLe:GET?
                // @getTablePoints_Init
                // Prepares a retrieving context for calling the @getTablePoints_Next routine.
                // Initializes such values as:
                // - a number of starting point to retrive
                // - a buffer to retrieve the values to
                // - points table (unit) identifier (@tableId)
                // Parameters:
                // @tableId - characterization table to operate with;
                // @nStartPoint - starting point to begin retrieving from (default = 0);
                // @nStartSegment - starting segment to begin retrieving from (default = 0);
                // @pValuesArray - a uint8_t point values buffer to store data to;
                // @BufferCapacity - receiving buffer capacity [@pFreqArray]
                // @xCtl - a control structure to intialize; use this structure to call @getTablePoints_Next. 
                //
                // Returns: integer result (see @eNFMGetPointError_t):
                // - eNFMGetPointError_DataError: error, can not load data;
                // - eNFMGetPointError_InvalidValue: error, invalid parameters;
                // - eNFMGetPointError_Success: success, all the points from all the segments have been read;
                int32_t (* getTablePoints_Init)( eChrz_t tableId, sSWTablePoint_t * pPointsArray, size_t BufferCapacity, xSWGetTablePoints_t * xCtl );

                // TABLe:GET?
                // @getTablePoints_Next
                // Related SCPI command: 'TABLe:GET?'
                // Reads the switch plan points of data table's points (either for Linear and Segment scale)
                // and stores it into the buffer specified by calling @getTablePoints_Init
                // Note: the points are stored to the top of the specified buffer each call.
                //
                // Parameters:
                // @xCtl - retrieve context, must be initialized by @NFMGetScaleFreqs_Begin
                // @pnPointsRetrieve - IN/OUT; IN: specifies a number of points to retrieve; OUT: stores the value of actually read points;
                //
                // !!! Attention: user shall control the @pPointsArray buffer range itself when calling @getTablePoints_Init
                // !!! and guarantee, that it has enough room to recevie specified number of points [@nPointsRetrieve].
                //
                // Returns:
                // - eNFMGetPointError_DataError: error, can not load data;
                // - eNFMGetPointError_InvalidValue: error, invalid parameters;
                // - eNFMGetPointError_Success: success, all the points from all the segments have been read;
                // - eNFMGetPointError_OutOfBuffer: warning, points have been read, but it is required to continue because user buffer ran out;
                // - eNFMGetPointError_Limit: warning, points have been read, but the caller specified less points to read than actually available;
                int32_t (* getTablePoints_Next)( xSWGetTablePoints_t * xCtl, size_t * pnPointsRetrieve );
            }xTable;
            
            struct
            {
                // MEM:TABL:THER:CORR:FREQ:STAR?
                // Reads the start frequency of the thermocompensation data
                bool (* getStartFreq)( double * pStartFreq );
                
                // MEM:TABL:THER:CORR:FREQ:STOP?
                // Reads the stop frequency of the thermocompensation data
                bool (* getStopFreq)( double * pStopFreq );
                
                // Reads the amount of points in the thermocompensation data
                size_t (* getPointsCount )( );

                // MEM:TABL:THER:CORR:POIN?
                // Reads the amount of points in the thermocompensation data
                bool (* getPointsCountSafe )( int16_t * count );

             // // MEM:TABL:THER:CORR:MAGN?
             // // Reads the magnitude data points of the thermocompensation table
             // size_t (* getPointsMagn )( ePortComb_t portComb, ePortStateId_t portState,
             //                       sNFMGetPoints_t * pCtl );
             // 
             // // MEM:TABL:THER:CORR:PHAS?
             // // Reads the phase data points of the thermocompensation table
             // size_t (* getPointsPhase )( ePortComb_t portComb, ePortStateId_t portState,
             //                       sNFMGetPoints_t * pCtl );


                // MEM:TABL:THERmo:CORRection:MAGNitude?
                // @getPointsThermoMagn_Init
                // Prepares the context before reading the data points of the thermocompensation table of magnitudes
                // This method is designed to replace the obsolete @getPointsMagn.
                // Parameters:
                // @portComb - port combination to request (NFM path);
                // @portState - port state to request (S-parameter);
                // @pDataBuffer - output data buffer;
                // @szDataBuffer - output data buffer capacity;
                // @xCtl - the control context to initialize;
                // Returns: 0 in case error, or number of points in case success.
                size_t (* getPointsThermoMagn_Init)( ePortComb_t portComb, ePortStateId_t portState,
                                                     sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer,
                                                     xNFMGetPointsSimplified_t * xCtl );

                // MEM:TABL:THERmo:CORRection:MAGNitude?
                // @getPointsThermoMagn_Next
                // Uses already prepared context and reads magnutude data points of the thermocompensation 
                // table to the top of specified buffer (see @getPointsThermoMagn_Init).
                // This method is designed to replace the obsolete @getPointsMagn.
                // Parameters:
                // @xCtl - control context prepared by previous getPointsThermoMagn_Init call
                // @pnPointsRetrieve - IN/OUT; IN: specifies a number of points to retrieve; OUT: stores the value of actually read points;
                //
                // Returns:
                // - eNFMGetPointError_DataError: error, can not load data;
                // - eNFMGetPointError_InvalidValue: error, invalid parameters;
                // - eNFMGetPointError_Success: success, all the points from the table have been read;
                // - eNFMGetPointError_OutOfBuffer: warning, points have been read, but it is required to continue because user buffer ran out;
                // - eNFMGetPointError_Limit: warning, points have been read, but the caller specified less points to read than actually available;
                int32_t (* getPointsThermoMagn_Next)( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve );
                
                // MEM:TABL:THERmo:CORRection:PHASe?
                // @getPointsThermoPhase_Init
                // Prepares the context before reading the data points of the thermocompensation table of phases
                // This method is designed to replace the obsolete @getPointsMagn.
                // Parameters:
                // @portComb - port combination to request (NFM path);
                // @portState - port state to request (S-parameter);
                // @pDataBuffer - output data buffer;
                // @szDataBuffer - output data buffer capacity;
                // @xCtl - the control context to initialize;
                // Returns: 0 in case error, or number of points in case success.
                size_t (* getPointsThermoPhase_Init)( ePortComb_t portComb, ePortStateId_t portState,
                                                     sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer,
                                                     xNFMGetPointsSimplified_t * xCtl );

                // MEM:TABL:THERmo:CORRection:PHASe?
                // @getPointsThermoPhase_Next
                // Uses already prepared context and reads phase data points of the thermocompensation 
                // table to the top of specified buffer (see @getPointsThermoPhase_Init).
                // This method is designed to replace the obsolete @getPointsPhase.
                // Parameters:
                // @xCtl - control context prepared by previous getPointsThermoPhase_Init call
                // @pnPointsRetrieve - IN/OUT; IN: specifies a number of points to retrieve; OUT: stores the value of actually read points;
                //
                // Returns:
                // - eNFMGetPointError_DataError: error, can not load data;
                // - eNFMGetPointError_InvalidValue: error, invalid parameters;
                // - eNFMGetPointError_Success: success, all the points from the table have been read;
                // - eNFMGetPointError_OutOfBuffer: warning, points have been read, but it is required to continue because user buffer ran out;
                // - eNFMGetPointError_Limit: warning, points have been read, but the caller specified less points to read than actually available;
                int32_t (* getPointsThermoPhase_Next)( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve );
            }
            xThermo;
            
            struct
            {
                bool ( * enable)( void );
                bool ( * disable)( void );
                bool ( * check)( void );
            }
            xMemoryProtection;
        } 
        methods;
    }
    NFMClass_t;
    
    #include "nfm/nfm_base_mem.h"
    #include "nfm/nfm_base_model.h"

    
    extern NFMClass_t * NFMClass;
    
    void nfmbase_init();
    void nfmbase_test();
    // service: change model id
    bool NFM_ROM_ChangeModel( eNFMModel_t modelId );
    bool NFM_ROM_ChangeSerialNumber( const char * serial );
    
    bool SW_ROM_ChangeTableHeader( sTableHeaderCRC_t * hdrcrc );
    
#endif
    
