// QDECODE.CPP $Date: 2021-09-03 16:58:38 -0800 (Fri, 03 Sep 2021) $ // Copyright (c) 2006, Microstar Laboratories, Inc. // https://www.mstarlabs.com/ // All rights reserved. // // License is granted to users of the "Develper's Toolkit for DAPL" // to use this code under the conditions of "redistributables" // as defined in the Developer's Toolkit for DAPL software license. // Under those terms, this code can be copied, modified, compiled, // and distributed with no fees. // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // QDECODE( pdigital, bits, vcounter ) // // Software-based quadrature signal pair decoder with 32-bit up-down // counting. This command will monitor the state of the specified pair // of digital inputs, and as logic transitions are identified, // appropriately modify a signed 32-bit accumulator upward or downward // so that other tasks can read the current angular position // represented by the encoder signals. // // Parameters: // // pdigital - pipe with high-rate samples of digital port // bits - location of encoder bits in digital port // vcounter - 32-bit accumulator for up-down counts // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // The processing logic is represented by a state machine. This // is also covered in the command description, but for completeness, // the following is the decoder state table. // // State 1 (Previously L-L) State 2 (Previously L-H) // L-L / State 1 ( +0 ) L-H / State 2 (+0) // L-H / State 2 ( +1 ) H-H / State 3 (+1) // H-L / State 4 ( -1 ) L-L / State 1 (-1) // // State 3 (Previously H-H) State 4 (Previously H-L) // H-H / State 3 ( +0 ) H-L / State 4 (+0) // H-L / State 4 ( +1 ) L-L / State 1 (+1) // L-H / State 2 ( -1 ) H-H / State 3 (-1) // // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "DTDMOD.H" #include "DTD.H" #define BUFFER_LENGTH 256 #define FOREVER 1 // - - - - - - - command interface section - - - - - - - - - - - - - extern "C" int __stdcall QDECODE_entry (PIB **plib); // Define the system callback function for identifying the command // prior to execution runtime. // extern "C" __declspec(dllexport) int __stdcall ModuleInstall(void *hModule) { return (CommandInstall(hModule, "QDECODE", QDECODE_entry, NULL)) ; } // - - - - - - - - - State representation - - - - - - - - - - - - - - // These are the bit patterns on the selected signal bits #define STATEMASK ( 0x0003 ) #define STATE1_BITS ( 0x00 ) #define STATE2_BITS ( 0x01 ) #define STATE3_BITS ( 0x03 ) #define STATE4_BITS ( 0x02 ) // Data type for identifying state transition operations. typedef struct st_trans STATE; typedef long int STATE_TRANSITION ( unsigned short, STATE * ); // The state is represented by a pointer to the state transition // processing function to apply. Other kinds of processing might have a // much more complex state. struct st_trans { STATE_TRANSITION * pTransition; }; // Identify the input bits that determine the next state inline unsigned short get_inbits( unsigned short inval, unsigned short inshift ) { inval >>= inshift; return (inval &= STATEMASK); } // - - - - - - - - - State update operations - - - - - - - - - - - // A state transition operation will examine the input bit pattern // and establish the next processing state. The return value is // the amount that the output counter must be adjusted. // static long int STATE0_TRANSITION ( unsigned short inbits, STATE * pState ); static long int STATE1_TRANSITION ( unsigned short inbits, STATE * pState ); static long int STATE2_TRANSITION ( unsigned short inbits, STATE * pState ); static long int STATE3_TRANSITION ( unsigned short inbits, STATE * pState ); static long int STATE4_TRANSITION ( unsigned short inbits, STATE * pState ); // The state initialization has the form of an "artificial transition" // that establishes the initial state based on current input, and always // returns zero. // static long int STATE0_TRANSITION ( unsigned short inbits, STATE * pState ) { switch ( inbits ) { case STATE1_BITS: pState->pTransition = &STATE1_TRANSITION; break; case STATE2_BITS: pState->pTransition = &STATE2_TRANSITION; break; case STATE3_BITS: pState->pTransition = &STATE3_TRANSITION; break; case STATE4_BITS: pState->pTransition = &STATE4_TRANSITION; break; } return 0L; } // The following functions implement the state transitions from the // state table. // static long int STATE1_TRANSITION ( unsigned short inbits, STATE * pState ) { long int count_update; switch ( inbits ) { case STATE1_BITS: case STATE3_BITS: count_update = 0L; break; case STATE2_BITS: pState->pTransition = &STATE2_TRANSITION; count_update = 1L; break; case STATE4_BITS: pState->pTransition = &STATE4_TRANSITION; count_update = -1L; break; } return count_update; } static long int STATE2_TRANSITION ( unsigned short inbits, STATE * pState ) { long int count_update; switch ( inbits ) { case STATE2_BITS: case STATE4_BITS: count_update = 0L; break; case STATE3_BITS: pState->pTransition = &STATE3_TRANSITION; count_update = 1L; break; case STATE1_BITS: pState->pTransition = &STATE1_TRANSITION; count_update = -1L; break; } return count_update; } static long int STATE3_TRANSITION ( unsigned short inbits, STATE * pState ) { long int count_update; switch ( inbits ) { case STATE1_BITS: case STATE3_BITS: count_update = 0L; break; case STATE4_BITS: pState->pTransition = &STATE4_TRANSITION; count_update = 1L; break; case STATE2_BITS: pState->pTransition = &STATE2_TRANSITION; count_update = -1L; break; } return count_update; } static long int STATE4_TRANSITION ( unsigned short inbits, STATE * pState ) { long int count_update; switch ( inbits ) { case STATE2_BITS: case STATE4_BITS: count_update = 0L; break; case STATE1_BITS: pState->pTransition = &STATE1_TRANSITION; count_update = 1L; break; case STATE3_BITS: pState->pTransition = &STATE3_TRANSITION; count_update = -1L; break; } return count_update; } // - - - - - command implementation section - - - - - - - - - - - - - // // Main Command Entry point // extern "C" int __stdcall QDECODE_entry (PIB **plib) { // Variables for accessing parameters void **argv; int argc; // Access to task parameters PIPE * pDigPipe; // digital bits access PBUF * pDigHandle; unsigned short * pBufStorage; short unsigned in_shift; // bit addressing long volatile * pOutVar; // accumulator // Run-time state STATE current_state; int iFetched, iNext; // Begin execution. Access task parameters argv = param_process( plib, &argc, 3, 3, T_PIPE_W, // stream of digital port bit patterns T_CONST_W, // address of bit pair T_VAR_L // output accumulator location ) ; // Connect to the input data stream pDigPipe = (PIPE *)(argv[1]); pipe_open(pDigPipe,P_READ); pDigHandle = pbuf_open(pDigPipe,BUFFER_LENGTH); pBufStorage = (unsigned short *)pbuf_get_data_ptr(pDigHandle); // Determine the digital signal bit address. Even number less than 16. in_shift = *(unsigned short *)(argv[2]); in_shift &= 0x000E; // Connect to the shared variable. Consume one input value to // establish the initial state. pOutVar = (long volatile *)(argv[3]); *pOutVar = STATE0_TRANSITION ( get_inbits((unsigned short) pipe_get(pDigPipe), in_shift), ¤t_state ); // Begin continuous processing while (FOREVER) { // Fetch any available buffered data from digital port iFetched = pbuf_get(pDigHandle); // Process each received sample for (iNext=0; iNext