CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

16F887 Race Track Code Looping at finish

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
donaldduck



Joined: 01 Jun 2010
Posts: 3

View user's profile Send private message

16F887 Race Track Code Looping at finish
PostPosted: Tue Jun 01, 2010 1:50 pm     Reply with quote

I've got this 4 lane race track timer code that i'm trying to modify to work with a 16F887 (originally for 16F648a).
Source: http://www.vermontficks.org/agpv030709c.htm

It will work with a 4 line eventually but i'm just testing it with a 2 line display for the moment.There are initially options for nulling lanes (that aren't to be used) then it goes on to measure the time of each lane, but it just seems to loop around the race start and end without actually showing any timings or which lane (R, Y, G, B etc) came first??

I'm testing this on an EasyPic6 board btw

Any help appreciatedThanks in advance!

Code:
// RACE START CHECKS.  These are defined at compile time.
// 0 = no checks,    1 = finish line check only,    2 = start gate and finish line check
#define START_CHECKS     2

/***************************************************************************


**************************************************************************/

#include <16F887.h>


#use delay ( clock = 8000000 )

#use rs232 ( baud = 9600, xmit = PIN_B6, rcv = PIN_B7 )

#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
#use standard_io ( D )


#byte PORT_A = 8
#byte PORT_B = 8
#byte PORT_C = 8
#byte PORT_D = 8
#define LCD_D7      PIN_B3
#define LCD_D6      PIN_B2
#define LCD_D5      PIN_B1
#define LCD_D4      PIN_B0
#define LCD_EN      PIN_B5
#define LCD_RS      PIN_B4
#define TRK_R_INPUT PIN_D0
#define TRK_B_INPUT PIN_D1
#define TRK_G_INPUT PIN_D2
#define TRK_Y_INPUT PIN_D3
#define SERVO_OUT   PIN_C0
#define PB_SWITCH   PIN_C1
#define SW1         PIN_C2
#define SW2         PIN_C3
#define SW3         PIN_C4
#define SW4         PIN_C5
#define SW5         PIN_C6
#define LINE_1      0x00
#define LINE_2      0x40
#define LINE_3      0x10
#define LINE_4      0x50
#define CLEAR_DISP  0x01
#define TRACK_R     0b00000001
#define TRACK_B     0b00000010
#define TRACK_G     0b00000100
#define TRACK_Y     0b00001000
#define TEXT_DELAY  2000
#define CMD_NUL     0
#define GATE_OPEN   0
#define GATE_CLOSE  1
#define ERR_NONE    0
#define ERR_GATE    1
#define ERR_FINISH  2
#define HIGH        0
#define LOW         1
#define ON          1
#define OFF         0


#separate void SendTime ( char cLane, long iTime );
#separate char CheckFinishLine ( void );
#separate char CheckStartGate ( void );
#separate char GetSerial ( char cChar );
#separate void Servo ( char cX );
#separate void SendAllTimes ( void );
#separate void DisplayTie ( char cLoc );
#separate void Display ( char cTie, char cPlace, char cTrackColor, long iTime, char * cDisplayFlag );
#separate void StartTimer ( void );
#separate void LCD_Init ( void );
#separate void LCD_SetPosition ( unsigned int cX );
#separate void LCD_PutChar ( unsigned int cX );
#separate void LCD_PutCmd ( unsigned int cX );
#separate void LCD_PulseEnable ( void );
#separate void LCD_SetData ( unsigned int cX );

static long iTime, iRTime, iBTime, iGTime, iYTime;
static char cDisplayLine, cPlaceNum, cDisplayCnt;
static char cRTie, cBTie, cGTie, cYTie, cStarted;
static char cRPlace, cBPlace, cGPlace, cYPlace;
static char cRDisplayFlag, cBDisplayFlag, cGDisplayFlag, cYDisplayFlag;
static char cDisplayLocTable [ 4 ] = { 0x06, 0x46, 0x16, 0x56 };
static char cSerialCmd, cLaneMask, cMaskDisplayLine;

#int_rda
void SerialInterrupt ( void )
    {
    // Reads incoming data from the USART
    cSerialCmd = getchar();       // get char from UART
    // command recipient resets cSerialCmd to CMD_NUL
    }
