| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- #ifndef USBTMCLIB_BASIC_H
- #define USBTMCLIB_BASIC_H
- // USB Test And Measurement Control Protocol (TMC)
- // Library version 1.0
- // 23/07/19
- // Sychov A.
- //----------------------------------------------------------------
- // Refer to:
- // [1] USBTMC Standard, rev. 1.0, 14/04/2003
- // "Universal Serial Bus Test and Measurement Class Specification (USBTMC)"
- // [2] USBTMC-USB488 Standard, rev. 1.0, 14/04/2003
- // "Universal Serial Bus Test and Measurement Class, Subclass USB488 Specification (USBTMC-USB488)
- //----------------------------------------------------------------
- #include <stddef.h>
- #include <stdint.h>
- #include "usbtmclib/usbtmclib_types.h"
- #include "usbtmclib/usbtmclib_requests.h"
- #include "usbtmclib/usbtmclib_errors.h"
- #include "app/usb/usb_transfers.h"
- #include "app/usb/usb_transfer_flags.h"
- #define USBTMC_VERSION 0x0100 // 4.2.1.8 GET_CAPABILITIES, table 37, [1]
- #define USB488_VERSION 0x0100 // 4.2.2 GET_CAPABILITIES, table 8, [2]
- typedef struct
- {
- bool bInProgress;
- uint32_t transferSize;
- uint32_t bytesCounter;
- bool bEndOfMessage;
- sUSBTransfer_t * transf;
- bool bNewTransfer;
- // @bytesCounter for BulkOut:
- // The total number of USBTMC message data bytes (not including
- // Bulk-OUT Header or alignment bytes) in the transfer received,
- // and not discarded, by the device
- // @bytesCounter for BulkIn:
- // The total number of USBTMC message data bytes (not including
- // Bulk-IN Header or alignment bytes) sent in the transfer
- // @bEndOfMessage for BulkOut:
- // Specifies if the EOM flag is set in Bulk-OUT header
- // See @bm_DEV_DEP_MSG_OUT_EOM for details.
- // @transf for BulkOUT:
- // Receiving buffer object
- // @transf for BulkIN:
- // Transmitting buffer object
- // @bNewTransfer for BulkOUT:
- // Set if new transfer just has been started
- // bLatestTag - the latest aborted/completed transaction bTag
- uint8_t bLatestTag;
- }
- sUSBTMCTransferState_t;
- typedef struct
- {
- bool bInProgress;
- uint32_t bytesCounter;
- bool bEndOfMessage;
- // @STB - status byte (IEEE 488.1/IEEE 488.2)
- // The part of USBTMC-USB488 Interrupt-IN Header, [2], 3.4 Interrupt-IN
- uint8_t STB;
- // @bTag - transfer identifier (bTag), [2], 4.3.1 READ_STATUS_BYTE
- // The part of USBTMC-USB488 Interrupt-IN Header, [2], 3.4 Interrupt-IN
- uint8_t bTag;
- // @transf for InterruptIn:
- // Transmitting buffer object
- sUSBTransfer_t * transf;
- // @bNewTransfer for InterruptIn:
- // Set if new transfer just has been started
- bool bNewTransfer;
- }
- sUSBTMCIntTransferState_t;
- typedef struct
- {
- sUSBTMCBulkOutHeader_t bulkOutHeader;
- sUSBTMCBulkInHeader_t bulkInHeader;
- sUSBTMCNotificationHeader_t interruptInHeader;
- sUSBTMCTransferState_t bulkOutState;
- sUSBTMCTransferState_t bulkInState;
- sUSBTMCIntTransferState_t interruptInState;
- sUSBTMCBulkInHeader_t * psActiveInHeader;
- sUSBTMCNotificationHeader_t * psActiveNotificationHeader;
- }
- sUSBTMCContext_t;
- typedef enum
- {
- tmclib_status_min = -2147483648,
- tmclib_status_invalid_param = -10, // ERROR/FAIL
- tmclib_status_invalid_length = -9, // ERROR/FAIL
- tmclib_status_halt_bulkin = -8, // ERROR/FAIL
- tmclib_status_unsupported_termchar = -7, // ERROR/FAIL
- tmclib_status_unsupported_message_error = -6, // ERROR/FAIL
- tmclib_status_invalid_message_error = -5, // ERROR/FAIL
- tmclib_status_header_error = -4, // ERROR/FAIL
- tmclib_status_read_error = -3, // ERROR/FAIL
- tmclib_status_header_fragmented_error = -2, // ERROR/FAIL
- tmclib_status_failure = -1, // ERROR/FAIL
- tmclib_status_success = 0, // SUCCESS/OK
- tmclib_status_in_progress = 1, // SIGNAL/WARNING
- tmclib_status_not_in_progress = 2, // SIGNAL/WARNING
- tmclib_status_again = 3, // SIGNAL/WARNING
- tmclib_status_need_data = 4, // SIGNAL/WARNING
- tmclib_status_need_read = 5, // SIGNAL/WARNING
- tmclib_status_no_more_data = 6, // SIGNAL/WARNING
- tmclib_status_max = 2147483647,
- }
- eTMCLibStatus_t;
- // @eTMCLibEvent_t
- // Common TMCLibrary event identifier.
- // Is used in tmclib_*_event() routines
- typedef enum
- {
- eTMCEventInterruptInStart, // InterruptIn initialize (only for Interrupt-IN)
- eTMCEventBulkIn, // BulkIn event
- eTMCEventBulkOut, // BulkOut event
- eTMCEventInterruptIn, // InterruptIn event
- eTMCEventBulkInStop, // BulkIn abort
- eTMCEventBulkOutStop, // BulkOut abort
- eTMCEventInterruptInStop, // InterruptIn abort
- eTMCEventDeviceClear, // Common Clear Event (*RST or Device Clear)
- }
- eTMCLibEvent_t;
- typedef struct
- {
- sUSBTransfer_t * tx;
- }
- sTMCBulkInEventCtx_t;
- #define DEFINE_tmclib_event_context_bulkin( _name, _tx ) \
- sTMCEventContext_t eventCtx = { \
- .event = (eTMCEventBulkIn),\
- .bulkIn = { \
- .tx = (_tx) \
- } \
- }
- #define COMPOUND_tmclib_event_context_bulkin( _name, _tx ) \
- &((sTMCEventContext_t){ \
- .event = (eTMCEventBulkIn),\
- .bulkIn = { \
- .tx = (_tx) \
- } \
- })
- typedef struct
- {
- sUSBTransfer_t * rx;
- }
- sTMCBulkOutEventCtx_t;
- #define DEFINE_tmclib_event_context_bulkout( _name, _rx ) \
- sTMCEventContext_t eventCtx = { \
- .event = (eTMCEventBulkOut),\
- .bulkOut = { \
- .rx = (_rx) \
- } \
- }
- #define COMPOUND_tmclib_event_context_bulkout( _name, _rx ) \
- &((sTMCEventContext_t){ \
- .event = (eTMCEventBulkOut),\
- .bulkOut = { \
- .rx = (_rx) \
- } \
- })
- typedef struct
- {
- sUSBTransfer_t * ntx;
- uint8_t bTag;
- }
- sTMCInterruptInEventCtx_t;
- #define DEFINE_tmclib_event_context_interruptin_start( _name, _ntx, _btag ) \
- sTMCEventContext_t _name = { \
- .event = (eTMCEventInterruptInStart),\
- .interruptIn = { \
- .ntx = (_ntx),\
- .bTag = (_btag) \
- } \
- }
- #define DEFINE_tmclib_event_context_interruptin( _name, _ntx ) \
- sTMCEventContext_t _name = { \
- .event = (eTMCEventInterruptIn),\
- .interruptIn = { \
- .ntx = (_ntx),\
- .bTag = (0) \
- } \
- }
- #define COMPOUND_tmclib_event_context_interruptin_start( _name, _ntx, _btag ) \
- &((sTMCEventContext_t){ \
- .event = (eTMCEventInterruptInStart),\
- .interruptIn = { \
- .ntx = (_ntx),\
- .bTag = (_btag) \
- } \
- })
- #define COMPOUND_tmclib_event_context_interruptin( _name, _ntx ) \
- &((sTMCEventContext_t){ \
- .event = (eTMCEventInterruptIn),\
- .interruptIn = { \
- .ntx = (_ntx),\
- .bTag = (0) \
- } \
- })
- typedef struct
- {
- // @force - makes to ignore the @transfer_bTag if true
- bool force;
- // @clearShortPacketIndicator - clear Short Packet Indicator assotiated with USB transfer
- bool clearShortPacketIndicator;
- // @noResetTransfer
- // By default shall be false.
- // If set, the transfer will not be reset. Is used only if buffer contains more data than
- // expected for the transfer
- bool noResetTransfer;
- // @transfer_bTag - The bTag value associated with the transfer to abort,
- // - BulkOut: see 4.2.1.2 [1]
- // - BulkIn: see 4.2.1.4 [1]
- // - InterruptIn: see 4.3.1 [2]
- uint8_t transfer_bTag;
- }
- sTMCAbortEventCtx_t;
- typedef struct
- {
- // @resetTransport - reset all the USBTMC transfers
- bool resetTransport;
- }
- sTMCDeviceClearEventCtx_t;
- #define DEFINE_tmclib_event_context_abort_bulkout( _name, _btag, _force ) \
- sTMCEventContext_t _name = { \
- .event = eTMCEventBulkOutStop,\
- .abort = { \
- .force = (_force),\
- .clearShortPacketIndicator = (false), \
- .noResetTransfer = (false), \
- .transfer_bTag = (_btag) \
- } \
- }
- #define DEFINE_tmclib_event_context_abort_bulkin( _name, _btag, _force ) \
- sTMCEventContext_t _name = { \
- .event = eTMCEventBulkInStop,\
- .abort = { \
- .force = (_force),\
- .clearShortPacketIndicator = (true), \
- .noResetTransfer = (false), \
- .transfer_bTag = (_btag) \
- } \
- }
- #define DEFINE_tmclib_event_context_complete_bulkin( _name, _btag ) \
- sTMCEventContext_t _name = { \
- .event = eTMCEventBulkInStop,\
- .abort = { \
- .force = (false),\
- .clearShortPacketIndicator = (false), \
- .noResetTransfer = (false), \
- .transfer_bTag = (_btag) \
- } \
- }
- #define DEFINE_tmclib_event_context_abort_interruptin( _name, _btag, _force ) \
- sTMCEventContext_t _name = { \
- .event = eTMCEventInterruptInStop,\
- .abort = { \
- .force = (_force),\
- .clearShortPacketIndicator = (false), \
- .noResetTransfer = (false), \
- .transfer_bTag = (_btag) \
- } \
- }
- #define COMPOUND_tmclib_event_context_abort_bulkout( _btag, _force ) \
- &((sTMCEventContext_t){ \
- .event = eTMCEventBulkOutStop,\
- .abort = { \
- .force = (_force),\
- .clearShortPacketIndicator = (false), \
- .noResetTransfer = (false), \
- .transfer_bTag = (_btag) \
- } \
- })
- #define COMPOUND_tmclib_event_context_abort_bulkout_noreset( _btag, _force ) \
- &((sTMCEventContext_t){ \
- .event = eTMCEventBulkOutStop,\
- .abort = { \
- .force = (_force),\
- .clearShortPacketIndicator = (false), \
- .noResetTransfer = (true), \
- .transfer_bTag = (_btag) \
- } \
- })
- #define COMPOUND_tmclib_event_context_abort_bulkin( _btag, _force ) \
- &((sTMCEventContext_t){ \
- .event = eTMCEventBulkInStop,\
- .abort = { \
- .force = (_force),\
- .clearShortPacketIndicator = (true), \
- .noResetTransfer = (false), \
- .transfer_bTag = (_btag) \
- } \
- })
- #define COMPOUND_tmclib_event_context_complete_bulkin( _btag, _force ) \
- &((sTMCEventContext_t){ \
- .event = eTMCEventBulkInStop,\
- .abort = { \
- .force = (_force),\
- .clearShortPacketIndicator = (false), \
- .noResetTransfer = (false), \
- .transfer_bTag = (_btag) \
- } \
- })
- #define COMPOUND_tmclib_event_context_abort_interruptin( _btag, _force ) \
- &((sTMCEventContext_t){ \
- .event = eTMCEventInterruptInStop,\
- .abort = { \
- .force = (_force),\
- .clearShortPacketIndicator = (false), \
- .noResetTransfer = (false), \
- .transfer_bTag = (_btag) \
- } \
- })
- #define COMPOUND_tmclib_event_context_device_clear( _fullReset ) \
- &((sTMCEventContext_t){ \
- .event = eTMCEventDeviceClear,\
- .clear = { \
- .resetTransport = (_fullReset),\
- } \
- })
- typedef struct
- {
- eTMCLibEvent_t event; // event identified
- union
- {
- sTMCBulkInEventCtx_t bulkIn; // for events: eTMCEventBulkIn
- sTMCBulkOutEventCtx_t bulkOut; // for events: eTMCEventBulkOut
- sTMCInterruptInEventCtx_t interruptIn; // for events: eTMCEventInterruptIn, eTMCEventBulkInStart
- sTMCAbortEventCtx_t abort; // for events: eTMCEventBulkInStop, eTMCEventBulkOutStop, eTMCEventInterruptInStop
- sTMCDeviceClearEventCtx_t clear; // for events: eTMCEventDeviceClear
- };
- }
- sTMCEventContext_t;
- #define USBTMC_CHECK_BITMAP( Bitmap, Flag ) ((bool)((Bitmap)&(Flag)))
- #define USBTMC_ERROR(status) ( tmclib_status_success > (status) )
- #define USBTMC_NOTERROR(status) ( tmclib_status_success <=(status) )
- #define USBTMC_WARNING(status) ( tmclib_status_success < (status) )
- // @tmclib_init()
- // Initialize TMC library
- // @rx - receiving buffer object
- // @tx - transmitting buffer object
- // @ntx - interrupt/notify transmitting buffer object
- eTMCLibStatus_t tmclib_init( sUSBTransfer_t * rx, sUSBTransfer_t * tx, sUSBTransfer_t * ntx );
- // @tmclib_deinit()
- // Deinitialize TMC library
- eTMCLibStatus_t tmclib_deinit();
- // // @tmclib_new_bulkout()
- // // Starts new BulkOUT transfer
- // eTMCLibStatus_t tmclib_new_bulkout();
- //
- // // @tmclib_new_bulkin()
- // // Starts new BulkIN transfer
- // eTMCLibStatus_t tmclib_new_bulkin();
- // @tmclib_bulkout_gettag
- // Returns the bTag field for current BulkOut transfer
- // @pbTag - pointer to the bTag to be filled, can not be NULL
- // Note: if there no transaction is, function returns bTag=0
- // Returns: returns @tmclib_status_success if @pbTag is not NULL,
- // otherwise returns @tmclib_status_failure
- eTMCLibStatus_t tmclib_bulkout_gettag( uint8_t * pbTag );
- // @tmclib_bulkin_gettag
- // Returns the bTag field for current BulkIn transfer
- // @pbTag - pointer to the bTag to be filled, can not be NULL
- // Note: if there no transaction is, function returns bTag=0
- // Returns: returns @tmclib_status_success if @pbTag is not NULL,
- // otherwise returns @tmclib_status_failure
- eTMCLibStatus_t tmclib_bulkin_gettag( uint8_t * pbTag );
- // @tmclib_bulkout_gettag_latest
- // Returns the bTag field for latest valid BulkOut transfer
- // @pbTag - pointer to the bTag to be filled, can not be NULL
- // Note: if there no transaction is, function returns bTag for the latest valid
- // BulkOut transfer, or bTag for current transaction otherwise.
- // Returns: returns @tmclib_status_success if @pbTag is not NULL,
- // otherwise returns @tmclib_status_invalid_param
- eTMCLibStatus_t tmclib_bulkout_gettag_latest( uint8_t * pbTag );
- // @tmclib_bulkin_gettag_latest
- // Returns the bTag field for latest valid BulkIn transfer
- // @pbTag - pointer to the bTag to be filled, can not be NULL
- // Note: if there no transaction is, function returns bTag for the latest valid
- // BulkIn transfer, or bTag for current transaction otherwise.
- // Returns: returns @tmclib_status_success if @pbTag is not NULL,
- // otherwise returns @tmclib_status_invalid_param
- eTMCLibStatus_t tmclib_bulkin_gettag_latest( uint8_t * pbTag );
- // @tmclib_bulkout_getcounter
- // Returns the bytes counter for current BulkOut transfer
- // @pnBytes - pointer to the uint32_t variable to be filled, can not be NULL
- // Note: if there no transaction is, function returns the counter for the last transfer
- // Returns: returns @tmclib_status_success if @pnBytes is not NULL,
- // otherwise returns @tmclib_status_failure
- eTMCLibStatus_t tmclib_bulkout_getcounter( uint32_t * pnBytes );
-
- // @tmclib_bulkin_getcounter
- // Returns the bytes counter for current BulkIn transfer
- // @pnBytes - pointer to the uint32_t variable to be filled, can not be NULL
- // Note: if there no transaction is, function returns the counter for the last transfer
- // Returns: returns @tmclib_status_success if @pnBytes is not NULL,
- // otherwise returns @tmclib_status_failure
- eTMCLibStatus_t tmclib_bulkin_getcounter( uint32_t * pnBytes );
-
- // @tmclib_generic_event()
- // Processes USBTMC specific event.
- // @eventCtx - event context, all the fields must be filled in accordance to @eventCtx->event code
- // @eventCtx->event - event identifier:
- //
- // +------------------------------------------------------------------------------------------------------------
- // * eTMCEventBulkInStop - Aborts currently running BulkIN transfer
- // |---> @eventCtx->abort:
- // | - @transfer_bTag - The bTag value associated with the transfer to abort, see 4.2.1.4 [1]
- // | - @force - makes to ignore the @transfer_bTag if true
- // +------------------------------------------------------------------------------------------------------------
- // * eTMCEventBulkOutStop - Aborts currently running BulkOUT transfer
- // |---> @eventCtx->abort:
- // | - @transfer_bTag - The bTag value associated with the transfer to abort, see 4.2.1.2 [1]
- // | - @force - makes to ignore the @transfer_bTag if true
- // +------------------------------------------------------------------------------------------------------------
- // * eTMCEventInterruptInStop - Aborts currently running InterruptIN transfer
- // |---> @eventCtx->abort:
- // | - @transfer_bTag - The bTag value associated with the transfer to abort, see 4.3.1 [2]
- // | - @force - makes to ignore the @transfer_bTag if true
- // +------------------------------------------------------------------------------------------------------------
- // * eTMCEventBulkIn - Processes USBTMC Bulk-IN event
- // |---> @eventCtx->bulkIn:
- // | - @tx - the buffer object to be used to transmit data
- // +------------------------------------------------------------------------------------------------------------
- // * eTMCEventBulkOut - Processes USBTMC Bulk-OUT event
- // |---> @eventCtx->bulkOut:
- // | - @rx - the buffer object to be used to receive data
- // +------------------------------------------------------------------------------------------------------------
- // * eTMCEventInterruptInStart - Initialize new Interrupt-IN transfer w/o data processing
- // | ...The function only creates new transfer without calling Tx-Handler. This call must be
- // | ...provided before 'eTMCEventInterruptIn' event to prapare transfer.
- // |----> @eventCtx->interruptIn:
- // | - @ntx - must be NULL, or 'tmclib_status_invalid_param' will be returned otherwise
- // | - @bTag - the Tag identifier, [2], 3.4.2 Interrupt-IN DATA sent due to READ_STATUS_BYTE request,
- // +------------------------------------------------------------------------------------------------------------
- // * eTMCEventInterruptIn - Processes USBTMC Interrupt-IN event.
- // | Note that 'eTMCEventInterruptInStart' must be generated before 'eTMCEventInterruptIn' for normal operation.
- // | Note: Each event generates a single INTERRUPT-IN packet begining with Interrupt-IN header
- // | Note: Each interrupt-in event must be not longer than @ntx transfer length.
- // | Note: In case it is required to send more data than @ntx can carry, you need:
- // | - increase Interrupt-IN EP buffer (see USB specification) and increase @ntx transfer space
- // | or:
- // | - send the data using multiple packets (each packet begins with INTERRUPT-IN header), pay
- // | attention that @ctx->interruptInState will not be reset until user layer return tmclib_status_success
- // | or tmclib_status_no_more_data.
- // |----> @eventCtx->interruptIn:
- // | - @ntx - the buffer object to be used to transmit data
- // | - @bTag - don't care
- // +------------------------------------------------------------------------------------------------------------
- //
- // Returns: the operation status:
- // tmclib_status_success in case of success,
- // tmclib_status_failure otherwise
- //
- eTMCLibStatus_t tmclib_generic_event( sTMCEventContext_t * eventCtx );
- #endif
|