Jump to content

Nathan Kumar

Members
  • Posts

    1
  • Joined

  • Last visited

Posts posted by Nathan Kumar

  1. Hi,

    I am using PCI-QUAD04 encoder board and I am able to read the value of the encoder using the windows library provided with the board.

    But when I try to read the encoder data using a real time OS called INtime, I running into problems. Under INtime when I try to get the base address of this PCI-QUAD04 board, I get 2 different base addresses:

    1) When windows driver is installed and running, I get one set of address( Mcc Quad04 base1 = 56961, base2 = 57137 with Mcc driver active)

    2) When windows driver is completely uninstalled, I get these address: base1 = = 53249, base2 = 53569

     

    I am not able read the encoder data under INtime. 

     

    Can you please help? I have attached both Windows side code and INtime side code for your perusal.

     

    Nathan

    The is the code on Windows side:

    ////////Windows example code that works correctly/////////////////////////////////

    /* Include files */
    #include "..\cbw.h"
    #include "Utilities.h"
    #include <time.h>

    int Delta( const SYSTEMTIME st1, const SYSTEMTIME st2 ) {
        union timeunion {
            FILETIME fileTime;
            ULARGE_INTEGER ul;
        };

        timeunion ft1;
        timeunion ft2;

        SystemTimeToFileTime( &st1, &ft1.fileTime );
        SystemTimeToFileTime( &st2, &ft2.fileTime );

        return max(1, (ft2.ul.QuadPart - ft1.ul.QuadPart) );
    }
    DWORD GetTimeDifference( SYSTEMTIME &st1, SYSTEMTIME &st2 )
    {
        FILETIME        ft1, ft2;
        LARGE_INTEGER   li1, li2, liDiff;
        DWORD dwDiff;

        SystemTimeToFileTime( &st1, &ft1 );
        SystemTimeToFileTime( &st2, &ft2 );

        li1.LowPart = ft1.dwLowDateTime;
        li1.HighPart = ft1.dwHighDateTime;
        li2.LowPart = ft2.dwLowDateTime;
        li2.HighPart = ft2.dwHighDateTime;

        //if ( CompareFileTime( &ft1, &ft2 ) < 0 ) 
        {
            liDiff.LowPart = li2.LowPart - li1.LowPart;
            liDiff.HighPart = li2.HighPart - li1.HighPart;
        }
        //else {
        //    liDiff.LowPart = li1.LowPart - li2.LowPart;
        //    liDiff.HighPart = li1.HighPart - li2.HighPart;
        //}

        dwDiff = ( (__int64)liDiff.HighPart << 32 ) + liDiff.LowPart;
        dwDiff /= ( (__int64)10 * 1000 * 1000 ); // Convert from n x 100ns intervals into seconds

        return max(1, dwDiff);
    }
    int main( void )
    {
        /* Variable Declarations */
        int        Row, Col;
        int        ULStat = NOERRORS;
        int        BoardNum = 0;
        int        CounterNum, Quadrature, CountingMode, DataEncoding, IndexMode;
        int        numCounters, defaultCtr;
        int        InvertIndex, FlagPins, GateEnable;
        long    LoadValue;
        ULONG   Count[4], StatusBits[4];
        ULONG    BackwardBadCount[4], PreviousCount[4];
        ULONG   DiffCount[4], PrevForwardCount[4], ForwardCount[4];
        int        RegName;
        float    RevLevel = (float)CURRENTREVNUM;
        const char*    DirectionStr;
        int        ctrType = CTR7266;
        char    BoardName[BOARDNAMELEN];
        int        dummy;
        int        MoreThan2inches = 0;
        bool    bBadEncoderData = false;

        double inchesTravelled = 0.0;
        double inchesTravelledInMinute = 0.0;
        double booksPerMinute = 10.0;

        /* Declare UL Revision Level */
        ULStat = cbDeclareRevision( &RevLevel );

        InitUL();    // Set up error handling

        // get the name of the board
        if ( !GetNameOfBoard( BoardNum, BoardName ) ) {
            DisplayMessage( NOERRORS );
            return 0;
        }

        ClearScreen();
        printf( "Demonstration of 7266 Counter Functions using %s\n\n", BoardName );

        // Determine if device is compatible with this example
        numCounters = FindCountersOfType( BoardNum, ctrType, &defaultCtr );
        if ( numCounters == 0 ) {
            printf( "%s (board %u) does not have 7266 counters.\n", BoardName, BoardNum );
            DisplayMessage( NOERRORS );
            return 0;
        }

        printf( "Press any key to stop reading counter.\n\n" );

        /* set the configurable operations of the counter
            Parameters:
                BoardNum       :the number used by CB.CFG to describe this board
                CounterNum     :the counter to be configured (0-5)
                Quadrature     :Select type of counter input
                CountingMode   :Slects how counter will operate
                IndexMode      :Selects what index signal will control
                InvertIndex    :Set to ENABLED id index signal is inverted
                FlagPins       :Select which signals will drive Flag pins
                GateEnable     :Set to ENABLED to use external gating signal
        */
        double pinSpacing = 14.0;//inches

        for(int ctrIdx = 0; ctrIdx < numCounters; ++ctrIdx )
        {
        CounterNum = defaultCtr + ctrIdx;
        Quadrature = X1_QUAD;//DONE
        CountingMode = NORMAL_MODE;//DONE
        DataEncoding = BINARY_ENCODING;//DONE
        IndexMode = LOAD_CTR;//INDEX_DISABLED;
        InvertIndex = DISABLED;
        FlagPins = CARRY_BORROW;//DONE
        GateEnable = DISABLED;//DONE
        /*
        int EXTCCONV cbC7266Config (int BoardNum, int CounterNum, int Quadrature,
                                    int CountingMode, int DataEncoding, int IndexMode,
                                    int InvertIndex, int FlagPins, int GateEnable);
        */
        ULStat = cbC7266Config( BoardNum, CounterNum, Quadrature, CountingMode,
            DataEncoding, IndexMode, InvertIndex, FlagPins, GateEnable );

        /* send a starting value to the counter with cbCLoad()
            Parameters:
                BoardNum    :the number used by CB.CFG to describe this board
                RegName     :the counter to be loading with the starting value
                LoadValue   :the starting value to place in the counter
        */

        LoadValue = 0x000000;//FFFFFF;
        RegName = COUNT1 + CounterNum - 1;
        printf( "Loading counter #%u with an initial count of %u using cbCLoad()\n", CounterNum, LoadValue );
        ULStat = cbCLoad32( BoardNum, RegName, LoadValue );

        LoadValue = 0xFFFFFF;
        RegName = PRESET1 + CounterNum - 1;
        printf( "Setting counter #%u maximum count to %u by loading PRESET register", CounterNum, LoadValue );
        ULStat = cbCLoad32( BoardNum, RegName, LoadValue );

        ForwardCount[ctrIdx] = 0l;
        PrevForwardCount[ctrIdx] = 0l;
        DiffCount[ctrIdx] = 0l;
        PreviousCount[ctrIdx] = 0l;
        BackwardBadCount[ctrIdx] = 0l;
        }
        /* use a loop to keep checking the counter value with cbCIn() */
        SYSTEMTIME dateTime1;
        ::GetLocalTime( &dateTime1 );
        
        GetTextCursor( &Col, &Row );
        time_t startTime;
        double seconds;

        time( &startTime );
        while ( !_kbhit() ) {
            for ( int ctrIdx = 0; ctrIdx < 1;/*numCounters*/ ++ctrIdx )
            {
                CounterNum = defaultCtr + ctrIdx;
            /* Parameters:
                BoardNum    :the number used by CB.CFG to describe this board
                CounterNum  :the counter to be setup
                Count       :the count value in the counter
            */
            ULStat = cbCIn32( BoardNum, CounterNum, &Count[ctrIdx] );

            /* Parameters:
                BoardNum    :the number used by CB.CFG to describe this board
                CounterNum  :the counter to be setup
                StatusBits  :counter's status returned here
            */
            ULStat = cbCStatus( BoardNum, CounterNum, &StatusBits[ctrIdx] );
            bool bDiretionUp = !( StatusBits[ctrIdx] & C_UP_DOWN );
            if ( StatusBits[ctrIdx] & C_UP_DOWN )
                DirectionStr = "UP  ";
            else
                DirectionStr = "DOWN";
            SYSTEMTIME dateTime2;
            ::GetLocalTime( &dateTime2 );
            int pulsesPerInch = 399;
            ForwardCount[ctrIdx] = 0x00FFFFFF - ( Count[ctrIdx] & 0x00FFFFFF );
            if(PrevForwardCount[ctrIdx] != 0L && ForwardCount[ctrIdx] != PrevForwardCount[ctrIdx] && bDiretionUp )
            {
                if( ForwardCount[ctrIdx] >= PrevForwardCount[ctrIdx] )
                {
                    DiffCount[ctrIdx] = (unsigned short)( ForwardCount[ctrIdx] - PrevForwardCount[ctrIdx] );
                }
                else 
                {
                    ULONG DiffCount1 = (unsigned short)(0x00FFFFFF - PrevForwardCount[ctrIdx]) + (unsigned short)ForwardCount[ctrIdx];
                    if( DiffCount1 < pulsesPerInch )
                    {
                        DiffCount[ctrIdx] = DiffCount1;
                        ++BackwardBadCount[ctrIdx];
                    }
                }
            }

            double inches = DiffCount[ctrIdx] / double( pulsesPerInch );
            inchesTravelled += inches;
            inchesTravelledInMinute += inches;
            time_t currentTime;
            time( &currentTime );
            int numberOfSeconds = difftime( currentTime, startTime );
            
            booksPerMinute = inchesTravelledInMinute / pinSpacing / numberOfSeconds * 60;
            MoveCursor( Col, Row + 2 + ctrIdx );
            printf( "\nCounter %1u is %10d, Diff is %3u, inches = %4.3f <RCOUNT %6d>%s BPMinute = %3.0f Inches Travelled  = %6.2f in %d seconds\n\n", 
                CounterNum, ForwardCount[ctrIdx], DiffCount[ctrIdx], inches, BackwardBadCount[ctrIdx], bBadEncoderData ? "<BAD>":"<GOOD>", 
                booksPerMinute, inchesTravelledInMinute, numberOfSeconds );

            if ( inches > 2.0 )
            {
                bBadEncoderData = true;
                ++MoreThan2inches;
            }
            if( numberOfSeconds > 30 && booksPerMinute > 350.0)
            {
                bBadEncoderData = true;
            }
            // /* Parameters:
            //     BoardNum    :the number used by CB.CFG to describe this board
            //     CounterNum  :the counter to be setup
            //     Count       :the count value in the counter
            // */
            // ULStat = cbCIn32( BoardNum, CounterNum, &Count );
            // 
            // /* Parameters:
            //     BoardNum    :the number used by CB.CFG to describe this board
            //     CounterNum  :the counter to be setup
            //     StatusBits  :counter's status returned here
            // */
            // ULStat = cbCStatus( BoardNum, CounterNum, &StatusBits );
            // if ( StatusBits & C_UP_DOWN )
            //     DirectionStr = "UP  ";
            // else
            //     DirectionStr = "DOWN";
            // 
            // MoveCursor( Col, Row + 1 + ctrIdx );
            // printf( "\nThe value of Counter %u is %u     \n", CounterNum, Count );
            // //printf( "The counter is now counting %s", DirectionStr );

            
            PrevForwardCount[ctrIdx] = ForwardCount[ctrIdx];
            PreviousCount[ctrIdx] = Count[ctrIdx];
            }
        }
        dummy = _getch();
        printf( "\n" );
        DisplayMessage( NOERRORS );
        return 0;
    }

    /////////////////////////////////////////

     

    ////This is the code on INtime side///////////////////

    //base address retrieval code

    //    process MCC-QUAD04 encoder d board
    //    ------------------------------------------

                                            // check for PCI9200 vendor and device ID
                                            // if not, go process pci8010 boards
                    if (  ( PciData->VendorID == PCI_VENDOR_ID_CBOARDS )
                       && ( PciData->DeviceID == PCI_DEVICE_ID_CBOARDS_QUAD04 ) )
                    {

                                            // check for previous board found
                                            // if so, initialize to first board
                        if ( dNumPciMccQuad04Found == 0 )
                            dNumPciMccQuad04Found = PCI_MCCQUAD04_1_NUM;

                                            // else, advance to next board
                        else
                            dNumPciMccQuad04Found++;

                                            // install PCI application data
                        gapciapp[dNumPciMccQuad04Found].lEnable = TRUE;
                        gapciapp[dNumPciMccQuad04Found].dBaseAdr0 = PciData->u.type0.BaseAddresses[1];// & 0xFFFFFFFE;
                        gapciapp[dNumPciMccQuad04Found].dBaseAdr1 = PciData->u.type0.BaseAddresses[2];// & 0xFFFFFFFE;//NULL;

                        BoardData[0].base1 = gapciapp[dNumPciMccQuad04Found].dBaseAdr0;
                        BoardData[0].base2 = gapciapp[dNumPciMccQuad04Found].dBaseAdr1;
                        BoardData[0].irq = PciData->u.type0.InterruptLine;
                        quad04_init_one( 0 );
                        unsigned int encoderData = 0;
                        {
                            byte counter_data[3];
                            int ret = quad04_read( 0, 0, counter_data, 3 );
                            encoderData = counter_data[2] << 16 | counter_data[1] << 8 | counter_data[0];
                            encoderData = 0x00FFFFFF - ( encoderData & 0x00FFFFFF );
                        }
    /////////////////////////////////////////////////////////////////////////////////////////////

    void quad04_init_one( int NumBoards )
    {
        int i;
        //int minor;
        dword base1;
        dword base2;
        byte data[3];
        unsigned int pci9052_intreg;
        unsigned long counterValue = 0;
        if ( NumBoards >= MAX_BOARDS )
        {
            //printk( "quad04_init_one: NumBoards = %d. Can't exceed MAX_BOARDS.  edit quad04.h.\n", NumBoards );
            return;// -ENODEV;
        }

        /*GETTING BASE ADDRESS 1 */
        base1 = BoardData[NumBoards].base1;

        /*GETTING BASE ADDRESS 2 */
        base2 = BoardData[NumBoards].base2;

        ///* Turn off interrupts */
        pci9052_intreg = _inpd( INTCSR_REG );
        pci9052_intreg &= ~( INTE | PCINT );
        _outpd( INTCSR_REG, pci9052_intreg );
        pci9052_intreg = _inpd( INTCSR_REG );

        _outpd( INTCSR_REG, pci9052_intreg | INTCLR );

        /* Initialize the LS7266R1 chip */
        BoardData[NumBoards].mode = CONFIG_0;  // (4) 24-bit counters (1/2/3/4) (default)
        BoardData[NumBoards].pic_A = 0x0;
        BoardData[NumBoards].pic_B = 0x0;
        _outp( PIC_A_REG, BoardData[NumBoards].pic_A );
        _outp( PIC_B_REG, BoardData[NumBoards].pic_B );

        BoardData[NumBoards].iscr = CONFIG_0; // default to 4 24 bit counters
        _outp( ISCR_REG, BoardData[NumBoards].iscr );
        BoardData[NumBoards].ircr = 0x0F;      // IDxSEL for all counters
        _outp( IRCR_REG, BoardData[NumBoards].ircr );

        for ( i = 0; i < NCOUNTERS; i++ )
        {
            Counter[NumBoards][i].open = TRUE;
            Counter[NumBoards][i].data_port = DATA1_REG + 2 * i;
            Counter[NumBoards][i].cmd_port = CMD1_REG + 2 * i;
            Counter[NumBoards][i].counter = i;

             //   /* Reset/Load Register */
             _outp( Counter[NumBoards][i].cmd_port, RESET_CNTR );
             _outp( Counter[NumBoards][i].cmd_port, RESET_FLAGS );
             _outp( Counter[NumBoards][i].cmd_port, RESET_E );
             _outp( Counter[NumBoards][i].cmd_port, RESET_BP );
             //   
             //   /* Be sure the prescaler is setup */
             _outp( Counter[NumBoards][i].data_port, 1 );
             _outp( Counter[NumBoards][i].cmd_port, TRAN_PR_PSC );
             _outp( Counter[NumBoards][i].cmd_port, RESET_BP );
             //   
             /* Set Counter Mode to Normal, Binary, QuadX1 */
             Counter[NumBoards][i].cmr = ( CMR1 | BIN | X1 | NORMAL );
             _outp( Counter[NumBoards][i].cmd_port, Counter[NumBoards][i].cmr );
             
             /* Enable Counter Inputs */
             Counter[NumBoards][i].ior = ( IOR1 | ENABLE_AB | LOL | RCNTR );//| FLG_CB );
             _outp( Counter[NumBoards][i].cmd_port, Counter[NumBoards][i].ior );
             
             /* Disable Index */
             Counter[NumBoards][i].idr = ( IDR1 | DISABLE_INDEX | LCNTRL_INDEX );//LOAD_CTR );//| 
             _outp( Counter[NumBoards][i].cmd_port, Counter[NumBoards][i].idr );
             //   
             ///* Load Counter Preset */
             _outp( Counter[NumBoards][i].cmd_port, RESET_BP );
             _outp( Counter[NumBoards][i].data_port, 0xFF );
             _outp( Counter[NumBoards][i].data_port, 0xFF );
             _outp( Counter[NumBoards][i].data_port, 0xFF );
            
            /* Transfer the loaded value to the counter */
            _outp( Counter[NumBoards][i].cmd_port, TRAN_PR_CNTR );
            
             /* Transfer counter to latch */
            _outp( Counter[NumBoards][i].cmd_port, ( TRAN_CNTR_OL | RESET_BP ) );
            //Init_7266( Counter[NumBoards][i].data_port );
            //Write_7266_PR( Counter[NumBoards][i].data_port, 0x00FFFFFF );
            //counterValue = Read_7266_OL( Counter[NumBoards][i].data_port );

            /* Now read back the data from the output latch */
            data[0] = _inp( Counter[NumBoards][i].data_port );
            data[1] = _inp( Counter[NumBoards][i].data_port );
            data[2] = _inp( Counter[NumBoards][i].data_port );
            
            ////* Clear the preset */
            _outp( Counter[NumBoards][i].cmd_port, RESET_BP );
            _outp( Counter[NumBoards][i].data_port, 0x0 );
            _outp( Counter[NumBoards][i].data_port, 0x0 );
            _outp( Counter[NumBoards][i].data_port, 0x0 );

            /* Reset all fags */
            _outp( Counter[NumBoards][i].cmd_port, RESET_CNTR );
            _outp( Counter[NumBoards][i].cmd_port, RESET_FLAGS );
            _outp( Counter[NumBoards][i].cmd_port, RESET_E );
            _outp( Counter[NumBoards][i].cmd_port, RESET_BP );
        }

        NumBoards++;
        return;

    }
    ////////////////////////////////////////////////////////////////////////////////

    size_t quad04_read( int board, int chan, unsigned char *buf, size_t count )
    {
        int i;
        dword base1;
        dword base2;
        byte data[12];    // counter could be 24 bit to 96 bits depending upon mode

        base1 = BoardData[board].base1;
        base2 = BoardData[board].base2;

        switch ( BoardData[board].mode ) 
        {

        case CONFIG_0:   // (4) 24-Bit counters  1/2/3/4
        {
            _outp( Counter[board][chan].cmd_port, ( TRAN_CNTR_OL | RESET_BP ) );  // transfer counter to output latch
            for ( i = 0; i < 3; i++ ) 
            {
                data[i] = _inp( Counter[board][chan].data_port );
                buf[i] = data[i];
            }
            return 3;
        }
        break;

        case CONFIG_1:  // (2) 48-Bit counters  1-2/3-4
        {
            if ( chan == 0 || chan == 1 ) 
            {
                _outp( CMD1_REG, ( TRAN_CNTR_OL | RESET_BP ) );
                for ( i = 0; i < 3; i++ ) 
                {
                    data[i] = _inp( DATA1_REG );
                    buf[i] = data[i];
                }
                _outp( CMD2_REG, ( TRAN_CNTR_OL | RESET_BP )  );
                for ( i = 3; i < 6; i++ ) 
                {
                    data[i] = _inp( DATA2_REG );
                    buf[i] = data[i];
                }
            }
            else 
            {
                _outp( CMD3_REG, ( TRAN_CNTR_OL | RESET_BP ) );
                for ( i = 0; i < 3; i++ ) 
                {
                    data[i] = _inp( DATA3_REG );
                    buf[i] = data[i];
                }
                _outp( CMD4_REG, ( TRAN_CNTR_OL | RESET_BP ) );
                for ( i = 3; i < 6; i++ ) 
                {
                    data[i] = _inp( DATA4_REG );
                    buf[i] = data[i];
                }
            }
            return 6;
        }
        break;

        case CONFIG_2: // (1) 24-bit counter,  (1) 72-bit counter  1/2-3-4
        {
            if ( chan == 0 ) 
            {
                _outp( CMD1_REG, ( TRAN_CNTR_OL | RESET_BP ) );
                for ( i = 0; i < 3; i++ ) 
                {
                    data[i] = _inp( DATA1_REG );
                    buf[i] = data[i];
                }
                return 3;
            }
            else {
                _outp( CMD2_REG, ( TRAN_CNTR_OL | RESET_BP ) );
                for ( i = 0; i < 3; i++ ) 
                {
                    data[i] = _inp( DATA2_REG );
                    buf[i] = data[i];
                }
                _outp( CMD3_REG, RESET_BP );
                for ( i = 3; i < 6; i++ ) 
                {
                    data[i] = _inp( DATA3_REG );
                    buf[i] = data[i];
                }
                _outp( CMD4_REG, RESET_BP );
                for ( i = 6; i < 8; i++ ) 
                {
                    data[i] = _inp( DATA4_REG );
                    buf[i] = data[i];
                }
                return 9;
            }
        }
        break;

        case CONFIG_3: // (1) 96-bit counter   1-2-3-4
            _outp( CMD1_REG, ( TRAN_CNTR_OL | RESET_BP ) );
            for ( i = 0; i < 3; i++ ) 
            {
                data[i] = _inp( DATA1_REG );
                buf[i] = data[i];
            }
            _outp( CMD2_REG, ( TRAN_CNTR_OL | RESET_BP ) );
            for ( i = 3; i < 6; i++ ) 
            {
                data[i] = _inp( DATA2_REG );
                buf[i] = data[i];
            }
            _outp( CMD3_REG, ( TRAN_CNTR_OL | RESET_BP ) );
            for ( i = 6; i < 9; i++ ) 
            {
                data[i] = _inp( DATA3_REG );
                buf[i] = data[i];
            }
            _outp( CMD4_REG, ( TRAN_CNTR_OL | RESET_BP ) );
            for ( i = 9; i < 12; i++ ) 
            {
                data[i] = _inp( DATA4_REG );
                buf[i] = data[i];
            }
            return 12;
            break;
        }
        return 0;
    }
     

    ////////////////////////////////////////////

×
×
  • Create New...