#int_rtcc
void TimerInterrupt ( void )
    {
    /*
    Gets here every 1mS.  Samples the track inputs, saves the
    current time for any tracks that have finished during this
    interrupt pass.  Increments the time count if not overflowed
    past 9999mS.
    */

    char cFinish;

    set_rtcc ( 73 );            // restart timer, adjusted to 1mS
    // GRAB ONE SAMPLE OF ALL FOUR TRACKS FOR THIS 1MS TIME SLICE
    cFinish = ( PORT_A ^ 0xff ) & 0x0f;   // invert Port A and null on lower four bits
    cFinish &= cLaneMask;       // mask any unused lanes
    // EXAMINE THIS 1mS SAMPLE, ONE TRACK AT A TIME, PROCESS ANY CAR(S) THAT FINSIHED
    if ( ( ( cFinish & TRACK_R ) == TRACK_R ) && ( cRPlace == 0 ) )    // Track R finished
        {
        iRTime = iTime;         // save the present time
        if ( ( iRTime == iBTime ) || ( iRTime == iGTime ) || ( iRTime == iYTime ) )
            {
            cRTie = "YES";        // if this matches any other track, indicate TIE
            }
        cRDisplayFlag = "YES";      // time to display this track
        cRPlace = cPlaceNum++;    // take the place number, increment place number
        }
    if ( ( ( cFinish & TRACK_B ) == TRACK_B ) && ( cBPlace == 0 ) )    // Track B finished
        {
        iBTime = iTime;         // save the present time
        if ( ( iBTime == iRTime ) || ( iBTime == iGTime ) || ( iBTime == iYTime ) )
            {
            cBTie = "YES";        // if this matches any other track, indicate TIE
            }
        cBDisplayFlag = "YES";        // time to display this track
        cBPlace = cPlaceNum++;    // take the place number, increment place number
        }
    if ( ( ( cFinish & TRACK_G ) == TRACK_G ) && ( cGPlace == 0 ) )    // Track G finished
        {
        iGTime = iTime;         // save the present time
        if ( ( iGTime == iRTime ) || ( iGTime == iBTime ) || ( iGTime == iYTime ) )
            {
            cGTie = "YES";        // if this matches any other track, indicate TIE
            }
        cGDisplayFlag = "YES";        // time to display this track
        cGPlace = cPlaceNum++;    // take the place number, increment place number
        }
    if ( ( ( cFinish & TRACK_Y ) == TRACK_Y ) && ( cYPlace == 0 ) )    // Track Y finished
        {
        iYTime = iTime;         // save the present time
        if ( ( iYTime == iRTime ) || ( iYTime == iBTime ) || ( iYTime == iGTime ) )
            {
            cYTie = "YES";        // if this matches any other track, indicate TIE
            }
        cYDisplayFlag = "YES";        // time to display this track
        cYPlace = cPlaceNum++;    // take the place number, increment place number
        }
    if ( iTime < 9999)      // if not overflow, increment the clock
        {
        iTime++;
        }
    else                // make unfinished races = 9.999 seconds
        {
        if ( cRPlace == 0 )
            {
            iRTime = 9999;
            cRPlace = cPlaceNum++;      // save the available place number
            cRDisplayFlag = "YES";        // time to display this track
            }
        if ( cBPlace == 0 )
            {
            iBTime = 9999;
            cBPlace = cPlaceNum++;      // save the available place number
            cBDisplayFlag = "YES";        // time to display this track
            }
        if ( cGPlace == 0 )
            {
            iGTime = 9999;
            cGPlace = cPlaceNum++;      // save the available place number
            cGDisplayFlag = "YES";        // time to display this track
            }
        if ( cYPlace == 0 )
            {
            iYTime = 9999;
            cYPlace = cPlaceNum++;      // save the available place number
            cYDisplayFlag = "YES";        // time to display this track
            }
        }
    }

