#include #include const uint8_t fsqvbl_CommandHandlerESR_context = 1; const uint8_t fsqvbl_CommandHandlerSTB_context = 2; #define SCPI_ARGS_N 0 #include "app/scpi/scpi_handler.h" #include "app/scpi/commandHandlers/esr.h" #include "app/nfm/nfm_base.h" // Refer to: // [1] SCPI Specification, revision 1999.0 // "Standard Commands for Programmable Instruments (SCPI), VERSION 1999.0, May 1999" // [2] Gpib Programming Tutorial, (http://g2pc1.bu.edu/~qzpeng/gpib/manual/GpibProgTut.pdf) // Electronics Group (http://www.few.vu.nl/~elec), 11 January 2000 Electronics Group // ================================================================================= // @fsqvbl_CommandHandlerESRSTB // State's virtual table static void fsqe_CommandHandlerESRSTB( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx ); static void fsql_CommandHandlerESRSTB( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx ); static const struct fFSeqEntry_t * fsqf_CommandHandlerESRSTB( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx, const struct fFSeqEntry_t * * pDeferredNext ); const fFSeqVTable_t fsqvbl_CommandHandlerESRSTB = { .f = fsqf_CommandHandlerESRSTB, .enter = fsqe_CommandHandlerESRSTB, .leave = fsql_CommandHandlerESRSTB }; static void fsqe_CommandHandlerESRSTB( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx ) { sProcessProgramDataCommonContext_t * common_ctx = ctx; common_ctx->ESRSTB.idx = 0; // reset position SCPI_PARSE_ARGUMENTS( common_ctx ); (void)common_ctx->argsParserStatus; // status is modified } static void fsql_CommandHandlerESRSTB( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx ) { } static const struct fFSeqEntry_t * fsqf_CommandHandlerESRSTB( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx, const struct fFSeqEntry_t * * pDeferredNext ) { const fFSeqEntry_t * nextstate = NULL; sProcessProgramDataCommonContext_t * common_ctx = ctx; sScpiParserContext_t * global_ctx = common_ctx->global_ctx; switch( common_ctx->event ) { case eProgramData_Event_Write: { if( ! common_ctx->isQuery ) { common_ctx->status = eProgramDataSyntaxError; // invalid command header type: COMMAND not supported (only query) } else if( eScpiStatus_success != common_ctx->argsParserStatus ) // check argument parser status { common_ctx->status = eProgramDataArgumentSyntax; // parameter syntax error, caller should generate error message } else { common_ctx->status = eProgramDataNeedRead; // request processed, wait for reading... (void)nextstate; // stay in this state } } break; case eProgramData_Event_Read: { // @idx - current position of the source data to be outputed if( 0 == common_ctx->ESRSTB.idx ) { memset( common_ctx->tempBuffer, 0, sizeof(common_ctx->tempBuffer) ); uint8_t esrstb = 0; if( common_ctx->handler_ctx == &fsqvbl_CommandHandlerESR_context ) { // Read ESB: // "11.5.1.2 Standard Event Status Register Operation", [3] // "<...> The Standard Event Status Register is destructively read (that is, read and cleared) <...>", [3] // retrieve ESB and clear it GPIBMachine.fGPIB_get_event_status_register( &global_ctx->sGPIB.registers, &esrstb ); } if( common_ctx->handler_ctx == &fsqvbl_CommandHandlerSTB_context ) { // It is required to call 'scpi_UpdateMessageAvailable' here due to the following reason: // The MAV bit is set automatically by SCPI core after this handler returns 'eProgramDataNeedRead' // above on 'Write' event in advance even there no data in the output buffer. So after the handler is // called the SCPI core updates this bit again, and if the EOM is set, the MAV bit will be reset. // But here, during the handler call, this bit is set ever for this command handler, so, it is required // to update the MAV bit value: only set if any data is already pushed into the output buffer by the // previous handler, and reset otherwise. If it is not done, the *STB? command will return this // bit as 1 each call whenever is there data in the buffer or not. scpi_UpdateMessageAvailable(); // Read STB // "11.2.2.1 Reading with a Serial Poll", [3] // "11.2.2.2 Reading With the *STB? Query", [3] GPIBMachine.fGPIB_get_status_byte_normal_poll( &global_ctx->sGPIB.registers, &esrstb ); } int iesrstb = (int)esrstb; // first call: prepare buffer _snprintf( common_ctx->tempBuffer, sizeof(common_ctx->tempBuffer), "%d", iesrstb ); } // Since @done flag is set, this dispatcher shall not be called anymore. // Since this handler is implemented as a single-state automat, there no // ... other states to go to: (void)nextstate; // modify current postion index: SCPI_RESPONSE_HELPER( common_ctx, common_ctx->ESRSTB.idx ); } break; } return nextstate; }