//*****************************************************************************
//
// End the graphics demo and return to the keypad.
//
//*****************************************************************************
void
GraphicsDemoHide(void)
{

    //
    // Remove the current panel from the demo tree.
    //
    WidgetRemove((tWidget *)(g_psPanels + g_ulPanel));

    //
    // Remove all the demo widgets.
    //
    WidgetRemove((tWidget *)&g_sDemoBackground);

    //
    // Reinstate the keypad widget tree.
    //
    WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sBlackBackground);

    //
    // Issue the initial paint request to the widgets.
    //
    WidgetPaint(WIDGET_ROOT);

    //
    // Revert to keypad operation.
    //
    g_ulMode = MODE_KEYPAD;
}
Exemple #2
0
/**
 * Deletes one Line from the Screen and sets the Pointer to the Next one
 */
void vDeleteDisplayLine(basicDisplayLine *toDelete)
{
	if (toDelete != NULL)
	{
		if (toDelete->type->onDestroy != NULL)
		{
			toDelete->type->onDestroy(toDelete);
		}

		if (toDelete->labelWidget != NULL)
		{
			WidgetRemove(toDelete->labelWidget);
			vPortFree(toDelete->labelWidget);
		}

		if (toDelete->valueWidget != NULL)
		{
			WidgetRemove(toDelete->valueWidget);
			vPortFree(toDelete->valueWidget);
		}

		if (toDelete->label != NULL)
		{
			vPortFree(toDelete->label);
		}

		if (toDelete->id != NULL)
		{
			vPortFree(toDelete->id);
		}

		vPortFree(toDelete);
		toDelete = NULL;
	}
}
Exemple #3
0
//*****************************************************************************
//
// The "Up" button widget callback function.
//
// This function is called whenever someone presses the "Up" button.
//
//*****************************************************************************
void
OnBtnUp(tWidget *pWidget)
{
    uint32_t ui32Reason;
    FRESULT fresult;

    //
    // Change up one directory.
    //
    fresult = ChangeToDirectory("..", &ui32Reason);

    if(fresult != FR_OK)
    {
        //
        // Update the status display to show the error.
        //
        PrintfStatus("Error changing directory.");
        PrintfStatus((char *)StringFromFresult(fresult));
    }
    else
    {
        //
        // Update the directory name and the list box contents.
        //
        WidgetPaint((tWidget *)&g_sPWD);
        PopulateFileListBox(true);

        //
        // If we are now in the root directory, hide the "Up" button.
        //
        if((strlen(g_cCwdBuf) == 1) && (g_cCwdBuf[0] == '/'))
        {
            WidgetRemove((tWidget *)&g_sUpBtn);
        }
        else
        {
            WidgetAdd((tWidget *)&g_sUpBackground, (tWidget *)&g_sUpBtn);
        }

        //
        // Disable the CD button since re-populating the list removes the
        // selection.
        //
        WidgetRemove((tWidget *)&g_sCDBtn);

        //
        // Tell the user what happened.
        //
        PrintfStatus("Changed to %s", g_cCwdBuf);

        //
        // Repaint the buttons.
        //
        WidgetPaint((tWidget *)&g_sUpBackground);
        WidgetPaint((tWidget *)&g_sCDBackground);
    }
}
Exemple #4
0
void vRemoveStatusMessage(tBoolean bRefresh)
{
	WidgetRemove((tWidget*) &xStatusMessage);
	if (bRefresh == true)
	{
		WidgetPaint((tWidget*)&xParentWidget);
	}
}
Exemple #5
0
//*****************************************************************************
//
// The listbox widget callback function.
//
// This function is called whenever someone changes the selected entry in the
// listbox containing the files and directories found in the current directory.
//
//*****************************************************************************
void
OnListBoxChange(tWidget *pWidget, int16_t ui16Selected)
{
    int16_t i16Selected;

    //
    // If no USB drive is present, just ignore this.
    //
    if(g_eState != STATE_DEVICE_READY)
    {
        return;
    }

    //
    // Get the current selection from the list box.
    //
    i16Selected = ListBoxSelectionGet(&g_sDirList);

    //
    // Is there any selection?
    //
    if(i16Selected == -1)
    {
        return;
    }
    else
    {
        //
        // Is the selection a directory name?
        //
        if(g_pcFilenames[i16Selected][1] == 'D')
        {
            //
            // Enable the "CD" button.
            //
            WidgetAdd((tWidget *)&g_sCDBackground, (tWidget *)&g_sCDBtn);
        }
        else
        {
            //
            // Hide the "CD" button.
            //
            WidgetRemove((tWidget *)&g_sCDBtn);
        }

        //
        // Make sure the CD button (or its background) is drawn correctly).
        //
        WidgetPaint((tWidget *)&g_sCDBackground);
    }

    //
    // Update the status display to say what we've done.
    //
    PrintfStatus("Selected %s %s\n",
                 (g_pcFilenames[i16Selected][1] == 'D') ? "dir" : "file",
                 &g_pcFilenames[i16Selected][4]);
}
Exemple #6
0
//*****************************************************************************
//
// This function disables the status display.
//
//*****************************************************************************
void
StatusDisable(void)
{
    unsigned long ulIdx;

    //
    // Disable the gathering of status information over CAN.
    //
    CANStatusDisable();

    //
    // Remove the status display widgets from the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
    {
        WidgetRemove((tWidget *)(g_psStatusWidgets + ulIdx));
    }
}
//*****************************************************************************
//
// Show the graphics demo
//
//*****************************************************************************
void
GraphicsDemoShow(void)
{
    //
    // Remove the keypad widget tree completely.
    //
    WidgetRemove((tWidget *)&g_sBlackBackground);

    //
    // Remember that we are showing the graphics demo.
    //
    g_ulMode = MODE_DEMO;

    //
    // Set the previous and next button text correctly for the first screen.
    //
    PushButtonTextSet(&g_sNext, "+");
    PushButtonTextSet(&g_sPrevious, "X");

    //
    // Add the title block and the previous and next buttons to the widget
    // tree.
    //
    WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sDemoBackground);

    //
    // Add the first panel to the widget tree.
    //
    g_ulPanel = 0;
    WidgetAdd((tWidget *)&g_sDemoBackground, (tWidget *)g_psPanels);
    CanvasTextSet(&g_sTitle, g_pcPanelNames[0]);

    //
    // Issue the initial paint request to the widgets.
    //
    WidgetPaint(WIDGET_ROOT);
}
Exemple #8
0
void vDrawElementsOnDisplay(void)
{

	int i;
	basicDisplayLine *toDraw;

	vTaskSuspendAll();
	{

		if (xDisplayRoot.menue == true)
		{
			WidgetAdd((tWidget*) &xParentWidget, (tWidget*) &xMenuButton);
		}
		else if (xMenuButton.sBase.pParent != NULL)
		{
			WidgetRemove((tWidget*) &xMenuButton);
		}

		if (xDisplayRoot.save == true)
		{
			WidgetAdd((tWidget*) &xParentWidget, (tWidget*) &xSaveButton);
		}
		else
		{
			WidgetRemove((tWidget*) &xSaveButton);
		}

		WidgetAdd((tWidget*) &xParentWidget, (tWidget*) &xTitle);

		if (xDisplayRoot.displayEntities == true)
		{

#if DEBUG_GRAPHIC
			printf("vDrawElementsOnDisplay: Draw Elements offset %d\n",
					elementOffset);
#endif

			toDraw = xDisplayRoot.entities;

			if (elementOffset > 0)
			{
				for (i = 0; i < elementOffset && toDraw != NULL && toDraw->next
						!= NULL; i++)
				{
					toDraw = toDraw->next;
				}
			}

			for (i = 0; toDraw != NULL && i < DISPLAY_LINES_PER_VIEW; i++)
			{
				xGetLabelWidget(toDraw, i);
				if (toDraw->labelWidget != NULL)
				{
#if DEBUG_GRAPHIC
					printf("vDrawElementsOnDisplay: addLabel\n");
#endif
					WidgetAdd((tWidget*) &xParentWidget,
							(tWidget*) toDraw->labelWidget);
				}

#if DEBUG_GRAPHIC
				printf("vDrawElementsOnDisplay: check onDisplay\n");
#endif

				if (((taglib*) toDraw->type)->onDisplay != NULL)
				{
#if DEBUG_GRAPHIC
					printf(
							"vDrawElementsOnDisplay: toDraw = %X ElementType= %s\n",
							(unsigned int) toDraw,
							((taglib*) toDraw->type)->tagname);
#endif
					((taglib*) toDraw->type)->onDisplay(toDraw, i);
				}
				else
				{
					toDraw->valueWidget = NULL;
				}

				if (toDraw->valueWidget != NULL)
				{
#if DEBUG_GRAPHIC
					printf("vDrawElementsOnDisplay: addValue\n");
#endif
					WidgetAdd((tWidget*) &xParentWidget,
							(tWidget*) toDraw->valueWidget);
				}
				toDraw = toDraw->next;
			}

			if (elementOffset > 0)
			{
				WidgetAdd((tWidget*) &xParentWidget, (tWidget*) &xUpButton);
				xDisplayRoot.up = true;
			}
			else
			{
				WidgetRemove((tWidget*) &xUpButton);
				xDisplayRoot.up = false;
			}

			if (toDraw != NULL)
			{
				xDisplayRoot.down = true;
				WidgetAdd((tWidget*) &xParentWidget, (tWidget*) &xDownButton);
			}
			else
			{
				xDisplayRoot.down = false;
				WidgetRemove((tWidget*) &xDownButton);
			}
		}
#if DEBUG_GRAPHIC
		printf("vDrawElementsOnDisplay: draw Elements ... ");
#endif
		WidgetPaint((tWidget*) &xParentWidget);
#if DEBUG_GRAPHIC
		printf("finished\n");
#endif
	}
	xTaskResumeAll();
}
Exemple #9
0
//*****************************************************************************
//
// Handles when a key is pressed on the keyboard.
//
//*****************************************************************************
void
KeyEvent(tWidget *psWidget, uint32_t ui32Key, uint32_t ui32Event)
{
    switch(ui32Key) {
        //
        // Look for a backspace key press.
        //
        case UNICODE_BACKSPACE: {
            if(ui32Event == KEYBOARD_EVENT_PRESS) {
                if(g_ui32StringIdx != 0) {
                    g_ui32StringIdx--;
                    g_pcKeyStr[g_ui32StringIdx] = 0;
                }

                WidgetPaint((tWidget *)&g_sKeyboardText);

                //
                // Save the pixel width of the current string.
                //
                g_i32StringWidth = GrStringWidthGet(&g_sContext, g_pcKeyStr,
                                                    40);
            }
            break;
        }
        //
        // Look for an enter/return key press.  This will exit the keyboard and
        // return to the current active screen.
        //
        case UNICODE_RETURN: {
            if(ui32Event == KEYBOARD_EVENT_RELEASE) {
                //
                // Get rid of the keyboard widget.
                //
                WidgetRemove(g_sScreens[g_i32ScreenIdx].psWidget);

                //
                // Switch back to the previous screen and add its widget back.
                //
                g_i32ScreenIdx = g_i32ScreenIdx;
                WidgetAdd(WIDGET_ROOT, g_sScreens[g_i32ScreenIdx].psWidget);

                //
                // If returning to the main screen then re-draw the frame to
                // indicate the main screen.
                //
                if(g_i32ScreenIdx == SCREEN_DETAILS) {
                    FrameDraw(&g_sContext, "nfc-p2p-demo : Details");
                    WidgetPaint(g_sScreens[g_i32ScreenIdx].psWidget);
                } else if(g_i32ScreenIdx == SCREEN_TI) {
                    //
                    // Returning to the settings screen.
                    //
                    FrameDraw(&g_sContext, "nfc-p2p-demo : TI");
                    WidgetPaint(g_sScreens[g_i32ScreenIdx].psWidget);
                    AnimateButtons(true);
                    WidgetMessageQueueProcess();
                }
                //
                // Assumed Screen = SCREEN_SUMMARY
                //
                else {
                    FrameDraw(&g_sContext, "nfc-p2p-demo : Summary");
                    WidgetPaint(g_sScreens[g_i32ScreenIdx].psWidget);
                }

                //
                // Enable gestures.
                //
                g_sSwipe.bEnable = true;
            }
            break;
        }
        //
        // If the key is not special then update the text string.
        //
        default: {
            if(ui32Event == KEYBOARD_EVENT_PRESS) {
                //
                // Set the string to the current string to be updated.
                //
                if(g_ui32StringIdx == 0) {
                    CanvasTextSet(&g_sKeyboardText, g_pcKeyStr);
                }
                g_pcKeyStr[g_ui32StringIdx] = (char)ui32Key;
                g_ui32StringIdx++;
                g_pcKeyStr[g_ui32StringIdx] = 0;

                WidgetPaint((tWidget *)&g_sKeyboardText);

                //
                // Save the pixel width of the current string.
                //
                g_i32StringWidth = GrStringWidthGet(&g_sContext, g_pcKeyStr,
                                                    40);
            }
            break;
        }
    }
}
Exemple #10
0
//*****************************************************************************
//
// Handle the touch screen movements.
//
//*****************************************************************************
void
HandleMovement(void)
{
    uint32_t ui32NewIdx;

    if(g_sSwipe.eMovement != iSwipeNone) {
        switch(g_sSwipe.eMovement) {
            case iSwipeUp: {
                ui32NewIdx = g_sScreens[g_i32ScreenIdx].ui32Up;
                break;
            }
            case iSwipeDown: {
                ui32NewIdx = g_sScreens[g_i32ScreenIdx].ui32Down;

                break;
            }
            case iSwipeRight: {
                ui32NewIdx = g_sScreens[g_i32ScreenIdx].ui32Left;

                break;
            }
            case iSwipeLeft: {
                ui32NewIdx = g_sScreens[g_i32ScreenIdx].ui32Right;

                break;
            }
            default: {
                ui32NewIdx = g_i32ScreenIdx;
                break;
            }
        }

        //
        // Check if the panel has changed.
        //
        if(ui32NewIdx != g_i32ScreenIdx) {
            //
            // Remove the current widget.
            //
            WidgetRemove(g_sScreens[g_i32ScreenIdx].psWidget);

            WidgetAdd(WIDGET_ROOT, g_sScreens[ui32NewIdx].psWidget);

            g_i32ScreenIdx = ui32NewIdx;

            //
            // Screen switched so disable the overlay buttons.
            //
            ButtonsDisable();

            if(g_i32ScreenIdx == SCREEN_SUMMARY) {
                //
                // Update the frame.
                //
                FrameDraw(&g_sContext, "nfc-p2p-demo : Summary");

                //
                // Animate the panel switch.
                //
                AnimatePanel(TI_BLACK);

                AnimateButtons(true);
            } else if(g_i32ScreenIdx == SCREEN_DETAILS) {
                //
                // Update the frame.
                //
                FrameDraw(&g_sContext, "nfc-p2p-demo : Details");

                //
                // Animate the panel switch.
                //
                AnimatePanel(TI_BLACK);

                AnimateButtons(true);

            } else if(g_i32ScreenIdx == SCREEN_TI) {
                //
                // Update the frame.
                //
                FrameDraw(&g_sContext, "nfc-p2p-demo : TI");

                //
                // Animate the panel switch.
                //
                AnimatePanel(TI_GRAY);

                //
                // Animate the pull up tab once.
                //
                AnimateButtons(true);
            }
        }

        g_sSwipe.eMovement = iSwipeNone;
    }
}
Exemple #11
0
//*****************************************************************************
//
// Handles presses of the next panel button.
//
//*****************************************************************************
void
OnNext(tWidget *pWidget)
{
    //
    // There is nothing to be done if the last panel is already being
    // displayed.
    //
    if(g_ulPanel == (NUM_PANELS - 1))
    {
        return;
    }

    //
    // Remove the current panel.
    //
    WidgetRemove((tWidget *)(g_psPanels + g_ulPanel));

    //
    // Increment the panel index.
    //
    g_ulPanel++;

    //
    // Add and draw the new panel.
    //
    WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psPanels + g_ulPanel));
    WidgetPaint((tWidget *)(g_psPanels + g_ulPanel));

    //
    // Set the title of this panel.
    //
    CanvasTextSet(&g_sTitle, g_pcPanelNames[g_ulPanel]);
    WidgetPaint((tWidget *)&g_sTitle);

    //
    // See if the previous panel was the first panel.
    //
    if(g_ulPanel == 1)
    {
        //
        // Display the previous button.
        //
        PushButtonImageOn(&g_sPrevious);
        PushButtonTextOn(&g_sPrevious);
        PushButtonFillOff(&g_sPrevious);
        WidgetPaint((tWidget *)&g_sPrevious);
    }

    //
    // See if this is the last panel.
    //
    if(g_ulPanel == (NUM_PANELS - 1))
    {
        //
        // Clear the next button from the display since the last panel is being
        // displayed.
        //
        PushButtonImageOff(&g_sNext);
        PushButtonTextOff(&g_sNext);
        PushButtonFillOn(&g_sNext);
        WidgetPaint((tWidget *)&g_sNext);
    }

    //
    // Play the key click sound.
    //
    //SoundPlay(g_pusKeyClick, sizeof(g_pusKeyClick) / 2);
	ClickPlay();
}
Exemple #12
0
//*****************************************************************************
//
// Handles presses of the previous panel button.
//
//*****************************************************************************
void
OnPrevious(tWidget *psWidget)
{
    //
    // There is nothing to be done if the first panel is already being
    // displayed.
    //
    if(g_ui32Panel == 0) {
        return;
    }

    //
    // Remove the current panel.
    //
    WidgetRemove((tWidget *)(g_psPanels + g_ui32Panel));

    //
    // Decrement the panel index.
    //
    g_ui32Panel--;

    //
    // Add and draw the new panel.
    //
    WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psPanels + g_ui32Panel));
    WidgetPaint((tWidget *)(g_psPanels + g_ui32Panel));

    //
    // Set the title of this panel.
    //
    CanvasTextSet(&g_sTitle, g_pcPanei32Names[g_ui32Panel]);
    WidgetPaint((tWidget *)&g_sTitle);

    //
    // See if this is the first panel.
    //
    if(g_ui32Panel == 0) {
        //
        // Clear the previous button from the display since the first panel is
        // being displayed.
        //
        PushButtonImageOff(&g_sPrevious);
        PushButtonTextOff(&g_sPrevious);
        PushButtonFillOn(&g_sPrevious);
        WidgetPaint((tWidget *)&g_sPrevious);
    }

    //
    // See if the previous panel was the last panel.
    //
    if(g_ui32Panel == (NUM_PANELS - 2)) {
        //
        // Display the next button.
        //
        PushButtonImageOn(&g_sNext);
        PushButtonTextOn(&g_sNext);
        PushButtonFillOff(&g_sNext);
        WidgetPaint((tWidget *)&g_sNext);
    }

}
Exemple #13
0
//****************************************************************************
//
// Handles updates to the current status.
//
//****************************************************************************
void
UIUpdateStatus(uint32_t ui32Indicators)
{
    if(g_eState == UI_NOT_CONNECTED)
    {
        PushButtonTextSet(&g_sToggle, "---");

        PushButtonTextColorSet(&g_sStatus1, ClrBlack);
        PushButtonTextSet(&g_sStatus1, "---");

        PushButtonTextColorSet(&g_sStatus2, ClrBlack);
        PushButtonTextSet(&g_sStatus2, "---");

        PushButtonTextColorSet(&g_sStatus3, ClrBlack);
        PushButtonTextSet(&g_sStatus3, "---");

        if(ui32Indicators & UI_STATUS_KEYBOARD)
        {
            WidgetRemove((tWidget *)&g_sKeyboard);
        }

        WidgetPaint((tWidget *)&g_sBackground);

        return;
    }

    //
    // See if there is a change to update.
    //
    if(ui32Indicators == g_sUIState.ui32Indicators)
    {
        return;
    }

    //
    // Was there a global change in the keyboard/mouse state.
    //
    if(((ui32Indicators ^ g_sUIState.ui32Indicators) & UI_STATUS_KEYBOARD) ||
       (ui32Indicators & UI_STATUS_UPDATE))
    {
        //
        // Update to keyboard mode or mouse mode for the UI.
        //
        if(ui32Indicators & UI_STATUS_KEYBOARD)
        {
            PushButtonTextSet(&g_sToggle, "Keyboard");
            WidgetPaint((tWidget *)&g_sToggle);
            UIUpdateCapsLock();
            UIUpdateScrollLock();
            UIUpdateNumLock();

            WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sKeyboard);

            WidgetPaint((tWidget *)&g_sKeyboard);
        }
        else
        {
            //
            // Switch back to a mouse UI.
            //
            PushButtonTextSet(&g_sToggle, "Mouse");

            PushButtonTextColorSet(&g_sStatus1, ClrBlack);
            PushButtonTextSet(&g_sStatus1, "Left");

            PushButtonTextColorSet(&g_sStatus2, ClrBlack);
            PushButtonTextSet(&g_sStatus2, "Middle");

            PushButtonTextColorSet(&g_sStatus3, ClrBlack);
            PushButtonTextSet(&g_sStatus3, "Right");

            WidgetRemove((tWidget *)&g_sKeyboard);

            WidgetPaint((tWidget *)&g_sBackground);
        }
    }

    //
    // Update the new state of the indicators.
    //
    g_sUIState.ui32Indicators = ui32Indicators & ~UI_STATUS_UPDATE;
}
//*****************************************************************************
//
// Displays the "Device List" panel.  The returned value is the ID of the panel
// to be displayed instead of the "Device List" panel.
//
//*****************************************************************************
unsigned long
DisplayDevList(void)
{
    unsigned long ulPosX, ulPosY, ulIdx;

    //
    // Disable the widget fill for all the widgets except the one for device
    // ID 1.
    //
    CanvasFillOn(g_psDevListWidgets);
    for(ulIdx = 1; ulIdx < 64; ulIdx++)
    {
        CanvasFillOff(g_psDevListWidgets + ulIdx);
    }

    //
    // Add the "Device List" panel widgets to the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
    {
        WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psDevListWidgets + ulIdx));
    }

    //
    // Set the default cursor position to device ID 1.
    //
    ulPosX = 0;
    ulPosY = 1;

    //
    // Loop forever.  This loop will be explicitly exited when the proper
    // condition is detected.
    //
    while(1)
    {
        //
        // Enumerate the devices on the CAN bus.
        //
        CANEnumerate();

        //
        // Delay for 100ms while the bus is being enumerated.
        //
        for(ulIdx = 0; ulIdx < 100; ulIdx++)
        {
            HWREGBITW(&g_ulFlags, FLAG_TICK) = 0;
            while(HWREGBITW(&g_ulFlags, FLAG_TICK) == 0)
            {
            }
        }

        //
        // See if a serial download has begun.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 1)
        {
            //
            // Remove the "Device List" panel widgets.
            //
            for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
            {
                WidgetRemove((tWidget *)(g_psDevListWidgets + ulIdx));
            }

            //
            // Return the ID of the update panel.
            //
            return(PANEL_UPDATE);
        }

        //
        // See if the up button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not already at the top of the
            // screen.
            //
            if(ulPosY != 0)
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psDevListWidgets + (ulPosY * 7) + ulPosX - 7);

                //
                // Decrement the cursor row.
                //
                ulPosY--;

                //
                // Enable the widget fill for the newly selected widget.
                //
                if(ulPosY == 0)
                {
                    CanvasFillOn(g_psDevListWidgets + 63);
                }
                else
                {
                    CanvasFillOn(g_psDevListWidgets + (ulPosY * 7) + ulPosX -
                                 7);
                }
            }

            //
            // Clear the press flag for the up button.
            //
            HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
        }

        //
        // See if the down button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not already at the bottom of the
            // screen.
            //
            if(ulPosY != 9)
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                if(ulPosY == 0)
                {
                    CanvasFillOff(g_psDevListWidgets + 63);
                }
                else
                {
                    CanvasFillOff(g_psDevListWidgets + (ulPosY * 7) + ulPosX -
                                  7);
                }

                //
                // Increment the cursor row.
                //
                ulPosY++;

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psDevListWidgets + (ulPosY * 7) + ulPosX - 7);
            }

            //
            // Clear the press flag for the down button.
            //
            HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
        }

        //
        // See if the left button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not on the top row of the screen
            // and if it is not already at the left edge of the screen.
            //
            if((ulPosX != 0) && (ulPosY != 0))
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psDevListWidgets + (ulPosY * 7) + ulPosX - 7);

                //
                // Decrement the cursor column.
                //
                ulPosX--;

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psDevListWidgets + (ulPosY * 7) + ulPosX - 7);
            }

            //
            // Clear the press flag for the left button.
            //
            HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
        }

        //
        // See if the right button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not on the top row of the screen
            // and if it is not already at the right edge of the screen.
            //
            if((ulPosX != 6) && (ulPosY != 0))
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psDevListWidgets + (ulPosY * 7) + ulPosX - 7);

                //
                // Increment the cursor column.
                //
                ulPosX++;

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psDevListWidgets + (ulPosY * 7) + ulPosX - 7);
            }

            //
            // Clear the press flag for the right button.
            //
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
        }

        //
        // Loop through the 63 possible device IDs and set the text color of
        // the corresponding widget based on that ID's presence or absence on
        // the bus.
        //
        for(ulIdx = 1; ulIdx < 64; ulIdx++)
        {
            if(g_pulStatusEnumeration[ulIdx / 32] & (1 << (ulIdx % 32)))
            {
                CanvasTextColorSet(g_psDevListWidgets + ulIdx - 1, ClrWhite);
            }
            else
            {
                CanvasTextColorSet(g_psDevListWidgets + ulIdx - 1,
                                   ClrNotPresent);
            }
        }

        //
        // See if the select button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 1)
        {
            //
            // Clear the press flag for the select button.
            //
            HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;

            //
            // See if the cursor is on the top row of the screen.
            //
            if(ulPosY == 0)
            {
                //
                // Display the menu.
                //
                ulIdx = DisplayMenu(PANEL_DEV_LIST);

                //
                // See if another panel was selected.
                //
                if(ulIdx != PANEL_DEV_LIST)
                {
                    //
                    // Remove the "Device List" panel widgets.
                    //
                    for(ulPosX = 0; ulPosX < NUM_WIDGETS; ulPosX++)
                    {
                        WidgetRemove((tWidget *)(g_psDevListWidgets + ulPosX));
                    }

                    //
                    // Return the ID of the newly selected panel.
                    //
                    return(ulIdx);
                }

                //
                // Since the "Device List" panel was selected from the menu,
                // move the cursor down one row.
                //
                CanvasFillOff(g_psDevListWidgets + 63);
                ulPosY++;
                CanvasFillOn(g_psDevListWidgets + (ulPosY * 7) + ulPosX - 7);
            }
            else
            {
                //
                // Indicate that the current ID is begin assigned.
                //
                usnprintf(g_pcBuffer, sizeof(g_pcBuffer), "Assigning %d...",
                          (ulPosY * 7) + ulPosX - 6);
                WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sAssignWidget);

                //
                // Update the display.
                //
                DisplayFlush();

                //
                // Perform a CAN device ID assignment.
                //
                CANAssign((ulPosY * 7) + ulPosX - 6);

                //
                // Delay for 5 seconds while the ID assignment takes place.
                //
                for(ulIdx = 0; ulIdx < 5000; ulIdx++)
                {
                    HWREGBITW(&g_ulFlags, FLAG_TICK) = 0;
                    while(HWREGBITW(&g_ulFlags, FLAG_TICK) == 0)
                    {
                    }
                }

                //
                // Remove the assignment indicator widget.
                //
                WidgetRemove((tWidget *)&g_sAssignWidget);

                //
                // Clear any button presses that may have occurred during the
                // ID assignment.
                //
                HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
                HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
                HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
                HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
                HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;
            }
        }

        //
        // Update the display.
        //
        DisplayFlush();
    }
}
//*****************************************************************************
//
// Handles presses of the next panel button.
//
//*****************************************************************************
void
OnNext(tWidget *pWidget)
{
    //
    // Play the key click sound.
    //
    SoundPlay(g_pusKeyClick, g_ulKeyClickLen);

    //
    // If we are on the last panel, return to the main application menu.
    //
    if(g_ulPanel == (NUM_PANELS - 1))
    {
        ShowUIScreen(HOME_SCREEN);
        return;
    }

    //
    // Remove the current panel.
    //
    WidgetRemove((tWidget *)(g_psPanels + g_ulPanel));

    //
    // Increment the panel index.
    //
    g_ulPanel++;

    //
    // Add and draw the new panel.
    //
    WidgetAdd((tWidget *)&g_sDemoScreen, (tWidget *)(g_psPanels + g_ulPanel));
    WidgetPaint((tWidget *)(g_psPanels + g_ulPanel));

    //
    // Set the title of this panel.
    //
    CanvasTextSet(&g_sTitle, g_pcPanelNames[g_ulPanel]);
    WidgetPaint((tWidget *)&g_sTitle);

    //
    // See if the previous panel was the first panel.
    //
    if(g_ulPanel == 1)
    {
        //
        // Replace the original text on the "Previous" button.
        //
        PushButtonTextSet(&g_sPrevious, "-");
        WidgetPaint((tWidget *)&g_sPrevious);
    }

    //
    // See if this is the last panel.
    //
    if(g_ulPanel == (NUM_PANELS - 1))
    {
        //
        // Replace the text on the "Next" button to read "X".
        //
        PushButtonTextSet(&g_sNext, "X");
        WidgetPaint((tWidget *)&g_sNext);
    }
}
//*****************************************************************************
//
// Displays the "About" panel.  The returned value is the ID of the panel to be
// displayed instead of the "About" panel.
//
//*****************************************************************************
unsigned long
DisplayAbout(void)
{
    unsigned long ulIdx, ulPanel;

    //
    // Add the "About" panel widgets to the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
    {
        WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psAboutWidgets + ulIdx));
    }

    //
    // Loop forever.  This loop will be explicitly exited when the proper
    // condition is detected.
    //
    while(1)
    {
        //
        // Update the display.
        //
        DisplayFlush();

        //
        // Wait until the select button is pressed or a serial download begins.
        //
        while((HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 0))
        {
        }

        //
        // Clear the press flags for the up, down, left, and right buttons.
        //
        HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
        HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
        HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
        HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;

        //
        // See if a serial download has begun.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 1)
        {
            //
            // Remove the "About" panel widgets.
            //
            for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
            {
                WidgetRemove((tWidget *)(g_psAboutWidgets + ulIdx));
            }

            //
            // Return the ID of the update panel.
            //
            return(PANEL_UPDATE);
        }

        //
        // See if the select button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 1)
        {
            //
            // Clear the press flag for the select button.
            //
            HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;

            //
            // Display the menu.
            //
            ulPanel = DisplayMenu(PANEL_ABOUT);

            //
            // See if another panel was selected.
            //
            if(ulPanel != PANEL_ABOUT)
            {
                //
                // Remove the "About" panel widgets.
                //
                for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
                {
                    WidgetRemove((tWidget *)(g_psAboutWidgets + ulIdx));
                }

                //
                // Return the ID of the newly selected panel.
                //
                return(ulPanel);
            }
        }
    }
}
//*****************************************************************************
//
// Handles presses of the next panel button.
//
//*****************************************************************************
void
OnNext(tWidget *pWidget)
{
    //
    // If this button is pressed when the last panel is displayed, we exit
    // back to keypad display.
    //
    if(g_ulPanel == (NUM_PANELS - 1))
    {
        //
        // Play the key click sound.
        //
        SoundPlay(g_pusKeyClick, sizeof(g_pusKeyClick) / 2);

        //
        // Fix up the widget tree to move us back to keypad mode.
        //
        GraphicsDemoHide();
        return;
    }

    //
    // Remove the current panel.
    //
    WidgetRemove((tWidget *)(g_psPanels + g_ulPanel));

    //
    // Increment the panel index.
    //
    g_ulPanel++;

    //
    // Add and draw the new panel.
    //
    WidgetAdd((tWidget *)&g_sDemoBackground,
              (tWidget *)(g_psPanels + g_ulPanel));
    WidgetPaint((tWidget *)(g_psPanels + g_ulPanel));

    //
    // Set the title of this panel.
    //
    CanvasTextSet(&g_sTitle, g_pcPanelNames[g_ulPanel]);
    WidgetPaint((tWidget *)&g_sTitle);

    //
    // Set the button text to read "X" (exit) if this is the last panel,
    // otherwise revert to the usual "+".
    //
    PushButtonTextSet(&g_sNext, (g_ulPanel == (NUM_PANELS - 1)) ? "X" : "+");
    WidgetPaint((tWidget *)&g_sNext);

    //
    // Set the "previous" button text to read "X" if this is the first panel,
    // otherwise revert to the usual "-".
    //
    PushButtonTextSet(&g_sPrevious, (g_ulPanel == 0) ? "X" : "-");
    WidgetPaint((tWidget *)&g_sPrevious);

    //
    // Play the key click sound.
    //
    SoundPlay(g_pusKeyClick, sizeof(g_pusKeyClick) / 2);
}
Exemple #18
0
//*****************************************************************************
//
// The "CD" button widget callback function.
//
// This function is called whenever someone presses the "CD" button.
//
//*****************************************************************************
void
OnBtnCD(tWidget *pWidget)
{
    int16_t i16Selected;
    uint32_t ui32Reason;
    FRESULT fresult;
    //
    // Get the current selection from the list box.
    //
    i16Selected = ListBoxSelectionGet(&g_sDirList);

    //
    // Is there any selection?
    //
    if(i16Selected == -1)
    {
        return;
    }
    else
    {
        //
        // Is the selection a directory name?
        //
        if(g_pcFilenames[i16Selected][1] == 'D')
        {
            //
            // Yes - change to the new directory.
            //
            fresult = ChangeToDirectory(&g_pcFilenames[i16Selected][4],
                                        &ui32Reason);

            if(fresult != FR_OK)
            {
                //
                // Update the status display to show the error.
                //
                PrintfStatus("Error changing directory.");
                PrintfStatus((char *)StringFromFresult(fresult));
            }
            else
            {
                //
                // Tell the user what happened.
                //
                PrintfStatus("Changed to %s", g_cCwdBuf);

                //
                // Update the directory name and the list box contents.
                //
                PopulateFileListBox(true);
                WidgetPaint((tWidget *)&g_sPWD);

                //
                // Enable the "Up" button and disable the "CD" button.
                //
                WidgetAdd((tWidget *)&g_sUpBackground, (tWidget *)&g_sUpBtn);
                WidgetRemove((tWidget *)&g_sCDBtn);

                //
                // Make sure the buttons are repainted correctly.
                //
                WidgetPaint((tWidget *)&g_sUpBtn);
                WidgetPaint((tWidget *)&g_sCDBackground);
            }
        }
    }
}
//*****************************************************************************
//
// Main application entry function.
//
//*****************************************************************************
int
main(void)
{
    tBoolean bSuccess, bRetcode, bInitialized;

    //
    // Set the system clock to run at 50MHz from the PLL
    //
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    //
    // NB: We don't call PinoutSet() in this testcase since the EM header
    // expansion board doesn't currently have an I2C ID EEPROM.  If we did
    // call PinoutSet() this would configure all the EPI pins for SDRAM and
    // we don't want to do this.
    //
    g_eDaughterType = DAUGHTER_NONE;

    //
    // Enable peripherals required to drive the LCD.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);

    //
    // Configure SysTick for a 10Hz interrupt.
    //
    ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / TICKS_PER_SECOND);
    ROM_SysTickEnable();
    ROM_SysTickIntEnable();

    //
    // Initialize the display driver.
    //
    Kitronix320x240x16_SSD2119Init();

    //
    // Initialize the touch screen driver.
    //
    TouchScreenInit();

    //
    // Set the touch screen event handler.
    //
    TouchScreenCallbackSet(WidgetPointerMessage);

    //
    // Add the compile-time defined widgets to the widget tree.
    //
    WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sHeading);

    //
    // Paint the widget tree to make sure they all appear on the display.
    //
    WidgetPaint(WIDGET_ROOT);

    //
    // Initialize the SimpliciTI BSP.
    //
    BSP_Init();

    //
    // Set the SimpliciTI device address using the current Ethernet MAC address
    // to ensure something like uniqueness.
    //
    bRetcode = SetSimpliciTIAddress();
    if(!bRetcode)
    {
        //
        // The Ethernet MAC address can't have been set so hang here since we
        // don't have an address to use for SimpliciTI.
        //
        WidgetMessageQueueProcess();
        while(1)
        {
            //
            // MAC address is not set so hang the app.
            //
        }
    }

    //
    // First time through, we need to initialize the SimpliciTI stack.
    //
    bInitialized = false;

    //
    // The main loop starts here now that we have joined the network.
    //
    while(1)
    {
        //
        // Tell the user what to do.
        //
        UpdateStatus(true, "Please choose the operating mode.");

        //
        // Now wait until the user selects whether we should run as the sender
        // or the receiver.
        //
        while(g_ulMode == MODE_UNDEFINED)
        {
            //
            // Just spin, processing UI messages and waiting for someone to
            // press one of the mode buttons.
            //
            WidgetMessageQueueProcess();
        }

        //
        // At this point, the mode is set so remove the buttons from the
        // display and replace them with the LEDs.
        //
        WidgetRemove((tWidget *)&g_sBtnContainer);
        WidgetAdd((tWidget *)&g_sBackground,
                  (tWidget *)&g_sLEDContainer);
        WidgetPaint((tWidget *)&g_sBackground);

        //
        // Tell the user what we're doing now.
        //
        UpdateStatus(false, "Joining network...");

        if(!bInitialized)
        {
            //
            // Initialize the SimpliciTI stack  We keep trying to initialize until
            // we get a success return code.  This indicates that we have also
            // successfully joined the network.
            //
            while(SMPL_SUCCESS != SMPL_Init((uint8_t (*)(linkID_t))0))
            {
                ToggleLED(1);
                ToggleLED(2);
                SPIN_ABOUT_A_SECOND;
            }

            //
            // Now that we are initialized, remember not to call this again.
            //
            bInitialized = true;
        }

        //
        // Once we have joined, turn both LEDs on and tell the user what we want
        // them to do.
        //
        SetLED(1, true);
        SetLED(2, true);

        //
        // Now call the function that initiates communication in
        // the desired mode.  Note that these functions will not return
        // until communication is established or an error occurs.
        //
        if(g_ulMode == MODE_SENDER)
        {
            bSuccess = LinkTo();
        }
        else
        {
            bSuccess = LinkFrom();
        }

        //
        // If we were unsuccessfull, go back to the mode selection
        // display.
        //
        if(!bSuccess)
        {
            //
            // Remove the LEDs and show the buttons again.
            //
            WidgetRemove((tWidget *)&g_sLEDContainer);
            WidgetAdd((tWidget *)&g_sBackground, (tWidget *)&g_sBtnContainer);
            WidgetPaint((tWidget *)&g_sBackground);

            //
            // Tell the user what happened.
            //
            UpdateStatus(false, "Error establishing communication!");

            //
            // Remember that we don't have an operating mode chosen.
            //
            g_ulMode = MODE_UNDEFINED;
        }
    }
}
//*****************************************************************************
//
// This function performs a CAN-based firmware update of a motor controller,
// displaying progress on the screen.
//
//*****************************************************************************
static void
CANUpdate(void)
{
    unsigned long ulIdx, ulLoop, *pulData, ulSize;

    //
    // Get a pointer to the local firmware image.
    //
    pulData = (unsigned long *)IMAGE_BASE;

    //
    // Get the size of the firmware image.
    //
    ulSize = *pulData++;

    //
    // Verify that the firmware image size is valid, the initial stack pointer
    // is valid, and the reset vector pointer is valid.
    //
    if((ulSize > 0x1f000) || ((pulData[0] & 0xffff0003) != 0x20000000) ||
       ((pulData[1] & 0xfff00001) != 0x00000001))
    {
        //
        // Indicate that the firmware image is not valid and return without
        // performing a firmware update.
        //
        usnprintf(g_pcMessageBuffer, sizeof(g_pcMessageBuffer),
                  "Invalid update image!");
        return;
    }

    //
    // Set the progress title to indicate that the motor controller is being
    // updated.
    //
    CanvasTextSet(g_psProgressWidgets + PROGRESS_TITLE, "Updating MDL-BDC");

    //
    // Add the progress bar widgets to the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_PROGRESS_WIDGETS; ulIdx++)
    {
        WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psProgressWidgets + ulIdx));
    }

    //
    // Gray the non-title widgets in the main panel.
    //
    UpdateWidgetsColor(ClrNotPresent);

    //
    // Set the progress bar to the beginning.
    //
    PROGRESS(0);

    //
    // Update the display.
    //
    DisplayFlush();

    //
    // Set the default message to a failure message.  This will be replaced
    // with a success message if the update is successful.
    //
    usnprintf(g_pcMessageBuffer, sizeof(g_pcMessageBuffer),
              "Update of %d failed!", g_ulCurrentID);

    //
    // A simple do/while(0) loop that is executed once (because of the while(0)
    // at the end) but can be easily exited with a break.  This allows a common
    // cleanup at the end (after the loop) while not having increasingly deep
    // nesting of the intervening code.
    //
    do
    {
        //
        // Tell the motor controller to enter firmware update mode.
        //
        CANUpdateStart();

        //
        // Delay for 50 milliseconds to allow it time to shut down and enter
        // the boot loader.
        //
        Delay(50);

        //
        // Try to ping the boot loader.
        //
        for(ulLoop = 10; (ulLoop != 0) && (g_ulCANUpdateAck == 0); ulLoop--)
        {
            //
            // Send a ping command.
            //
            g_ulCANUpdateAck = 0;
            CANUpdatePing();

            //
            // Delay up to 10 milliseconds waiting for the ACK.
            //
            DelayAck(10);
        }

        //
        // Abort the firmware update if the ACK was not received.
        //
        if(ulLoop == 0)
        {
            break;
        }

        //
        // Delay for 50 milliseconds.  If there were some CAN network delays,
        // it is possible that two pings were sent with the ACK from the first
        // ping being received right after the second ping was sent.  In this
        // case, this delay will allow time for the second ACK to be received
        // and processed; failure to do so would cause the remaining actions to
        // become out of sync.
        //
        Delay(50);

        //
        // Send the download command, causing the appropriate portion of flash
        // to be erased.
        //
        g_ulCANUpdateAck = 0;
        CANUpdateDownload(0x800, ulSize);

        //
        // Delay for up to 4 seconds waiting for the ACK.  Since flash is being
        // erased, it could take up to ~2.5 seconds (depending on the size of
        // the firmware image).
        //
        if(DelayAck(4000) == 0)
        {
            break;
        }

        //
        // Loop over the data in the firmware image.
        //
        for(ulLoop = 0; ulLoop < ulSize; ulLoop += 8)
        {
            //
            // Send the next two words of the firmware image.
            //
            g_ulCANUpdateAck = 0;
            CANUpdateSendData(((ulSize - ulLoop) > 8) ? 8 : ulSize - ulLoop,
                              pulData[0], pulData[1]);
            pulData += 2;

            //
            // Delay for up to 10 milliseconds waiting for the ACK.  Since
            // flash is being programming, it could take up to ~44
            // microseconds.
            //
            if(DelayAck(10) == 0)
            {
                break;
            }

            //
            // Update the progress bar and update the screen if the progress
            // bar has moved.
            //
            ulIdx = g_psProgressWidgets[PROGRESS_BAR].sBase.sPosition.sXMax;
            PROGRESS((ulLoop * 100) / ulSize);
            if(g_psProgressWidgets[PROGRESS_BAR].sBase.sPosition.sXMax !=
               ulIdx)
            {
                DisplayFlush();
            }
        }

        //
        // Abort the firmware update if the entire image was not programmed.
        //
        if(ulLoop < ulSize)
        {
            break;
        }

        //
        // Reset the motor controller.
        //
        CANUpdateReset();

        //
        // Delay for 500 milliseconds while the motor controller is being
        // reset.
        //
        Delay(500);

        //
        // Indicate that the firmware update was successful.
        //
        usnprintf(g_pcMessageBuffer, sizeof(g_pcMessageBuffer),
                  "Device %d updated.", g_ulCurrentID);

        //
        // Set the device ID so that any default configuration can be
        // performed.
        //
        CANSetID(g_ulCurrentID);
    }
    while(0);

    //
    // Remove the progress bar widgets.
    //
    for(ulIdx = 0; ulIdx < NUM_PROGRESS_WIDGETS; ulIdx++)
    {
        WidgetRemove((tWidget *)(g_psProgressWidgets + ulIdx));
    }

    //
    // Un-gray the non-title widgets in the main panel.
    //
    UpdateWidgetsColor(ClrWhite);
}
Exemple #21
0
//*****************************************************************************
//
// Displays the "Position Control Mode" panel.  The returned valud is the ID of
// the panel to be displayed instead of the "Position Control Mode" panel.
//
//*****************************************************************************
unsigned long
DisplayPosition(void)
{
    unsigned long ulPos, ulIdx, ulDelay, ulDemo, ulTime, ulStep;

    //
    // Read the current position mode configuration.
    //
    PositionConfigRead();

    //
    // Enable position control mode.
    //
    CANPositionModeEnable(((g_sPositionConfig.lPosition / 100) * 65536) +
                          (((g_sPositionConfig.lPosition % 100) * 65536) /
                           100));

    //
    // Initially, updates to the position occur immediately.
    //
    ulDelay = 0;

    //
    // Initially, demo mode is disabled.
    //
    ulDemo = 0;
    ulTime = 0;
    ulStep = 0;

    //
    // Disable the widget fill for all the widgets except the one for the
    // device ID selection.
    //
    for(ulIdx = 0; ulIdx < 7; ulIdx++)
    {
        CanvasFillOff(g_psPositionWidgets + ulIdx);
    }
    CanvasFillOn(g_psPositionWidgets + 1);

    //
    // Add the "Position Control Mode" panel widgets to the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
    {
        WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psPositionWidgets + ulIdx));
    }

    //
    // Enable the status display.
    //
    StatusEnable(0);

    //
    // Set the default cursor position to the device ID selection.
    //
    ulPos = 1;

    //
    // Loop forever.  This loop will be explicitly exited when the proper
    // condition is detected.
    //
    while(1)
    {
        //
        // Print out the current device ID.
        //
        usnprintf(g_pcIDBuffer, sizeof(g_pcIDBuffer), "%d", g_ulCurrentID);

        //
        // Print out the current position.
        //
        if(g_sPositionConfig.lPosition < 0)
        {
            usnprintf(g_pcPositionBuffer, sizeof(g_pcPositionBuffer),
                      "-%d.%02d", (0 - g_sPositionConfig.lPosition) / 100,
                      (0 - g_sPositionConfig.lPosition) % 100);
        }
        else
        {
            usnprintf(g_pcPositionBuffer, sizeof(g_pcPositionBuffer),
                      "%d.%02d", g_sPositionConfig.lPosition / 100,
                      g_sPositionConfig.lPosition % 100);
        }

        //
        // Print out the current P coefficient.
        //
        if(g_sPositionConfig.lP < 0)
        {
            usnprintf(g_pcPositionPBuffer, sizeof(g_pcPositionPBuffer),
                      "-%d.%03d", (0 - g_sPositionConfig.lP) / 1000,
                      (0 - g_sPositionConfig.lP) % 1000);
        }
        else
        {
            usnprintf(g_pcPositionPBuffer, sizeof(g_pcPositionPBuffer),
                      "%d.%03d", g_sPositionConfig.lP / 1000,
                      g_sPositionConfig.lP % 1000);
        }

        //
        // Irint out the current I coefficient.
        //
        if(g_sPositionConfig.lI < 0)
        {
            usnprintf(g_pcPositionIBuffer, sizeof(g_pcPositionIBuffer),
                      "-%d.%03d", (0 - g_sPositionConfig.lI) / 1000,
                      (0 - g_sPositionConfig.lI) % 1000);
        }
        else
        {
            usnprintf(g_pcPositionIBuffer, sizeof(g_pcPositionIBuffer),
                      "%d.%03d", g_sPositionConfig.lI / 1000,
                      g_sPositionConfig.lI % 1000);
        }

        //
        // Print out the current D coefficient.
        //
        if(g_sPositionConfig.lD < 0)
        {
            usnprintf(g_pcPositionDBuffer, sizeof(g_pcPositionDBuffer),
                      "-%d.%03d", (0 - g_sPositionConfig.lD) / 1000,
                      (0 - g_sPositionConfig.lD) % 1000);
        }
        else
        {
            usnprintf(g_pcPositionDBuffer, sizeof(g_pcPositionDBuffer),
                      "%d.%03d", g_sPositionConfig.lD / 1000,
                      g_sPositionConfig.lD % 1000);
        }

        //
        // Print out the current position reference source.
        //
        usnprintf(g_pcReferenceBuffer, sizeof(g_pcReferenceBuffer), "%s",
                  g_ppcPosReference[g_sPositionConfig.ulPosRef]);

        //
        // Update the status display.
        //
        StatusUpdate();

        //
        // Update the display.
        //
        DisplayFlush();

        //
        // See if a serial download has begun.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 1)
        {
            //
            // Disable the status display.
            //
            StatusDisable();

            //
            // Remove the "Position Control Mode" panel widgets.
            //
            for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
            {
                WidgetRemove((tWidget *)(g_psPositionWidgets + ulIdx));
            }
            CanvasTextColorSet(g_psPositionWidgets + 2, ClrWhite);

            //
            // Disable position control mode.
            //
            CANPositionModeDisable();

            //
            // Return the ID of the update panel.
            //
            return(PANEL_UPDATE);
        }

        //
        // See if demo mode is enabled.
        //
        if(ulDemo != 0)
        {
            //
            // See if the current time delay has expired.
            //
            if(ulTime < g_ulTickCount)
            {
                //
                // Increment to the next step, wrapping back to the beginning
                // of the sequence when the end has been reached.
                //
                ulStep++;
                if(ulStep == (sizeof(g_plPositionDemo) /
                              sizeof(g_plPositionDemo[0])))
                {
                    ulStep = 0;
                }

                //
                // Set the position as directed by the next step.
                //
                g_sPositionConfig.lPosition = g_plPositionDemo[ulStep][0];
                CANPositionSet(((g_sPositionConfig.lPosition / 100) * 65536) +
                               (((g_sPositionConfig.lPosition % 100) * 65536) /
                                100), 0);

                //
                // Set the time delay for this step.
                //
                ulTime = g_ulTickCount + g_plPositionDemo[ulStep][1];
            }
        }

        //
        // See if the up button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not already at the top of the
            // screen and a delayed position update is not in progress.
            //
            if((ulPos != 0) && (ulDelay == 0))
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psPositionWidgets + ulPos);

                //
                // Decrement the cursor row, skipping the position row when
                // demo mode is enabled.
                //
                ulPos--;
                if((ulPos == 2) && (ulDemo != 0))
                {
                    ulPos--;
                }

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psPositionWidgets + ulPos);
            }

            //
            // Clear the press flag for the up button.
            //
            HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
        }

        //
        // See if the down button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not already at the bottom of the
            // screen and a delayed position update is not in progress.
            //
            if((ulPos != 6) && (ulDelay == 0))
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psPositionWidgets + ulPos);

                //
                // Increment the cursor row, skipping the position row when
                // demo mode is enabled.
                //
                ulPos++;
                if((ulPos == 2) && (ulDemo != 0))
                {
                    ulPos++;
                }

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psPositionWidgets + ulPos);
            }

            //
            // Clear the press flag for the down button.
            //
            HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
        }

        //
        // See if the left button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) == 1)
        {
            //
            // See if the device ID is being changed.
            //
            if(ulPos == 1)
            {
                //
                // Only change the device ID if it is greater than one.
                //
                if(g_ulCurrentID > 1)
                {
                    //
                    // Exit demo mode.
                    //
                    ulDemo = 0;
                    CanvasTextColorSet(g_psPositionWidgets + 2, ClrWhite);

                    //
                    // Disable position control mode for the current device ID.
                    //
                    CANPositionModeDisable();

                    //
                    // Decrement the device ID.
                    //
                    if((HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1) ||
                       (HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1) ||
                       (HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1))
                    {
                        if(g_ulCurrentID > 3)
                        {
                            CANSetID(g_ulCurrentID - 3);
                        }
                        else
                        {
                            CANSetID(1);
                        }
                    }
                    else
                    {
                        CANSetID(g_ulCurrentID - 1);
                    }

                    //
                    // Read the configuration of the new device.
                    //
                    PositionConfigRead();

                    //
                    // Enable position control mode.
                    //
                    CANPositionModeEnable(((g_sPositionConfig.lPosition /
                                            100) * 65536) +
                                          (((g_sPositionConfig.lPosition %
                                             100) * 65536) / 100));
                }
            }

            //
            // See if the position is being changed.
            //
            else if(ulPos == 2)
            {
                //
                // Only change the position if it is not already fully
                // negative.
                //
                if(g_sPositionConfig.lPosition > -20000)
                {
                    //
                    // Decrement the position.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1)
                    {
                        g_sPositionConfig.lPosition -= 11;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1)
                    {
                        g_sPositionConfig.lPosition -= 111;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1)
                    {
                        g_sPositionConfig.lPosition -= 1111;
                    }
                    else
                    {
                        g_sPositionConfig.lPosition--;
                    }
                    if(g_sPositionConfig.lPosition < -20000)
                    {
                        g_sPositionConfig.lPosition = -20000;
                    }

                    //
                    // Send the updated position to the motor controller if a
                    // delayed update is not in progress.
                    //
                    if(ulDelay == 0)
                    {
                        CANPositionSet(((g_sPositionConfig.lPosition / 100) *
                                        65536) +
                                       (((g_sPositionConfig.lPosition % 100) *
                                         65536) / 100), 0);
                    }
                }
            }

            //
            // See if the position P gain is being changed.
            //
            else if(ulPos == 3)
            {
                //
                // Only change the P gain if it is not already fully negative.
                //
                if(g_sPositionConfig.lP > (-32767 * 1000))
                {
                    //
                    // Decrement the P gain.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1)
                    {
                        g_sPositionConfig.lP -= 11;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1)
                    {
                        g_sPositionConfig.lP -= 111;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1)
                    {
                        g_sPositionConfig.lP -= 1111;
                    }
                    else
                    {
                        g_sPositionConfig.lP--;
                    }
                    if(g_sPositionConfig.lP < (-32767 * 1000))
                    {
                        g_sPositionConfig.lP = -32767 * 1000;
                    }

                    //
                    // Send the new P gain to the motor controller.
                    //
                    CANPositionPGainSet(((g_sPositionConfig.lP / 1000) *
                                         65536) +
                                        (((g_sPositionConfig.lP % 1000) *
                                          65536) / 1000));
                }
            }

            //
            // See if the position I gain is being changed.
            //
            else if(ulPos == 4)
            {
                //
                // Only change the I gain if it is not already fully negative.
                //
                if(g_sPositionConfig.lI > (-32767 * 1000))
                {
                    //
                    // Decrement the I gain.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1)
                    {
                        g_sPositionConfig.lI -= 11;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1)
                    {
                        g_sPositionConfig.lI -= 111;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1)
                    {
                        g_sPositionConfig.lI -= 1111;
                    }
                    else
                    {
                        g_sPositionConfig.lI--;
                    }
                    if(g_sPositionConfig.lI < (-32767 * 1000))
                    {
                        g_sPositionConfig.lI = -32767 * 1000;
                    }

                    //
                    // Send the new I gain to the motor controller.
                    //
                    CANPositionIGainSet(((g_sPositionConfig.lI / 1000) *
                                         65536) +
                                        (((g_sPositionConfig.lI % 1000) *
                                          65536) / 1000));
                }
            }

            //
            // See if the position D gain is being changed.
            //
            else if(ulPos == 5)
            {
                //
                // Only change the D gain if it is not already fully negative.
                //
                if(g_sPositionConfig.lD > (-32767 * 1000))
                {
                    //
                    // Decrement the D gain.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1)
                    {
                        g_sPositionConfig.lD -= 11;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1)
                    {
                        g_sPositionConfig.lD -= 111;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1)
                    {
                        g_sPositionConfig.lD -= 1111;
                    }
                    else
                    {
                        g_sPositionConfig.lD--;
                    }
                    if(g_sPositionConfig.lD < (-32767 * 1000))
                    {
                        g_sPositionConfig.lD = -32767 * 1000;
                    }

                    //
                    // Send the new D gain to the motor controller.
                    //
                    CANPositionDGainSet(((g_sPositionConfig.lD / 1000) *
                                         65536) +
                                        (((g_sPositionConfig.lD % 1000) *
                                          65536) / 1000));
                }
            }

            //
            // See if the position reference source is being changed.
            //
            else if(ulPos == 6)
            {
                //
                // Toggle to the other position reference source.
                //
                g_sPositionConfig.ulPosRef ^= 1;

                //
                // Send the position reference source to the motor controller.
                //
                CANPositionRefSet(g_sPositionConfig.ulPosRef);
            }

            //
            // Clear the press flag for the left button.
            //
            HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) = 0;
            HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) = 0;
            HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) = 0;
        }

        //
        // See if the right button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) == 1)
        {
            //
            // See if the device ID is being changed.
            //
            if(ulPos == 1)
            {
                //
                // Only change the device ID if it is less than 63.
                //
                if(g_ulCurrentID < 63)
                {
                    //
                    // Exit demo mode.
                    //
                    ulDemo = 0;
                    CanvasTextColorSet(g_psPositionWidgets + 2, ClrWhite);

                    //
                    // Disable position control mode for the current device ID.
                    //
                    CANPositionModeDisable();

                    //
                    // Increment the device ID.
                    //
                    if((HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1) ||
                       (HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1) ||
                       (HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1))
                    {
                        if(g_ulCurrentID < 60)
                        {
                            CANSetID(g_ulCurrentID + 3);
                        }
                        else
                        {
                            CANSetID(63);
                        }
                    }
                    else
                    {
                        CANSetID(g_ulCurrentID + 1);
                    }

                    //
                    // Read the configuration of the new device.
                    //
                    PositionConfigRead();

                    //
                    // Enable position control mode.
                    //
                    CANPositionModeEnable(((g_sPositionConfig.lPosition /
                                            100) * 65536) +
                                          (((g_sPositionConfig.lPosition %
                                             100) * 65536) / 100));
                }
            }

            //
            // See if the position is being changed.
            //
            else if(ulPos == 2)
            {
                //
                // Only change the position if it is not already fully
                // positive.
                //
                if(g_sPositionConfig.lPosition < 20000)
                {
                    //
                    // Increment the position.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1)
                    {
                        g_sPositionConfig.lPosition += 11;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1)
                    {
                        g_sPositionConfig.lPosition += 111;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1)
                    {
                        g_sPositionConfig.lPosition += 1111;
                    }
                    else
                    {
                        g_sPositionConfig.lPosition++;
                    }
                    if(g_sPositionConfig.lPosition > 20000)
                    {
                        g_sPositionConfig.lPosition = 20000;
                    }

                    //
                    // Send the updated position to the motor controller if a
                    // delayed update is not in progress.
                    //
                    if(ulDelay == 0)
                    {
                        CANPositionSet(((g_sPositionConfig.lPosition / 100) *
                                        65536) +
                                       (((g_sPositionConfig.lPosition % 100) *
                                         65536) / 100), 0);
                    }
                }
            }

            //
            // See if the position P gain is being changed.
            //
            else if(ulPos == 3)
            {
                //
                // Only change the P gain if it is not already fully positive.
                //
                if(g_sPositionConfig.lP < (32767 * 1000))
                {
                    //
                    // Increment the P gain.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1)
                    {
                        g_sPositionConfig.lP += 11;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1)
                    {
                        g_sPositionConfig.lP += 111;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1)
                    {
                        g_sPositionConfig.lP += 1111;
                    }
                    else
                    {
                        g_sPositionConfig.lP++;
                    }
                    if(g_sPositionConfig.lP > (32767 * 1000))
                    {
                        g_sPositionConfig.lP = 32767 * 1000;
                    }

                    //
                    // Send the new P gain to the motor controller.
                    //
                    CANPositionPGainSet(((g_sPositionConfig.lP / 1000) *
                                         65536) +
                                        (((g_sPositionConfig.lP % 1000) *
                                          65536) / 1000));
                }
            }

            //
            // See if the position I gain is being changed.
            //
            else if(ulPos == 4)
            {
                //
                // Only change the I gain if it is not already fully positive.
                //
                if(g_sPositionConfig.lI < (32767 * 1000))
                {
                    //
                    // Increment the I gain.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1)
                    {
                        g_sPositionConfig.lI += 11;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1)
                    {
                        g_sPositionConfig.lI += 111;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1)
                    {
                        g_sPositionConfig.lI += 1111;
                    }
                    else
                    {
                        g_sPositionConfig.lI++;
                    }
                    if(g_sPositionConfig.lI > (32767 * 1000))
                    {
                        g_sPositionConfig.lI = 32767 * 1000;
                    }

                    //
                    // Send the new I gain to the motor controller.
                    //
                    CANPositionIGainSet(((g_sPositionConfig.lI / 1000) *
                                         65536) +
                                        (((g_sPositionConfig.lI % 1000) *
                                          65536) / 1000));
                }
            }

            //
            // See if the position D gain is being changed.
            //
            else if(ulPos == 5)
            {
                //
                // Only change the D gain if it is not already fully positive.
                //
                if(g_sPositionConfig.lD < (32767 * 1000))
                {
                    //
                    // Increment the D gain.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1)
                    {
                        g_sPositionConfig.lD += 11;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1)
                    {
                        g_sPositionConfig.lD += 111;
                    }
                    else if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1)
                    {
                        g_sPositionConfig.lD += 1111;
                    }
                    else
                    {
                        g_sPositionConfig.lD++;
                    }
                    if(g_sPositionConfig.lD > (32767 * 1000))
                    {
                        g_sPositionConfig.lD = 32767 * 1000;
                    }

                    //
                    // Send the new D gain to the motor controller.
                    //
                    CANPositionDGainSet(((g_sPositionConfig.lD / 1000) *
                                         65536) +
                                        (((g_sPositionConfig.lD % 1000) *
                                          65536) / 1000));
                }
            }

            //
            // See if the position reference source is being changed.
            //
            else if(ulPos == 6)
            {
                //
                // Toggle to the other position reference source.
                //
                g_sPositionConfig.ulPosRef ^= 1;

                //
                // Send the position reference source to the motor controller.
                //
                CANPositionRefSet(g_sPositionConfig.ulPosRef);
            }

            //
            // Clear the press flag for the right button.
            //
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) = 0;
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) = 0;
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) = 0;
        }

        //
        // See if the select button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 1)
        {
            //
            // Clear the press flag for the select button.
            //
            HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;

            //
            // See if the cursor is on the top row of the screen.
            //
            if(ulPos == 0)
            {
                //
                // Display the menu.
                //
                ulIdx = DisplayMenu(PANEL_POSITION);

                //
                // See if another panel was selected.
                //
                if(ulIdx != PANEL_POSITION)
                {
                    //
                    // Disable the status display.
                    //
                    StatusDisable();

                    //
                    // Remove the "Position Control Mode" panel widgets.
                    //
                    for(ulPos = 0; ulPos < NUM_WIDGETS; ulPos++)
                    {
                        WidgetRemove((tWidget *)(g_psPositionWidgets + ulPos));
                    }
                    CanvasTextColorSet(g_psPositionWidgets + 2, ClrWhite);

                    //
                    // Disable position control mode.
                    //
                    CANPositionModeDisable();

                    //
                    // Return the ID of the newly selected panel.
                    //
                    return(ulIdx);
                }

                //
                // Since the "Position Control Mode" panel was selected from
                // the menu, move the cursor down one row.
                //
                CanvasFillOff(g_psPositionWidgets);
                ulPos++;
                CanvasFillOn(g_psPositionWidgets + 1);
            }

            //
            // See if the cursor is on the ID selection.
            //
            else if(ulPos == 1)
            {
                //
                // Toggle demo mode.
                //
                ulDemo ^= 1;

                //
                // See if the demo has just been disabled.
                //
                if(ulDemo == 0)
                {
                    //
                    // Set the output position to the current position.
                    //
                    if(g_lStatusPosition < 0)
                    {
                        g_sPositionConfig.lPosition =
                            (((g_lStatusPosition / 65536) * 100) +
                             ((((g_lStatusPosition % 65536) * 100) - 32768) /
                              65536));
                    }
                    else
                    {
                        g_sPositionConfig.lPosition =
                            (((g_lStatusPosition / 65536) * 100) +
                             ((((g_lStatusPosition % 65536) * 100) + 32768) /
                              65536));
                    }
                    CANPositionSet(((g_sPositionConfig.lPosition / 100) *
                                    65536) +
                                   (((g_sPositionConfig.lPosition % 100) *
                                     65536) / 100), 0);

                    //
                    // Indicate that demo mode has exited by setting the text
                    // color to white.
                    //
                    CanvasTextColorSet(g_psPositionWidgets + 2, ClrWhite);
                }

                //
                // Otherwise start demo mode.
                //
                else
                {
                    //
                    // Indicate that demo mode is active by setting the text
                    // color to gray.
                    //
                    CanvasTextColorSet(g_psPositionWidgets + 2, ClrSelected);

                    //
                    // Start with the first step.
                    //
                    ulStep = 0;

                    //
                    // Set the position as directed by the first step.
                    //
                    g_sPositionConfig.lPosition = g_plPositionDemo[0][0];
                    CANPositionSet(((g_sPositionConfig.lPosition / 100) *
                                    65536) +
                                   (((g_sPositionConfig.lPosition % 100) *
                                     65536) / 100), 0);

                    //
                    // Set the time delay for the first step.
                    //
                    ulTime = g_ulTickCount + g_plPositionDemo[0][1];
                }
            }

            //
            // See if the cursor is on the position selection.
            //
            else if(ulPos == 2)
            {
                //
                // Toggle the state of the delayed update.
                //
                ulDelay ^= 1;

                //
                // See if a delayed update should be performed.
                //
                if(ulDelay == 0)
                {
                    //
                    // Send the delayed position update.
                    //
                    CANPositionSet(((g_sPositionConfig.lPosition / 100) *
                                    65536) +
                                   (((g_sPositionConfig.lPosition % 100) *
                                     65536) / 100), 0);

                    //
                    // Change the text color of the position selection to white
                    // to indicate that updates will occur immediately.
                    //
                    CanvasTextColorSet(g_psPositionWidgets + 2, ClrWhite);
                }
                else
                {
                    //
                    // Change the text color of the position selection to black
                    // to indicate that updates will be delayed.
                    //
                    CanvasTextColorSet(g_psPositionWidgets + 2, ClrBlack);
                }
            }
        }
    }
}
//*****************************************************************************
//
// This function monitors the UART-based firmware update and displays the
// progress on the screen.
//
//*****************************************************************************
static unsigned long
UARTUpdate(void)
{
    unsigned long ulIdx, ulCount;

    //
    // Set the progress title to indicate that the firmware is being downloaded
    // from the PC.
    //
    CanvasTextSet(g_psProgressWidgets + PROGRESS_TITLE, "Updating from PC");

    //
    // Add the progress bar widgets to the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_PROGRESS_WIDGETS; ulIdx++)
    {
        WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psProgressWidgets + ulIdx));
    }

    //
    // Gray the non-title widgets in the main panel.
    //
    UpdateWidgetsColor(ClrNotPresent);

    //
    // Set the progress bar to the beginning.
    //
    PROGRESS(0);

    //
    // Update the display.
    //
    DisplayFlush();

    //
    // Reset the counter of the amount of time since the last serial boot
    // loader packet was seen.
    //
    ulCount = 0;

    //
    // Loop while there is still data to be received from the UART.
    //
    while(g_ulImageSize)
    {
        //
        // Wait for a tick or a serial boot loader packet.
        //
        while((HWREGBITW(&g_ulFlags, FLAG_TICK) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 0))
        {
        }

        //
        // See if a serial boot loader packet was received.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 1)
        {
            //
            // Reset the timeout counter.
            //
            ulCount = 0;

            //
            // Clear the serial boot loader packet flag.
            //
            HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) = 0;
        }

        //
        // See if a timer tick has occurred.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_TICK) == 1)
        {
            //
            // Increment the timeout counter.
            //
            ulCount++;

            //
            // Stop waiting if the serial download has timed out.
            //
            if(ulCount == SERIAL_UPDATE_TIMEOUT)
            {
                break;
            }

            //
            // Clear the timer tick flag.
            //
            HWREGBITW(&g_ulFlags, FLAG_TICK) = 0;
        }

        //
        // Update the progress bar and update the screen if the progress bar
        // has moved.
        //
        ulIdx = g_psProgressWidgets[PROGRESS_BAR].sBase.sPosition.sXMax;
        PROGRESS((g_ulImageOffset * 100) / g_ulImageSize);
        if(g_psProgressWidgets[PROGRESS_BAR].sBase.sPosition.sXMax != ulIdx)
        {
            DisplayFlush();
        }
    }

    //
    // Clear the serial boot loader packet flag.
    //
    HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) = 0;

    //
    // Remove the progress bar widgets.
    //
    for(ulIdx = 0; ulIdx < NUM_PROGRESS_WIDGETS; ulIdx++)
    {
        WidgetRemove((tWidget *)(g_psProgressWidgets + ulIdx));
    }

    //
    // Un-gray the non-title widgets in the main panel.
    //
    UpdateWidgetsColor(ClrWhite);

    //
    // If the update timed out, set the message to indicate the failure and
    // return a failure.
    //
    if(ulCount == SERIAL_UPDATE_TIMEOUT)
    {
        usnprintf(g_pcMessageBuffer, sizeof(g_pcMessageBuffer),
                  "Update from PC failed");
        return(1);
    }

    //
    // Return indicating that the serial download was successful.
    //
    return(0);
}
//*****************************************************************************
//
// Handles presses of the next panel button.
//
//*****************************************************************************
void
OnNext(tWidget *psWidget)
{
    //
    // There is nothing to be done if the last panel is already being
    // displayed.
    //
    if(g_ui32Panel == (NUM_PANELS - 1))
    {
        return;
    }

    //
    // Remove the current panel.
    //
    WidgetRemove((tWidget *)(g_psPanels + g_ui32Panel));

    //
    // Increment the panel index.
    //
    g_ui32Panel++;

    //
    // Add and draw the new panel.
    //
    WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psPanels + g_ui32Panel));
    WidgetPaint((tWidget *)(g_psPanels + g_ui32Panel));

    //
    // Set the title of this panel.
    //
    GrStringGet(g_ui32PanelNames[g_ui32Panel], g_pcTitle, TITLE_MAX_SIZE);
    WidgetPaint((tWidget *)&g_sTitle);

    //
    // See if the previous panel was the first panel.
    //
    if(g_ui32Panel == 1)
    {
        //
        // Display the previous button.
        //
        PushButtonImageOn(&g_sPrevious);
        PushButtonTextOn(&g_sPrevious);
        PushButtonFillOff(&g_sPrevious);
        WidgetPaint((tWidget *)&g_sPrevious);
    }

    //
    // See if this is the last panel.
    //
    if(g_ui32Panel == (NUM_PANELS - 1))
    {
        //
        // Clear the next button from the display since the last panel is being
        // displayed.
        //
        PushButtonImageOff(&g_sNext);
        PushButtonTextOff(&g_sNext);
        PushButtonFillOn(&g_sNext);
        WidgetPaint((tWidget *)&g_sNext);
    }
}
//*****************************************************************************
//
// Displays the "Firmware Update" panel.  The returned valud is the ID of the
// panel to be displayed instead of the "Firmware Update" panel.
//
//*****************************************************************************
unsigned long
DisplayUpdate(void)
{
    unsigned long ulPos, ulIdx;

    //
    // Disable the widget fill for all the widgets except the one for device
    // ID 1.
    //
    for(ulIdx = 0; ulIdx < 3; ulIdx++)
    {
        CanvasFillOff(g_psUpdateWidgets + ulIdx);
    }
    CanvasFillOn(g_psUpdateWidgets + 1);

    //
    // Add the "Firmware Update" panel widgets to the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_UPDATE_WIDGETS; ulIdx++)
    {
        WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psUpdateWidgets + ulIdx));
    }

    //
    // Set the default cursor position to the device ID selection.
    //
    ulPos = 1;

    //
    // Clear the message buffer.
    //
    g_pcMessageBuffer[0] = '\0';

    //
    // Loop forever.  This loop will be explicitly exited when the proper
    // condition is detected.
    //
    while(1)
    {
        //
        // Print out the current device ID.
        //
        usnprintf(g_pcIDBuffer, sizeof(g_pcIDBuffer), "%d", g_ulCurrentID);

        //
        // Print out the firmware version.
        //
        if(g_ulStatusFirmwareVersion == 0xffffffff)
        {
            usnprintf(g_pcVersionBuffer, sizeof(g_pcVersionBuffer), "---");
        }
        else
        {
            usnprintf(g_pcVersionBuffer, sizeof(g_pcVersionBuffer), "%d",
                      g_ulStatusFirmwareVersion);
        }

        //
        // Update the display.
        //
        DisplayFlush();

        //
        // Wait until a button is pressed, the firmware version is received, or
        // a serial download begins.
        //
        while((HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 0))
        {
        }

        //
        // See if the up button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not already at the top of the
            // screen.
            //
            if(ulPos != 0)
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psUpdateWidgets + ulPos);

                //
                // Decrement the cursor row.
                //
                ulPos--;

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psUpdateWidgets + ulPos);
            }

            //
            // Clear the press flag for the up button.
            //
            HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
        }

        //
        // See if the down button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not already at the bottom of the
            // screen.
            //
            if(ulPos != 2)
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psUpdateWidgets + ulPos);

                //
                // Increment the cursor row.
                //
                ulPos++;

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psUpdateWidgets + ulPos);
            }

            //
            // Clear the press flag for the down button.
            //
            HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
        }

        //
        // See if the left button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) == 1)
        {
            //
            // Only change the device ID if it is greater than one.
            //
            if((ulPos == 1) && (g_ulCurrentID > 1))
            {
                //
                // Decrement the device ID.
                //
                CANSetID(g_ulCurrentID - 1);
            }

            //
            // Clear the press flag for the left button.
            //
            HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
        }

        //
        // See if the right button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) == 1)
        {
            //
            // Only change the device ID if it is less than 63.
            //
            if((ulPos == 1) && (g_ulCurrentID < 63))
            {
                //
                // Increment the device ID.
                //
                CANSetID(g_ulCurrentID + 1);
            }

            //
            // Clear the press flag for the right button.
            //
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
        }

        //
        // See if the select button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 1)
        {
            //
            // Clear the press flag for the select button.
            //
            HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;

            //
            // See if the cursor is on the top row of the screen.
            //
            if(ulPos == 0)
            {
                //
                // Display the menu.
                //
                ulIdx = DisplayMenu(PANEL_UPDATE);

                //
                // See if another panel was selected.
                //
                if(ulIdx != PANEL_UPDATE)
                {
                    //
                    // Remove the "Firmware Update" panel widgets.
                    //
                    for(ulPos = 0; ulPos < NUM_UPDATE_WIDGETS; ulPos++)
                    {
                        WidgetRemove((tWidget *)(g_psUpdateWidgets + ulPos));
                    }

                    //
                    // Return the ID of the newly selected panel.
                    //
                    return(ulIdx);
                }

                //
                // Since the "Firmware Update" panel was selected from the
                // menu, move the cursor down one row.
                //
                CanvasFillOff(g_psUpdateWidgets);
                ulPos++;
                CanvasFillOn(g_psUpdateWidgets + 1);
            }

            //
            // See if the cursor is on the start button.
            //
            else if(ulPos == 2)
            {
                //
                // Turn off the fill on the start button.
                //
                CanvasFillOff(g_psUpdateWidgets + 2);

                //
                // Perform the CAN update.
                //
                CANUpdate();

                //
                // Turn on the fill on the start button.
                //
                CanvasFillOn(g_psUpdateWidgets + 2);

                //
                // Clear the button press flags so that any button presses that
                // occur during the firmware update are ignored.
                //
                HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
                HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
                HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
                HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
                HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;
            }
        }

        //
        // See if a serial download has begun.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 1)
        {
            //
            // Turn off the fill on the current cursor location.
            //
            CanvasFillOff(g_psUpdateWidgets + ulPos);

            //
            // Monitor the UART firmware download.
            //
            if(UARTUpdate() == 0)
            {
                //
                // The firmware was successfully downloaded via the UART, so
                // update the current motor controller with the new firmware.
                //
                CANUpdate();
            }

            //
            // Turn on the fill on the current cursor location.
            //
            CanvasFillOn(g_psUpdateWidgets + ulPos);

            //
            // Clear the button press flags so that any button presses that
            // occur during the firmware update are ignored.
            //
            HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;
        }
    }
}
//*****************************************************************************
//
// Main application entry function.
//
//*****************************************************************************
int
main(void)
{
    tBoolean bSuccess, bRetcode;
    unsigned char pucMsg[2];
    unsigned char ucTid;
    unsigned char ucDelay;
    unsigned long ulLastRxCount, ulLastTxCount;
    smplStatus_t eRetcode;

    //
    // Set the system clock to run at 50MHz from the PLL
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    //
    // NB: We don't call PinoutSet() in this testcase since the EM header
    // expansion board doesn't currently have an I2C ID EEPROM.  If we did
    // call PinoutSet() this would configure all the EPI pins for SDRAM and
    // we don't want to do this.
    //
    g_eDaughterType = DAUGHTER_NONE;

    //
    // Enable peripherals required to drive the LCD.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);

    //
    // Configure SysTick for a 10Hz interrupt.
    //
    ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / TICKS_PER_SECOND);
    ROM_SysTickEnable();
    ROM_SysTickIntEnable();

    //
    // Initialize the display driver.
    //
    Kitronix320x240x16_SSD2119Init();

    //
    // Initialize the touch screen driver.
    //
    TouchScreenInit();

    //
    // Set the touch screen event handler.
    //
    TouchScreenCallbackSet(WidgetPointerMessage);

    //
    // Add the compile-time defined widgets to the widget tree.
    //
    WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sHeading);

    //
    // Initialize the status string.
    //
    UpdateStatus(true, "Please choose the operating mode.");

    //
    // Paint the widget tree to make sure they all appear on the display.
    //
    WidgetPaint(WIDGET_ROOT);

    //
    // Initialize the SimpliciTI BSP.
    //
    BSP_Init();

    //
    // Set the SimpliciTI device address using the current Ethernet MAC address
    // to ensure something like uniqueness.
    //
    bRetcode = SetSimpliciTIAddress();
    if(!bRetcode)
    {
        //
        // The board does not have a MAC address configured so we can't set
        // the SimpliciTI device address (which we derive from the MAC address).
        //
        while(1);
    }

    //
    // Initialize the SimpliciTI stack and supply our receive callback
    // function pointer.
    //
    SMPL_Init(RxCallback);

    //
    // Initialize our message ID, initial inter-message delay and packet
    // counters.
    //
    ucTid = 0;
    ucDelay = 0;
    ulLastRxCount = 0;
    ulLastTxCount = 0;

    //
    // Fall into the command line processing loop.
    //
    while (1)
    {
        //
        // Process any messages from or for the widgets.
        //
        WidgetMessageQueueProcess();

        //
        // Check to see if we've been told to do anything.
        //
        if(g_ulCommandFlags)
        {
            //
            // Has the mode been set?  If so, set up the display to show the
            // "LEDs" and then start communication.
            //
            if(HWREGBITW(&g_ulCommandFlags, COMMAND_MODE_SET))
            {
                //
                // Clear the bit now that we have seen it.
                //
                HWREGBITW(&g_ulCommandFlags, COMMAND_MODE_SET) = 0;

                //
                // Remove the buttons and replace them with the LEDs then
                // repaint the display.
                //
                WidgetRemove((tWidget *)&g_sBtnContainer);
                WidgetAdd((tWidget *)&g_sBackground,
                          (tWidget *)&g_sLEDContainer);
                WidgetPaint((tWidget *)&g_sBackground);

                //
                // Now call the function that initiates communication in
                // the desired mode.  Note that these functions will not return
                // until communication is established or an error occurs.
                //
                if(g_ulMode == MODE_TALKER)
                {
                    bSuccess = LinkTo();
                }
                else
                {
                    bSuccess = LinkFrom();
                }

                //
                // If we were unsuccessfull, go back to the mode selection
                // display.
                //
                if(!bSuccess)
                {
                    //
                    // Remove the LEDs and show the buttons again.
                    //
                    WidgetRemove((tWidget *)&g_sLEDContainer);
                    WidgetAdd((tWidget *)&g_sBackground,
                              (tWidget *)&g_sBtnContainer);
                    WidgetPaint((tWidget *)&g_sBackground);

                    //
                    // Tell the user what happened.
                    //
                    UpdateStatus(false, "Error establishing communication!");
                    UpdateStatus(true, "Please choose the operating mode.");

                    //
                    // Remember that we don't have an operating mode chosen.
                    //
                    g_ulMode = MODE_UNDEFINED;
                }
            }

            //
            // Have we been asked to toggle the first "LED"?
            //
            if(HWREGBITW(&g_ulCommandFlags, COMMAND_LED1_TOGGLE))
            {
                //
                // Clear the bit now that we have seen it.
                //
                HWREGBITW(&g_ulCommandFlags, COMMAND_LED1_TOGGLE) = 0;

                //
                // Toggle the LED.
                //
                ToggleLED(1);
            }

            //
            // Have we been asked to toggle the second "LED"?
            //
            if(HWREGBITW(&g_ulCommandFlags, COMMAND_LED2_TOGGLE))
            {
                //
                // Clear the bit now that we have seen it.
                //
                HWREGBITW(&g_ulCommandFlags, COMMAND_LED2_TOGGLE) = 0;

                //
                // Toggle the LED.
                //
                ToggleLED(2);
            }

            //
            // Have we been asked to send a packet back to our peer?  This
            // command is only ever sent to the main loop when we are running
            // in listener mode (LinkListen).
            //
            if(HWREGBITW(&g_ulCommandFlags, COMMAND_SEND_REPLY))
            {
                //
                // Clear the bit now that we have seen it.
                //
                HWREGBITW(&g_ulCommandFlags, COMMAND_SEND_REPLY) = 0;

                //
                // Create the message.  The first byte tells the receiver to
                // toggle LED1 and the second is a sequence counter.
                //
                pucMsg[0] = 1;
                pucMsg[1] = ++ucTid;
                eRetcode = SMPL_Send(sLinkID, pucMsg, 2);

                //
                // Update our transmit counter if we transmitted the packet
                // successfully.
                //
                if(eRetcode == SMPL_SUCCESS)
                {
                    g_ulTxCount++;
                }
                else
                {
                    UpdateStatus(false, "TX error %s (%d)", MapSMPLStatus(eRetcode),
                                 eRetcode);
                }
            }
        }

        //
        // If we are the talker (LinkTo mode), check to see if it's time to
        // send another packet to our peer.
        //
        if((g_ulMode == MODE_TALKER) &&
           (g_ulSysTickCount >= g_ulNextPacketTick))
        {
            //
            // Create the message.  The first byte tells the receiver to
            // toggle LED1 and the second is a sequence counter.
            //
            pucMsg[0] = 1;
            pucMsg[1] = ++ucTid;
            eRetcode = SMPL_Send(sLinkID, pucMsg, 2);

            //
            // Update our transmit counter if we transmitted the packet
            // correctly.
            //
            if(eRetcode == SMPL_SUCCESS)
            {
                g_ulTxCount++;
            }
            else
            {
                UpdateStatus(false, "TX error %s (%d)", MapSMPLStatus(eRetcode),
                             eRetcode);
            }

            //
            // Set the delay before the next message.
            //
#ifndef USE_2_SECOND_DELAY
            //
            // Set the delay before the next message.  We increase this from 1
            // second to 4 seconds then cycle back to 1.
            //
            ucDelay = (ucDelay == 4) ? 1 : (ucDelay + 1);
#else
            //
            // Wait 2 seconds before sending the next message.
            //
            ucDelay = 2;
#endif

            //
            // Calculate the system tick count when our delay has completed.
            // This algorithm will generate a spurious packet every 13.7 years
            // since I don't handle the rollover case in the comparison above
            // but I'm pretty sure you will forgive me for this oversight.
            //
            g_ulNextPacketTick = g_ulSysTickCount +
                                 (TICKS_PER_SECOND * ucDelay);
        }

        //
        // If either the transmit or receive packet count changed, update
        // the status on the display.
        //
        if((g_ulRxCount != ulLastRxCount) || (g_ulTxCount != ulLastTxCount))
        {
            ulLastTxCount = g_ulTxCount;
            ulLastRxCount = g_ulRxCount;
            UpdateStatus(false, "Received %d pkts, sent %d (%d)",
                         ulLastRxCount, ulLastTxCount);
        }
    }
}
//*****************************************************************************
//
// Displays the "VComp Control Mode" panel.  The returned valud is the ID of
// the panel to be displayed instead of the "VComp Control Mode" panel.
//
//*****************************************************************************
unsigned long
DisplayVComp(void)
{
    unsigned long ulRamp, ulComp, ulPos, ulIdx, ulDelay, ulDemo, ulTime;
    unsigned long ulStep;
    long lVoltage;

    //
    // Enable voltage compensation control mode.
    //
    CANVCompModeEnable();

    //
    // Set the default voltage.
    //
    lVoltage = 0;
    CANVCompSet(0, 0);

    //
    // Read the ramp rate.
    //
    if(CANReadParameter(LM_API_VCOMP_IN_RAMP, 0, &ulRamp, 0) == 0)
    {
        ulRamp = 0;
    }
    else
    {
        ulRamp = (((ulRamp & 0xffff) * 100) + 128) / 256;
    }

    //
    // Read the compensation rate.
    //
    if(CANReadParameter(LM_API_VCOMP_COMP_RAMP, 0, &ulComp, 0) == 0)
    {
        ulComp = 0;
    }
    else
    {
        ulComp = (((ulComp & 0xffff) * 100) + 128) / 256;
    }

    //
    // Initially, updates to the voltage occur immediately.
    //
    ulDelay = 0;

    //
    // Initially, demo mode is disabled.
    //
    ulDemo = 0;
    ulTime = 0;
    ulStep = 0;

    //
    // Disable the widget fill for all the widgets except the one for the
    // device ID selection.
    //
    for(ulIdx = 0; ulIdx < 4; ulIdx++)
    {
        CanvasFillOff(g_psVCompWidgets + ulIdx);
    }
    CanvasFillOn(g_psVCompWidgets + 1);

    //
    // Add the "VComp Control Mode" panel widgets to the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
    {
        WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psVCompWidgets + ulIdx));
    }

    //
    // Enable the status display.
    //
    StatusEnable(0);

    //
    // Set the default cursor position to the device ID selection.
    //
    ulPos = 1;

    //
    // Loop forever.  This loop will be explicitly exited when the proper
    // condition is detected.
    //
    while(1)
    {
        //
        // Print out the current device ID.
        //
        usnprintf(g_pcIDBuffer, sizeof(g_pcIDBuffer), "%d", g_ulCurrentID);

        //
        // Print out the current voltage.
        //
        if(lVoltage < 0)
        {
            usnprintf(g_pcVoltageBuffer, sizeof(g_pcVoltageBuffer),
                      "-%d.%01d V", (0 - lVoltage) / 10, (0 - lVoltage) % 10);
        }
        else
        {
            usnprintf(g_pcVoltageBuffer, sizeof(g_pcVoltageBuffer),
                      "%d.%01d V", lVoltage / 10, lVoltage % 10);
        }

        //
        // Print out the current ramp rate.
        //
        if(ulRamp == 0)
        {
            usnprintf(g_pcRampBuffer, sizeof(g_pcRampBuffer), "none");
        }
        else
        {
            usnprintf(g_pcRampBuffer, sizeof(g_pcRampBuffer), "%d.%02d V/ms",
                      ulRamp / 100, ulRamp % 100);
        }

        //
        // Print out the current compensation rate.
        //
        if(ulComp == 0)
        {
            usnprintf(g_pcCompBuffer, sizeof(g_pcCompBuffer), "none");
        }
        else
        {
            usnprintf(g_pcCompBuffer, sizeof(g_pcCompBuffer), "%d.%02d V/ms",
                      ulComp / 100, ulComp % 100);
        }

        //
        // Update the status display.
        //
        StatusUpdate();

        //
        // Update the display.
        //
        DisplayFlush();

        //
        // See if a serial download has begun.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 1)
        {
            //
            // Disable the status display.
            //
            StatusDisable();

            //
            // Remove the "VComp Control Mode" panel widgets.
            //
            for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
            {
                WidgetRemove((tWidget *)(g_psVCompWidgets + ulIdx));
            }
            CanvasTextColorSet(g_psVCompWidgets + 2, ClrWhite);

            //
            // Set the output voltage to zero.
            //
            CANVCompSet(0, 0);

            //
            // Return the ID of the update panel.
            //
            return(PANEL_UPDATE);
        }

        //
        // See if demo mode is enabled.
        //
        if(ulDemo != 0)
        {
            //
            // See if the current time delay has expired.
            //
            if(ulTime < g_ulTickCount)
            {
                //
                // Increment to the next step, wrapping back to the beginning
                // of the sequence when the end has been reached.
                //
                ulStep++;
                if(ulStep ==
                   (sizeof(g_plVCompDemo) / sizeof(g_plVCompDemo[0])))
                {
                    ulStep = 0;
                }

                //
                // Set the voltage as directed by the next step.
                //
                lVoltage = g_plVCompDemo[ulStep][0];
                CANVCompSet((lVoltage * 256) / 10, 0);

                //
                // Set the time delay for this step.
                //
                ulTime = g_ulTickCount + g_plVCompDemo[ulStep][1];
            }
        }

        //
        // See if the up button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not already at the top of the
            // screen and a delayed voltage update is not in progress.
            //
            if((ulPos != 0) && (ulDelay == 0))
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psVCompWidgets + ulPos);

                //
                // Decrement the cursor row, skipping the voltage row when demo
                // mode is enabled.
                //
                ulPos--;
                if((ulPos == 2) && (ulDemo != 0))
                {
                    ulPos--;
                }

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psVCompWidgets + ulPos);
            }

            //
            // Clear the press flag for the up button.
            //
            HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
        }

        //
        // See if the down button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) == 1)
        {
            //
            // Only move the cursor if it is not already at the bottom of the
            // screen and a delayed voltage update is not in progress.
            //
            if((ulPos != 4) && (ulDelay == 0))
            {
                //
                // Disable the widget fill for the currently selected widget.
                //
                CanvasFillOff(g_psVCompWidgets + ulPos);

                //
                // Increment the cursor row, skipping the voltage row when demo
                // mode is enabled.
                //
                ulPos++;
                if((ulPos == 2) && (ulDemo != 0))
                {
                    ulPos++;
                }

                //
                // Enable the widget fill for the newly selected widget.
                //
                CanvasFillOn(g_psVCompWidgets + ulPos);
            }

            //
            // Clear the press flag for the down button.
            //
            HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
        }

        //
        // See if the left button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) == 1)
        {
            //
            // See if the device ID is being changed.
            //
            if(ulPos == 1)
            {
                //
                // Only change the device ID if it is greater than one.
                //
                if(g_ulCurrentID > 1)
                {
                    //
                    // Exit demo mode.
                    //
                    ulDemo = 0;
                    CanvasTextColorSet(g_psVCompWidgets + 2, ClrWhite);

                    //
                    // Set the voltage to 0 for the current device ID.
                    //
                    CANVCompSet(0, 0);

                    //
                    // Decrement the device ID.
                    //
                    if((HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1) ||
                       (HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1) ||
                       (HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1))
                    {
                        if(g_ulCurrentID > 3)
                        {
                            CANSetID(g_ulCurrentID - 3);
                        }
                        else
                        {
                            CANSetID(1);
                        }
                    }
                    else
                    {
                        CANSetID(g_ulCurrentID - 1);
                    }

                    //
                    // Enable voltage compensation mode.
                    //
                    CANVCompModeEnable();

                    //
                    // Set the voltage for the new device.
                    //
                    lVoltage = 0;
                    CANVCompSet(0, 0);

                    //
                    // Read the ramp rate.
                    //
                    if(CANReadParameter(LM_API_VCOMP_IN_RAMP, 0, &ulRamp,
                                        0) == 0)
                    {
                        ulRamp = 0;
                    }
                    else
                    {
                        ulRamp = (((ulRamp & 0xffff) * 100) + 128) / 256;
                    }

                    //
                    // Read the compensation rate.
                    //
                    if(CANReadParameter(LM_API_VCOMP_COMP_RAMP, 0, &ulComp,
                                        0) == 0)
                    {
                        ulComp = 0;
                    }
                    else
                    {
                        ulComp = (((ulComp & 0xffff) * 100) + 128) / 256;
                    }
                }
            }

            //
            // See if the voltage is being changed.
            //
            else if(ulPos == 2)
            {
                //
                // Only change the voltage if it is not already full reverse.
                //
                if(lVoltage > -120)
                {
                    //
                    // Decrement the voltage.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1)
                    {
                        lVoltage -= 11;
                    }
                    else if((HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1) ||
                            (HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1))
                    {
                        lVoltage -= 111;
                    }
                    else
                    {
                        lVoltage--;
                    }
                    if(lVoltage < -120)
                    {
                        lVoltage = -120;
                    }

                    //
                    // Send the updated voltage to the motor controller if a
                    // delayed update is not in progress.
                    //
                    if(ulDelay == 0)
                    {
                        CANVCompSet((lVoltage * 256) / 10, 0);
                    }
                }
            }

            //
            // See if the voltage ramp rate is being changed.
            //
            else if(ulPos == 3)
            {
                //
                // Only change the ramp rate if it is not already zero.
                //
                if(ulRamp > 0)
                {
                    //
                    // Decrement the voltage ramp rate.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1)
                    {
                        ulRamp -= 11;
                    }
                    else if((HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1) ||
                            (HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1))
                    {
                        ulRamp -= 111;
                    }
                    else
                    {
                        ulRamp--;
                    }
                    if(ulRamp & 0x80000000)
                    {
                        ulRamp = 0;
                    }

                    //
                    // Send the updated voltage ramp rate.
                    //
                    CANVCompInRampSet((ulRamp * 256) / 100);
                }
            }

            //
            // See if the compensation rate is being changed.
            //
            else if(ulPos == 4)
            {
                //
                // Only change the compensation rate if it is not already zero.
                //
                if(ulComp > 0)
                {
                    //
                    // Decrement the compensation rate.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) == 1)
                    {
                        ulComp -= 11;
                    }
                    else if((HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) == 1) ||
                            (HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) == 1))
                    {
                        ulComp -= 111;
                    }
                    else
                    {
                        ulComp--;
                    }
                    if(ulComp & 0x80000000)
                    {
                        ulComp = 0;
                    }

                    //
                    // Send the updated compensation rate.
                    //
                    CANVCompCompRampSet((ulComp * 256) / 100);
                }
            }

            //
            // Clear the press flag for the left button.
            //
            HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL1) = 0;
            HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL2) = 0;
            HWREGBITW(&g_ulFlags, FLAG_LEFT_ACCEL3) = 0;
        }

        //
        // See if the right button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) == 1)
        {
            //
            // See if the device ID is being changed.
            //
            if(ulPos == 1)
            {
                //
                // Only change the device ID if it is less than 63.
                //
                if(g_ulCurrentID < 63)
                {
                    //
                    // Exit demo mode.
                    //
                    ulDemo = 0;
                    CanvasTextColorSet(g_psVCompWidgets + 2, ClrWhite);

                    //
                    // Set the voltage to 0 for the current device ID.
                    //
                    CANVCompSet(0, 0);

                    //
                    // Increment the device ID.
                    //
                    if((HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1) ||
                       (HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1) ||
                       (HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1))
                    {
                        if(g_ulCurrentID < 60)
                        {
                            CANSetID(g_ulCurrentID + 3);
                        }
                        else
                        {
                            CANSetID(63);
                        }
                    }
                    else
                    {
                        CANSetID(g_ulCurrentID + 1);
                    }

                    //
                    // Enable voltage compensation control mode.
                    //
                    CANVCompModeEnable();

                    //
                    // Set the voltage for the new device.
                    //
                    lVoltage = 0;
                    CANVCompSet(0, 0);

                    //
                    // Read the ramp rate.
                    //
                    if(CANReadParameter(LM_API_VCOMP_IN_RAMP, 0, &ulRamp,
                                        0) == 0)
                    {
                        ulRamp = 0;
                    }
                    else
                    {
                        ulRamp = (((ulRamp & 0xffff) * 100) + 128) / 256;
                    }

                    //
                    // Read the compensation rate.
                    //
                    if(CANReadParameter(LM_API_VCOMP_COMP_RAMP, 0, &ulComp,
                                        0) == 0)
                    {
                        ulComp = 0;
                    }
                    else
                    {
                        ulComp = (((ulComp & 0xffff) * 100) + 128) / 256;
                    }
                }
            }

            //
            // See if the voltage is being changed.
            //
            else if(ulPos == 2)
            {
                //
                // Only change the voltage if it is not already full forward.
                //
                if(lVoltage < 120)
                {
                    //
                    // Increment the voltage.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1)
                    {
                        lVoltage += 11;
                    }
                    else if((HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1) ||
                            (HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1))
                    {
                        lVoltage += 111;
                    }
                    else
                    {
                        lVoltage++;
                    }
                    if(lVoltage > 120)
                    {
                        lVoltage = 120;
                    }

                    //
                    // Send the updated voltage to the motor controller if a
                    // delayed update is not in progress.
                    //
                    if(ulDelay == 0)
                    {
                        CANVCompSet((lVoltage * 256) / 10, 0);
                    }
                }
            }

            //
            // See if the voltage ramp rate is being changed.
            //
            else if(ulPos == 3)
            {
                //
                // Only change the ramp rate if it is not already the maximum.
                //
                if(ulRamp < 1200)
                {
                    //
                    // Increment the voltage ramp rate.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1)
                    {
                        ulRamp += 11;
                    }
                    else if((HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1) ||
                            (HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1))
                    {
                        ulRamp += 111;
                    }
                    else
                    {
                        ulRamp++;
                    }
                    if(ulRamp > 1200)
                    {
                        ulRamp = 1200;
                    }

                    //
                    // Send the updated voltage ramp rate.
                    //
                    CANVCompInRampSet((ulRamp * 256) / 100);
                }
            }

            //
            // See if the compensation rate is being changed.
            //
            else if(ulPos == 4)
            {
                //
                // Only change the compensation rate if it is not already the
                // maximum.
                //
                if(ulComp < 1200)
                {
                    //
                    // Increment the compensation rate.
                    //
                    if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) == 1)
                    {
                        ulComp += 11;
                    }
                    else if((HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) == 1) ||
                            (HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) == 1))
                    {
                        ulComp += 111;
                    }
                    else
                    {
                        ulComp++;
                    }
                    if(ulComp > 1200)
                    {
                        ulComp = 1200;
                    }

                    //
                    // Send the updated compensation rate.
                    //
                    CANVCompCompRampSet((ulComp * 256) / 100);
                }
            }

            //
            // Clear the press flag for the right button.
            //
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL1) = 0;
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL2) = 0;
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_ACCEL3) = 0;
        }

        //
        // See if the select button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 1)
        {
            //
            // Clear the press flag for the select button.
            //
            HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;

            //
            // See if the cursor is on the top row of the screen.
            //
            if(ulPos == 0)
            {
                //
                // Display the menu.
                //
                ulIdx = DisplayMenu(PANEL_VCOMP);

                //
                // See if another panel was selected.
                //
                if(ulIdx != PANEL_VCOMP)
                {
                    //
                    // Disable the status display.
                    //
                    StatusDisable();

                    //
                    // Remove the "VComp Control Mode" panel widgets.
                    //
                    for(ulPos = 0; ulPos < NUM_WIDGETS; ulPos++)
                    {
                        WidgetRemove((tWidget *)(g_psVCompWidgets + ulPos));
                    }
                    CanvasTextColorSet(g_psVCompWidgets + 2, ClrWhite);

                    //
                    // Set the output voltage to zero.
                    //
                    CANVCompSet(0, 0);

                    //
                    // Return the ID of the newly selected panel.
                    //
                    return(ulIdx);
                }

                //
                // Since the "VComp Control Mode" panel was selected from the
                // menu, move the cursor down one row.
                //
                CanvasFillOff(g_psVCompWidgets);
                ulPos++;
                CanvasFillOn(g_psVCompWidgets + 1);
            }

            //
            // See if the cursor is on the ID selection.
            //
            else if(ulPos == 1)
            {
                //
                // Toggle demo mode.
                //
                ulDemo ^= 1;

                //
                // See if the demo has just been disabled.
                //
                if(ulDemo == 0)
                {
                    //
                    // Set the output voltage to zero.
                    //
                    lVoltage = 0;
                    CANVCompSet(0, 0);

                    //
                    // Indicate that demo mode has exited by setting the text
                    // color to white.
                    //
                    CanvasTextColorSet(g_psVCompWidgets + 2, ClrWhite);
                }

                //
                // Otherwise start demo mode.
                //
                else
                {
                    //
                    // Indicate that demo mode is active by setting the text
                    // color to gray.
                    //
                    CanvasTextColorSet(g_psVCompWidgets + 2, ClrSelected);

                    //
                    // Start with the first step.
                    //
                    ulStep = 0;

                    //
                    // Set the voltage as directed by the first step.
                    //
                    lVoltage = g_plVCompDemo[0][0];
                    CANVCompSet((lVoltage * 256) / 10, 0);

                    //
                    // Set the time delay for the first step.
                    //
                    ulTime = g_ulTickCount + g_plVCompDemo[0][1];
                }
            }

            //
            // See if the cursor is on the voltage selection.
            //
            else if(ulPos == 2)
            {
                //
                // Toggle the state of the delayed update.
                //
                ulDelay ^= 1;

                //
                // See if a delayed update should be performed.
                //
                if(ulDelay == 0)
                {
                    //
                    // Send the delayed voltage update.
                    //
                    CANVCompSet((lVoltage * 256) / 10, 0);

                    //
                    // Change the text color of the voltage selection to white
                    // to indicate that updates will occur immediately.
                    //
                    CanvasTextColorSet(g_psVCompWidgets + 2, ClrWhite);
                }
                else
                {
                    //
                    // Change the text color of the voltage selection to black
                    // to indicate that updates will be delayed.
                    //
                    CanvasTextColorSet(g_psVCompWidgets + 2, ClrBlack);
                }
            }
        }
    }
}
Exemple #27
0
void ClrMyWidget() {
	WidgetRemove((tWidget *) &g_sBackground);
}
Exemple #28
0
//*****************************************************************************
//
// Displays the "Help" panel.  The returned value is the ID of the panel to be
// displayed instead of the "Help" panel.
//
//*****************************************************************************
unsigned long
DisplayHelp(void)
{
    unsigned long ulIdx, ulPanel;

    //
    // Add the "Help" panel widgets to the widget list.
    //
    for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
    {
        WidgetAdd(WIDGET_ROOT, (tWidget *)(g_psHelpWidgets + ulIdx));
    }

    //
    // Set the help text offset to zero.
    //
    g_ulDelta = 0;

    //
    // Loop forever.  This loop will be explicitly exited when the proper
    // condition is detected.
    //
    while(1)
    {
        //
        // Update the display.
        //
        DisplayFlush();

        //
        // Wait until the up, down, left, right, or select button is pressed,
        // or a serial download begins.
        //
        while((HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 0) &&
              (HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 0))
        {
        }

        //
        // See if a serial download has begun.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SERIAL_BOOTLOADER) == 1)
        {
            //
            // Remove the "Help" panel widgets.
            //
            for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
            {
                WidgetRemove((tWidget *)(g_psHelpWidgets + ulIdx));
            }

            //
            // Return the ID of the update panel.
            //
            return(PANEL_UPDATE);
        }

        //
        // See if the up button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) == 1)
        {
            //
            // Decrement the help text offset if the first line of help text is
            // not presently visible.
            //
            if(g_ulDelta > 0)
            {
                g_ulDelta--;
            }

            //
            // Clear the press flag for the up button.
            //
            HWREGBITW(&g_ulFlags, FLAG_UP_PRESSED) = 0;
        }

        //
        // See if the down button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) == 1)
        {
            //
            // Increment the help text offset if the last line of help text is
            // not presently visible.
            //
            if(g_ulDelta < (NUM_LINES - 10))
            {
                g_ulDelta++;
            }

            //
            // Clear the press flag for the down button.
            //
            HWREGBITW(&g_ulFlags, FLAG_DOWN_PRESSED) = 0;
        }

        //
        // See if the left button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) == 1)
        {
            //
            // Skip to the previous section only if not already at the
            // beginning of the help text.
            //
            if(g_ulDelta != 0)
            {
                //
                // Decrement by one line.
                //
                g_ulDelta--;

                //
                // Look for the start of the previous section, stopping at the
                // beginning of the help text if one is not found.
                //
                while(g_ulDelta != 0)
                {
                    //
                    // Stop looking if this line starts a section.
                    //
                    if(g_ppcHelpText[g_ulDelta][0] == '\001')
                    {
                        break;
                    }

                    //
                    // Decrement by one line.
                    //
                    g_ulDelta--;
                }
            }

            //
            // Clear the press flag for the left button.
            //
            HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
        }

        //
        // See if the right button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) == 1)
        {
            //
            // Skip to the next section only if not already at the end of the
            // help text.
            //
            if(g_ulDelta != (NUM_LINES - 10))
            {
                //
                // Increment by one line.
                //
                g_ulDelta++;

                //
                // Look for the start of the next section, stopping at the end
                // of the help text if one is not found.
                //
                while(g_ulDelta != (NUM_LINES - 10))
                {
                    //
                    // Stop looking if this line starts a section.
                    //
                    if(g_ppcHelpText[g_ulDelta][0] == '\001')
                    {
                        break;
                    }

                    //
                    // Increment by one line.
                    //
                    g_ulDelta++;
                }
            }

            //
            // Clear the press flag for the right button.
            //
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
        }

        //
        // See if the select button was pressed.
        //
        if(HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) == 1)
        {
            //
            // Clear the press flag for the left, right, and select buttons.
            //
            HWREGBITW(&g_ulFlags, FLAG_LEFT_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_RIGHT_PRESSED) = 0;
            HWREGBITW(&g_ulFlags, FLAG_SELECT_PRESSED) = 0;

            //
            // Display the menu.
            //
            ulPanel = DisplayMenu(PANEL_HELP);

            //
            // See if another panel was selected.
            //
            if(ulPanel != PANEL_HELP)
            {
                //
                // Remove the "About" panel widgets.
                //
                for(ulIdx = 0; ulIdx < NUM_WIDGETS; ulIdx++)
                {
                    WidgetRemove((tWidget *)(g_psHelpWidgets + ulIdx));
                }

                //
                // Return the ID of the newly selected panel.
                //
                return(ulPanel);
            }
        }
    }
}