void main ( void )
    {
    char cX, cWaitForNextMaskChar;

    delay_ms ( 200 );
    port_b_pullups ( HIGH );  /////////////////// WAS PORT B PULLUPS "ON"
    output_float ( TRK_R_INPUT );
    output_float ( TRK_B_INPUT );
    output_float ( TRK_G_INPUT );
    output_float ( TRK_Y_INPUT );
    output_float ( SERVO_OUT );
   
   
   
    setup_counters ( RTCC_INTERNAL, RTCC_DIV_8 );   // 256 * 4uS = 1.024mS timer wrap
   
    LCD_Init();             // set up LCD for 4-wire bus, etc.
    cLaneMask = 0b11111111;     // default to all lanes working
    cWaitForNextMaskChar = "NO";

    if ( input ( PB_SWITCH ) == LOW )       // diag mode if switch is down upon power up
        {
        LCD_PutCmd ( CLEAR_DISP );
        LCD_SetPosition ( LINE_4 + 0 );
        printf ( LCD_PutChar, "Diagnostics!" );        // welcome screen
        LCD_SetPosition ( LINE_1 + 0 );
        printf ( LCD_PutChar, "Gates:" );
        LCD_SetPosition ( LINE_2 + 0 );
        printf ( LCD_PutChar, "Lanes:" );
        while ( input ( PB_SWITCH ) == LOW )
            {
            LCD_SetPosition ( LINE_1 + 8 );
            if ( input ( SW1 ) == HIGH )
                {
                printf ( LCD_PutChar, "DOWN" );
                }
            else
                {
                printf ( LCD_PutChar, "UP  " );
                }
            LCD_SetPosition ( LINE_2 + 12 );
            if ( ( ( PORT_A ^ 0xff ) & TRACK_R ) != 0 )
                {
                printf ( LCD_PutChar, "R" );
                }
            else
                {
                printf ( LCD_PutChar, " " );
                }
            LCD_SetPosition ( LINE_2 + 13 );
            if ( ( ( PORT_A ^ 0xff2 ) & TRACK_B ) != 0 )
                {
                printf ( LCD_PutChar, "B" );
                }
            else
                {
                printf ( LCD_PutChar, " " );
                }
            LCD_SetPosition ( LINE_2 + 14 );
            if ( ( ( PORT_A ^ 0xff ) & TRACK_G ) != 0 )
                {
                printf ( LCD_PutChar, "G" );
                }
            else
                {
                printf ( LCD_PutChar, " " );
                }
            LCD_SetPosition ( LINE_2 + 15 );
            if ( ( ( PORT_A ^ 0xff ) & TRACK_Y ) != 0 )
                {
                printf ( LCD_PutChar, "Y" );
                }
            else
                {
                printf ( LCD_PutChar, " " );
                }
            delay_ms ( 10 );
            }
        }

    LCD_PutCmd ( CLEAR_DISP );
    LCD_SetPosition ( LINE_1 + 0 );
    printf ( LCD_PutChar, "ABCDEFGHIJKLMNOP" );        // welcome screen
    LCD_SetPosition ( LINE_2 + 0 );
    printf ( LCD_PutChar, "1234567890123456" );
    LCD_SetPosition ( LINE_1 + 0 );
    printf ( LCD_PutChar, "1234567890123456" );
    LCD_SetPosition ( LINE_2 + 0 );
    printf ( LCD_PutChar, "ABCDEFGHIJKLMNOP" );
    delay_ms (TEXT_DELAY );

    LCD_PutCmd ( CLEAR_DISP );
    LCD_SetPosition ( LINE_1 + 0 );
    printf ( LCD_PutChar, "Press and hold" );
    LCD_SetPosition ( LINE_2 + 0 );
    printf ( LCD_PutChar, "FOR LANE NULLING" );
    delay_ms ( TEXT_DELAY );

    if ( input ( SW1 ) == LOW )           // lane masking if pushbutton is pressed after welcome screen
        {
        LCD_PutCmd ( CLEAR_DISP );
        LCD_SetPosition ( LINE_1 + 0 );
        printf ( LCD_PutChar, "Release button" );
        while ( input ( SW1 ) == LOW );       // wait until released
        LCD_PutCmd ( CLEAR_DISP );
        LCD_SetPosition ( LINE_1 + 0 );
        printf ( LCD_PutChar, "Press & hold" );
        LCD_SetPosition ( LINE_2 + 0 );
        printf ( LCD_PutChar, "2 Null Red" );
        delay_ms ( TEXT_DELAY );
        if ( input ( SW1 ) == LOW )
            {
            LCD_PutCmd ( CLEAR_DISP );
            LCD_SetPosition ( LINE_1 + 0 );
            printf ( LCD_PutChar, "RED NULLED" );
            LCD_SetPosition ( LINE_2 + 0 );
            printf ( LCD_PutChar, "Release button" );
            cLaneMask &= 0b11111110;
            cRPlace = 'M';   // masked lane
            }
        while ( input ( SW1 ) == LOW );       // wait until released
        LCD_PutCmd ( CLEAR_DISP );
        LCD_SetPosition ( LINE_1 + 0 );
        printf ( LCD_PutChar, "Press & hold" );
        LCD_SetPosition ( LINE_2 + 0 );
        printf ( LCD_PutChar, "2 Null BLUE" );
        delay_ms ( TEXT_DELAY );
        if ( input ( SW1 ) == LOW )
            {
            LCD_PutCmd ( CLEAR_DISP );
            LCD_SetPosition ( LINE_1 + 0 );
            printf ( LCD_PutChar, "BLUE NULLED" );
            LCD_SetPosition ( LINE_2 + 0 );
            printf ( LCD_PutChar, "Release button" );
            cLaneMask &= 0b11111101;
            cBPlace = 'M';   // masked lane
            }
        while ( input ( SW1 ) == LOW );       // wait until released
        LCD_PutCmd ( CLEAR_DISP );
        LCD_SetPosition ( LINE_1 + 0 );
        printf ( LCD_PutChar, "Press & Hold" );
        LCD_SetPosition ( LINE_2 + 0 );
        printf ( LCD_PutChar, "2 Null Green" );
        delay_ms ( TEXT_DELAY );
        if ( input ( SW1 ) == LOW )
            {
            LCD_PutCmd ( CLEAR_DISP );
            LCD_SetPosition ( LINE_1 + 0 );
            printf ( LCD_PutChar, "GREEN NULLED" );
            LCD_SetPosition ( LINE_2 + 0 );
            printf ( LCD_PutChar, "Release button" );
            cLaneMask &= 0b11111011;
            cGPlace = 'M';   // masked lane
            }
        while ( input ( SW1 ) == LOW );       // wait until released
        LCD_PutCmd ( CLEAR_DISP );
        LCD_SetPosition ( LINE_1 + 0 );
        printf ( LCD_PutChar, "Press & Hold" );
        LCD_SetPosition ( LINE_2 + 0 );
        printf ( LCD_PutChar, "2 Null Yellow" );
        delay_ms ( TEXT_DELAY );
        if ( input ( SW1 ) == LOW )
            {
            LCD_PutCmd ( CLEAR_DISP );
            LCD_SetPosition ( LINE_1 + 0 );
            printf ( LCD_PutChar, "YELLOW NULLED" );
            LCD_SetPosition ( LINE_2 + 0 );
            printf ( LCD_PutChar, "Release button" );
            cLaneMask &= 0b11110111;
            cYPlace = 'M';   // masked lane
            }
        while ( input ( SW2 ) == LOW );       // wait until released
        }
    if ( cLaneMask == 0b11111111 )
        {
        LCD_PutCmd ( CLEAR_DISP );
        LCD_SetPosition ( LINE_1 + 0 );
        printf ( LCD_PutChar, "All Lanes Ok :)" );
        delay_ms ( TEXT_DELAY );
        }

    Servo ( GATE_CLOSE );           // reset gate

    LCD_PutCmd ( CLEAR_DISP );
    LCD_SetPosition ( LINE_2 + 0 );
    printf ( LCD_PutChar, "Ready, Set, Go!" );

    cStarted = FALSE;
    cWaitForNextMaskChar = "NO";
    enable_interrupts ( GLOBAL );   // enable all interrupts
    enable_interrupts ( INT_RDA );  // enable serial interrupt
    cSerialCmd = CMD_NUL;           // reset to no command

    while ( TRUE )
        {
        while ( TRUE )
            {
            if ( input ( SW3 ) == LOW )     // PUSHBUTTON MANUAL RACE START
                {
                output_float ( TRK_R_INPUT );
                output_float ( TRK_B_INPUT );
                output_float ( TRK_G_INPUT );
                output_float ( TRK_Y_INPUT );
                cX = ERR_NONE;    // default
                #if START_CHECKS == 1
                cX |= CheckFinishLine();   // check that all lanes are clear at the finish line
                #endif
                #if START_CHECKS == 2
                cX |= CheckStartGate();    // check that the start gate is closed
                cX |= CheckFinishLine();   // check that all lanes are clear at the finish line
                #endif
                if ( cX == ERR_NONE )
                    {
                    break;
                    }
                if ( ( cX & ERR_GATE ) == ERR_GATE )
                    {
                    LCD_PutCmd ( CLEAR_DISP );
                    LCD_SetPosition ( LINE_1 + 0 );
                    printf ( LCD_PutChar, "Close The Gate" );
                    LCD_SetPosition ( LINE_2 + 0 );
                    printf ( LCD_PutChar, "0" );
                    }
                else
                    {
                    if ( ( cX & ERR_FINISH )== ERR_FINISH )
                        {
                        LCD_PutCmd ( CLEAR_DISP );
                        LCD_SetPosition ( LINE_1 + 0 );
                        printf ( LCD_PutChar, "Finish Line" );
                        LCD_SetPosition ( LINE_2 + 0 );
                        printf ( LCD_PutChar, "0" );
                        }
                    }
                }
            if ( GetSerial ( 'R' ) )            // "READY" command from computer
                {
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_2 + 5 );
                printf ( LCD_PutChar, "Ready" );
                cWaitForNextMaskChar = "NO";
                }
            if ( GetSerial ( 'T' ) )            // "RACE START" command from computer
                {
                output_float ( TRK_R_INPUT );
                output_float ( TRK_B_INPUT );
                output_float ( TRK_G_INPUT );
                output_float ( TRK_Y_INPUT );
                cWaitForNextMaskChar = "NO";
                break;          // break out, time to start this race
                }
            if ( GetSerial ( 'C' ) )            // "CHECK" command from computer
                {
                #if START_CHECKS == 1
                // signal if finish line photocell is blocked
                if ( CheckFinishLine() != ERR_NONE )
                    {
                    printf ( "NG" );
                    }
                #endif
                #if START_CHECKS == 2
                // signal if start gate switch is not closed or finish line photocell is blocked
                if ( ( CheckStartGate() != ERR_NONE ) || ( CheckFinishLine() != ERR_NONE ) )
                    {
                    printf ( "NG" );
                    }
                #endif
                cWaitForNextMaskChar = "NO";
                }
            if ( GetSerial ( 'A' ) )            // "GET ALL TIMES" command from computer
                {
                SendAllTimes();
                cWaitForNextMaskChar = "NO";
                }
            if ( GetSerial ( 'X' ) )            // "UNMASK ALL LANES" command from computer
                {
                LCD_PutCmd ( CLEAR_DISP );
                LCD_SetPosition ( LINE_2 + 0 );
                printf ( LCD_PutChar, "Unmask all lanes" );
                delay_ms ( TEXT_DELAY );
                cLaneMask = 0b11111111;   // bitmask all lanes on
                cRPlace = 0;   // unmask lane
                cBPlace = 0;   // unmask lane
                cGPlace = 0;   // unmask lane
                cYPlace = 0;   // unmask lane
                cWaitForNextMaskChar = "NO";
                }
            if ( GetSerial ( 'M' ) )            // MASK command from computer
                {
                cWaitForNextMaskChar = "YES";
                }
            if ( cWaitForNextMaskChar == "YES" )
                {
                if ( GetSerial ( '1' ) )            // MASK LANE 1 command from computer
                    {
                    LCD_PutCmd ( CLEAR_DISP );
                    LCD_SetPosition ( LINE_2 + 1 );
                    printf ( LCD_PutChar, "Lane R masked" );
                    delay_ms ( TEXT_DELAY );
                    cLaneMask &= 0b11111110;   // bitmask this lane bad
                    cRPlace = 'M';   // masked lane
                    cWaitForNextMaskChar = "NO";
                    }
                if ( GetSerial ( '2' ) )            // MASK LANE 2 command from computer
                    {
                    LCD_PutCmd ( CLEAR_DISP );
                    LCD_SetPosition ( LINE_2 + 1 );
                    printf ( LCD_PutChar, "Lane B masked" );
                    delay_ms ( TEXT_DELAY );
                    cLaneMask &= 0b11111101;   // bitmask this lane bad
                    cBPlace = 'M';   // masked lane
                    cWaitForNextMaskChar = "NO";
                    }
                if ( GetSerial ( '3' ) )            // MASK LANE 3 command from computer
                    {
                    LCD_PutCmd ( CLEAR_DISP );
                    LCD_SetPosition ( LINE_2 + 1 );
                    printf ( LCD_PutChar, "Lane G masked" );
                    delay_ms ( TEXT_DELAY );
                    cLaneMask &= 0b11111011;   // bitmask this lane bad
                    cGPlace = 'M';   // masked lane
                    cWaitForNextMaskChar = "NO";
                    }
                if ( GetSerial ( '4' ) )            // MASK LANE 4 command from computer
                    {
                    LCD_PutCmd ( CLEAR_DISP );
                    LCD_SetPosition ( LINE_2 + 1 );
                    printf ( LCD_PutChar, "Lane Y masked" );
                    delay_ms ( TEXT_DELAY );
                    cLaneMask &= 0b11110111;   // bitmask this lane bad
                    cYPlace = 'M';   // masked lane
                    cWaitForNextMaskChar = "NO";
                    }
                }
            }
        // GETS HERE EITHER BY MANUAL PUSHBUTTON OR BY COMPUTER COMMAND WHEN TIMING NEEDS TO START
        LCD_PutCmd ( CLEAR_DISP );
        LCD_SetPosition ( LINE_2 + 0 );
        printf ( LCD_PutChar, "GO! GO! GO!" ); // signal that the race has begun
        StartTimer();                       // zeros everything except mask conditions
        //Servo ( GATE_OPEN );
        cStarted = FALSE;
        enable_interrupts ( INT_RTCC );     // otherwise just allow the timer interrupt, which will start timer later
        delay_ms ( 1000 );                  // wait 1 second
        LCD_PutCmd ( CLEAR_DISP );          // clear display and put in 1st, 2nd, etc.
        LCD_SetPosition ( LINE_1 );
        printf ( LCD_PutChar, "1ST" );
        LCD_SetPosition ( LINE_2 );
        printf ( LCD_PutChar, "2ND" );
        LCD_SetPosition ( LINE_3 );
        printf ( LCD_PutChar, "3RD" );
        LCD_SetPosition ( LINE_4 );
        printf ( LCD_PutChar, "4TH" );
        Servo ( GATE_CLOSE );

        while ( TRUE )
            {
            Display ( cRTie, cRPlace, 'R', iRTime, &cRDisplayFlag );  // check and display Track 1
            Display ( cBTie, cBPlace, 'B', iBTime, &cBDisplayFlag );  // check and display Track 2
            Display ( cGTie, cGPlace, 'G', iGTime, &cGDisplayFlag );  // check and display Track 3
            Display ( cYTie, cYPlace, 'Y', iYTime, &cYDisplayFlag );  // check and display Track 4
            delay_ms ( 100 );
            if ( GetSerial ( 'F' ) )    // "EARLY DONE" command from computer
                {
                cWaitForNextMaskChar = "NO";
                if ( cRPlace == 0 )
                    {
                    cRPlace = 5;
                    iRTime = 9999;
                    }
                if ( cBPlace == 0 )
                    {
                    cBPlace = 5;
                    iBTime = 9999;
                    }
                if ( cGPlace == 0 )
                    {
                    cGPlace = 5;
                    iGTime = 9999;
                    }
                if ( cYPlace == 0 )
                    {
                    cYPlace = 5;
                    iYTime = 9999;
                    }
                SendAllTimes();
                break;
                }
            if ( cDisplayCnt == 4 )     // if all lines actually written to display
                {
                SendAllTimes();
                break;
                }
            }
        }
    }

