#include "core/config.h" #if CONFIG_NFMBASECLASS #include #include #include "core/main.h" // _snprintf #include "core/config_pins.h" #include "crc32.h" #include "drivers/keycontrol/keycontrol_ll.h" #include "drivers/power_management/power_management.h" #include "app/nfm/nfm_base_excls.h" #include "app/thermo/tsensor.h" #include "app/led/led.h" #include "app/thermo/NTCtsensor.h" #include "app/version/version.h" #include // atoi[NFMCLASS_ENABLE__SERIAL_NUMBER_LEGACY] #include // tolower #define NFMCLASS_ENABLE__SERIAL_NUMBER_LEGACY 0 #include "my_assert.h" #include "app/control_table/control_table.h" STATIC_ASSERT( sizeof(xNFMGetFreqPoints_t) == sizeof(sNFMGetFreqPoints_t), "Invalid xNFMGetPoints_t/sNFMGetPoints_t size" ); STATIC_ASSERT( sizeof(xNFMGetPointsSimplified_t) == sizeof(sNFMGetPointsSimplified_t), "Invalid xNFMGetPointsSimplified_t/sNFMGetPointsSimplified_t size" ); #if defined(PLANAR) // Device Manufacturer ID const static char manufacturerId[] = "Planar"; //#elif defined(CMT) //const static char manufacturerId[] = "Copper Mountain Technologies"; #elif defined(CMT) const static char manufacturerId[] = "CMT"; #else #error Please, specify VENDOR macro #endif // Firmware ID static char g_firmwareId[16] = "0.1/01"; // NFM model name static char g_modelName[16] = "R0467"; // Serial Number String static char g_serialNumber[9] = "25230066"; // NFM Connectors descriptions const static char * const aConnectorsNames[] = { "Type-N50 -M-", "Type-N50 -F-", "3.5mm -M-", "3.5mm -F-", "2.4mm -M-", "2.4mm -F-", "Type-N75 -M-", "Type-N75 -F-", "Type-F -M-", "Type-F -F-", "7/16 -M-", "7/16 -F-", "APC-7", }; const static char pcConnectorUndefined[] = "Unknown"; //------------------------------------------------------------------------------ static void private_ClassInit(); static size_t static_StrCpyLimit( const char * source, size_t srcMaxLen, char * dest, size_t destMaxLen ); static const sNFMModel_t * static_GetModelProfileByDeviceId( uint16_t deviceId ); static bool private_getModelId( uint16_t * pDeviceId ); static bool private_CheckTableParams( ePortComb_t portComb, ePortStateId_t portState ); static size_t NFMGetDeviceManufacturer( char * buffer, size_t size ); static size_t NFMGetDeviceSerial( char * buffer, size_t size ); static size_t NFMGetModelName( char * buffer, size_t size ); static bool NFMCheckPortStateAvailable( ePortStateId_t portState ); static bool NFMCheckPortCombinationAvailable( ePortComb_t portComb ); // static bool NFMCheckPortParamsAvailable( ePortComb_t portComb, ePortStateId_t portState ); // static size_t NFMGetPoints( eChrz_t tableId, ePortComb_t portComb, ePortStateId_t portState, sNFMGetPoints_t * pCtl ); // static size_t NFMGetPointsMagnThermo( ePortComb_t portComb, ePortStateId_t portState, sNFMGetPoints_t * pCtl ); // static size_t NFMGetPointsPhaseThermo( ePortComb_t portComb, ePortStateId_t portState, sNFMGetPoints_t * pCtl ); static size_t NFMGetPointsCount( eChrz_t tableId ); static bool NFMGetPointsCount_Safe( eChrz_t tableId, int16_t * count ); static bool NFMGetDate( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ); static bool NFMGetTime( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ); static bool NFMGetScaleType( eChrz_t tableId, eChrzScaleType_t * pType ); static size_t NFMGetScaleSegment( eChrz_t tableId, sEcalSegment_t * pSegment, size_t nSegmentId ); //------------------------------------------------------------------------------ static int32_t NFMGetScaleFreqs_Begin( eChrz_t tableId, double * pFreqArray, size_t BufferCapacity, xNFMGetFreqPoints_t * xCtl ); static int32_t NFMGetScaleFreqs_Continue( xNFMGetFreqPoints_t * xCtl, size_t * pnPointsRetrieve ); //------------------------------------------------------------------------------ static int32_t SWGetTablePoints_Begin( eChrz_t tableId, sSWTablePoint_t * pPointsArray, size_t BufferCapacity, xSWGetTablePoints_t * xCtl ); static int32_t SWGetTablePoints_Continue( xSWGetTablePoints_t * xCtl, size_t * pnPointsRetrieve ); //------------------------------------------------------------------------------ static size_t NFMGetPoints_Begin( eChrz_t sectorId, ePortComb_t portComb, ePortStateId_t portState, sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer, xNFMGetPointsSimplified_t * xCtl ); static int32_t NFMGetPoints_Continue( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve ); //------------------------------------------------------------------------------ static size_t NFMGetPointsThermo_Begin( ePortComb_t portComb, ePortStateId_t portState, sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer, sNFMGetPointsSimplified_t * pCtl ); static size_t NFMGetPointsThermoMagn_Begin( ePortComb_t portComb, ePortStateId_t portState, sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer, xNFMGetPointsSimplified_t * xCtl ); static size_t NFMGetPointsThermoPhase_Begin( ePortComb_t portComb, ePortStateId_t portState, sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer, xNFMGetPointsSimplified_t * xCtl ); //------------------------------------------------------------------------------ static int32_t NFMGetPointsThermo_Continue( sNFMGetPointsSimplified_t * pCtl, size_t * pnPointsRetrieve ); static int32_t NFMGetPointsThermoMagn_Continue( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve ); static int32_t NFMGetPointsThermoPhase_Continue( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve ); //------------------------------------------------------------------------------ static bool NFMGetStartFreq( eChrz_t tableId, double * pStartFreq ); static bool NFMGetStopFreq( eChrz_t tableId, double * pStopFreq ); static bool NFMGetChrzTemp( eChrz_t tableId, double * pTemperature ); static bool NFMGetConnectorType( ePortId_t portId, char * buffer, size_t size, size_t * bytes ); static bool NFMGetAdapterDesc( eChrz_t tableId, ePortId_t portId, char * buffer, size_t size, size_t * bytes ); static bool NFMGetAnalyzer( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ); static bool NFMGetPlace( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ); static bool NFMGetOperator( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ); //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ static bool NFMGetInterface( eNFMUSBInterface_t * pCurrentIface ); static bool NFMSetInterface( eNFMUSBInterface_t activateInterface ); //------------------------------------------------------------------------------ static uint16_t NFMGetPortState (uint16_t portNumber); static bool NFMSetPortState (uint16_t portNumber, uint16_t portState); //------------------------------------------------------------------------------ static bool NFMSetMemoryProtect(); static bool NFMSetMemoryUnProtect(); static bool NFMGetMemoryProtect(); //------------------------------------------------------------------------------ static bool NFMGetStartFreqThermo( double * pStartFreq ); static bool NFMGetStopFreqThermo( double * pStopFreq ); static size_t NFMGetPointsThermo(); static bool NFMGetPointsThermo_Safe( int16_t * count ); //------------------------------------------------------------------------------ static NFMClassEx_t __NFMClass = { .public = { .properties = { .manufacturerId = manufacturerId, .firmwareId = g_firmwareId, .modelName = g_modelName, .serialNumber = g_serialNumber, .allowedInputPorts = 2, .allowedOutputPorts = 12, .defaultInputState = eTerminatePortState, //.inputPortStates = {0, 0}, .deviceId = eModel_undefined, .isServiceMode = false }, .methods = { .usbInterface = { .getInterface = NFMGetInterface, .setInterface = NFMSetInterface }, .portMethods = { .getPortState = NFMGetPortState, .setPortState = NFMSetPortState, }, .getDeviceManufacturer = NFMGetDeviceManufacturer, .getDeviceSerial = NFMGetDeviceSerial, .getModelName = NFMGetModelName, .checkPortStateAvailable = NFMCheckPortStateAvailable, .checkPortCombinationAvailable = NFMCheckPortCombinationAvailable, .checkTableParams = private_CheckTableParams, .xCharacterization = { //.getPoints = NFMGetPoints, .getPoints_Init = NFMGetPoints_Begin, .getPoints_Next = NFMGetPoints_Continue, .getPointsCount = NFMGetPointsCount, .getPointsCountSafe = NFMGetPointsCount_Safe, .getDate = NFMGetDate, .getTime = NFMGetTime, .getScaleType = NFMGetScaleType, .getScaleSegment = NFMGetScaleSegment, .getScaleFreqs_Init = NFMGetScaleFreqs_Begin, .getScaleFreqs_Next = NFMGetScaleFreqs_Continue, .getStartFreq = NFMGetStartFreq, .getStopFreq = NFMGetStopFreq, .getChrzTemp = NFMGetChrzTemp, .getConnectorType = NFMGetConnectorType, .getAdapterDesc = NFMGetAdapterDesc, .getAnalyzer = NFMGetAnalyzer, .getPlace = NFMGetPlace, .getOperator = NFMGetOperator, }, .xTable = { .getTablePoints_Init = SWGetTablePoints_Begin, .getTablePoints_Next = SWGetTablePoints_Continue, }, .xThermo = { .getStartFreq = NFMGetStartFreqThermo, .getStopFreq = NFMGetStopFreqThermo, .getPointsCount = NFMGetPointsThermo, .getPointsCountSafe = NFMGetPointsThermo_Safe, //.getPointsMagn = NFMGetPointsMagnThermo, //.getPointsPhase = NFMGetPointsPhaseThermo, .getPointsThermoMagn_Init = NFMGetPointsThermoMagn_Begin, .getPointsThermoMagn_Next = NFMGetPointsThermoMagn_Continue, .getPointsThermoPhase_Init = NFMGetPointsThermoPhase_Begin, .getPointsThermoPhase_Next = NFMGetPointsThermoPhase_Continue, }, .xMemoryProtection = { .enable = NFMSetMemoryProtect, .disable = NFMSetMemoryUnProtect, .check = NFMGetMemoryProtect, }, }, }, .private = { .methods = { .classInit = private_ClassInit, .getModelId = private_getModelId, .memory = { .setProtect = NFM_ROM_SetMemoryProtectStatus_Bank0, .getProtect = NFM_ROM_GetMemoryProtectStatus_Bank0, .getCommonHeader = NFM_ROM_GetCommonHeader, .getDataHeader = NFM_ROM_GetDataHeader, .getTCompHeader = NFM_ROM_GetTCompHeader, .getChrzTableIndex = NFM_ROM_GetChrzTableIndex, .getTCompTableIndex = NFM_ROM_GetTCompTableIndex, .getChrzTableHeader = NFM_ROM_ReadChrzTableHeader, .getChrzPoints = NFM_ROM_ReadChrzTablePoints, .getTCompMagnTableHeader = NFM_ROM_GetTCompMagnTableHeader, .getTCompPhaseTableHeader = NFM_ROM_GetTCompPhaseTableHeader, .getTCompMagnPoints = NFM_ROM_GetTCompMagnPoints, .getTCompPhasePoints = NFM_ROM_GetTCompPhasePoints, .getSettingsBlock = NFM_ROM_ReadDeviceSettings, .setSettingsBlock = NFM_ROM_WriteDeviceSettings, .getSettingsBlockSize = NFM_ROM_GetDeviceSettingsSize, .validateSettings = NFM_ROM_ValidateUserSettings, } }, .properties = { .deviceId = eModel_undefined, .modelProfile = NULL, } } }; __root NFMClass_t * NFMClass = (NFMClass_t*)&__NFMClass; __root NFMClassEx_t * NFMClassExtended = &__NFMClass; //------------------------------------------------------------------------------------------------------------ //-- Global methods ------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------ void nfmbase_init() { // initialize NFM object NFMClassExtended->private.methods.classInit(); // set key-switch state by default //NFMClass->methods.keyStatesMethods.setKeyStateDefault(); // sTableTablePoint_t TablePoint; // TablePoint.port1 = 12; // TablePoint.port2 = 2; // SW_ROM_SetDataPoint(0, &TablePoint); // TablePoint.port1 = 4; // TablePoint.port2 = 6; // SW_ROM_SetDataPoint(0, &TablePoint); // TablePoint.port1 = 1; // TablePoint.port2 = 3; // SW_ROM_SetDataPoint(0, &TablePoint); // uint8_t buffer[100]; // memset(&buffer, 0x00, sizeof(buffer)); // SW_ROM_GetDataPoint(0, 5, &buffer, sizeof(sTableTablePoint_t)); // SW_ROM_GetDataPoint(0, 6, &buffer, sizeof(sTableTablePoint_t)); // SW_ROM_GetDataPoint(0, 7, &buffer, sizeof(sTableTablePoint_t)); // SW_ROM_GetDataPoint(0, 8, &buffer, sizeof(sTableTablePoint_t)); // uint32_t crc = SW_ROM_Get_Table_crc( eChValues ); // SW_ROM_Set_Table_crc ( crc ); // SW_ROM_Check_Table_crc(); // SW_ROM_Table_Clear(); #if CONFIG_NFMCLASS_AUTOPROTECT_MEMORY // protect factory data: set memory protection NFMClass->methods.xMemoryProtection.enable(); #endif } #define NFMCLASS_TEST CONFIG_NFMBASECLASS_TEST #define NFMCLASS_TEST_TEMPERATURE 0 #define NFMCLASS_TEST_TEMPERATURESTR 0 #define NFMCLASS_TEST_MANUFACTURERSTR 0 #define NFMCLASS_TEST_SERIALSTR 0 #define NFMCLASS_TEST_SERIALLEGACY 0 #define NFMCLASS_TEST_STATENAMES 0 #define NFMCLASS_TEST_STATELIST 0 #define NFMCLASS_TEST_KEYSWSTATENAME 0 #define NFMCLASS_TEST_MODELNAME 0 #define NFMCLASS_TEST_CURRENTSTATE 0 #define NFMCLASS_TEST_LEGACYSTATE 0 #define NFMCLASS_TEST_RAWKEYCODE 0 #define NFMCLASS_TEST_KEYSTATESHORTCUTS 0 #define NFMCLASS_TEST_CHRZ_ADAPTERSTR 0 #define NFMCLASS_TEST_CHRZ_ANALYZERSTR 0 #define NFMCLASS_TEST_CHRZ_TEMP 0 #define NFMCLASS_TEST_CHRZ_CONNECTORSTR 0 #define NFMCLASS_TEST_CHRZ_DATESTR 0 #define NFMCLASS_TEST_CHRZ_TIMESTR 0 #define NFMCLASS_TEST_CHRZ_OPERATORSTR 0 #define NFMCLASS_TEST_CHRZ_PLACESTR 0 #define NFMCLASS_TEST_CHRZ_POINTSCOUNT 0 #define NFMCLASS_TEST_CHRZ_SEGMENTS 0 #define NFMCLASS_TEST_CHRZ_STARTFREQ 0 #define NFMCLASS_TEST_CHRZ_STOPFREQ 0 #define NFMCLASS_TEST_THERMO_POINTSCOUNT 0 #define NFMCLASS_TEST_THERMO_STOPFREQ 0 #define NFMCLASS_TEST_THERMO_STARTFREQ 0 #define NFMCLASS_TEST_MEM_PROTECTION 0 void nfmbase_test() { #if NFMCLASS_TEST asm( "bkpt #0" ); #if 1 && NFMCLASS_TEST_TEMPERATURE { float avgTemp = NFMClass->methods.getAverageTemperature(); asm( "bkpt #0" ); (void)avgTemp; } #endif #if 0 && NFMCLASS_TEST_TEMPERATURESTR { char avgTempStrBuffer[ 20 ] = {0}; NFMClass->methods.getAverageTemperatureString( avgTempStrBuffer, sizeof(avgTempStrBuffer) ) asm( "bkpt #0" ); (void)avgTempStrBuffer; } #endif #if 1 && NFMCLASS_TEST_MANUFACTURERSTR { char manufacturerStrBuffer[ 20 ] = {0}; NFMClass->methods.getDeviceManufacturer( manufacturerStrBuffer, sizeof(manufacturerStrBuffer) ); asm( "bkpt #0" ); (void)manufacturerStrBuffer; } #endif #if 1 && NFMCLASS_TEST_SERIALSTR { char serialStrBuffer[ 20 ] = {0}; NFMClass->methods.getDeviceSerial( serialStrBuffer, sizeof(serialStrBuffer) ); asm( "bkpt #0" ); (void)serialStrBuffer; } #endif #if 1 && NFMCLASS_TEST_SERIALLEGACY { uint32_t serialNumber = NFMClass->methods.getDeviceSerialLegacy(); asm( "bkpt #0" ); (void)serialNumber; } #endif #if 1 && NFMCLASS_TEST_STATENAMES { char stateNameStrBuffer[ 20 ] = {0}; eNFMKeyState_t state = NFMClass->methods.getKeyStateByName( "SALL", 4 ); asm( "bkpt #0" ); NFMClass->methods.getKeyStateName( state, stateNameStrBuffer, sizeof(stateNameStrBuffer) ); asm( "bkpt #0" ); (void)state, (void)stateNameStrBuffer; } { char stateNameStrBuffer[ 20 ] = {0}; eNFMKeyState_t state = NFMClass->methods.getKeyStateByName( "OALL", 4 ); asm( "bkpt #0" ); NFMClass->methods.getKeyStateName( state, stateNameStrBuffer, sizeof(stateNameStrBuffer) ); asm( "bkpt #0" ); (void)state, (void)stateNameStrBuffer; } { char stateNameStrBuffer[ 20 ] = {0}; eNFMKeyState_t state = NFMClass->methods.getKeyStateByName( "LALL", 4 ); asm( "bkpt #0" ); NFMClass->methods.getKeyStateName( state, stateNameStrBuffer, sizeof(stateNameStrBuffer) ); asm( "bkpt #0" ); (void)state, (void)stateNameStrBuffer; } #endif #if 1 && NFMCLASS_TEST_STATELIST { char statesListStrBuffer[ 64 ] = {0}; NFMClass->methods.getKeyStateList( statesListStrBuffer, sizeof(statesListStrBuffer) ); asm( "bkpt #0" ); (void)statesListStrBuffer; } #endif #if 1 && NFMCLASS_TEST_KEYSWSTATENAME { char keySwitchNameStrBuffer[ 20 ] = {0}; NFMClass->methods.getKeySwitchName( keySwitchNameStrBuffer, sizeof(keySwitchNameStrBuffer) ); asm( "bkpt #0" ); (void)keySwitchNameStrBuffer; } #endif #if 1 && NFMCLASS_TEST_MODELNAME { char modelNameStrBuffer[ 20 ] = {0}; NFMClass->methods.getModelName( modelNameStrBuffer, sizeof(modelNameStrBuffer) ); asm( "bkpt #0" ); (void)modelNameStrBuffer; } #endif #if 1 && NFMCLASS_TEST_CURRENTSTATE { eNFMKeyState_t currentState = NFMClass->methods.keyStatesMethods.getKeyStateCommon(); asm( "bkpt #0" ); (void)currentState; } #endif #if 1 && NFMCLASS_TEST_LEGACYSTATE { uint32_t legacyState = 0; eNFMKeyState_t testState = eKeyState_CHECK; if( NFMClass->methods.keyStatesMethods.getKeyStateLegacy( &legacyState ) ) { asm( "bkpt #0" ); // OK NFMClass->methods.keyStatesMethods.setKeyStateCommon( testState ); if( testState == NFMClass->methods.keyStatesMethods.getKeyStateCommon() ) asm( "bkpt #0" ); // OK else asm( "bkpt #0" ); // ERROR if( NFMClass->methods.keyStatesMethods.setKeyStateLegacy( legacyState ) ) asm( "bkpt #0" ); // OK else asm( "bkpt #0" ); // ERROR uint32_t legacyState_2 = 0; if( NFMClass->methods.keyStatesMethods.getKeyStateLegacy( &legacyState_2 ) ) asm( "bkpt #0" ); // OK else asm( "bkpt #0" ); // ERROR if( legacyState_2 == legacyState ) asm( "bkpt #0" ); // OK else asm( "bkpt #0" ); // ERROR } else asm( "bkpt #0" ); // ERROR } #endif #if 1 && NFMCLASS_TEST_RAWKEYCODE { uint32_t rawCode = NFMClass->methods.keyStatesMethods.getRawKeyControlCode(); asm( "bkpt #0" ); (void)rawCode; } #endif #if 1 && NFMCLASS_TEST_KEYSTATESHORTCUTS { eNFMKeyState_t prevState = NFMClass->methods.keyStatesMethods.getKeyStateCommon(); int32_t eKeyState_SALL_shortcut=-1, eKeyState_OALL_shortcut=-1, eKeyState_LALL_shortcut=-1; if( !NFMClass->methods.keyStatesMethods.shortcuts.findShortCutForState( eKeyState_SALL, &eKeyState_SALL_shortcut ) ) asm( "bkpt #0" ); // ERROR if( !NFMClass->methods.keyStatesMethods.shortcuts.findShortCutForState( eKeyState_OALL, &eKeyState_OALL_shortcut ) ) asm( "bkpt #0" ); // ERROR if( !NFMClass->methods.keyStatesMethods.shortcuts.findShortCutForState( eKeyState_LALL, &eKeyState_LALL_shortcut ) ) asm( "bkpt #0" ); // ERROR if( !NFMClass->methods.keyStatesMethods.shortcuts.setKeyStateByShortcut( eKeyState_SALL_shortcut ) ) asm( "bkpt #0" ); // ERROR else if( eKeyState_SALL != NFMClass->methods.keyStatesMethods.getKeyStateCommon() ) asm( "bkpt #0" ); // ERROR if( !NFMClass->methods.keyStatesMethods.shortcuts.setKeyStateByShortcut( eKeyState_OALL_shortcut ) ) asm( "bkpt #0" ); // ERROR else if( eKeyState_OALL != NFMClass->methods.keyStatesMethods.getKeyStateCommon() ) asm( "bkpt #0" ); // ERROR if( !NFMClass->methods.keyStatesMethods.shortcuts.setKeyStateByShortcut( eKeyState_LALL_shortcut ) ) asm( "bkpt #0" ); // ERROR else if( eKeyState_LALL != NFMClass->methods.keyStatesMethods.getKeyStateCommon() ) asm( "bkpt #0" ); // ERROR if( !NFMClass->methods.keyStatesMethods.setKeyStateCommon( prevState ) ) asm( "bkpt #0" ); // ERROR } #endif asm( "bkpt #0" ); #if 1 && NFMCLASS_TEST_CHRZ_ADAPTERSTR { size_t n; char adapterStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getAdapterDesc( eChFactory, ePortId_A, adapterStrBuffer, sizeof(adapterStrBuffer), &n ); asm( "bkpt #0" ); (void)adapterStrBuffer; } { size_t n; char adapterStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getAdapterDesc( eChFactory, ePortId_B, adapterStrBuffer, sizeof(adapterStrBuffer), &n ); asm( "bkpt #0" ); (void)adapterStrBuffer; } #endif #if 1 && NFMCLASS_TEST_CHRZ_ANALYZERSTR { size_t n; char analyzerStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getAnalyzer( eChFactory, analyzerStrBuffer, sizeof(analyzerStrBuffer), &n ); asm( "bkpt #0" ); (void)analyzerStrBuffer; } #endif #if 1 && NFMCLASS_TEST_CHRZ_TEMP { double chrzTemp = 0.0; NFMClass->methods.xCharacterization.getChrzTemp( eChFactory, &chrzTemp ); asm( "bkpt #0" ); } #endif #if 1 && NFMCLASS_TEST_CHRZ_CONNECTORSTR { size_t n; char connectorStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getConnectorType( ePortId_A, connectorStrBuffer, sizeof(connectorStrBuffer), &n ); asm( "bkpt #0" ); (void)connectorStrBuffer; } { size_t n; char connectorStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getConnectorType( ePortId_B, connectorStrBuffer, sizeof(connectorStrBuffer), &n ); asm( "bkpt #0" ); (void)connectorStrBuffer; } #endif #if 1 && NFMCLASS_TEST_CHRZ_DATESTR { size_t n; char dateStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getDate( eChFactory, dateStrBuffer, sizeof(dateStrBuffer), &n ); asm( "bkpt #0" ); (void)dateStrBuffer; } #endif #if 1 && SWCLASS_TEST_TABLE_HEADER { //SW_ROM_ChangeTableHeader(5); } #endif #if 1 && NFMCLASS_TEST_CHRZ_TIMESTR { size_t n; char timeStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getTime( eChFactory, timeStrBuffer, sizeof(timeStrBuffer), &n ); asm( "bkpt #0" ); (void)timeStrBuffer; } #endif #if 1 && NFMCLASS_TEST_CHRZ_OPERATORSTR { size_t n; char operatorStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getOperator( eChFactory, operatorStrBuffer, sizeof(operatorStrBuffer), &n ); asm( "bkpt #0" ); (void)operatorStrBuffer; } #endif #if 1 && NFMCLASS_TEST_CHRZ_PLACESTR { size_t n; char placeStrBuffer[ 20 ] = {0}; NFMClass->methods.xCharacterization.getPlace( eChFactory, placeStrBuffer, sizeof(placeStrBuffer), &n ); asm( "bkpt #0" ); (void)placeStrBuffer; } #endif #if 1 && NFMCLASS_TEST_CHRZ_POINTSCOUNT { size_t nPoints = NFMClass->methods.xCharacterization.getPointsCount( eChFactory ); asm( "bkpt #0" ); (void)nPoints; } #endif #if 1 && NFMCLASS_TEST_CHRZ_SEGMENTS { size_t nSegments = NFMClass->methods.xCharacterization.getScaleSegment( eChFactory, NULL, 0 ); asm( "bkpt #0" ); (void)nSegments; asm( "bkpt #0" ); for( size_t i = 0; i < nSegments; ++i ) { sEcalSegment_t segm; if( 0 == NFMClass->methods.xCharacterization.getScaleSegment( eChFactory, &segm, i ) ) asm( "bkpt #0" ); // ERROR else asm( "bkpt #0" ); // OK (void)segm; } asm( "bkpt #0" ); } #endif #if 1 && NFMCLASS_TEST_CHRZ_STARTFREQ { double startFreq = 0.0; if( NFMClass->methods.xCharacterization.getStartFreq( eChFactory, &startFreq ) ) asm( "bkpt #0" ); // OK else asm( "bkpt #0" ); // ERROR (void)startFreq; } #endif #if 1 && NFMCLASS_TEST_CHRZ_STOPFREQ { double stopFreq = 0.0; if( NFMClass->methods.xCharacterization.getStopFreq( eChFactory, &stopFreq ) ) asm( "bkpt #0" ); // OK else asm( "bkpt #0" ); // ERROR (void)stopFreq; } #endif asm( "bkpt #0" ); #if 1 && NFMCLASS_TEST_MEM_PROTECTION { bool oldstate = NFMClass->methods.xMemoryProtection.check(); asm( "bkpt #0" ); NFMClass->methods.xMemoryProtection.disable(); asm( "bkpt #0" ); bool state = NFMClass->methods.xMemoryProtection.check(); asm( "bkpt #0" ); NFMClass->methods.xMemoryProtection.enable(); asm( "bkpt #0" ); state = NFMClass->methods.xMemoryProtection.check(); asm( "bkpt #0" ); if( oldstate ) NFMClass->methods.xMemoryProtection.enable(); else NFMClass->methods.xMemoryProtection.disable(); } #endif #if 1 && NFMCLASS_TEST_THERMO_STARTFREQ { double startFreq = 0.0; if( NFMClass->methods.xThermo.getStartFreq( &startFreq ) ) asm( "bkpt #0" ); // OK else asm( "bkpt #0" ); // ERROR (void)startFreq; } #endif #if 1 && NFMCLASS_TEST_THERMO_STOPFREQ { double stopFreq = 0.0; if( NFMClass->methods.xThermo.getStopFreq( &stopFreq ) ) asm( "bkpt #0" ); // OK else asm( "bkpt #0" ); // ERROR (void)stopFreq; } #endif #if 1 && NFMCLASS_TEST_THERMO_POINTSCOUNT { size_t nPoints = NFMClass->methods.xThermo.getPointsCount( eChFactory ); asm( "bkpt #0" ); (void)nPoints; } #endif #endif } //------------------------------------------------------------------------------------------------------------ //-- Public methods ------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------ // Enable Memory Protection for BANK0 static bool NFMSetMemoryProtect() { return NFMClassExtended->private.methods.memory.setProtect( true ); } // Disable Memory Protection for BANK0 static bool NFMSetMemoryUnProtect() { return NFMClassExtended->private.methods.memory.setProtect( false ); } // Check the Memory Protection Status for BANK0 static bool NFMGetMemoryProtect() { return NFMClassExtended->private.methods.memory.getProtect(); } #if 0 // Set common key-switch state static bool NFMSetKeyStateCommon( eNFMKeyState_t state ) { if( NFMClassExtended->public.methods.checkStateAvailable( state ) ) { if( NULL != NFMClassExtended->private.properties.statesEncoding ) { for( size_t i = 0; i < NFMClassExtended->public.properties.allowedStatesCount; ++i ) { if( state == NFMClassExtended->private.properties.statesEncoding[i].commonKeyState ) { NFMClassExtended->private.methods.switchControl( &NFMClassExtended->private.properties.statesEncoding[i] ); NFMClassExtended->private.properties.keyState = state; return true; } } } } return false; } #endif // Get device serial number in string format static size_t NFMGetDeviceSerial( char * buffer, size_t size ) { const sEcalHeader_t * Header = NFMClassExtended->private.methods.memory.getCommonHeader( NULL, 0 ); if( NULL != Header ) { size_t n = static_StrCpyLimit( (const char*)Header->SN, sizeof(Header->SN), buffer, size ); if( n + 1 <= size ) { buffer[n] = '\0'; return (n + 1); } } return 0; } // Set device serial number in string format static size_t NFMSetDeviceSerial( char * buffer, size_t size ) { const sEcalHeader_t * Header = NFMClassExtended->private.methods.memory.getCommonHeader( NULL, 0 ); if( NULL != Header ) { size_t n = static_StrCpyLimit( (const char*)Header->SN, sizeof(Header->SN), buffer, size ); if( n + 1 <= size ) { buffer[n] = '\0'; return (n + 1); } } return 0; } // Get device manufacturer ID in string format // See more: NFMClass->properties.manufacturerId static size_t NFMGetDeviceManufacturer( char * buffer, size_t size ) { size_t retval = 0; if( NULL != buffer && size > 1 ) { const char * manufacturer_id = NFMClassExtended->public.properties.manufacturerId; while( (size > 1) && (*manufacturer_id != '\0') ) { *buffer = *manufacturer_id; manufacturer_id++; buffer++; retval++; size--; } *buffer = '\0'; } return retval; } // Get device model name in string format static size_t NFMGetModelName( char * buffer, size_t size ) { if( NULL == buffer || 0 == size ) return 0; size_t l = strlen( NFMClassExtended->public.properties.modelName ); if( l <= size ) { memcpy( buffer, NFMClassExtended->public.properties.modelName, l ); } else { l = 0; } return l; } static bool NFMCheckPortStateAvailable( ePortStateId_t portState ) { extern NFMClassEx_t * NFMClassExtended; // if( ePortStateId_MAX <= portState // || ePortStateId_UNDEFINED == portState // ) // { // return (false); // } // // if( // NULL == NFMClassExtended->private.properties.memProfile // || NULL == NFMClassExtended->private.properties.memProfile->tbls_raw ) // { // return (false); // } // // const sNFMMemory_ChrzTableMatrix_XPort_t * tableProfile_XPort = NFMClassExtended->private.properties.memProfile->tbls_raw; // // switch(tableProfile_XPort->Header.ChrzTableType.eType) // { // case eNfmChrzTable2Port: // { // if( ePortStateId_MIN_SINGLE_2Port <= portState // && ePortStateId_MAX_SINGLE_2Port >= portState ) // { // return true; // } // if( ePortStateId_MIN_THRU_2Port <= portState // && ePortStateId_MAX_THRU_2Port >= portState ) // { // return true; // } // if( ePortStateId_MIN_CHECK_2Port <= portState // && ePortStateId_MAX_CHECK_2Port >= portState ) // { // return true; // } // } // break; // case eNfmChrzTable4Port: // { // if( ePortStateId_MIN_SINGLE_4Port <= portState // && ePortStateId_MAX_SINGLE_4Port >= portState ) // { // return true; // } // if( ePortStateId_MIN_THRU_4Port <= portState // && ePortStateId_MAX_THRU_4Port >= portState ) // { // return true; // } // if( ePortStateId_MIN_CHECK_4Port <= portState // && ePortStateId_MAX_CHECK_4Port >= portState ) // { // return true; // } // } // break; // } return (false); // unsupported characterization table type } static bool NFMCheckPortCombinationAvailable( ePortComb_t portCombination ) { extern NFMClassEx_t * NFMClassExtended; if( ePortComb_MAX <= portCombination || ePortComb_UNDEFINED == portCombination ) { return (false); } // if( // NULL == NFMClassExtended->private.properties.memProfile // || NULL == NFMClassExtended->private.properties.memProfile->tbls_raw ) // { // return (false); // } // // const sNFMMemory_ChrzTableMatrix_XPort_t * tableProfile_XPort = NFMClassExtended->private.properties.memProfile->tbls_raw; // // if( ePortComb_MIN_SINGLE_XPort <= portCombination // && ePortComb_MAX_SINGLE_XPort >= portCombination ) // { // switch(tableProfile_XPort->Header.ChrzTableType.eType) // { // case eNfmChrzTable2Port: // { // if( ePortComb_MIN_SINGLE_2Port <= portCombination // && ePortComb_MAX_SINGLE_2Port >= portCombination ) // { // return true; // } // } // break; // case eNfmChrzTable4Port: // { // if( ePortComb_MIN_SINGLE_4Port <= portCombination // && ePortComb_MAX_SINGLE_4Port >= portCombination ) // { // return true; // } // } // break; // } // // return 0; // unsupported characterization table type // } // else // if( ePortComb_MIN_THRU_XPort <= portCombination // && ePortComb_MAX_THRU_XPort >= portCombination ) // { // switch(tableProfile_XPort->Header.ChrzTableType.eType) // { // case eNfmChrzTable2Port: // { // if( ePortComb_MIN_THRU_2Port <= portCombination // && ePortComb_MAX_THRU_2Port >= portCombination ) // { // return true; // } // } // break; // case eNfmChrzTable4Port: // { // if( ePortComb_MIN_THRU_4Port <= portCombination // && ePortComb_MAX_THRU_4Port >= portCombination ) // { // return true; // } // } // break; // } // // return 0; // unsupported characterization table type // } // else // if( ePortComb_CHECK == portCombination ) // { // return true; // always available // } return (false); } #if 0 static bool NFMCheckPortParamsAvailable( ePortComb_t portComb, ePortStateId_t portState ) { return ( NFM_CHRZ_TABLEIDX_INVALID != NFMClassExtended->private.methods.memory .getChrzTableIndex( portComb, portState ) ); } #endif //------------------------------------------------------------------------------------------------------------ //-- Private methods ----------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------ // private_ClassInit: // NFMClass object constructor static void private_ClassInit() { // ------------------------------------------------------------------------- // Load device model profile by DeviceID from Common Header uint16_t deviceId; NFMClassExtended->private.properties.deviceId = eModel_undefined; NFMClassExtended->private.properties.modelProfile = NULL; NFMClassExtended->private.properties.memProfile = NULL; NFMClassExtended->public.properties.modelName = g_modelName; NFMClassExtended->public.properties.firmwareId = g_firmwareId; // prepare firmware ID string memset( (char*)g_firmwareId, 0, sizeof(g_firmwareId) ); uint16_t firmware_version = pProgramVersion->firmware_version; _snprintf(g_firmwareId, sizeof(g_firmwareId) - 1, "%d%c%d%c%02d", ((firmware_version & 0xF000)>>12), '.', ((firmware_version & 0x0F00)>>8), '/', ((firmware_version & 0xFF)) ); // // check model version // if(!NFMClassExtended->private.methods.getModelId(&deviceId)) // FOR DEBUGGING (ïèøåì äåâàéñ ID âî ôëåø) // { // bool xPro = NFMClassExtended->public.methods.xMemoryProtection.check(); // // if( xPro ) // { // NFMClassExtended->public.methods.xMemoryProtection.disable(); // } // // NFM_ROM_ChangeModel( eModel_NFM ); // // // if( xPro ) // { // NFMClassExtended->public.methods.xMemoryProtection.enable(); // } // } //const char serial[10] = {'0', '0', '0', '1', '5', '9', '1', '6', '5', '7'}; //NFM_ROM_ChangeSerialNumber(serial); //NFM_ROM_ChangeModel(eModel_SWB); if( NFMClassExtended->private.methods.getModelId( &deviceId ) ) { const sNFMModel_t * modelProfile = static_GetModelProfileByDeviceId( deviceId ); if( NULL != modelProfile ) { NFMClassExtended->public.properties.deviceId = (uint16_t)deviceId; NFMClassExtended->public.properties.modelName = modelProfile->modelName; NFMClassExtended->private.properties.deviceId = deviceId; NFMClassExtended->private.properties.modelProfile = modelProfile; NFMClassExtended->private.properties.memProfile = modelProfile->memProfile; if( NULL != modelProfile->nfProfile ) { // NOTE: do not initialize if wrong number has been set // --------------------------------------------------- NFMClassExtended->public.properties.allowedInputPorts = modelProfile->nfProfile->controlProfile.allowedInputPorts; NFMClassExtended->public.properties.allowedOutputPorts = modelProfile->nfProfile->controlProfile.allowedOutputPorts; NFMClassExtended->public.properties.defaultInputState = modelProfile->nfProfile->controlProfile.defaultInputState; NFMClassExtended->public.properties.inputPortStates = modelProfile->nfProfile->controlProfile.inputPortStates; } } NFMClassExtended->public.methods.getDeviceSerial( g_serialNumber, sizeof(g_serialNumber) ); NFMClassExtended->public.properties.serialNumber = g_serialNumber; if( ! NFMClassExtended->private.methods.memory.validateSettings()) { // set default parameters unsigned char interface[8] = {'U', 'S', 'B', 'T', 'M', 'C', '!', 0}; sNFMSettingsBlockCrc_t sSettingsBlock; for(int i = 0; i < sizeof(interface); i++) { sSettingsBlock.settings.rawBytes[i] = interface[i]; } sSettingsBlock.settings.settingsVersion = 1; sSettingsBlock.settings.tempCoeff = 3988; // Not used TCRC crc = ICRC32; crc = CRC32( crc, (uint8_t *)&sSettingsBlock.settings, sizeof(sSettingsBlock.settings)); sSettingsBlock.CRCValue = crc; NFMClassExtended->private.methods.memory.setSettingsBlock( (uint8_t*)&sSettingsBlock, 0, sizeof(sSettingsBlock) ); } } /* else { asm("bkpt #0"); bool xPro = NFMClassExtended->public.methods.xMemoryProtection.check(); if( xPro ) { NFMClassExtended->public.methods.xMemoryProtection.disable(); } NFM_ROM_ChangeModel( eModel_SC4520_v1 ); if( xPro ) { NFMClassExtended->public.methods.xMemoryProtection.enable(); } asm("bkpt #0"); } */ } // Checks the characterization table parameters for compatibility bool private_CheckTableParams( ePortComb_t portComb, ePortStateId_t portState ) { // Validate the combination of @portComb, @portState and // validate the @portComb and @portState itself. // Retrieve the table index (ordered index) size_t tableIdx = NFMClassExtended->private.methods.memory.getChrzTableIndex( portComb, portState ); if( NFM_CHRZ_TABLEIDX_INVALID == tableIdx ) { // Invalid combination or value return false; } return true; } /* // private_getModelName // Get device model name by DeviceID static const char * private_getModelName() { uint16_t deviceId = eModel_undefined; if( ! NFMClassExtended->private.methods.getModelId( &deviceId ) ) { deviceId = eModel_undefined; } return NFMClassExtended->private.methods.getModelNameById( deviceId ); } */ /* // private_getModelNameById // Get device model name by DeviceID static const char * private_getModelNameById( uint16_t deviceId ) { const sNFMModel_t * modelProfile = static_GetModelProfileByDeviceId( deviceId ); if( NULL == modelProfile ) return NULL; return modelProfile->modelName; } */ // private_getModelId // Get device model ID (DeviceID) static bool private_getModelId( uint16_t * pDeviceId ) { const sEcalHeader_t * Header = NFMClassExtended->private.methods.memory.getCommonHeader( NULL, 0 ); if( NULL != Header ) { if( NULL != pDeviceId ) { *pDeviceId = Header->DeviceID; return true; } } return false; } //------------------------------------------------------------------------------------------------------------ //-- Static methods ----------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------ static bool static_KeyStateNameCompare( const char * name1, const char * name2, size_t size ) { if( NULL == name1 || NULL == name2 || 0 == size ) return false; for( size_t i = 0; i < size; ++i ) { if( tolower(name1[i]) != tolower(name2[i]) ) { return false; } } return true; } static size_t static_StrCpyLimit( const char * source, size_t srcMaxLen, char * dest, size_t destMaxLen ) { size_t srcLen = srcMaxLen; for( size_t i = 0; (0 == srcMaxLen) || (i < srcMaxLen); ++i ) { if( source[i] == '\0' ) { srcLen = i; break; } } size_t rc = 0; for( size_t i = 0; true; ++i ) { if( (i >= destMaxLen) || (i >= srcLen) ) { rc = (i); break; } dest[i] = source[i]; } return (rc); } // Searches the model profile by device ID static const sNFMModel_t * static_GetModelProfileByDeviceId( uint16_t deviceId ) { for( size_t i = 0; i < aNFMModels_count; ++i ) { if( aNFMModels[i].deviceId == deviceId ) { return &aNFMModels[i]; } } for( size_t i = 0; i < aNFMModels_count; ++i ) { if( eModel_undefined == aNFMModels[i].deviceId ) { return &aNFMModels[i]; } } return NULL; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ #if 0 // MEM:TABL:DATA? // Reads the data points of the characterization table size_t NFMGetPoints( eChrz_t sectorId, ePortComb_t portComb, ePortStateId_t portState, sNFMGetPoints_t * pCtl ) { if( portComb >= ePortComb_MAX || portComb == ePortComb_UNDEFINED || portState >= ePortStateId_MAX || portState == ePortStateId_UNDEFINED || NULL == pCtl || NULL == pCtl->in.pDataArray ) { if( NULL != pCtl ) pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; return 0; } /* --- do it later: inside @getChrzTableHeader() call // Validate the combination of @portComb, @portState and // validate the @portComb and @portState itself. // Retrieve the table index (ordered index) size_t tableIdx = NFMClassExtended->private.methods.memory.getChrzTableIndex( portComb, portState ); if( NFM_CHRZ_TABLEIDX_INVALID == tableIdx ) { // Invalid combination or value return 0; } */ // Check the input parameter: @pCtl->in.nCount // For zero value: required to load the table header // During the loading the table header it is required: // - load the main characterization header, check CRC // - retrieve number of points (@nPoints) from the header for specified @sectorId // - load the table header and check it's CRC // - retrieve the table address @TableAddress (for next operations) // - retrieve the @min and @max fields from the table header // - store @min, @max, @TableAddress, @nPoints into @pCtl.out // - return (1) in case of success, or (0) on error if( 0 == pCtl->in.nCount ) { // load characterization main header // and check the CRC const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory .getDataHeader( sectorId, NULL, 0 ); // check the main header: number of points if( NULL == pChrzHeader || 0 == pChrzHeader->Points ) { pCtl->svc.errCode = ERR_NFMGETPOINTS_INVHDR; return (0); } // move @.Points into @nPoints // due to @pChrzHeader will be corrupted size_t nPoints = pChrzHeader->Points; sEcalChrzTableHeader_t tableMicroHeader; // load the table base address // Note: the data by @pChrzHeader is not valid after this call, // due to the function uses the same internal buffer! size_t tableAddress = NFMClassExtended->private.methods.memory .getChrzTableHeader( // load the table base address sectorId, // for specified memory sector portComb, // for specified port combination portState, // for specified port state nPoints, // for retrieved number of points &tableMicroHeader, // and store the header into @tableMicroHeader &pCtl->svc.errCode // And fill the error code ); // check the result: @tableAddress // 0 - table corrupted or invalid port combination or port state. // but since the @portComb and @portState are validated above... // this result means only that the table is corrupted // non zero - this is the absolute address of the requested table. if( 0 == tableAddress ) { (void)pCtl->svc.errCode; return 0; // error, sorry } // - store @min, @max, @TableAddress, @nPoints into @pCtl.out pCtl->out.max = tableMicroHeader.MaxMagn; pCtl->out.min = tableMicroHeader.MinMagn; pCtl->out.TableAddress = tableAddress; pCtl->out.nPoints = nPoints; pCtl->svc.errCode = ERR_NFMGETPOINTS_NOERR; // success return 1; } // ----------------- // User must call this function with (pCtl->in.nCount=0) first time // to initialize the @pCtl->out contents. // Here: 0 != pCtl->in.nCount // ----------------- // Check the header data, loaded at previous step ( see pCtl->in.nCount == 0 ) if( 0 == pCtl->out.nPoints // check the number of points in the table || 0 == pCtl->out.TableAddress ) // check the table base address { // error, invalid parameters // Call the function with (pCtl->in.nCount = 0) to load the header pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; return 0; } // Check the input parameters if( pCtl->in.nCount > pCtl->out.nPoints // check the amount of requested points || pCtl->in.nStartPoint >= pCtl->out.nPoints // check the starting point || NULL == pCtl->in.pDataArray ) // check receiving data buffer { // error: invalid input parameters pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; return 0; } return NFMClassExtended->private.methods.memory.getChrzPoints( pCtl ); } #endif // MEM:TABL:DATA? // Prepares the context before reading the data points of the characterization table // This method is designed to replace the obsolete @NFMGetPoints. // 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 NFMGetPoints_Begin( eChrz_t sectorId, ePortComb_t portComb, ePortStateId_t portState, sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer, xNFMGetPointsSimplified_t * xCtl ) { sNFMGetPointsSimplified_t * pCtl = (sNFMGetPointsSimplified_t*)xCtl; // Check if arguments are valid in general if( ( sectorId >= eCh_MAX ) || ( portComb >= ePortComb_MAX ) || ( portState >= ePortStateId_MAX ) || ( portComb == ePortComb_UNDEFINED ) || ( NULL == xCtl ) || ( 0 == szDataBuffer ) ) { if( NULL != pCtl ) pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVAL; return 0; } // Check if arguments are valid particularly for this device if( ! NFMClassExtended->public.methods.checkTableParams( portComb, portState ) ) { // Invalid combination or value pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVAL; return 0; } // Try to validate configuration (table ID) size_t tableIdx = NFMClassExtended->private.methods.memory.getChrzTableIndex( portComb, portState ); if( NFM_CHRZ_TABLEIDX_INVALID == tableIdx ) { // Invalid combination or value pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVAL; return 0; } // Fill input parameters: pCtl->BufferCapacity = szDataBuffer; // - output buffer capacity pCtl->sectorId = sectorId; // - requested bank pCtl->portComb = portComb; // - requested port combination (nfm path) pCtl->portState = portState; // - requested state (S-parameter) pCtl->intCtx.in.nCount = szDataBuffer; // - number of points to get pCtl->intCtx.in.nStartPoint = 0; // - start point pCtl->intCtx.in.pDataArray = pDataBuffer; // - output buffer // During the loading the table header it is required: // - load the main characterization header, check CRC // - retrieve number of points (@nPoints) from the header for specified @sectorId // - load the table header and check it's CRC // - retrieve the table address @TableAddress (for next operations) // - retrieve the @min and @max fields from the table header // - store @min, @max, @TableAddress, @nPoints into @pCtl.intCtx.out // load characterization main header // and check the CRC const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory .getDataHeader( sectorId, NULL, 0 ); // check the main header: number of points if( NULL == pChrzHeader || 0 == pChrzHeader->Points ) { pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVHDR; return (0); } // move @.Points into @nPoints // due to @pChrzHeader will be corrupted size_t nPoints = pChrzHeader->Points; sEcalChrzTableHeader_t tableMicroHeader; // load the table base address // Note: the data by @pChrzHeader is not valid after this call, // due to the function uses the same internal buffer! size_t tableAddress = NFMClassExtended->private.methods.memory .getChrzTableHeader( // load the table base address sectorId, // for specified memory sector portComb, // for specified port combination portState, // for specified port state nPoints, // for retrieved number of points &tableMicroHeader, // and store the header into @tableMicroHeader &pCtl->intCtx.svc.errCode // And fill the error code ); // check the result: @tableAddress // 0 - table corrupted or invalid port combination or port state. // but since the @portComb and @portState are validated above... // this result means only that the table is corrupted // non zero - this is the absolute address of the requested table. if( 0 == tableAddress ) { (void)pCtl->intCtx.svc.errCode; return 0; // error, sorry } // - store @min, @max, @TableAddress, @nPoints into @pCtl.out pCtl->intCtx.out.max = tableMicroHeader.MaxMagn; pCtl->intCtx.out.min = tableMicroHeader.MinMagn; pCtl->intCtx.out.TableAddress = tableAddress; pCtl->intCtx.out.nPoints = nPoints; pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_NOERR; // success return nPoints; } // MEM:TABL:DATA? // @NFMGetPoints_Continue // Uses already prepared context and reads the data points of the characterization // table to the top of specified buffer (see @NFMGetPoints_Begin). // 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 NFMGetPoints_Continue( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve ) { sNFMGetPointsSimplified_t * pCtl = (sNFMGetPointsSimplified_t*)xCtl; if( NULL == pCtl || NULL == pnPointsRetrieve ) { return eNFMGetPointError_InvalidValue; } // Check if arguments are valid in general if( ( pCtl->sectorId >= eCh_MAX ) || ( pCtl->portComb >= ePortComb_MAX ) || ( pCtl->portState >= ePortStateId_MAX ) || ( pCtl->portComb == ePortComb_UNDEFINED ) || ( 0 == pCtl->BufferCapacity ) || ( 0 == pCtl->intCtx.out.nPoints ) || ( 0 == pCtl->intCtx.out.TableAddress ) || ( NULL == pCtl->intCtx.in.pDataArray ) ) { pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVAL; return eNFMGetPointError_InvalidValue; } // check ranges if( pCtl->intCtx.in.nCount > pCtl->intCtx.out.nPoints ) pCtl->intCtx.in.nCount = pCtl->intCtx.out.nPoints; if( pCtl->intCtx.in.nStartPoint >= pCtl->intCtx.out.nPoints ) pCtl->intCtx.in.nStartPoint = pCtl->intCtx.out.nPoints; // end-of-points if( pCtl->intCtx.in.nStartPoint + pCtl->intCtx.in.nCount > pCtl->intCtx.out.nPoints ) { pCtl->intCtx.in.nCount = pCtl->intCtx.out.nPoints - pCtl->intCtx.in.nStartPoint; } // check for end condition if( 0 == pCtl->intCtx.in.nCount || pCtl->intCtx.in.nStartPoint == pCtl->intCtx.out.nPoints ) { *pnPointsRetrieve = 0; // number of points read is zero pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_NOERR; return eNFMGetPointError_Success; } int32_t success_rc = eNFMGetPointError_Success; // check buffer capacity range if( pCtl->intCtx.in.nCount > pCtl->BufferCapacity ) { pCtl->intCtx.in.nCount = pCtl->BufferCapacity; success_rc = eNFMGetPointError_OutOfBuffer; // out of buffer, the number of points is limited } else if( pCtl->intCtx.in.nStartPoint + pCtl->intCtx.in.nCount < pCtl->intCtx.out.nPoints ) { success_rc = eNFMGetPointError_Limit; // number of points is limited by user } pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_IO; size_t nRead = NFMClassExtended->private.methods.memory.getChrzPoints( &pCtl->intCtx ); // check for error condition if( nRead == 0 ) { *pnPointsRetrieve = 0; // number of points read is zero (void)pCtl->intCtx.svc.errCode; return eNFMGetPointError_DataError; } pCtl->intCtx.in.nStartPoint += nRead; // increment start point for next call // check range if( pCtl->intCtx.in.nStartPoint + pCtl->intCtx.in.nCount > pCtl->intCtx.out.nPoints ) { pCtl->intCtx.in.nCount = pCtl->intCtx.out.nPoints - pCtl->intCtx.in.nStartPoint; } *pnPointsRetrieve = nRead; // number of points read return success_rc; } // Reads amount of points in the characterization table size_t NFMGetPointsCount( eChrz_t tableId ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader ) return (0); return (size_t)pChrzHeader->Points; } // MEM:TABL:POIN? // Reads amount of points in the characterization table bool NFMGetPointsCount_Safe( eChrz_t tableId, int16_t * count ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == count ) return false; *count = pChrzHeader->Points; return true; } // MEM:TABL:DATE? // Reads the date of characterization table bool NFMGetDate( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == buffer || 0 == size || NULL == bytes ) return (false); size_t nCpy = static_StrCpyLimit( (const char*)pChrzHeader->CalDate, sizeof(pChrzHeader->CalDate), buffer, size ); *bytes = nCpy; return true; } // MEM:TABL:TIME? // Reads the time of characterization table bool NFMGetTime( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == buffer || 0 == size || NULL == bytes ) return (false); size_t nCpy = static_StrCpyLimit( (const char*)pChrzHeader->CalTime, sizeof(pChrzHeader->CalTime), buffer, size ); *bytes = nCpy; return true; } // MEM:TABL:FREQ:TYPE? // Reads the type of the frequency scale of data characterization table bool NFMGetScaleType( eChrz_t tableId, eChrzScaleType_t * pType ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader ) return (false); if( NULL != pType ) { if( SWEEP_VERSION_LINEAR == pChrzHeader->Version ) { *pType = eChScaleLinear; return true; } else if( SWEEP_VERSION_SEGMENT == pChrzHeader->Version ) { *pType = eChScaleSegment; return true; } } return false; } // 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 NFMGetScaleSegment( eChrz_t tableId, sEcalSegment_t * pSegment, size_t nSegmentId ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader ) return (0); // in case @pSegment is NULL, return amount of segments if( NULL == pSegment ) { if( 1 == pChrzHeader->Version ) // Linear Sweep { return 1; // One segment } return pChrzHeader->NSegm; } if( ( (nSegmentId >= pChrzHeader->NSegm) && (pChrzHeader->Version == 2) ) || ( (nSegmentId != 0) && (pChrzHeader->Version == 1) ) || ( pChrzHeader->Version != 1 && pChrzHeader->Version != 2) ) { // error: check the @nSegmentId, it must be less than amount of segments return 0; } else { if( 1 == pChrzHeader->Version ) // Linear Sweep pSegment->Points = pChrzHeader->Points; else pSegment->Points = pChrzHeader->Segm[ nSegmentId ].Points; double Fstart = 0.0; double Fstop = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fstart, // & pChrzHeader->Segm[ nSegmentId ].Fstart_unaligned, // sizeof(Fstart) // ); if( 1 == pChrzHeader->Version ) // Linear Sweep Fstart = pChrzHeader->Fmin_unaligned; else Fstart = pChrzHeader->Segm[ nSegmentId ].Fstart_unaligned; // aligned access to the unaligned 'double' field // memcpy( & Fstop, // & pChrzHeader->Segm[ nSegmentId ].Fstop_unaligned, // sizeof(Fstop) // ); if( 1 == pChrzHeader->Version ) // Linear Sweep Fstop = pChrzHeader->Fmax_unaligned; else Fstop = pChrzHeader->Segm[ nSegmentId ].Fstop_unaligned; pSegment->Fstart = Fstart; pSegment->Fstop = Fstop; } return 1; } // @NFMGetScaleFreqs_Begin // Prepares a retrieving context for calling the @NFMGetScaleFreqs_Continue 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 @NFMGetScaleFreqs_Continue. // // 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 NFMGetScaleFreqs_Begin( eChrz_t tableId, double * pFreqArray, size_t BufferCapacity, xNFMGetFreqPoints_t * xCtl ) { sNFMGetFreqPoints_t * pCtl = (sNFMGetFreqPoints_t*)(xCtl); // Checking arguments: if( tableId >= eCh_MAX || NULL == pFreqArray || NULL == xCtl || 0 == BufferCapacity ) { return (eNFMGetPointError_InvalidValue); // error condition } // initialize the fields pCtl->pDataArray = pFreqArray; // specify receiving buffer pCtl->tableId = tableId; // specify table ID; // Get the scale type (LIN | SEGM): if( ! NFMClass->methods.xCharacterization.getScaleType( tableId, &pCtl->scaleType ) ) { return (eNFMGetPointError_DataError); // error condition } // Get segments count for linear or segment scale switch( pCtl->scaleType ) { case eChScaleSegment: { // Get segments count pCtl->nSegments = NFMClass->methods.xCharacterization.getScaleSegment( tableId, NULL, 0 ); // Check segments count if( 0 == pCtl->nSegments ) { return (eNFMGetPointError_DataError); // error condition: invalid segments count (=0) } } break; case eChScaleLinear: { // For linear scale: number of segments is 1 pCtl->nSegments = 1; } break; default: return (eNFMGetPointError_DataError); // error condition: invalid scale type } // Initialize the rest fields pCtl->BufferCapacity = BufferCapacity; // set user buffer capacity pCtl->nStartSegment = 0; // specify starting segment pCtl->nStartPoint = 0; // specify starting point pCtl->Segment.Points = 0; // forward set, will be updated in @NFMGetScaleFreqs_Continue pCtl->Segment.Fstart = 0.0; pCtl->Segment.Fstop = 0.0; return eNFMGetPointError_Success; } // @NFMGetScaleFreqs_Continue // 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 @NFMGetScaleFreqs_Begin // 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 @NFMGetScaleFreqs_Begin // !!! 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 NFMGetScaleFreqs_Continue( xNFMGetFreqPoints_t * xCtl, size_t * pnPointsRetrieve ) { sNFMGetFreqPoints_t * pCtl = (sNFMGetFreqPoints_t*)(xCtl); // Checking arguments: if( NULL == xCtl || NULL == pnPointsRetrieve || 0 == *pnPointsRetrieve ) { return (eNFMGetPointError_InvalidValue); // error condition } // Check input parameters from context: if( 0 == pCtl->nSegments || eChScale_undefined == pCtl->scaleType || eCh_MAX <= pCtl->tableId || NULL == pCtl->pDataArray || 0 == pCtl->BufferCapacity ) { return (eNFMGetPointError_InvalidValue); // error condition } size_t iPointRequested = 0; bool bBreak = false; int32_t rc = eNFMGetPointError_Success; // forward set to success code // For each segment and each point: for( (void)pCtl->nStartSegment; (pCtl->nStartSegment < pCtl->nSegments) && (!bBreak); ++ pCtl->nStartSegment ) { for( (void)pCtl->nStartPoint; ((void)pCtl->Segment.Points, (!bBreak)); ++ pCtl->nStartPoint ) { // Check if the segment is loaded if( 0 == pCtl->Segment.Points ) { // load segment data: switch( pCtl->scaleType ) { case eChScaleSegment: { // Retrieve the segment data if( 1 != NFMClass->methods.xCharacterization.getScaleSegment( pCtl->tableId, &pCtl->Segment, pCtl->nStartSegment ) ) { return (eNFMGetPointError_DataError); // error condition: can not load segment data } } break; case eChScaleLinear: { // For linear scale: retrieve from the common characterization header if( ! NFMClass->methods.xCharacterization.getPointsCountSafe( pCtl->tableId, &pCtl->Segment.Points ) || ! NFMClass->methods.xCharacterization.getStartFreq( pCtl->tableId, &pCtl->Segment.Fstart ) || ! NFMClass->methods.xCharacterization.getStopFreq( pCtl->tableId, &pCtl->Segment.Fstop ) ) { return (eNFMGetPointError_DataError); // error condition: can not load segment data } } break; default: return (eNFMGetPointError_DataError); // error condition: invalid scale type } // Calculate the discrette pCtl->Fdesc = (pCtl->Segment.Fstop - pCtl->Segment.Fstart) / (pCtl->Segment.Points - 1); pCtl->nStartPoint = 0; // Reset start point for current segment } // Segment loaded? if( 0 != pCtl->Segment.Points ) { // yes, check condition: all the points of segment have been processed? if( pCtl->nStartPoint >= pCtl->Segment.Points ) break; } else { // Invalid segment return (eNFMGetPointError_DataError); // error condition: can not load segment data } // Fill the output array from the begining // Note @pDataArray have at least one cell due to input checking pCtl->pDataArray[ iPointRequested++ ] = (pCtl->Segment.Fstart + pCtl->Fdesc * pCtl->nStartPoint); // Check for overflow: user buffer overflow if( iPointRequested >= pCtl->BufferCapacity ) { bBreak = true; rc = eNFMGetPointError_OutOfBuffer; // warning /* break; DO NOT BREAK, need to increment @nStartPoint */ } // Check for end condition: user limit if( iPointRequested >= *pnPointsRetrieve ) { bBreak = true; rc = eNFMGetPointError_Limit; // warning /* break; DO NOT BREAK, need to increment @nStartPoint */; } } // Check for end condition: out of points in segment or out of segments if( pCtl->nStartPoint >= pCtl->Segment.Points ) { if( pCtl->nStartSegment >= pCtl->nSegments - 1 ) /* -1: because @nStartSegment has not been incremented yet */ { pCtl->nStartSegment++; // instead of reaching the top of operator 'for' bBreak = true; (void)rc; // eNFMGetPointError_Success, end-of-data } pCtl->Segment.Points = 0; // Reset points count: make to load the segment data at next iteration pCtl->nStartPoint = 0; // Reset start point for next segment } if( bBreak ) break; // do not increment @nStartSegment } (void)rc; // If no points are available, the @eNFMGetPointError_Success code is returned with *pnPointsRetrieve set to zero *pnPointsRetrieve = iPointRequested; // write number of points read return rc; } // @SWGetTablePoints_Begin // Prepares a retrieving context for calling the @SWGetTablePoints_Continue 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); // @pPointsArray - 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 @SWGetTablePoints_Continue. // // 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 SWGetTablePoints_Begin( eChrz_t tableId, sSWTablePoint_t * pPointsArray, size_t BufferCapacity, xSWGetTablePoints_t * xCtl ) { sSWGetTablePoints_t * pCtl = (sSWGetTablePoints_t*)(xCtl); // Checking arguments: if( tableId >= eCh_MAX || NULL == pPointsArray || NULL == xCtl || 0 == BufferCapacity ) { return (eNFMGetPointError_InvalidValue); // error condition } // initialize the fields pCtl->pDataArray = pPointsArray; // specify receiving buffer pCtl->tableId = tableId; // specify table ID; // Initialize the rest fields pCtl->BufferCapacity = BufferCapacity; // set user buffer capacity pCtl->nStartPoint = 0; // specify starting point //pCtl->nNumberOfPoints = TableHandle.GetNumberOfPoints(); pCtl->nNumberOfPoints = TableHandle.GetNumberOfPoints(); pCtl->TablePoint.port1 = 0; pCtl->TablePoint.port2 = 0; return eNFMGetPointError_Success; } // @NFMGetScaleFreqs_Continue // 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 @NFMGetScaleFreqs_Begin // 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 @NFMGetScaleFreqs_Begin // !!! 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 SWGetTablePoints_Continue( xSWGetTablePoints_t * xCtl, size_t * pnPointsRetrieve ) { sSWGetTablePoints_t * pCtl = (sSWGetTablePoints_t*)(xCtl); // Checking arguments: if( NULL == xCtl || NULL == pnPointsRetrieve || 0 == *pnPointsRetrieve ) { return (eNFMGetPointError_InvalidValue); // error condition } // Check input parameters from context: if( eCh_MAX <= pCtl->tableId || NULL == pCtl->pDataArray || 0 == pCtl->BufferCapacity ) { return (eNFMGetPointError_InvalidValue); // error condition } size_t iPointRequested = 0; bool bBreak = false; int32_t rc = eNFMGetPointError_Success; // forward set to success code // For each point: for( (void)pCtl->nStartPoint; ((void)pCtl->nNumberOfPoints, (!bBreak)); ++ pCtl->nStartPoint ) { // Check if the point is loaded if( 0 != pCtl->nNumberOfPoints ) { // yes, check condition: all the points of segment have been processed? if( pCtl->nStartPoint >= pCtl->nNumberOfPoints ) { // Check for end condition: out of points in segment or out of segments bBreak = true; (void)rc; // eNFMGetPointError_Success, end-of-data pCtl->nNumberOfPoints = 0; // Reset points count: make to load the segment data at next iteration pCtl->nStartPoint = 0; // Reset start point for next segment break; } if( ! TableHandle.Get_Point(pCtl->nStartPoint, &pCtl->TablePoint)) { return (eNFMGetPointError_DataError); // error condition: can not load segment data } } else { // Invalid segment return (eNFMGetPointError_DataError); // error condition: can not load segment data } // Fill the output array from the begining // Note @pDataArray have at least one cell due to input checking pCtl->pDataArray[ iPointRequested ].port1 = pCtl->TablePoint.port1; pCtl->pDataArray[ iPointRequested ].port2 = pCtl->TablePoint.port2; // To next point iPointRequested++; // Check for overflow: user buffer overflow if( iPointRequested >= pCtl->BufferCapacity ) { bBreak = true; rc = eNFMGetPointError_OutOfBuffer; // warning /* break; DO NOT BREAK, need to increment @nStartPoint */ } // Check for end condition: user limit if( iPointRequested >= *pnPointsRetrieve ) { bBreak = true; rc = eNFMGetPointError_Limit; // warning /* break; DO NOT BREAK, need to increment @nStartPoint */; } } (void)rc; // If no points are available, the @eNFMGetPointError_Success code is returned with *pnPointsRetrieve set to zero *pnPointsRetrieve = iPointRequested; // write number of points read return rc; } /* /// -------------------------------------------------------------------------- /// /// \brief createAbscissa /// \details ������� ��� �������� ������������ �������� ��� ��������� ��������� /// \param[in] segment - QVector �� ��������� ��������� (Fmin, Fmax, NPoints) /// \return ��������� �� ������ ������������ �������� � ���������� ������� � ��������� ����� /// �� ���� ��������� ��������� (RndAbscissa) /// \note �������� � lambda ����� �� ���������� Hardware � ������������ ����� NfmKit.h, /// �.�. ��� ��������� ����� ������ ������ ���������� ������. /// \note ������� �����������, �� �������������� �� ������. static auto createAbscissa( const QVector& segments ) { // ���������� ����� �� ���� ���������: size_t nPointsTotal = 0; // ��������� ��� ������� ���������� �������� ���������� ������� ��������������: // (��������� ������ ���������� ����� �� ���� ��������� ���������): for ( auto& segment : segments ) { // ���������� ����� � ��������: size_t nPoints = static_cast(segment.Points); // ������������ ������ ���������� ����� � ��������� nPointsTotal += nPoints; } // �������� ������� ������������ ������� ��� ���� ��������� (����� ���������� �����): Dsp::RndAbscissa* customAbscissa = new Dsp::RndAbscissa( nPointsTotal ); // �������� �������, ��������� ������� ������ ������������� // ����� � ��������: @abscissaPointIndex size_t abscissaPointIndex = 0; // ��������� ��� ������� ���������� �������� ���������� ������� ��������������: // (���������� ������ � ���������� ��������� �����): for ( auto& segment : segments ) { // ���������� ����� � ��������: size_t nPoints = static_cast(segment.Points); // �������� ��������� � ������� ��: // - ��������� ������� ��������: @Fmin auto Fmin = Unit(segment.Fmin).toSI().value(); // - �������� ������� ��������: @Fmax auto Fmax = Unit(segment.Fmax).toSI().value(); // - ��� ����� ������ � ������� ��������: @Fstep auto Fstep = (Fmax - Fmin) / nPoints; // ���������� ��������� ����� �������: for ( size_t p = 0; p < nPoints; ++p ) { customAbscissa->setValue( abscissaPointIndex + p, Fmin + Fstep * p ); } // �������� �������� ������� �� ���������� ����� � ������� ��������, // ������������� � ���������� ��������: abscissaPointIndex += nPoints; } return QSharedPointer(customAbscissa); */ // MEM:TABL:FREQ:STAR? // Reads the start frequency of the characterization table bool NFMGetStartFreq( eChrz_t tableId, double * pStartFreq ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == pStartFreq ) return (false); if( SWEEP_VERSION_LINEAR == pChrzHeader->Version ) { double Fmin = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fmin, // & pChrzHeader->Fmin_unaligned, // sizeof(Fmin) // ); // *pStartFreq = pChrzHeader->Fmin, fixed 28/08/18 Fmin = pChrzHeader->Fmin_unaligned; *pStartFreq = Fmin; return true; } else if( SWEEP_VERSION_SEGMENT == pChrzHeader->Version ) { if( 0 < pChrzHeader->NSegm ) { // double min = pChrzHeader->Segm[0].Fstart; // fixed 28/08/18 double Fstart_min = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fstart_min, // & pChrzHeader->Segm[0].Fstart_unaligned, // sizeof(Fstart_min) // ); // min = pChrzHeader->Segm[0].Fstart Fstart_min = pChrzHeader->Segm[0].Fstart_unaligned; for( size_t n = 0; n < pChrzHeader->NSegm; ++n ) { double Fstart_n = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fstart_n, // & pChrzHeader->Segm[n].Fstart_unaligned, // sizeof(Fstart_n) // ); // min = pChrzHeader->Segm[n].Fstart, fixed 28/08/18 Fstart_n = pChrzHeader->Segm[n].Fstart_unaligned; if( Fstart_n < Fstart_min ) { Fstart_min = Fstart_n; } } *pStartFreq = Fstart_min; return true; } } return false; } // MEM:TABL:FREQ:STOP? // Reads the stop frequency of the characterization table bool NFMGetStopFreq( eChrz_t tableId, double * pStopFreq ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == pStopFreq ) return (false); if( SWEEP_VERSION_LINEAR == pChrzHeader->Version ) { double Fmax = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fmax, // & pChrzHeader->Fmax_unaligned, // sizeof(Fmax) // ); // *pStopFreq = pChrzHeader->Fmax;, fixed 28/08/18 Fmax = pChrzHeader->Fmax_unaligned; *pStopFreq = Fmax; return true; } else if( SWEEP_VERSION_SEGMENT == pChrzHeader->Version ) { if( 0 < pChrzHeader->NSegm ) { double Fstop_max = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fstop_max, // & pChrzHeader->Segm[ pChrzHeader->NSegm - 1 ].Fstop_unaligned, // sizeof(Fstop_max) // ); // double max = pChrzHeader->Segm[ pChrzHeader->NSegm - 1 ].Fstop;, fixed 28/08/18 Fstop_max = pChrzHeader->Segm[ pChrzHeader->NSegm - 1 ].Fstop_unaligned; for( size_t n = 0; n < pChrzHeader->NSegm; ++n ) { double Fstop_n = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fstop_n, // & pChrzHeader->Segm[ pChrzHeader->NSegm - 1 - n ].Fstop_unaligned, // sizeof(Fstop_n) // ); // max = pChrzHeader->Segm[ pChrzHeader->NSegm - 1 - n ].Fstop;, fixed 28/08/18 Fstop_n = pChrzHeader->Segm[ pChrzHeader->NSegm - 1 - n ].Fstop_unaligned; if( Fstop_n > Fstop_max ) { Fstop_max = Fstop_n; } } *pStopFreq = Fstop_max; return true; } } return false; } // MEM:TABL:TEMP? // Reads the characterization temperature of characterization table bool NFMGetChrzTemp( eChrz_t tableId, double * pTemperature ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == pTemperature ) return (false); double temperature = 0.0; // aligned access to the unaligned 'double' field // memcpy( & temperature, // & pChrzHeader->Temperature_unaligned, // sizeof(temperature) // ); // *pTemperature = pChrzHeader->Temperature;, fixed 28/08/18 temperature = pChrzHeader->Temperature_unaligned; *pTemperature = temperature; return true; } // MEM:TABL:CONN? // Reads the connector type of the NFM bool NFMGetConnectorType( ePortId_t portId, char * buffer, size_t size, size_t * bytes ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( eChFactory, NULL, 0 ); if( NULL == pChrzHeader || NULL == buffer || size == 0 || NULL == bytes ) return (false); uint16_t connector; const char * pDescConnector = NULL; size_t nCpy = 0; switch( portId ) { case ePortId_A: connector = pChrzHeader->ConnectorA; break; case ePortId_B: connector = pChrzHeader->ConnectorB; break; case ePortId_C: connector = pChrzHeader->ConnectorC; break; case ePortId_D: connector = pChrzHeader->ConnectorD; break; default: return (false); } if( connector >= sizeof(aConnectorsNames)/sizeof(aConnectorsNames[0]) ) { pDescConnector = pcConnectorUndefined; } else { pDescConnector = aConnectorsNames[ connector ]; } nCpy = static_StrCpyLimit( (const char*)pDescConnector, 0, buffer, size ); *bytes = nCpy; return true; } // MEM:TABL:ADAP? // Reads the adapter description of the NFM connector bool NFMGetAdapterDesc( eChrz_t tableId, ePortId_t portId, char * buffer, size_t size, size_t * bytes ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == buffer || size == 0 || NULL == bytes ) return (false); size_t nCpy = 0; switch( portId ) { case ePortId_A: nCpy = static_StrCpyLimit( (const char*)pChrzHeader->AdapterDescriptionA, sizeof(pChrzHeader->AdapterDescriptionA), buffer, size ); break; case ePortId_B: nCpy = static_StrCpyLimit( (const char*)pChrzHeader->AdapterDescriptionB, sizeof(pChrzHeader->AdapterDescriptionB), buffer, size ); break; case ePortId_C: nCpy = static_StrCpyLimit( (const char*)pChrzHeader->AdapterDescriptionC, sizeof(pChrzHeader->AdapterDescriptionC), buffer, size ); break; case ePortId_D: nCpy = static_StrCpyLimit( (const char*)pChrzHeader->AdapterDescriptionD, sizeof(pChrzHeader->AdapterDescriptionD), buffer, size ); break; default: return (false); } *bytes = nCpy; return true; } // MEM:TABL:ANAL? ( =ANALyzer) // Reads the analyzer type bool NFMGetAnalyzer( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == buffer || size == 0 || NULL == bytes ) return (false); size_t nCpy = static_StrCpyLimit( (const char*)pChrzHeader->Analyzer, sizeof(pChrzHeader->Analyzer), buffer, size ); *bytes = nCpy; return true; } // MEM:TABL:PLAC? // Reads the place where the characterization had been created bool NFMGetPlace( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == buffer || size == 0 || NULL == bytes ) return (false); size_t nCpy = static_StrCpyLimit( (const char*)pChrzHeader->Location, sizeof(pChrzHeader->Location), buffer, size ); *bytes = nCpy; return true; } // MEM:TABL:OPER? // Reads the the characterization operator's name bool NFMGetOperator( eChrz_t tableId, char * buffer, size_t size, size_t * bytes ) { const sEcalDataHeader_t * pChrzHeader = NFMClassExtended->private.methods.memory.getDataHeader( tableId, NULL, 0 ); if( NULL == pChrzHeader || NULL == buffer || size == 0 || NULL == bytes ) return (false); size_t nCpy = static_StrCpyLimit( (const char*)pChrzHeader->Operator, sizeof(pChrzHeader->Operator), buffer, size ); *bytes = nCpy; return true; } // MEM:TABL:THER:CORR:FREQ:START // Reads the the start frequency of thermocompensation data static bool NFMGetStartFreqThermo( double * pStartFreq ) { const sEcalTCompHeader_t * pTCompHeader = NFMClassExtended->private.methods.memory.getTCompHeader( NULL, 0 ); if( NULL == pTCompHeader || NULL == pStartFreq ) return (false); double Fmin = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fmin, // & pTCompHeader->Fmin_unaligned, // sizeof(Fmin) // ); // *pStartFreq = pTCompHeader->Fmin;, fixed 28/08/18 Fmin = pTCompHeader->Fmin_unaligned; *pStartFreq = Fmin; return true; } // MEM:TABL:THER:CORR:FREQ:STOP // Reads the the stop frequency of thermocompensation data static bool NFMGetStopFreqThermo( double * pStopFreq ) { const sEcalTCompHeader_t * pTCompHeader = NFMClassExtended->private.methods.memory.getTCompHeader( NULL, 0 ); if( NULL == pTCompHeader || NULL == pStopFreq ) return (false); double Fmax = 0.0; // aligned access to the unaligned 'double' field // memcpy( & Fmax, // & pTCompHeader->Fmax_unaligned, // sizeof(Fmax) // ); // *pStopFreq = pTCompHeader->Fmax;, fixed 28/08/18 Fmax = pTCompHeader->Fmax_unaligned; *pStopFreq = Fmax; return true; } // Reads the amount of points of thermocompensation data static size_t NFMGetPointsThermo() { const sEcalTCompHeader_t * pTCompHeader = NFMClassExtended->private.methods.memory.getTCompHeader( NULL, 0 ); if( NULL == pTCompHeader ) return (0); return pTCompHeader->Points; } // MEM:TABL:THER:CORR:POIN? // Reads the amount of points of thermocompensation data static bool NFMGetPointsThermo_Safe( int16_t * count ) { const sEcalTCompHeader_t * pTCompHeader = NFMClassExtended->private.methods.memory.getTCompHeader( NULL, 0 ); if( NULL == pTCompHeader || NULL == count ) return false; *count = pTCompHeader->Points; return true; } // // MEM:TABL:THER:CORR:MAGN? // // Reads the magnitude data points of the thermocompensation table // static size_t NFMGetPointsMagnThermo( ePortComb_t portComb, ePortStateId_t portState, sNFMGetPoints_t * pCtl ) // { // if( portComb >= ePortComb_MAX // || portComb == ePortComb_UNDEFINED // || portState >= ePortStateId_MAX // || portState == ePortStateId_UNDEFINED // || NULL == pCtl // || NULL == pCtl->in.pDataArray // ) // { // if( NULL != pCtl ) // pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; // // return 0; // } // // /* --- do it later: inside @getChrzTableHeader() call // // Validate the combination of @portComb, @portState and // // validate the @portComb and @portState itself. // // Retrieve the table index (ordered index) // size_t tableIdx = NFMClassExtended->private.methods.memory.getChrzTableIndex( portComb, portState ); // // if( NFM_CHRZ_TABLEIDX_INVALID == tableIdx ) // { // // Invalid combination or value // return 0; // } // */ // // // Check the input parameter: @pCtl->in.nCount // // For zero value: required to load the table header // // During the loading the table header it is required: // // - load the main thermocompensation header, check CRC // // - retrieve number of points (@nPoints) from the header // // - load the table header and check it's CRC // // - retrieve the table address @TableAddress (for next operations) // // - retrieve the @min and @max fields from the table header // // - store @min, @max, @TableAddress, @nPoints into @pCtl.out // // - return (1) in case of success, or (0) on error // if( 0 == pCtl->in.nCount ) // { // // load thermocompensation main header // // and check the CRC // const sEcalTCompHeader_t * pTCompHeader = NFMClassExtended->private.methods.memory // .getTCompHeader( NULL, 0 ); // // // check the TComp header: number of points // if( NULL == pTCompHeader // || 0 == pTCompHeader->Points ) // { // pCtl->svc.errCode = ERR_NFMGETPOINTS_INVHDR; // return (0); // } // // // move @.Points into @nPoints // // due to @pTCompHeader will be corrupted // size_t nPoints = pTCompHeader->Points; // // sEcalTCompTableMagnHeader_t tableMicroHeader; // // // load the table base address // // Note: the data by @pChrzHeader is not valid after this call, // // due to the function uses the same internal buffer! // size_t tableAddress = NFMClassExtended->private.methods.memory // .getTCompMagnTableHeader( // load the table base address // portComb, // for specified port combination // portState, // for specified port state // nPoints, // for retrieved number of points // &tableMicroHeader, // and store the header into @tableMicroHeader // &pCtl->svc.errCode // And fill up the error code // ); // // // check the result: @tableAddress // // 0 - table corrupted or invalid port combination or port state. // // but since the @portComb and @portState are validated above... // // this result means only that the table is corrupted // // non zero - this is the absolute address of the requested table. // if( 0 == tableAddress ) // { // (void)pCtl->svc.errCode; // return 0; // error, sorry // } // // // - store @min, @max, @TableAddress, @nPoints into @pCtl.out // pCtl->out.max = tableMicroHeader.MaxMagn; // pCtl->out.min = tableMicroHeader.MinMagn; // pCtl->out.TableAddress = tableAddress; // pCtl->out.nPoints = nPoints; // // pCtl->svc.errCode = ERR_NFMGETPOINTS_NOERR; // // success // return 1; // } // // // ----------------- // // User must call this function with (pCtl->in.nCount=0) first time // // to initialize the @pCtl->out contents. // // Here: 0 != pCtl->in.nCount // // ----------------- // // // Check the header data, loaded at previous step ( see pCtl->in.nCount == 0 ) // if( 0 == pCtl->out.nPoints // check the number of points in the table // || 0 == pCtl->out.TableAddress ) // check the table base address // { // // error, invalid parameters // // Call the function with (pCtl->in.nCount = 0) to load the header // pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; // // return 0; // } // // // Check the input parameters // if( pCtl->in.nCount > pCtl->out.nPoints // check the amount of requested points // || pCtl->in.nStartPoint >= pCtl->out.nPoints // check the starting point // || NULL == pCtl->in.pDataArray ) // check receiving data buffer // { // // error: invalid input parameters // pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; // // return 0; // } // // return NFMClassExtended->private.methods.memory.getTCompMagnPoints( pCtl ); // } // // MEM:TABL:THER:CORR:PHASE? // // Reads the phase data points of the thermocompensation table // static size_t NFMGetPointsPhaseThermo( ePortComb_t portComb, ePortStateId_t portState, sNFMGetPoints_t * pCtl ) // { // if( portComb >= ePortComb_MAX // || portComb == ePortComb_UNDEFINED // || portState >= ePortStateId_MAX // || portState == ePortStateId_UNDEFINED // || NULL == pCtl // || NULL == pCtl->in.pDataArray // ) // { // if( NULL != pCtl ) // pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; // // return 0; // } // // /* --- do it later: inside @getChrzTableHeader() call // // Validate the combination of @portComb, @portState and // // validate the @portComb and @portState itself. // // Retrieve the table index (ordered index) // size_t tableIdx = NFMClassExtended->private.methods.memory.getChrzTableIndex( portComb, portState ); // // if( NFM_CHRZ_TABLEIDX_INVALID == tableIdx ) // { // // Invalid combination or value // return 0; // } // */ // // // Check the input parameter: @pCtl->in.nCount // // For zero value: required to load the table header // // During the loading the table header it is required: // // - load the main thermocompensation header, check CRC // // - retrieve number of points (@nPoints) from the header // // - load the table header and check it's CRC // // - retrieve the table address @TableAddress (for next operations) // // - retrieve the @min and @max fields from the table header // // - store @min, @max, @TableAddress, @nPoints into @pCtl.out // // - return (1) in case of success, or (0) on error // if( 0 == pCtl->in.nCount ) // { // // load thermocompensation main header // // and check the CRC // const sEcalTCompHeader_t * pTCompHeader = NFMClassExtended->private.methods.memory // .getTCompHeader( NULL, 0 ); // // // check the TComp header: number of points // if( NULL == pTCompHeader // || 0 == pTCompHeader->Points ) // { // pCtl->svc.errCode = ERR_NFMGETPOINTS_INVHDR; // // return (0); // } // // // move @.Points into @nPoints // // due to @pTCompHeader will be corrupted // size_t nPoints = pTCompHeader->Points; // // sEcalTCompTablePhaseHeader_t tableMicroHeader; // // // load the table base address // // Note: the data by @pChrzHeader is not valid after this call, // // due to the function uses the same internal buffer! // size_t tableAddress = NFMClassExtended->private.methods.memory // .getTCompPhaseTableHeader( // load the table base address // portComb, // for specified port combination // portState, // for specified port state // nPoints, // for retrieved number of points // &tableMicroHeader, // and store the header into @tableMicroHeader // &pCtl->svc.errCode // And fill up the error code // ); // // // check the result: @tableAddress // // 0 - table corrupted or invalid port combination or port state. // // but since the @portComb and @portState are validated above... // // this result means only that the table is corrupted // // non zero - this is the absolute address of the requested table. // if( 0 == tableAddress ) // { // (void)pCtl->svc.errCode; // return 0; // error, sorry // } // // // - store @min, @max, @TableAddress, @nPoints into @pCtl.out // pCtl->out.max = tableMicroHeader.MaxPhase; // pCtl->out.min = tableMicroHeader.MinPhase; // pCtl->out.TableAddress = tableAddress; // pCtl->out.nPoints = nPoints; // // pCtl->svc.errCode = ERR_NFMGETPOINTS_NOERR; // // // success // return 1; // } // // // ----------------- // // User must call this function with (pCtl->in.nCount=0) first time // // to initialize the @pCtl->out contents. // // Here: 0 != pCtl->in.nCount // // ----------------- // // // Check the header data, loaded at previous step ( see pCtl->in.nCount == 0 ) // if( 0 == pCtl->out.nPoints // check the number of points in the table // || 0 == pCtl->out.TableAddress ) // check the table base address // { // // error, invalid parameters // // Call the function with (pCtl->in.nCount = 0) to load the header // pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; // // return 0; // } // // // Check the input parameters // if( pCtl->in.nCount > pCtl->out.nPoints // check the amount of requested points // || pCtl->in.nStartPoint >= pCtl->out.nPoints // check the starting point // || NULL == pCtl->in.pDataArray ) // check receiving data buffer // { // // error: invalid input parameters // pCtl->svc.errCode = ERR_NFMGETPOINTS_INVAL; // // return 0; // } // // return NFMClassExtended->private.methods.memory.getTCompPhasePoints( pCtl ); // } // MEM:TABL:THERmo:CORRection:MAGNitude? // NFMGetPointsThermoMagn_Begin // Prepares the context before reading the data points of the thermocompensation table of magnitudes // This method is designed to replace the obsolete @NFMGetPointsMagnThermo // 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 NFMGetPointsThermoMagn_Begin( ePortComb_t portComb, ePortStateId_t portState, sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer, xNFMGetPointsSimplified_t * xCtl ) { sNFMGetPointsSimplified_t * pCtl = (sNFMGetPointsSimplified_t*)xCtl; if( NULL == pCtl ) { return eNFMGetPointError_InvalidValue; } pCtl->isThermoPhase = 0; return NFMGetPointsThermo_Begin( portComb, portState, pDataBuffer, szDataBuffer, pCtl ); } // MEM:TABL:THERmo:CORRection:PHASe? // NFMGetPointsThermoPhase_Begin // Prepares the context before reading the data points of the thermocompensation table of magnitudes/phases // This method is designed to replace the obsolete NFMGetPointsPhaseThermo. // 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 NFMGetPointsThermoPhase_Begin( ePortComb_t portComb, ePortStateId_t portState, sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer, xNFMGetPointsSimplified_t * xCtl ) { sNFMGetPointsSimplified_t * pCtl = (sNFMGetPointsSimplified_t*)xCtl; if( NULL == pCtl ) { return eNFMGetPointError_InvalidValue; } pCtl->isThermoPhase = 1; return NFMGetPointsThermo_Begin( portComb, portState, pDataBuffer, szDataBuffer, pCtl ); } // MEM:TABL:THERmo:CORRection:MAGNitude? // MEM:TABL:THERmo:CORRection:PHASe? // NFMGetPointsThermo_Begin // Prepares the context before reading the data points of the thermocompensation table of magnitudes/phases // This method is designed to replace the obsolete @NFMGetPointsMagnThermo/NFMGetPointsPhaseThermo. // 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. static size_t NFMGetPointsThermo_Begin( ePortComb_t portComb, ePortStateId_t portState, sNFMChrzPoint_t * pDataBuffer, size_t szDataBuffer, sNFMGetPointsSimplified_t * pCtl ) { my_assert( pCtl ); // see @NFMGetPointsThermoMagn_Begin/NFMGetPointsThermoPhase_Begin // Check if arguments are valid in general if( ( portComb >= ePortComb_MAX ) || ( portState >= ePortStateId_MAX ) || ( portComb == ePortComb_UNDEFINED ) || ( 0 == szDataBuffer ) ) { pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVAL; return 0; } // Check if arguments are valid particularly for this device if( ! NFMClassExtended->public.methods.checkTableParams( portComb, portState ) ) { // Invalid combination or value pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVAL; return 0; } // Fill input parameters: pCtl->BufferCapacity = szDataBuffer; // - output buffer capacity pCtl->sectorId = eChFactory; // - don't care for Thermocompensation pCtl->portComb = portComb; // - requested port combination (nfm path) pCtl->portState = portState; // - requested state (S-parameter) pCtl->intCtx.in.nCount = szDataBuffer; // - number of points to get pCtl->intCtx.in.nStartPoint = 0; // - start point pCtl->intCtx.in.pDataArray = pDataBuffer; // - output buffer // During the loading the table header it is required: // - load the main characterization header, check CRC // - retrieve number of points (@nPoints) from the header for specified @sectorId // - load the table header and check it's CRC // - retrieve the table address @TableAddress (for next operations) // - retrieve the @min and @max fields from the table header // - store @min, @max, @TableAddress, @nPoints into @pCtl.intCtx.out // load thermocompensation main header // and check the CRC const sEcalTCompHeader_t * pTCompHeader = NFMClassExtended->private.methods.memory.getTCompHeader( NULL, 0 ); // check the TComp header: number of points if( NULL == pTCompHeader || 0 == pTCompHeader->Points ) { pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVHDR; return (0); } // move @.Points into @nPoints // due to @pTCompHeader will be corrupted size_t nPoints = pTCompHeader->Points; union { sEcalTCompTableMagnHeader_t tableMicroHeaderMagn; sEcalTCompTablePhaseHeader_t tableMicroHeaderPhase; }; // load the table base address // Note: the data by @pChrzHeader is not valid after this call, // due to the function uses the same internal buffer! size_t tableAddress = 0; if( 0 == pCtl->isThermoPhase ) tableAddress = NFMClassExtended->private.methods.memory .getTCompMagnTableHeader( // load the table base address: magnitude portComb, // for specified port combination portState, // for specified port state nPoints, // for retrieved number of points &tableMicroHeaderMagn, // and store the header into @tableMicroHeaderMagn &pCtl->intCtx.svc.errCode // And fill up the error code ); else tableAddress = NFMClassExtended->private.methods.memory .getTCompPhaseTableHeader( // load the table base address: phase portComb, // for specified port combination portState, // for specified port state nPoints, // for retrieved number of points &tableMicroHeaderPhase, // and store the header into @tableMicroHeaderPhase &pCtl->intCtx.svc.errCode // And fill up the error code ); // check the result: @tableAddress // 0 - table corrupted or invalid port combination or port state. // but since the @portComb and @portState are validated above... // this result means only that the table is corrupted // non zero - this is the absolute address of the requested table. if( 0 == tableAddress ) { (void)pCtl->intCtx.svc.errCode; return 0; // error, sorry } // - store @min, @max, @TableAddress, @nPoints into @pCtl.out if( 0 == pCtl->isThermoPhase ) { pCtl->intCtx.out.max = tableMicroHeaderMagn.MaxMagn; pCtl->intCtx.out.min = tableMicroHeaderMagn.MinMagn; } else { pCtl->intCtx.out.max = tableMicroHeaderPhase.MaxPhase; pCtl->intCtx.out.min = tableMicroHeaderPhase.MinPhase; } pCtl->intCtx.out.TableAddress = tableAddress; pCtl->intCtx.out.nPoints = nPoints; pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_NOERR; // success return nPoints; } // MEM:TABL:THER:CORR:MAGN? // @NFMGetPointsThermoMagn_Continue // Uses already prepared context and reads magnutude data points of the thermocompensation // table to the top of specified buffer (see @NFMGetPointsThermo_Begin). // This method is designed to replace the obsolete @NFMGetPointsMagnThermo. // Parameters: // @xCtl - control context prepared by previous NFMGetPointsThermo_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 NFMGetPointsThermoMagn_Continue( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve ) { sNFMGetPointsSimplified_t * pCtl = (sNFMGetPointsSimplified_t*)xCtl; if( NULL == pCtl || NULL == pnPointsRetrieve || 0 != pCtl->isThermoPhase ) { return eNFMGetPointError_InvalidValue; } return NFMGetPointsThermo_Continue( pCtl, pnPointsRetrieve ); } // MEM:TABL:THER:CORR:PHAS? // @NFMGetPointsThermoPhase_Continue // Uses already prepared context and reads phase data points of the thermocompensation // table to the top of specified buffer (see @NFMGetPointsThermo_Begin). // This method is designed to replace the obsolete @NFMGetPointsPhaseThermo. // Parameters: // @xCtl - control context prepared by previous NFMGetPointsThermo_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 NFMGetPointsThermoPhase_Continue( xNFMGetPointsSimplified_t * xCtl, size_t * pnPointsRetrieve ) { sNFMGetPointsSimplified_t * pCtl = (sNFMGetPointsSimplified_t*)xCtl; if( NULL == pCtl || NULL == pnPointsRetrieve || 0 == pCtl->isThermoPhase ) { return eNFMGetPointError_InvalidValue; } return NFMGetPointsThermo_Continue( pCtl, pnPointsRetrieve ); } // MEM:TABL:THER:CORR:MAGN? // MEM:TABL:THER:CORR:PHAS? // @NFMGetPointsThermo_Continue // Uses already prepared context and reads magnutude/phase data points of the thermocompensation // table to the top of specified buffer (see @NFMGetPointsThermo_Begin). // This method is designed to replace the obsolete @NFMGetPointsMagnThermo/NFMGetPointsPhaseThermo. // Parameters: // @xCtl - control context prepared by previous NFMGetPointsThermo_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; static int32_t NFMGetPointsThermo_Continue( sNFMGetPointsSimplified_t * pCtl, size_t * pnPointsRetrieve ) { my_assert( pCtl ); // see @NFMGetPointsThermoMagn_Continue, @NFMGetPointsThermoPhase_Continue my_assert( pnPointsRetrieve ); // see @NFMGetPointsThermoMagn_Continue, @NFMGetPointsThermoPhase_Continue // Check if arguments are valid in general if( ( pCtl->sectorId != eChFactory ) // Formal checking: actually it is does not matter what value is specified here || ( pCtl->portComb >= ePortComb_MAX ) || ( pCtl->portState >= ePortStateId_MAX ) || ( pCtl->portComb == ePortComb_UNDEFINED ) || ( 0 == pCtl->BufferCapacity ) || ( 0 == pCtl->intCtx.out.nPoints ) || ( 0 == pCtl->intCtx.out.TableAddress ) || ( NULL == pCtl->intCtx.in.pDataArray ) ) { pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_INVAL; return eNFMGetPointError_InvalidValue; } // check ranges if( pCtl->intCtx.in.nCount > pCtl->intCtx.out.nPoints ) pCtl->intCtx.in.nCount = pCtl->intCtx.out.nPoints; if( pCtl->intCtx.in.nStartPoint >= pCtl->intCtx.out.nPoints ) pCtl->intCtx.in.nStartPoint = pCtl->intCtx.out.nPoints; // end-of-points if( pCtl->intCtx.in.nStartPoint + pCtl->intCtx.in.nCount > pCtl->intCtx.out.nPoints ) { pCtl->intCtx.in.nCount = pCtl->intCtx.out.nPoints - pCtl->intCtx.in.nStartPoint; } // check for end condition if( 0 == pCtl->intCtx.in.nCount || pCtl->intCtx.in.nStartPoint == pCtl->intCtx.out.nPoints ) { *pnPointsRetrieve = 0; // number of points read is zero pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_NOERR; return eNFMGetPointError_Success; } int32_t success_rc = eNFMGetPointError_Success; // check buffer capacity range if( pCtl->intCtx.in.nCount > pCtl->BufferCapacity ) { pCtl->intCtx.in.nCount = pCtl->BufferCapacity; success_rc = eNFMGetPointError_OutOfBuffer; // out of buffer, the number of points is limited } else if( pCtl->intCtx.in.nStartPoint + pCtl->intCtx.in.nCount < pCtl->intCtx.out.nPoints ) { success_rc = eNFMGetPointError_Limit; // number of points is limited by user } pCtl->intCtx.svc.errCode = ERR_NFMGETPOINTS_IO; size_t nRead = 0; if( 0 == pCtl->isThermoPhase ) nRead = NFMClassExtended->private.methods.memory.getTCompMagnPoints( &pCtl->intCtx ); else nRead = NFMClassExtended->private.methods.memory.getTCompPhasePoints( &pCtl->intCtx ); // check for error condition if( nRead == 0 ) { *pnPointsRetrieve = 0; // number of points read is zero (void)pCtl->intCtx.svc.errCode; return eNFMGetPointError_DataError; } pCtl->intCtx.in.nStartPoint += nRead; // increment start point for next call // check range if( pCtl->intCtx.in.nStartPoint + pCtl->intCtx.in.nCount > pCtl->intCtx.out.nPoints ) { pCtl->intCtx.in.nCount = pCtl->intCtx.out.nPoints - pCtl->intCtx.in.nStartPoint; } *pnPointsRetrieve = nRead; // number of points read return success_rc; } static bool NFMGetInterface( eNFMUSBInterface_t * pCurrentIface ) { if( NULL != pCurrentIface ) { if( sizeof(sNFMSettingsBlockCrc_t) == NFMClassExtended->private.methods.memory.getSettingsBlockSize() ) { sNFMSettingsBlockCrc_t sSettingsBlock; if( NFMClassExtended->private.methods.memory.getSettingsBlock( (uint8_t*)&sSettingsBlock, 0, sizeof(sSettingsBlock) ) ) { *pCurrentIface = eNFM_IfaceUSBVendor; if( sSettingsBlock.settings.rawBytes[0] == 'U' ) if( sSettingsBlock.settings.rawBytes[1] == 'S' ) if( sSettingsBlock.settings.rawBytes[2] == 'B' ) if( sSettingsBlock.settings.rawBytes[3] == 'T' ) if( sSettingsBlock.settings.rawBytes[4] == 'M' ) if( sSettingsBlock.settings.rawBytes[5] == 'C' ) if( sSettingsBlock.settings.rawBytes[6] == '!' ) if( sSettingsBlock.settings.rawBytes[7] == 0 ) *pCurrentIface = eNFM_IfaceUSBTMC; return true; } } } return false; } static bool NFMSetInterface( eNFMUSBInterface_t activateInterface ) { if( (activateInterface == eNFM_IfaceUSBVendor) ||(activateInterface == eNFM_IfaceUSBTMC) ) { if( sizeof(sNFMSettingsBlockCrc_t) == NFMClassExtended->private.methods.memory.getSettingsBlockSize() ) { sNFMSettingsBlockCrc_t sSettingsBlock; if( NFMClassExtended->private.methods.memory.getSettingsBlock( (uint8_t*)&sSettingsBlock, 0, sizeof(sSettingsBlock) ) ) { if( eNFM_IfaceUSBTMC == activateInterface ) { sSettingsBlock.settings.rawBytes[0] = 'U'; sSettingsBlock.settings.rawBytes[1] = 'S'; sSettingsBlock.settings.rawBytes[2] = 'B'; sSettingsBlock.settings.rawBytes[3] = 'T'; sSettingsBlock.settings.rawBytes[4] = 'M'; sSettingsBlock.settings.rawBytes[5] = 'C'; sSettingsBlock.settings.rawBytes[6] = '!'; sSettingsBlock.settings.rawBytes[7] = 0 ; } else { sSettingsBlock.settings.rawBytes[0] = 'V'; sSettingsBlock.settings.rawBytes[1] = 'E'; sSettingsBlock.settings.rawBytes[2] = 'N'; sSettingsBlock.settings.rawBytes[3] = 'D'; sSettingsBlock.settings.rawBytes[4] = 'O'; sSettingsBlock.settings.rawBytes[5] = 'R'; sSettingsBlock.settings.rawBytes[6] = '!'; sSettingsBlock.settings.rawBytes[7] = 0 ; } TCRC crc = ICRC32; crc = CRC32( crc, (uint8_t *)&sSettingsBlock.settings, sizeof(sSettingsBlock.settings)); sSettingsBlock.CRCValue = crc; return NFMClassExtended->private.methods.memory.setSettingsBlock( (uint8_t*)&sSettingsBlock, 0, sizeof(sSettingsBlock) ); } } } return false; } static uint16_t* GetPort(uint16_t portNumber) { switch(portNumber) { case eNFMPort_1: return &NFMClassExtended->public.properties.inputPortStates[ePort_1]; case eNFMPort_2: return &NFMClassExtended->public.properties.inputPortStates[ePort_2]; default: return 0; } } static uint16_t NFMGetPortState (uint16_t portNumber) { return *GetPort(portNumber); } static bool NFMSetPortState (uint16_t portNumber, uint16_t portState) { uint16_t* port = GetPort(portNumber); if(port == NULL) return false; *port = portState; return true; } #endif