#separate char CheckStartGate ( void )
    {
    // signal if start gate switch is not closed
    if ( input ( SW5 ) == "HIGH" )
        {
        return ( ERR_GATE );
        }
    return ( ERR_NONE );        // otherwise OK
    }

#separate char CheckFinishLine ( void )
    {
    // signal if photocell is blocked
    if ( ( ( PORT_A ^ 0xff ) & 0x0f & cLaneMask ) != 0 )  // invert Port A, mask the four lane bits on, and exclude any masked lanes
        {
        return ( ERR_FINISH );
        }
    return ( ERR_NONE );        // otherwise OK
    }

#separate char GetSerial ( char cChar )
    {
    if ( cSerialCmd == cChar )
        {
        cSerialCmd = CMD_NUL;
        return ( "YES" );
        }
    else
        {
        return ( "NO" );
        }
    }

#separate void Servo ( char cX )
    {
    char cCnt;

    switch ( cX )
        {
        case GATE_OPEN:
            {
            for ( cCnt = 0; cCnt < 15; cCnt++ )
               {
               output_high ( SERVO_OUT );
               delay_us ( 1000 );
               output_low ( SERVO_OUT );
               delay_ms ( 30 );
               }
            break;
            }
        case GATE_CLOSE:
            {
            for ( cCnt = 0; cCnt < 15; cCnt++ )
                {
                output_high ( SERVO_OUT );
                delay_us ( 2000 );
                output_low ( SERVO_OUT );
                delay_ms ( 30 );
                }
            break;
            }
        }
    output_float ( SERVO_OUT );     // go back to hi-z
    }

#separate void SendAllTimes ( void )
    {
    // send lane time if that lane finished
    if ( cRPlace != 0 )
        {
        SendTime ( 1, iRTime );
        }
    if ( cBPlace != 0 )
        {
        SendTime ( 2, iBTime );
        }
    if ( cGPlace != 0 )
        {
        SendTime ( 3, iGTime );
        }
    if ( cYPlace != 0 )
        {
        SendTime ( 4, iYTime );
        }
    }

#separate void SendTime ( char cLane, long iTime )
    {
    printf ( "%u %01lu.%03lu ", cLane, iTime/1000, iTime%1000 );
    }

#separate void StartTimer ( void )
    {
    disable_interrupts ( INT_RTCC );    // turn off timer interrupt while resetting time
    cRTie = "NO";             // preset to "NO" tie conditions
    cBTie = "NO";
    cGTie = "NO";
    cYTie = "NO";
    if ( cRPlace != 'M' )       // if lane is not masked
        {
        cRPlace = 0;            // preset to no place
        iRTime = 65535;         // set the individual track times off zero, to max
        cRDisplayFlag = "OFF";    // allow one-time display
        }
    else
        {
        cRDisplayFlag = "ON";     // allow one-time display
        iRTime = 9999;          // set to max time
        }
    if ( cBPlace != 'M' )       // if lane is not masked
        {
        cBPlace = 0;            // preset to no place
        iBTime = 65535;         // set the individual track times off zero, to max
        cBDisplayFlag = "OFF";    // allow one-time display
        }
    else
        {
        cBDisplayFlag = "ON";     // allow one-time display
        iBTime = 9999;          // set to max time
        }
    if ( cGPlace != 'M' )       // if lane is not masked
        {
        cGPlace = 0;            // preset to no place
        iGTime = 65535;         // set the individual track times off zero, to max
        cGDisplayFlag = "OFF";    // allow one-time display
        }
    else
        {
        cGDisplayFlag = "ON";     // allow one-time display
        iGTime = 9999;          // set to max time
        }
    if ( cYPlace != 'M' )       // if lane is not masked
        {
        cYPlace = 0;            // preset to no place
        iYTime = 65535;         // set the individual track times off zero, to max
        cYDisplayFlag = "OFF";    // allow one-time display
        }
    else
        {
        cYDisplayFlag = "ON";     // allow one-time display
        iYTime = 9999;          // set to max time
        }
    iTime = 0;              // zero the count
    cDisplayLine = 1;       // preset to first display line
    cMaskDisplayLine = 4;     // any masked lane gets displayed from the bottom line and upward in the display
    cPlaceNum = 1;          // start with first place
    cStarted = TRUE;        // signal: running
    cDisplayCnt = 0;
    enable_interrupts ( INT_RTCC );     // turn on timer interrupt to begin timing
    }

#separate void Display ( char cTie, char cPlace, char cTrackColor, long iTime, char *cDisplayFlag )
    {
    char cTablePtr;

    if ( *cDisplayFlag == "YES" ) // if this track's done flag was turned on by the interrupt or in the START function (if this lane is masked)
        {
        if ( cPlace != 'M' )
            {
            cTablePtr = cPlace - 1; // place value determines which display line from top row of display, downward
            LCD_SetPosition ( cDisplayLocTable [ cTablePtr ] );
            printf ( LCD_PutChar, "%c  %2lu.%03lu", cTrackColor, iTime/1000, iTime%1000 );
            if ( cTie == "YES" )
                {
                DisplayTie ( cDisplayLocTable [ cTablePtr ] );    // point to line
                DisplayTie ( cDisplayLocTable [ cTablePtr - 1 ] );    // point to line above
                }
            *cDisplayFlag = "NO";             // prevent displaying again
            cDisplayCnt += 1;
            }
        else
            {
            cTablePtr = cMaskDisplayLine-- - 1; // masked lanes show at bottom row of display, upward
            LCD_SetPosition ( cDisplayLocTable [ cTablePtr ] );
            printf ( LCD_PutChar, "%c   MASKED", cTrackColor );
            *cDisplayFlag = "NO";             // prevent displaying again
            cDisplayCnt += 1;
            }
        }
    }

#separate void DisplayTie ( char cLoc )
    {
    LCD_SetPosition ( cLoc - 6 );    // point to beginning of this line
    printf ( LCD_PutChar, "TIE!" );
    }

#separate void LCD_Init ( void )
    {
    LCD_SetData ( 0x00 );
    delay_ms ( 200 );       // wait enough time after Vdd rise
    output_low ( LCD_RS );
    LCD_SetData ( 0x03 );   // init with specific nibbles to start 4-bit mode
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_SetData ( 0x02 );   // set 4-bit interface
    LCD_PulseEnable();      // send dual nibbles hereafter, MSN first
    LCD_PutCmd ( 0x2C );    // function set (all lines, 5x7 characters)
    LCD_PutCmd ( 0x0C );    // display ON, cursor off, no blink
    LCD_PutCmd ( 0x01 );    // clear display
    LCD_PutCmd ( 0x06 );    // entry mode set, increment & scroll left
    }

#separate void LCD_SetPosition ( unsigned int cX )
    {
    // this subroutine works specifically for 4-bit Port A
    LCD_SetData ( swap ( cX ) | 0x08 );
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );
    LCD_PulseEnable();
    }

#separate void LCD_PutChar ( unsigned int cX )
    {
    // this subroutine works specifically for 4-bit Port A
    output_high ( LCD_RS );
    LCD_SetData ( swap ( cX ) );     // send high nibble
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );     // send low nibble
    LCD_PulseEnable();
    output_low ( LCD_RS );
    }

#separate void LCD_PutCmd ( unsigned int cX )
    {
    // this subroutine works specifically for 4-bit Port A
    LCD_SetData ( swap ( cX ) );     // send high nibble
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );     // send low nibble
    LCD_PulseEnable();
    }

#separate void LCD_PulseEnable ( void )
    {
    output_high ( LCD_EN );
    delay_us ( 20 );
    output_low ( LCD_EN );
    delay_ms ( 5 );
    }

#separate void LCD_SetData ( unsigned int cX )
    {
    output_bit ( LCD_D4, cX & 0x01 );
    output_bit ( LCD_D5, cX & 0x02 );
    output_bit ( LCD_D6, cX & 0x04 );
    output_bit ( LCD_D7, cX & 0x08 );
    }
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Jun 01, 2010 4:00 pm     Reply with quote

I do like the small programs, not the 800+ line versions....
A lot of the code has nothing to do with your problem and could have been omitted.

As a general comment I would say the code is in need of re-factoring. The four lanes use almost identical code repeated four times. This makes the code hard to read and is prone to errors being fixed in one version and overlooked in another.
A good coding guide line is to keep functions small, so they fit onto the screen as a whole. These 50 lines are about the maximum an average human brain can comprehend. Your 400 lines main function is obese.

Code:
#use rs232 ( baud = 9600, xmit = PIN_B6, rcv = PIN_B7)
Always add the ERRORS directive so the compiler will add code for clearing communication errors (prevents the UART from stalling on receive buffer overflow).

Code:
#byte PORT_A = 8
#byte PORT_B = 8
#byte PORT_C = 8
#byte PORT_D = 8
This can't be correct.

Code:
#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
#use standard_io ( D )
This is the default setting for having the compiler control the TRIS registers for you. Nothing wrong in setting it again, but...
Code:
cFinish = ( PORT_A ^ 0xff ) & 0x0f;
Here you access the I/O register directly, bypassing the CCS method of using the input_x() functions. Meaning the setting of the TRIS register is left to chance...
Either use #fast_io and take control of the TRIS register yourself. Or use #standard_io in combination with the CCS I/O functions. Don't mix these methods.

as a side note:
Code:
    cFinish = ( PORT_A ^ 0xff ) & 0x0f;   // invert Port A and null on lower four bits
    cFinish = ( ~PORT_A) & 0x0f;   // invert Port A and null on lower four bits
Both versions compile to exactly the same code, but in the second line the code is more self explaining. Let the compiler do the optimization for you.

Code:
static char cRTie;
...
cRTie = "YES";
This is a bug, multiple times present in the code. This is not the correct method to assign a string. Let alone that the string would fit into a single character.
What you intended to do was to use a defined constant (without the quotes):
Code:
#define YES    1
#define NO     0
...
cRTie = YES;


Code:
 if ( input ( SW5 ) == "HIGH" )
Ehhh..... Same error, again remove the quotes.
Check your whole program, this same error is present about 50 times (and was correct in the original program).

Good luck. You have a lot of work to do.
donaldduck



Joined: 01 Jun 2010
Posts: 3

View user's profile Send private message

PostPosted: Tue Jun 01, 2010 4:57 pm     Reply with quote

ckielstra wrote:
................................
Good luck. You have a lot of work to do.


Thanks very much for your patience and help.. I'll make all of the changes that you've suggested and read up on all of the mistakes i've made Very Happy

Cheers again,
donaldduck



Joined: 01 Jun 2010
Posts: 3

View user's profile Send private message

PostPosted: Wed Jun 02, 2010 1:19 pm     Reply with quote

Thanks again for your help ckielstra

After a good few hours, i've managed to get it working Very Happy

But, the PIC isn't addressing the bottom two lines of the 4x20 line LCD display i've purchased (Hitatchi HD44780)

The top two lines are ok, but the bottom two lines aren't, and the for variables like;

Code:
while ( TRUE )
            {
            Display ( cRTie, cRPlace, 'R', iRTime, &cRDisplayFlag );  // check and display Track 1
            Display ( cBTie, cBPlace, 'B', iBTime, &cBDisplayFlag );  // check and display Track 2
            Display ( cGTie, cGPlace, 'G', iGTime, &cGDisplayFlag );  // check and display Track 3
            Display ( cYTie, cYPlace, 'Y', iYTime, &cYDisplayFlag );  // check and display Track 4
            delay_ms ( 100 );


The text is shifted 4 blocks to the left, Unless you implicitly define the position of the text .. like

Code:
 LCD_SetPosition ( LINE_4 + 16 );


where it is ok.. How do I get it to show the variables cYTie, cYplace, 'Y', and iYTime etc in the correct position?

Thanks in advance
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Jun 02, 2010 3:24 pm     Reply with quote

The original circuit was designed for a 4x16 display, not 4x20. That's where the offset by 4 error comes from.

By now you should know the code better than I do and it took me longer to load the file than to find the fix. Have you studied the Display() function?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group