This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LM4F

I am working on a motor control project, and I have made my design based on LM4F211H5QR processor due to DK-LM4F-DRV8312 kit. TI has replaced these series with TIVA processors. I couldn't find any support for TIVA regarding INSTASPIN. What should I do? Can I use my software that I have written to L4F211H5QR?

  • Hi Tarik,

         

    Tarik KABAKLI said:
    Can I use my software that I have written to L4F211H5QR?

         See app note below.

         Migrating Software Projects from Stellarisware to Tivaware

    -kel

  • Hello,

    I am a new TI product user.

    I use a EK-LM4120XL rev B with LM4F120H5QR processor and I am on Code Compose Studio 5.5.0. I use the SSI communication with pins : pa2, pa3, pa4,pa5.

    I want to make a SSI communication with a LCD. It doesn't work yet. So I tested with an oscilloscope if there is a voltage on SSI0CLK, SSI0Tx, and the SSI0Fss. But there is nothing, except V(SSI0Fs)=3,3V

    My data width is 1bit DCX + 8 bit Data ( 9bit ).

    However my UART0 communication with a terminal works well.

    Could someone please give me some helps ?

    /*
     * hello_demo.c
     *
     *  Created on: 22 mai 2014
     *      Author: r.jost
     */
    
    //
    // Copyright (c) 2008-2012 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // Texasnstruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    //
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    //
    // This is part of revision 9453 of the RDK-IDM Firmware Package.
    //
    //*****************************************************************************
    
    #include "inc/hw_types.h"
    #include "driverlib/flash.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "grlib/grlib.h"
    #include "utils/locator.h"
    #include "utils/swupdate.h"
    #include "utils/ustdlib.h"
    #include "utils/uartstdio.h"
    #include "drivers/formike240x320x16_ili9340.h"
    #include "driverlib/gpio.h"
    #include "driverlib/uart.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_sysctl.h"
    #include "driverlib/flash.h"
    
    
    // The number of SysTick ticks per second.
    //
    //*****************************************************************************
    #define TICKS_PER_SECOND 100
    
    //*****************************************************************************
    //
    // Defines for the pins that are used to communicate with the ILI934x.
    //
    //*****************************************************************************
    #define GPIO_PA0_U0RX        0x00000001
    #define GPIO_PA1_U0TX        0x00000401
    
    void
    InitConsoleUART(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
        //     (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioInit(0);
    }
    
    
    
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    
    
    //*****************************************************************************
    //
    // Print "Hello World!" to the display on the Intelligent Display Module.
    //
    //*****************************************************************************
    int
    main(void)
    {
        tContext sContext;
        tRectangle sRect;
        //unsigned long Clock;
    
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //The Stellaris LaunchPad uses a 16.0-MHz crystal (Y2) to complete the LM4F120H5QR microcontroller
        //main internal clock circuit. An internal PLL, configured in software, multiples this clock to higher
        //frequencies for core and peripheral timing.
        SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
        //SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
    
        SysCtlClockGet();
    
        //
        // Configure SysTick for a 100Hz interrupt.
        //
        //SysTickPeriodSet(SysCtlClockGet() / TICKS_PER_SECOND);
        //SysTickEnable();
        //SysTickIntEnable();
    
        //
        // Enable Interrupts
        //
        //IntMasterEnable();
    
    
        InitConsoleUART();
    
        UARTprintf("LCD Initialization\n");
    
        //
        // Initialize the display driver.
        //
        Formike240x320x16_ILI9340Init();
    
        //
        // Turn on the backlight.
        //
        Formike240x320x16_ILI9340BacklightOn();
    
        //
        // Initialize the graphics context.
        //
        GrContextInit(&sContext, &g_sFormike240x320x16_ILI9340);
    
        //
        // Fill the top 24 rows of the screen with blue to create the banner.
        //
        sRect.sXMin = 0;
        sRect.sYMin = 0;
        sRect.sXMax = GrContextDpyWidthGet(&sContext) - 1;
        sRect.sYMax = 23;
        GrContextForegroundSet(&sContext, ClrDarkBlue);
        GrRectFill(&sContext, &sRect);
    
        //
        // Put a white box around the banner.
        //
        GrContextForegroundSet(&sContext, ClrYellow);
        GrRectDraw(&sContext, &sRect);
    
        //
        // Put the application name in the middle of the banner.
        //
        GrContextFontSet(&sContext, g_pFontCm20);
        GrStringDrawCentered(&sContext, "hello", -1,
                             GrContextDpyWidthGet(&sContext) / 2, 11, 0);
    
        //
        // Say hello using the Computer Modern 40 point font.
        //
        GrContextFontSet(&sContext, g_pFontCm40);
        GrStringDrawCentered(&sContext, "Hello World!", -1,
                             GrContextDpyWidthGet(&sContext) / 2,
                             ((GrContextDpyHeightGet(&sContext) - 24) / 2) + 24,
                             0);
    
        //
        // Flush any cached drawing operations.
        //
        GrFlush(&sContext);
    
    }
    
    
    
    //*****************************************************************************
    //
    // grlib_demo.c - Demonstration of the Stellaris Graphics Library.
    //
    // Copyright (c) 2008-2012 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 9453 of the RDK-IDM Firmware Package.
    //
    //*****************************************************************************
    //#define PART_LM4F120H5QR
    #define PART_LM4F120E5QR
    
    #include "inc/hw_memmap.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_types.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/flash.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/gpio.h"
    #include "grlib/grlib.h"
    #include "grlib/widget.h"
    #include "grlib/canvas.h"
    #include "grlib/checkbox.h"
    #include "grlib/container.h"
    #include "grlib/pushbutton.h"
    #include "grlib/radiobutton.h"
    #include "grlib/slider.h"
    #include "drivers/formike240x320x16_ili9340.h"
    #include "drivers/sound.h"
    #include "drivers/touch.h"
    #include "images.h"
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>Graphics Library Demonstration (grlib_demo)</h1>
    //!
    //! This application provides a demonstration of the capabilities of the
    //! Stellaris Graphics Library.  A series of panels show different features of
    //! the library.  For each panel, the bottom provides a forward and back button
    //! (when appropriate), along with a brief description of the contents of the
    //! panel.
    //!
    //! The first panel provides some introductory text and basic instructions for
    //! operation of the application.
    //!
    //! The second panel shows the available drawing primitives: lines, circles,
    //! rectangles, strings, and images.
    //!
    //! The third panel shows the canvas widget, which provides a general drawing
    //! surface within the widget hierarchy.  A text, image, and application-drawn
    //! canvas are displayed.
    //!
    //! The fourth panel shows the check box widget, which provides a means of
    //! toggling the state of an item.  Four check boxes are provided, with each
    //! having a red ``LED'' to the right.  The state of the LED tracks the state
    //! of the check box via an application callback.
    //!
    //! The fifth panel shows the container widget, which provides a grouping
    //! construct typically used for radio buttons.  Containers with a title, a
    //! centered title, and no title are displayed.
    //!
    //! The sixth panel shows the push button widget.  Two columns of push buttons
    //! are provided; the appearance of each column is the same but the left column
    //! does not utilize auto-repeat while the right column does.  Each push button
    //! has a red ``LED'' to its left, which is toggled via an application callback
    //! each time the push button is pressed.
    //!
    //! The seventh panel shows the radio button widget.  Two groups of radio
    //! buttons are displayed, the first using text and the second using images for
    //! the selection value.  Each radio button has a red ``LED'' to its right,
    //! which tracks the selection state of the radio buttons via an application
    //! callback.  Only one radio button from each group can be selected at a time,
    //! though the radio buttons in each group operate independently.
    //!
    //! The eighth panel shows the slider widget.  Six sliders constructed using
    //! the various supported style options are shown.  The slider value callback
    //! is used to update two widgets to reflect the values reported by sliders.
    //! A canvas widget in the top right of the display tracks the value of the
    //! red and green image-based slider to its left and the text of the grey slider
    //! on the left side of the panel is update to show its own value.  The
    //! rightmost slider is configured as an indicator which tracks the state of
    //! the upper slider and ignores user input.
    //!
    //! The final panel provides instructions and information necessary to update
    //! the board firmware via ethernet using the LM Flash Programmer application.
    //! When using a version of LM Flash Programmer with a build number greater
    //! than 560, software updates will occur automatically without user
    //! intervention being required in the application.  If using an earlier
    //! version of LM Flash Programmer which does not send the ``magic packet''
    //! signalling an update request, the ``Update'' button on the final screen may
    //! be pressed to transfer control to the boot loader in preparation for a
    //! firmware download.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // A global flag used to indicate if a remote firmware update request has been
    // received.
    //
    //*****************************************************************************
    volatile tBoolean g_bFirmwareUpdate = false;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, unsigned long ulLine)
    {
    }
    #endif
    
    void InitConsole(void);
    
    //*****************************************************************************
    //
    // The number of SysTick ticks per second.
    //
    //*****************************************************************************
    #define TICKS_PER_SECOND 100
    
    
    //*****************************************************************************
    //
    // This is the handler for this SysTick interrupt.
    //
    //*****************************************************************************
    void
    SysTickIntHandler(void)
    {
    
        //
        // Call the lwIP timer.
        //
    //    lwIPTimer(1000 / TICKS_PER_SECOND);
    }
    
    //*****************************************************************************
    //
    // This function is called by the software update module whenever a remote
    // host requests to update the firmware on this board.  We set a flag that
    // will cause the bootloader to be entered the next time the user enters a
    // command on the console.
    //
    //*****************************************************************************
    void SoftwareUpdateRequestCallback(void)
    {
        g_bFirmwareUpdate = true;
    }
    
    //*****************************************************************************
    //
    // The sound effect that is played when a key is pressed.
    //
    //*****************************************************************************
    static const unsigned short g_pusKeyClick[] =
    {
        0, G5,
        25, SILENCE
    };
    
    //*****************************************************************************
    //
    // Forward declarations for the globals required to define the widgets at
    // compile-time.
    //
    //*****************************************************************************
    void OnPrevious(tWidget *pWidget);
    void OnNext(tWidget *pWidget);
    void OnIntroPaint(tWidget *pWidget, tContext *pContext);
    void OnFirmwarePaint(tWidget *pWidget, tContext *pContext);
    void OnFirmwareUpdate(tWidget *pWidget);
    void OnPrimitivePaint(tWidget *pWidget, tContext *pContext);
    void OnCanvasPaint(tWidget *pWidget, tContext *pContext);
    void OnCheckChange(tWidget *pWidget, unsigned long bSelected);
    void OnButtonPress(tWidget *pWidget);
    void OnRadioChange(tWidget *pWidget, unsigned long bSelected);
    void OnSliderChange(tWidget *pWidget, long lValue);
    extern tCanvasWidget g_psPanels[];
    
    //*****************************************************************************
    //
    // The first panel, which contains introductory text explaining the
    // application.
    //
    //*****************************************************************************
    Canvas(g_sIntroduction, g_psPanels, 0, 0, &g_sFormike240x320x16_ILI9340, 0, 24,
           240, 246, CANVAS_STYLE_APP_DRAWN, 0, 0, 0, 0, 0, 0, OnIntroPaint);
    
    //*****************************************************************************
    //
    // The second panel, which demonstrates the graphics primitives.
    //
    //*****************************************************************************
    Canvas(g_sPrimitives, g_psPanels + 1, 0, 0, &g_sFormike240x320x16_ILI9340, 0,
           24, 240, 246, CANVAS_STYLE_APP_DRAWN, 0, 0, 0, 0, 0, 0,
           OnPrimitivePaint);
    
    //*****************************************************************************
    //
    // The third panel, which demonstrates the canvas widget.
    //
    //*****************************************************************************
    Canvas(g_sCanvas3, g_psPanels + 2, 0, 0, &g_sFormike240x320x16_ILI9340, 5, 191,
           230, 76, CANVAS_STYLE_OUTLINE | CANVAS_STYLE_APP_DRAWN, 0, ClrGray, 0,
           0, 0, 0, OnCanvasPaint);
    Canvas(g_sCanvas2, g_psPanels + 2, &g_sCanvas3, 0,
           &g_sFormike240x320x16_ILI9340, 5, 109, 230, 76,
           CANVAS_STYLE_OUTLINE | CANVAS_STYLE_IMG, 0, ClrGray, 0, 0, 0, g_pucLogo,
           0);
    Canvas(g_sCanvas1, g_psPanels + 2, &g_sCanvas2, 0,
           &g_sFormike240x320x16_ILI9340, 5, 27, 230, 76,
           CANVAS_STYLE_FILL | CANVAS_STYLE_OUTLINE | CANVAS_STYLE_TEXT,
           ClrMidnightBlue, ClrGray, ClrSilver, g_pFontCm22, "Text", 0, 0);
    
    //*****************************************************************************
    //
    // The fourth panel, which demonstrates the checkbox widget.
    //
    //*****************************************************************************
    tCanvasWidget g_psCheckBoxIndicators[] =
    {
        CanvasStruct(g_psPanels + 3, g_psCheckBoxIndicators + 1, 0,
                     &g_sFormike240x320x16_ILI9340, 190, 30, 50, 50,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 3, g_psCheckBoxIndicators + 2, 0,
                     &g_sFormike240x320x16_ILI9340, 190, 90, 50, 50,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 3, g_psCheckBoxIndicators + 3, 0,
                     &g_sFormike240x320x16_ILI9340, 190, 150, 50, 50,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 3, 0, 0,
                     &g_sFormike240x320x16_ILI9340, 190, 210, 50, 50,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0)
    };
    tCheckBoxWidget g_psCheckBoxes[] =
    {
        CheckBoxStruct(g_psPanels + 3, g_psCheckBoxes + 1, 0,
                       &g_sFormike240x320x16_ILI9340, 0, 30, 185, 50,
                       CB_STYLE_OUTLINE | CB_STYLE_FILL | CB_STYLE_TEXT, 16,
                       ClrMidnightBlue, ClrGray, ClrSilver, g_pFontCm22, "Select",
                       0, OnCheckChange),
        CheckBoxStruct(g_psPanels + 3, g_psCheckBoxes + 2, 0,
                       &g_sFormike240x320x16_ILI9340, 0, 90, 185, 50,
                       CB_STYLE_IMG, 16, 0, ClrGray, 0, 0, 0, g_pucLogo,
                       OnCheckChange),
        CheckBoxStruct(g_psPanels + 3, g_psCheckBoxes + 3, 0,
                       &g_sFormike240x320x16_ILI9340, 0, 150, 185, 50,
                       CB_STYLE_OUTLINE | CB_STYLE_TEXT, 32, 0,
                       ClrGreen, ClrSpringGreen, g_pFontCm22, "Select",
                       0, OnCheckChange),
        CheckBoxStruct(g_psPanels + 3, g_psCheckBoxIndicators, 0,
                       &g_sFormike240x320x16_ILI9340, 0, 210, 185, 50,
                       CB_STYLE_IMG, 32, 0, ClrDarkRed, 0, 0, 0, g_pucLogo,
                       OnCheckChange)
    };
    #define NUM_CHECK_BOXES         (sizeof(g_psCheckBoxes) /   \
                                     sizeof(g_psCheckBoxes[0]))
    
    //*****************************************************************************
    //
    // The fifth panel, which demonstrates the container widget.
    //
    //*****************************************************************************
    Container(g_sContainer3, g_psPanels + 4, 0, 0, &g_sFormike240x320x16_ILI9340,
              5, 191, 230, 76, CTR_STYLE_OUTLINE | CTR_STYLE_FILL, ClrMidnightBlue,
              ClrGray, 0, 0, 0);
    Container(g_sContainer2, g_psPanels + 4, &g_sContainer3, 0,
              &g_sFormike240x320x16_ILI9340, 5, 109, 230, 76,
              (CTR_STYLE_OUTLINE | CTR_STYLE_FILL | CTR_STYLE_TEXT |
               CTR_STYLE_TEXT_CENTER), ClrMidnightBlue, ClrGray, ClrSilver,
              g_pFontCm22, "Group2");
    Container(g_sContainer1, g_psPanels + 4, &g_sContainer2, 0,
              &g_sFormike240x320x16_ILI9340, 5, 27, 230, 76,
              CTR_STYLE_OUTLINE | CTR_STYLE_FILL | CTR_STYLE_TEXT, ClrMidnightBlue,
              ClrGray, ClrSilver, g_pFontCm22, "Group1");
    
    //*****************************************************************************
    //
    // The sixth panel, which contains a selection of push buttons.
    //
    //*****************************************************************************
    tCanvasWidget g_psPushButtonIndicators[] =
    {
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 1, 0,
                     &g_sFormike240x320x16_ILI9340, 5, 45, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 2, 0,
                     &g_sFormike240x320x16_ILI9340, 125, 45, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 3, 0,
                     &g_sFormike240x320x16_ILI9340, 5, 105, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 4, 0,
                     &g_sFormike240x320x16_ILI9340, 125, 105, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 5, 0,
                     &g_sFormike240x320x16_ILI9340, 5, 165, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 6, 0,
                     &g_sFormike240x320x16_ILI9340, 125, 165, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 7, 0,
                     &g_sFormike240x320x16_ILI9340, 5, 205, 110, 24,
                     CANVAS_STYLE_TEXT, 0, 0, ClrSilver, g_pFontCm20, "Non-auto",
                     0, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 8, 0,
                     &g_sFormike240x320x16_ILI9340, 5, 225, 110, 24,
                     CANVAS_STYLE_TEXT, 0, 0, ClrSilver, g_pFontCm20, "repeat",
                     0, 0),
        CanvasStruct(g_psPanels + 5, g_psPushButtonIndicators + 9, 0,
                     &g_sFormike240x320x16_ILI9340, 125, 205, 110, 24,
                     CANVAS_STYLE_TEXT, 0, 0, ClrSilver, g_pFontCm20, "Auto",
                     0, 0),
        CanvasStruct(g_psPanels + 5, 0, 0,
                     &g_sFormike240x320x16_ILI9340, 125, 225, 110, 24,
                     CANVAS_STYLE_TEXT, 0, 0, ClrSilver, g_pFontCm20, "repeat",
                     0, 0),
    };
    tPushButtonWidget g_psPushButtons[] =
    {
        RectangularButtonStruct(g_psPanels + 5, g_psPushButtons + 1, 0,
                                &g_sFormike240x320x16_ILI9340, 30, 30, 50, 50,
                                PB_STYLE_FILL | PB_STYLE_OUTLINE | PB_STYLE_TEXT,
                                ClrMidnightBlue, ClrBlack, ClrGray, ClrSilver,
                                g_pFontCm22, "1", 0, 0, 0, 0, OnButtonPress),
        RectangularButtonStruct(g_psPanels + 5, g_psPushButtons + 2, 0,
                                &g_sFormike240x320x16_ILI9340, 150, 30, 50, 50,
                                (PB_STYLE_FILL | PB_STYLE_OUTLINE | PB_STYLE_TEXT |
                                 PB_STYLE_AUTO_REPEAT), ClrMidnightBlue, ClrBlack,
                                ClrGray, ClrSilver, g_pFontCm22, "2", 0, 0, 125,
                                25, OnButtonPress),
        CircularButtonStruct(g_psPanels + 5, g_psPushButtons + 3, 0,
                             &g_sFormike240x320x16_ILI9340, 55, 115, 25,
                             PB_STYLE_FILL | PB_STYLE_OUTLINE | PB_STYLE_TEXT,
                             ClrMidnightBlue, ClrBlack, ClrGray, ClrSilver,
                             g_pFontCm22, "3", 0, 0, 0, 0, OnButtonPress),
        CircularButtonStruct(g_psPanels + 5, g_psPushButtons + 4, 0,
                             &g_sFormike240x320x16_ILI9340, 175, 115, 25,
                             (PB_STYLE_FILL | PB_STYLE_OUTLINE | PB_STYLE_TEXT |
                              PB_STYLE_AUTO_REPEAT), ClrMidnightBlue, ClrBlack,
                             ClrGray, ClrSilver, g_pFontCm22, "4", 0, 0, 125, 25,
                             OnButtonPress),
        RectangularButtonStruct(g_psPanels + 5, g_psPushButtons + 5, 0,
                                &g_sFormike240x320x16_ILI9340, 30, 150, 50, 50,
                                PB_STYLE_IMG | PB_STYLE_TEXT, 0, 0, 0, ClrSilver,
                                g_pFontCm22, "5", g_pucBlue50x50,
                                g_pucBlue50x50Press, 0, 0, OnButtonPress),
        RectangularButtonStruct(g_psPanels + 5, g_psPushButtonIndicators, 0,
                                &g_sFormike240x320x16_ILI9340, 150, 150, 50, 50,
                                (PB_STYLE_IMG | PB_STYLE_TEXT |
                                 PB_STYLE_AUTO_REPEAT), 0, 0, 0, ClrSilver,
                                g_pFontCm22, "6", g_pucBlue50x50,
                                g_pucBlue50x50Press, 125, 25, OnButtonPress),
    };
    #define NUM_PUSH_BUTTONS        (sizeof(g_psPushButtons) /   \
                                     sizeof(g_psPushButtons[0]))
    unsigned long g_ulButtonState;
    
    //*****************************************************************************
    //
    // The seventh panel, which contains a selection of radio buttons.
    //
    //*****************************************************************************
    tContainerWidget g_psRadioContainers[];
    tCanvasWidget g_psRadioButtonIndicators[] =
    {
        CanvasStruct(g_psRadioContainers, g_psRadioButtonIndicators + 1, 0,
                     &g_sFormike240x320x16_ILI9340, 95, 62, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psRadioContainers, g_psRadioButtonIndicators + 2, 0,
                     &g_sFormike240x320x16_ILI9340, 95, 107, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psRadioContainers, g_psRadioButtonIndicators + 3, 0,
                     &g_sFormike240x320x16_ILI9340, 210, 62, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psRadioContainers, 0, 0,
                     &g_sFormike240x320x16_ILI9340, 210, 107, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psRadioContainers + 1, g_psRadioButtonIndicators + 5, 0,
                     &g_sFormike240x320x16_ILI9340, 95, 177, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psRadioContainers + 1, g_psRadioButtonIndicators + 6, 0,
                     &g_sFormike240x320x16_ILI9340, 95, 222, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psRadioContainers + 1, g_psRadioButtonIndicators + 7, 0,
                     &g_sFormike240x320x16_ILI9340, 210, 177, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
        CanvasStruct(g_psRadioContainers + 1, 0, 0,
                     &g_sFormike240x320x16_ILI9340, 210, 222, 20, 20,
                     CANVAS_STYLE_IMG, 0, 0, 0, 0, 0, g_pucLightOff, 0),
    };
    tRadioButtonWidget g_psRadioButtons1[] =
    {
        RadioButtonStruct(g_psRadioContainers, g_psRadioButtons1 + 1, 0,
                          &g_sFormike240x320x16_ILI9340, 10, 50, 80, 45,
                          RB_STYLE_TEXT, 16, 0, ClrSilver, ClrSilver, g_pFontCm20,
                          "One", 0, OnRadioChange),
        RadioButtonStruct(g_psRadioContainers, g_psRadioButtons1 + 2, 0,
                          &g_sFormike240x320x16_ILI9340, 10, 95, 80, 45,
                          RB_STYLE_TEXT, 16, 0, ClrSilver, ClrSilver, g_pFontCm20,
                          "Two", 0, OnRadioChange),
        RadioButtonStruct(g_psRadioContainers, g_psRadioButtons1 + 3, 0,
                          &g_sFormike240x320x16_ILI9340, 125, 50, 80, 45,
                          RB_STYLE_TEXT, 24, 0, ClrSilver, ClrSilver, g_pFontCm20,
                          "Three", 0, OnRadioChange),
        RadioButtonStruct(g_psRadioContainers, g_psRadioButtonIndicators, 0,
                          &g_sFormike240x320x16_ILI9340, 125, 95, 80, 45,
                          RB_STYLE_TEXT, 24, 0, ClrSilver, ClrSilver, g_pFontCm20,
                          "Four", 0, OnRadioChange)
    };
    #define NUM_RADIO1_BUTTONS      (sizeof(g_psRadioButtons1) /   \
                                     sizeof(g_psRadioButtons1[0]))
    tRadioButtonWidget g_psRadioButtons2[] =
    {
        RadioButtonStruct(g_psRadioContainers + 1, g_psRadioButtons2 + 1, 0,
                          &g_sFormike240x320x16_ILI9340, 10, 165, 80, 45,
                          RB_STYLE_IMG, 16, 0, ClrSilver, 0, 0, 0, g_pucLogo,
                          OnRadioChange),
        RadioButtonStruct(g_psRadioContainers + 1, g_psRadioButtons2 + 2, 0,
                          &g_sFormike240x320x16_ILI9340, 10, 210, 80, 45,
                          RB_STYLE_IMG, 24, 0, ClrSilver, 0, 0, 0, g_pucLogo,
                          OnRadioChange),
        RadioButtonStruct(g_psRadioContainers + 1, g_psRadioButtons2 + 3, 0,
                          &g_sFormike240x320x16_ILI9340, 125, 165, 80, 45,
                          RB_STYLE_IMG, 16, 0, ClrSilver, 0, 0, 0, g_pucLogo,
                          OnRadioChange),
        RadioButtonStruct(g_psRadioContainers + 1, g_psRadioButtonIndicators + 4,
                          0, &g_sFormike240x320x16_ILI9340, 125, 210, 80, 45,
                          RB_STYLE_IMG, 24, 0, ClrSilver, 0, 0, 0, g_pucLogo,
                          OnRadioChange)
    };
    #define NUM_RADIO2_BUTTONS      (sizeof(g_psRadioButtons2) /   \
                                     sizeof(g_psRadioButtons2[0]))
    tContainerWidget g_psRadioContainers[] =
    {
        ContainerStruct(g_psPanels + 6, g_psRadioContainers + 1, g_psRadioButtons1,
                        &g_sFormike240x320x16_ILI9340, 5, 30, 230, 111,
                        CTR_STYLE_OUTLINE | CTR_STYLE_TEXT, 0, ClrGray, ClrSilver,
                        g_pFontCm20, "Group One"),
        ContainerStruct(g_psPanels + 6, 0, g_psRadioButtons2,
                        &g_sFormike240x320x16_ILI9340, 5, 145, 230, 111,
                        CTR_STYLE_OUTLINE | CTR_STYLE_TEXT, 0, ClrGray, ClrSilver,
                        g_pFontCm20, "Group Two")
    };
    
    //*****************************************************************************
    //
    // The eighth panel, which demonstrates the slider widget.
    //
    //*****************************************************************************
    Canvas(g_sSliderValueCanvas, g_psPanels + 7, 0, 0,
           &g_sFormike240x320x16_ILI9340, 200, 40, 40, 30,
           CANVAS_STYLE_TEXT | CANVAS_STYLE_TEXT_OPAQUE, ClrBlack, 0, ClrSilver,
           g_pFontCm20, "50%",
           0, 0);
    
    tSliderWidget g_psSliders[] =
    {
        SliderStruct(g_psPanels + 7, g_psSliders + 1, 0,
                     &g_sFormike240x320x16_ILI9340, 5, 153, 150, 30, 0, 100, 25,
                     (SL_STYLE_FILL | SL_STYLE_BACKG_FILL | SL_STYLE_OUTLINE |
                      SL_STYLE_TEXT | SL_STYLE_BACKG_TEXT),
                     ClrGray, ClrBlack, ClrSilver, ClrWhite, ClrWhite,
                     g_pFontCm20, "25%", 0, 0, OnSliderChange),
        SliderStruct(g_psPanels + 7, g_psSliders + 2, 0,
                     &g_sFormike240x320x16_ILI9340, 5, 210, 150, 30, 0, 100, 25,
                     (SL_STYLE_FILL | SL_STYLE_BACKG_FILL | SL_STYLE_OUTLINE |
                      SL_STYLE_TEXT),
                     ClrWhite, ClrBlueViolet, ClrSilver, ClrBlack, 0,
                     g_pFontCm20, "Foreground", 0, 0, OnSliderChange),
        SliderStruct(g_psPanels + 7, g_psSliders + 3, 0,
                     &g_sFormike240x320x16_ILI9340, 205, 90, 30, 160, 0, 100, 50,
                     (SL_STYLE_FILL | SL_STYLE_BACKG_FILL | SL_STYLE_VERTICAL |
                      SL_STYLE_OUTLINE | SL_STYLE_LOCKED), ClrDarkGreen,
                      ClrDarkRed, ClrSilver, 0, 0, 0, 0, 0, 0, 0),
        SliderStruct(g_psPanels + 7, g_psSliders + 4, 0,
                     &g_sFormike240x320x16_ILI9340, 165, 90, 30, 162, 0, 100, 75,
                     (SL_STYLE_IMG | SL_STYLE_BACKG_IMG | SL_STYLE_VERTICAL |
                     SL_STYLE_OUTLINE), 0, ClrBlack, ClrSilver, 0, 0, 0,
                     0, g_pucGettingHotter28x160, g_pucGettingHotter28x160Mono,
                     OnSliderChange),
        SliderStruct(g_psPanels + 7, g_psSliders + 5, 0,
                     &g_sFormike240x320x16_ILI9340, 0, 40, 195, 37, 0, 100, 50,
                     SL_STYLE_IMG | SL_STYLE_BACKG_IMG, 0, 0, 0, 0, 0, 0,
                     0, g_pucGreenSlider195x37, g_pucRedSlider195x37,
                     OnSliderChange),
        SliderStruct(g_psPanels + 7, &g_sSliderValueCanvas, 0,
                     &g_sFormike240x320x16_ILI9340, 5, 96, 150, 30, 0, 100, 50,
                     (SL_STYLE_FILL | SL_STYLE_BACKG_FILL | SL_STYLE_TEXT |
                      SL_STYLE_BACKG_TEXT | SL_STYLE_TEXT_OPAQUE |
                      SL_STYLE_BACKG_TEXT_OPAQUE),
                     ClrBlue, ClrYellow, ClrSilver, ClrYellow, ClrBlue,
                     g_pFontCm20, "Slider with text", 0, 0, OnSliderChange),
    };
    
    #define SLIDER_TEXT_VAL_INDEX   0
    #define SLIDER_LOCKED_INDEX     2
    #define SLIDER_CANVAS_VAL_INDEX 4
    
    #define NUM_SLIDERS (sizeof(g_psSliders) / sizeof(g_psSliders[0]))
    
    //*****************************************************************************
    //
    // The ninth panel, which contains text describing how to perform a firmware
    // update and a button to initiate the process.
    //
    //*****************************************************************************
    Canvas(g_sFirmwareUpdate, g_psPanels + 8, 0, 0, &g_sFormike240x320x16_ILI9340,
           0, 24, 240, 246, CANVAS_STYLE_APP_DRAWN, 0, 0, 0, 0, 0, 0,
           OnFirmwarePaint);
    RectangularButton(g_sFirmwareUpdateBtn, g_psPanels + 8, &g_sFirmwareUpdate,
                      0, &g_sFormike240x320x16_ILI9340, 50, 200, 140, 40,
                      (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT |
                       PB_STYLE_FILL), ClrNavy, ClrBlue, ClrSilver, ClrSilver,
                       g_pFontCm20, "Update", 0, 0, 0, 0, OnFirmwareUpdate);
    
    //*****************************************************************************
    //
    // An array of canvas widgets, one per panel.  Each canvas is filled with
    // black, overwriting the contents of the previous panel.
    //
    //*****************************************************************************
    tCanvasWidget g_psPanels[] =
    {
        CanvasStruct(0, 0, &g_sIntroduction, &g_sFormike240x320x16_ILI9340, 0, 24,
                     240, 246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0),
        CanvasStruct(0, 0, &g_sPrimitives, &g_sFormike240x320x16_ILI9340, 0, 24,
                     240, 246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0),
        CanvasStruct(0, 0, &g_sCanvas1, &g_sFormike240x320x16_ILI9340, 0, 24, 240,
                     246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0),
        CanvasStruct(0, 0, g_psCheckBoxes, &g_sFormike240x320x16_ILI9340, 0, 24,
                     240, 246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0),
        CanvasStruct(0, 0, &g_sContainer1, &g_sFormike240x320x16_ILI9340, 0, 24,
                     240, 246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0),
        CanvasStruct(0, 0, g_psPushButtons, &g_sFormike240x320x16_ILI9340, 0, 24,
                     240, 246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0),
        CanvasStruct(0, 0, g_psRadioContainers, &g_sFormike240x320x16_ILI9340, 0,
                     24, 240, 246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0),
        CanvasStruct(0, 0, g_psSliders, &g_sFormike240x320x16_ILI9340, 0, 24, 240,
                     246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0),
        CanvasStruct(0, 0, &g_sFirmwareUpdateBtn, &g_sFormike240x320x16_ILI9340, 0,
                     24, 240, 246, CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0)
    };
    
    //*****************************************************************************
    //
    // The number of panels.
    //
    //*****************************************************************************
    #define NUM_PANELS              (sizeof(g_psPanels) / sizeof(g_psPanels[0]))
    
    //*****************************************************************************
    //
    // The names for each of the panels, which is displayed at the bottom of the
    // screen.
    //
    //*****************************************************************************
    char *g_pcPanelNames[] =
    {
        "     Introduction     ",
        "     Primitives     ",
        "     Canvas     ",
        "     Checkbox     ",
        "     Container     ",
        "     Push Buttons     ",
        "     Radio Buttons     ",
        "     Sliders     ",
        "     S/W Update    "
    };
    
    //*****************************************************************************
    //
    // The buttons and text across the bottom of the screen.
    //
    //*****************************************************************************
    RectangularButton(g_sPrevious, 0, 0, 0, &g_sFormike240x320x16_ILI9340, 0, 270,
                      50, 50, PB_STYLE_FILL, ClrBlack, ClrBlack, 0, ClrSilver,
                      g_pFontCm20, "-", g_pucBlue50x50, g_pucBlue50x50Press, 0, 0,
                      OnPrevious);
    Canvas(g_sTitle, 0, 0, 0, &g_sFormike240x320x16_ILI9340, 50, 270, 140, 50,
           CANVAS_STYLE_TEXT | CANVAS_STYLE_TEXT_OPAQUE, 0, 0, ClrSilver,
           g_pFontCm20, 0, 0, 0);
    RectangularButton(g_sNext, 0, 0, 0, &g_sFormike240x320x16_ILI9340, 190, 270,
                      50, 50, PB_STYLE_IMG | PB_STYLE_TEXT, ClrBlack, ClrBlack, 0,
                      ClrSilver, g_pFontCm20, "+", g_pucBlue50x50,
                      g_pucBlue50x50Press, 0, 0, OnNext);
    
    //*****************************************************************************
    //
    // The panel that is currently being displayed.
    //
    //*****************************************************************************
    unsigned long g_ulPanel;
    
    //*****************************************************************************
    //
    // Handles presses of the previous panel button.
    //
    //*****************************************************************************
    void
    OnPrevious(tWidget *pWidget)
    {
        //
        // There is nothing to be done if the first panel is already being
        // displayed.
        //
        if(g_ulPanel == 0)
        {
            return;
        }
    
        //
        // Remove the current panel.
        //
        WidgetRemove((tWidget *)(g_psPanels + g_ulPanel));
    
        //
        // Decrement 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 this is the first panel.
        //
        if(g_ulPanel == 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_ulPanel == (NUM_PANELS - 2))
        {
            //
            // Display the next button.
            //
            PushButtonImageOn(&g_sNext);
            PushButtonTextOn(&g_sNext);
            PushButtonFillOff(&g_sNext);
            WidgetPaint((tWidget *)&g_sNext);
        }
    
        //
        // Play the key click sound.
        //
        SoundPlay(g_pusKeyClick, sizeof(g_pusKeyClick) / 2);
    }
    
    //*****************************************************************************
    //
    // 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);
    }
    
    //*****************************************************************************
    //
    // Handles paint requests for the introduction canvas widget.
    //
    //*****************************************************************************
    void
    OnIntroPaint(tWidget *pWidget, tContext *pContext)
    {
        //
        // Display the introduction text in the canvas.
        //
        GrContextFontSet(pContext, g_pFontCm18);
        GrContextForegroundSet(pContext, ClrSilver);
        GrStringDraw(pContext, "This application demonstrates", -1, 0, 32, 0);
        GrStringDraw(pContext, "the capabilities of the Stellaris", -1, 0, 50, 0);
        GrStringDraw(pContext, "Graphics Library.", -1, 0, 68, 0);
        GrStringDraw(pContext, "Each panel shows a different", -1, 0, 94, 0);
        GrStringDraw(pContext, "feature of the graphics library.", -1, 0, 112, 0);
        GrStringDraw(pContext, "Widgets on the panels are fully", -1, 0, 130, 0);
        GrStringDraw(pContext, "operational; pressing them will", -1, 0, 148, 0);
        GrStringDraw(pContext, "result in a visible feedback of", -1, 0, 166, 0);
        GrStringDraw(pContext, "some kind.", -1, 0, 184, 0);
        GrStringDraw(pContext, "Press the + and - buttons at", -1, 0, 210, 0);
        GrStringDraw(pContext, "the bottom of the screen to", -1, 0, 228, 0);
        GrStringDraw(pContext, "move between the panels.", -1, 0, 246, 0);
    }
    
    //*****************************************************************************
    //
    // Handles paint requests for the firmware update canvas widget.
    //
    //*****************************************************************************
    void
    OnFirmwarePaint(tWidget *pWidget, tContext *pContext)
    {
        //char pcBuffer[32];
    
        //
        // Display the firmware update instruction text in the canvas.
        //
        GrContextFontSet(pContext, g_pFontCm18);
        GrContextForegroundSet(pContext, ClrSilver);
        GrStringDraw(pContext, "You may replace the software", -1, 0, 32, 0);
        GrStringDraw(pContext, "image flashed by pressing the", -1, 0, 50, 0);
        GrStringDraw(pContext, "\"Update\" button after setting", -1, 0, 68, 0);
        GrStringDraw(pContext, "up the LMFlash utility with", -1, 0, 86, 0);
        GrStringDraw(pContext, "the following information:", -1, 0, 104, 0);
    
    /*
        //
        // Get the current IP address.
        //
        ulIPAddr = 0;
    
        //
        // Format the address as a string and display it.
        //
        if(ulIPAddr)
        {
            usprintf(pcBuffer, "IP: %d.%d.%d.%d",
                     ulIPAddr & 0xff, (ulIPAddr >> 8) & 0xff,
                     (ulIPAddr >> 16) & 0xff, ulIPAddr >> 24);
        }
        else
        {
            usprintf(pcBuffer, "IP: Not yet assigned");
        }
        GrStringDraw(pContext, pcBuffer, -1, 0, 148, 0);
    */
    }
    
    //*****************************************************************************
    //
    // Handles press notifications for the push button widgets.
    //
    //*****************************************************************************
    void
    OnFirmwareUpdate(tWidget *pWidget)
    {
        //
        // Play the key click sound.
        //
        SoundPlay(g_pusKeyClick, sizeof(g_pusKeyClick) / 2);
    
        //
        // Change the button text to show that the update is starting
        //
        PushButtonTextSet(&g_sFirmwareUpdateBtn, "Updating...");
        WidgetPaint((tWidget *)&g_sFirmwareUpdateBtn);
    
        //
        // Trigger a software update
        //
        g_bFirmwareUpdate = true;
    }
    
    //*****************************************************************************
    //
    // Handles paint requests for the primitives canvas widget.
    //
    //*****************************************************************************
    void
    OnPrimitivePaint(tWidget *pWidget, tContext *pContext)
    {
        unsigned long ulIdx;
        tRectangle sRect;
    
        //
        // Draw a vertical sweep of lines from red to green.
        //
        for(ulIdx = 0; ulIdx <= 10; ulIdx++)
        {
            GrContextForegroundSet(pContext,
                                   (((((10 - ulIdx) * 255) / 10) << ClrRedShift) |
                                    (((ulIdx * 255) / 10) << ClrGreenShift)));
            GrLineDraw(pContext, 115, 139, 5, 139 - (11 * ulIdx));
        }
    
        //
        // Draw a horizontal sweep of lines from green to blue.
        //
        for(ulIdx = 1; ulIdx <= 10; ulIdx++)
        {
            GrContextForegroundSet(pContext,
                                   (((((10 - ulIdx) * 255) / 10) <<
                                     ClrGreenShift) |
                                    (((ulIdx * 255) / 10) << ClrBlueShift)));
            GrLineDraw(pContext, 115, 139, 5 + (ulIdx * 11), 29);
        }
    
        //
        // Draw a filled circle with an overlapping circle.
        //
        GrContextForegroundSet(pContext, ClrBrown);
        GrCircleFill(pContext, 165, 69, 40);
        GrContextForegroundSet(pContext, ClrSkyBlue);
        GrCircleDraw(pContext, 195, 99, 40);
    
        //
        // Draw a filled rectangle with an overlapping rectangle.
        //
        GrContextForegroundSet(pContext, ClrSlateGray);
        sRect.sXMin = 5;
        sRect.sYMin = 149;
        sRect.sXMax = 75;
        sRect.sYMax = 219;
        GrRectFill(pContext, &sRect);
        GrContextForegroundSet(pContext, ClrSlateBlue);
        sRect.sXMin += 40;
        sRect.sYMin += 40;
        sRect.sXMax += 40;
        sRect.sYMax += 40;
        GrRectDraw(pContext, &sRect);
    
        //
        // Draw a piece of text in fonts of increasing size.
        //
        GrContextForegroundSet(pContext, ClrSilver);
        GrContextFontSet(pContext, g_pFontCm14);
        GrStringDraw(pContext, "Strings", -1, 125, 149, 0);
        GrContextFontSet(pContext, g_pFontCm18);
        GrStringDraw(pContext, "Strings", -1, 125, 163, 0);
        GrContextFontSet(pContext, g_pFontCm22);
        GrStringDraw(pContext, "Strings", -1, 125, 181, 0);
        GrContextFontSet(pContext, g_pFontCm26);
        GrStringDraw(pContext, "Strings", -1, 125, 203, 0);
        GrContextFontSet(pContext, g_pFontCm30);
        GrStringDraw(pContext, "Strings", -1, 125, 229, 0);
    
        //
        // Draw an image.
        //
        GrImageDraw(pContext, g_pucLogo, 190, 149);
    }
    
    //*****************************************************************************
    //
    // Handles paint requests for the canvas demonstration widget.
    //
    //*****************************************************************************
    void
    OnCanvasPaint(tWidget *pWidget, tContext *pContext)
    {
        unsigned long ulIdx;
    
        //
        // Draw a set of radiating lines.
        //
        GrContextForegroundSet(pContext, ClrGoldenrod);
        for(ulIdx = 10; ulIdx <= 230; ulIdx += 10)
        {
            GrLineDraw(pContext, ulIdx, 196, 240 - ulIdx, 261);
        }
    
        //
        // Indicate that the contents of this canvas were drawn by the application.
        //
        GrContextFontSet(pContext, g_pFontCm12);
        GrStringDraw(pContext, "App Drawn", -1, 10, 223, 1);
    }
    
    //*****************************************************************************
    //
    // Handles change notifications for the check box widgets.
    //
    //*****************************************************************************
    void
    OnCheckChange(tWidget *pWidget, unsigned long bSelected)
    {
        unsigned long ulIdx;
    
        //
        // Find the index of this check box.
        //
        for(ulIdx = 0; ulIdx < NUM_CHECK_BOXES; ulIdx++)
        {
            if(pWidget == (tWidget *)(g_psCheckBoxes + ulIdx))
            {
                break;
            }
        }
    
        //
        // Return if the check box could not be found.
        //
        if(ulIdx == NUM_CHECK_BOXES)
        {
            return;
        }
    
        //
        // Set the matching indicator based on the selected state of the check box.
        //
        CanvasImageSet(g_psCheckBoxIndicators + ulIdx,
                       bSelected ? g_pucLightOn : g_pucLightOff);
        WidgetPaint((tWidget *)(g_psCheckBoxIndicators + ulIdx));
    
        //
        // Play the key click sound.
        //
        SoundPlay(g_pusKeyClick, sizeof(g_pusKeyClick) / 2);
    }
    
    //*****************************************************************************
    //
    // Handles press notifications for the push button widgets.
    //
    //*****************************************************************************
    void
    OnButtonPress(tWidget *pWidget)
    {
        unsigned long ulIdx;
    
        //
        // Find the index of this push button.
        //
        for(ulIdx = 0; ulIdx < NUM_PUSH_BUTTONS; ulIdx++)
        {
            if(pWidget == (tWidget *)(g_psPushButtons + ulIdx))
            {
                break;
            }
        }
    
        //
        // Return if the push button could not be found.
        //
        if(ulIdx == NUM_PUSH_BUTTONS)
        {
            return;
        }
    
        //
        // Toggle the state of this push button indicator.
        //
        g_ulButtonState ^= 1 << ulIdx;
    
        //
        // Set the matching indicator based on the selected state of the check box.
        //
        CanvasImageSet(g_psPushButtonIndicators + ulIdx,
                       (g_ulButtonState & (1 << ulIdx)) ? g_pucLightOn :
                       g_pucLightOff);
        WidgetPaint((tWidget *)(g_psPushButtonIndicators + ulIdx));
    
        //
        // Play the key click sound.
        //
        SoundPlay(g_pusKeyClick, sizeof(g_pusKeyClick) / 2);
    }
    
    //*****************************************************************************
    //
    // Handles notifications from the slider controls.
    //
    //*****************************************************************************
    void
    OnSliderChange(tWidget *pWidget, long lValue)
    {
        static char pcCanvasText[5];
        static char pcSliderText[5];
    
        //
        // Is this the widget whose value we mirror in the canvas widget and the
        // locked slider?
        //
        if(pWidget == (tWidget *)&g_psSliders[SLIDER_CANVAS_VAL_INDEX])
        {
            //
            // Yes - update the canvas to show the slider value.
            //
            //usprintf(pcCanvasText, "%3d%%", lValue);
            CanvasTextSet(&g_sSliderValueCanvas, pcCanvasText);
            WidgetPaint((tWidget *)&g_sSliderValueCanvas);
    
            //
            // Also update the value of the locked slider to reflect this one.
            //
            SliderValueSet(&g_psSliders[SLIDER_LOCKED_INDEX], lValue);
            WidgetPaint((tWidget *)&g_psSliders[SLIDER_LOCKED_INDEX]);
        }
    
        if(pWidget == (tWidget *)&g_psSliders[SLIDER_TEXT_VAL_INDEX])
        {
            //
            // Yes - update the canvas to show the slider value.
            //
            //usprintf(pcSliderText, "%3d%%", lValue);
            SliderTextSet(&g_psSliders[SLIDER_TEXT_VAL_INDEX], pcSliderText);
            WidgetPaint((tWidget *)&g_psSliders[SLIDER_TEXT_VAL_INDEX]);
        }
    }
    
    //*****************************************************************************
    //
    // Handles change notifications for the radio button widgets.
    //
    //*****************************************************************************
    void
    OnRadioChange(tWidget *pWidget, unsigned long bSelected)
    {
        unsigned long ulIdx;
    
        //
        // Find the index of this radio button in the first group.
        //
        for(ulIdx = 0; ulIdx < NUM_RADIO1_BUTTONS; ulIdx++)
        {
            if(pWidget == (tWidget *)(g_psRadioButtons1 + ulIdx))
            {
                break;
            }
        }
    
        //
        // See if the radio button was found.
        //
        if(ulIdx == NUM_RADIO1_BUTTONS)
        {
            //
            // Find the index of this radio button in the second group.
            //
            for(ulIdx = 0; ulIdx < NUM_RADIO2_BUTTONS; ulIdx++)
            {
                if(pWidget == (tWidget *)(g_psRadioButtons2 + ulIdx))
                {
                    break;
                }
            }
    
            //
            // Return if the radio button could not be found.
            //
            if(ulIdx == NUM_RADIO2_BUTTONS)
            {
                return;
            }
    
            //
            // Sind the radio button is in the second group, offset the index to
            // the indicators associated with the second group.
            //
            ulIdx += NUM_RADIO1_BUTTONS;
        }
    
        //
        // Set the matching indicator based on the selected state of the radio
        // button.
        //
        CanvasImageSet(g_psRadioButtonIndicators + ulIdx,
                       bSelected ? g_pucLightOn : g_pucLightOff);
        WidgetPaint((tWidget *)(g_psRadioButtonIndicators + ulIdx));
    
        //
        // Play the key click sound.
        //
        SoundPlay(g_pusKeyClick, sizeof(g_pusKeyClick) / 2);
    }
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioInit(0);
    }
    
    //*****************************************************************************
    //
    // formike240x320x16_ili9340.c - Display driver for the Formike Electronic
    //                               KWH028Q02-F03 TFT panel with an ILI9340
    //                               controller, the KWH028Q02-F05 with an
    //                               ILI9325 or the KWH028Q02-F02 with an ILI9328
    //                               controller.
    //
    // Copyright (c) 2008-2012 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 9453 of the RDK-IDM Firmware Package.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    //! \addtogroup display_api
    //! @{
    //
    //*****************************************************************************
    
    #include "inc/hw_gpio.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_ssi.h"
    #include "inc/hw_types.h"
    #include "driverlib/ssi.h"
    #include "driverlib/gpio.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/ssi.h"
    //#include "driverlib/pin_map.h"
    #include "grlib/grlib.h"
    #include "formike240x320x16_ili9340.h"
    
    
    //*****************************************************************************
    //
    // This driver operates in four different screen orientations.  They are:
    //
    // * Portrait - The screen is taller than it is wide, and the flex connector is
    //              on the bottom of the display.  This is selected by defining
    //              PORTRAIT.
    //
    // * Landscape - The screen is wider than it is tall, and the flex connector is
    //               on the right side of the display.  This is selected by
    //               defining LANDSCAPE.
    //
    // * Portrait flip - The screen is taller than it is wide, and the flex
    //                   connector is on the top of the display.  This is selected
    //                   by defining PORTRAIT_FLIP.
    //
    // * Landscape flip - The screen is wider than it is tall, and the flex
    //                    connector is on the left side of the display.  This is
    //                    selected by defining LANDSCAPE_FLIP.
    //
    // These can also be imagined in terms of screen rotation; if portrait mode is
    // 0 degrees of screen rotation, landscape is 90 degrees of counter-clockwise
    // rotation, portrait flip is 180 degrees of rotation, and landscape flip is
    // 270 degress of counter-clockwise rotation.
    //
    // If no screen orientation is selected, portrait mode will be used.
    //
    //*****************************************************************************
    #if ! defined(PORTRAIT) && ! defined(PORTRAIT_FLIP) && \
        ! defined(LANDSCAPE) && ! defined(LANDSCAPE_FLIP)
    #define PORTRAIT
    #endif
    
    //*****************************************************************************
    //
    // Defines for the pins that are used to communicate with the ILI934x.
    //
    //*****************************************************************************
    #define GPIO_PA2_SSI0CLK        0x00000801
    #define GPIO_PA3_SSI0FSS        0x00000C01
    #define GPIO_PA4_SSI0RX         0x00001001
    #define GPIO_PA5_SSI0TX         0x00001401
    
    //*****************************************************************************
    //
    // DCX bit
    //
    //*****************************************************************************
    #define DCX_DATA		0x100
    #define DCX_COMMAND		0x000
    
    
    //*****************************************************************************
    //
    // Translates a 24-bit RGB color to a display driver-specific color.
    //
    // \param c is the 24-bit RGB color.  The least-significant byte is the blue
    // channel, the next byte is the green channel, and the third byte is the red
    // channel.
    //
    // This macro translates a 24-bit RGB color into a value that can be written
    // into the display's frame buffer in order to reproduce that color, or the
    // closest possible approximation of that color.
    //
    // \return Returns the display-driver specific color.
    //
    //*****************************************************************************
    #define DPYCOLORTRANSLATE(c)    ((((c) & 0x00ff0000) >> 19) |               \
                                     ((((c) & 0x0000ff00) >> 5) & 0x000007e0) | \
                                     ((((c) & 0x000000ff) << 8) & 0x0000f800))
    
    //*****************************************************************************
    //
    // Writes a data word to the ILI934x.
    //
    //*****************************************************************************
    static void
    WriteData(unsigned short usData)		//	DCX =�1� => data selected  & DCX=�0� => command selected
    {		//	DCX =�1�
    	SSIDataPut(SSI0_BASE, (unsigned long)(usData+DCX_DATA));	//	Puts a data element; usData, into the SSI transmit FIFO
    }
    
    //*****************************************************************************
    //
    // Reads a data word from the ILI934x.
    //
    //*****************************************************************************
    static unsigned short
    ReadData(void)
    {
        unsigned long usData;
    
        //
        // Return the data that was read.
        //
        SSIDataGet (SSI0_BASE, &usData);
        return((unsigned short)usData);
    }
    
    //*****************************************************************************
    //
    // Writes a command to the ILI934x.
    //
    //*****************************************************************************
    static void
    WriteCommand(unsigned char ucData)		//	DCX =�1� => data selected  & DCX=�0� => command selected
    {				//	DCX=�0�
    	SSIDataPut(SSI0_BASE, (unsigned long)(ucData+DCX_COMMAND));	//	Puts a data element, ucData, into the SSI transmit FIFO
    }
    
    //*****************************************************************************
    //
    // Read the value of a register from the ILI934x display controller.
    //
    //*****************************************************************************
    static unsigned short
    ReadRegister(unsigned char ucIndex)
    {
        WriteCommand(ucIndex);
        return(ReadData());
    }
    
    //*****************************************************************************
    //
    // Write a particular controller register with a value.
    //
    //*****************************************************************************
    //static void
    //WriteRegister(unsigned char ucIndex, unsigned short usValue)
    //{
    //    WriteCommand(ucIndex);
    //    WriteData(usValue);
    //}
    
    //******************************************************************************
    //
    //Function which initialize the LCD screen.
    //
    //******************************************************************************
    
    void
    Formike240x320x16_ILI9340InitScreen(void)
    {
    	unsigned long temp;
    	temp = SysCtlClockGet() / (3 * 1000);		//	temp=1 ms
    
    	WriteCommand(0x01);  //software reset
    
    	//	Wait until the data has been transmitted
    	//while(SSIBusy(SSI0_BASE))
    	//{
    	//}
    
        SysCtlDelay(5 * temp);
        WriteCommand(0x28);   // display off
    	
    //---------------------------------------------------------
    	WriteCommand(0xcf);		//	Power control B  default value  : 00   A2  F0
    	WriteData(0x00);		// 1rst parameter
    	WriteData(0x83);		//	2nd parameter: power control[1:0] sur datasheet, il y a 0x81
    	WriteData(0x30);		//	3rd parameter: Discharge path enable. Enable high for ESD protection
    
    //---------------------------------------------------------
        WriteCommand(0xcf);		//	Power control B  default value  : 00   A2  F0
        WriteData(0x00);		// 1rst parameter
        WriteData(0x83);		//	2nd parameter: power control[1:0] sur datasheet, il y a 0x81
        WriteData(0x30);		//	3rd parameter: Discharge path enable. Enable high for ESD protection
    
        WriteCommand(0xed);		//	Power on sequence control  default value :  55    01    23   01
        WriteData(0x64);		//	1st parameter:soft start control avec CP1 soft start=CP23 soft start = 01
        WriteData(0x03);		//	2 / 3  parameter : power on sequence control   En_ddvdh=11 et En_vcl=00
        WriteData(0x12);		//	En_vgh= 01    &  En_vgl= 10
        WriteData(0x81);		//	4th parameter : DDVDH enhance mode (only for 8 external capacitors)  DDVDH_ENH =1
    
        WriteCommand(0xe8);		//	Driver timing control A  default value : 84    11   7A
        WriteData(0x85);		//	1  parameter:gate driver non-overlap timing control 	NOW=1
        WriteData(0x01);		//	2nd parameter:EQ timing control   EQ=0    &  CR= 1
        WriteData(0x79);		//	3rd parameter:pre-charge timing control   PC[1:0] = 01
    
        WriteCommand(0xcb);		//	Power control A		default value  :	39	2C	00	34	02
        WriteData(0x39);		//	default
        WriteData(0x2c);		//	default
        WriteData(0x00);		//	default
        WriteData(0x34);		//	vcore control  :  REG_VD[2:0]=001
        WriteData(0x02);		//	VBC[2:0]: ddvdh control  :  VBC[2:0] = 001
    
    	WriteCommand(0xf7);		//	Pump ratio control  default value : 10
    	WriteData(0x20);		//	1st parameter:ratio control : Ratio[1:0] = 01
    
    	WriteCommand(0xea);		//	Driver timing control B		default value  :	1rst parametre 66  2nd parametre 00
    	WriteData(0x00);		// 1st parameter : gate driver timing control    VG_SW_T4=00 VG_SW_T3=00 VG_SW_T2=00 VG_SW_T1=00
    	WriteData(0x00);
    
    
    	WriteCommand(0xc0);  	//	Power Control 1   default value : 21 (VRH [5:0]= 100001)
    	WriteData(0x26);		//	VRH [5:0]= 100110    Set the GVDD level, which is a reference level for the VCOM level and the grayscale voltage level.
    
    	WriteCommand(0xc1);  	//	Power Control 2  default value : BT [2:0]:000
    	WriteData(0x11);		//	BT [2:0]:001 Sets the factor used in the step-up circuits.
    
    	WriteCommand(0xc5);  	//	VCOM Control 1		default value : 31 (VMH [6:0] = 0110001  )  3C (VML [6:0] = 0111100 )
    	WriteData(0x35);		//	 Set the VCOMH voltage.  VMH [6:0] = 0010101
    	WriteData(0x3e);		//	VMH [6:0] = 0111110
    
    	WriteCommand(0xc7);  	//	VCOM Control 2    default value  C0  (VMF [6:0] =  1000000  nVM = 1  )
    	WriteData(0xbe); 		// 	VMF [6:0] = 0111110     Set the VCOM offset voltage.
    							//	nVM =  1        nVM equals to �0� after power on reset and VCOM offset equals to program MTP value. When nVM set to �1�, setting
    							//	of VMF [6:0] becomes valid and VCOMH/VCOML can be adjusted.
    
    	WriteCommand(0x36);   	// 	Memory Access Control
    	WriteData(0x48); 		//	my = 0 ,mx = 1 ,mv = 0 ,ml = 0 ,BGR =1 ,mh = 0
    
    	WriteCommand(0x3a);   	// COLMOD: Pixel Format Set		default value  : parametre = 66   DPI [2:0] = 110       DBI [2:0] = 110
    	WriteData(0x55);		//	DBI [2:0] =101   DPI [2:0] = 101  ie  16 bits / pixel
    
    	WriteCommand(0xb1);    	//  Frame Rate Control (In Normal Mode/Full Colors)   default value  : DIVA [1:0] = 00   RTNA [4:0] = 11011
    	WriteData(0x00);		//	DIVA [1:0] = 00     ie fosc = 0
    	WriteData(0x1B);  		//	RTNA [4:0] = 11011 Frame rate = 70Hz
    							//	DIVA [1:0] : division ratio for internal clocks when Normal mode.
    							//	RTNA [4:0] : RTNA[4:0] is used to set 1H (line) period of Normal mode at MCU interface.
    
    	WriteCommand(0xf2);  	// Enable 3G: default value : parametre = 02
    	WriteData(0x08);		//	3G_enb=        BIZARRERIE
    
    	WriteCommand(0x26);		//	Gamma Set  default value : parametre= 01h   avec GC [7:0] =000000001
    	WriteData(0x01); 		//  gamma set 4 gamma curve 01
    
    	WriteCommand(0xE0);  	//	Positive Gamma Correction. Set the gray scale voltage to adjust the gamma characteristics of the TFT panel
    	WriteData(0x1f);		//	VP63 [3:0] = 1111
    	WriteData(0x1a);		//	VP62 [5:0] = 011010
    	WriteData(0x18);		//	VP61 [5:0] = 011000
    	WriteData(0x0a);		//	VP59 [3:0]=1010
    	WriteData(0x0f);		//	VP57 [4:0] =01111
    	WriteData(0x06);		//	VP50 [3:0]=0110
    	WriteData(0x45);		//	VP43 [6:0] =1000101
    	WriteData(0x87);		//	VP27 [3:0] =  1000   VP36 [3:0] =0111
    	WriteData(0x32);		//	VP20 [6:0] =0110010
    	WriteData(0x0a);		//	VP13 [3:0]= 1010
    	WriteData(0x07);		//	VP6 [4:0] =00111
    	WriteData(0x02);		//	VP4 [3:0] =0010
    	WriteData(0x07);		//	VP2 [5:0] =000111
    	WriteData(0x05);		//	VP1 [5:0] =000101
    	WriteData(0x00);		//	VP0 [3:0] =0000
    
    	WriteCommand(0xE1);  	// 	Negative Gamma Correction
    	WriteData(0x00);		//	VN63 [3:0] =0000
    	WriteData(0x25);		//	VN62 [5:0]=100101
    	WriteData(0x27);		//	VN61 [5:0] =100111
    	WriteData(0x05);		//	VN59 [3:0] =0101
    	WriteData(0x10);		//	VN57 [4:0] =10000
    	WriteData(0x09);		//	VN50 [3:0] =1001
    	WriteData(0x3a);		//	VN43 [6:0] =0111010
    	WriteData(0x78);		//	VN36 [3:0]=1111   VN27 [3:0]  =0000
    	WriteData(0x4d);		//	VN20 [6:0] =1001101
    	WriteData(0x05);		//	VN13 [3:0]=0101
    	WriteData(0x18);		//	VN6 [4:0] = 11000
    	WriteData(0x0d);		//	VN4 [3:0] =1101
    	WriteData(0x38);		//	VN2 [5:0] =111000
    	WriteData(0x3a);		//	VN1 [5:0] =111010
    	WriteData(0x1f);		//	VN0 [3:0] =11111                     ATTENTION SUREMENT ERREUR ICI ON EST SUR 4-BITS SUR LA DATASHEET ET ON A 1F EST SUR 5-BITS DANS WRITEDATA
    
    
    	//	This command is used to define area of frame memory where MCU can access. This command makes no change on the
    	//	other driver status. The values of SC [15:0] and EC [15:0] are referred when RAMWR command comes. Each value
    	//	represents one column line in the Frame Memory.
    	// Voir note 1 page 110 de la datasheet pour
    	WriteCommand(0x2a);    	//	Column Address Set
    	WriteData(0x00);		//	SC15  SC14  SC13  SC12  SC11  SC10  SC9 SC8 =0
    	WriteData(0x00);		//	SC7 SC6 SC5 SC4 SC3 SC2 SC1 SC0 =0
    	WriteData(0x00);		//	EC15  EC14  EC13  EC12  EC11  EC10  EC9 EC8 =0
    	WriteData(0xEF);		//	EC7=1  EC6=1  EC5=1  EC4=0  EC3=1  EC2=1  EC1=1  EC0= 1
    
    
    	//	This command is used to define area of frame memory where MCU can access. This command makes no change on the
    	//	other driver status. The values of SP [15:0] and EP [15:0] are referred when RAMWR command comes. Each value
    	//	represents one Page line in the Frame Memory.
    	WriteCommand(0x2b);   	// 	Page Address Set
    	WriteData(0x00);		//	SP15  SP14  SP13  SP12  SP11  SP10  SP9 SP8 =0
    	WriteData(0x00);		//	SP7 SP6 SP5 SP4 SP3 SP2 SP1 SP0 =0
    	WriteData(0x01);		//	EP15  EP14  EP13  EP12  EP11  EP10  EP9=0     EP8 =1
    	WriteData(0x3F);		//	EP7=1=0 EP6=0 EP5=1 EP4=1 EP3=1 EP2=1 EP1=1 EP0 =1
    
    	WriteCommand(0x34);   // tearing effect off
    	// WriteCommand(0x35);   // tearing effect on
    
    	//WriteCommand(0xb4);   // display inversion
    	//WriteData(0x00);
    
    
    	//	GAS: Low voltage detection control.
    	//	GON/DTE: Set the output level of gate driver G1 ~ G320 as follows
    	WriteCommand(0xb7);  	//	Entry Mode Set Default Value : 06h  ( GON=1  DTE=1  GAS =0)
    	WriteData(0x07);		//	GON = 1 DTE= 1  GAS= 1   Low voltage detection=DISABLE et G1~G320 Gate Output = Normal display
    
    	WriteCommand(0xb6);   	//  Display Function Control
    	WriteData(0x0a);		//	PTG [1:0] =10  PT [1:0]=10        PTG [1:0]: Set the scan mode in non-display area. = Interval scan     PT [1:0]: Determine source/VCOM output in a non-display area in the partial display mode. =AGND AGND AGND AGND
    	WriteData(0x82);		//	REV= 1  GS=0 SS=1  SM=1  ISC [3:0]=0010   SS: Select the shift direction of outputs from the source driver/REV: Select whether the liquid crystal type is normally white type or normally black type/ISC [3:0]: Specify the scan cycle interval of gate driver in non-display area when PTG [1:0] =�10� to select interval scan.
    	WriteData(0x27);		//	NL [5:0] = 100111     /  NL [5:0]: Sets the number of lines to drive the LCD at an interval of 8 lines. The GRAM address mapping is not affected by the number of lines set by NL [5:0].
    	WriteData(0x00);		//	PCDIV [5:0] =000000  external fosc=DOTCLOCK/ (2*(PCDIV   2DOTCLK+1)
    
    
    	WriteCommand(0x11);  	//	Sleep Out
    	//	This command has no effect when module is already in sleep out mode. Sleep Out Mode can only be left by the Sleep In
    	//	Command (10h). It will be necessary to wait 5msec before sending next command, this is to allow time for the supply voltages
    	//	and clock circuits stabilize. The display module loads all display supplier�s factory default values to the registers during this
    	//	5msec and there cannot be any abnormal visual effect on the display image if factory default and register values are same
    	//	when this load is done and when the display module is already Sleep Out �mode. The display module is doing self-diagnostic
    	//	functions during this 5msec. It will be necessary to wait 120msec after sending Sleep In command (when in Sleep Out mode)
    	//	before Sleep Out command can be sent.
    
    	SysCtlDelay(100 * temp);
    
    	WriteCommand(0x29);   	// Display ON
    	//	This command is used to recover from DISPLAY OFF mode. Output from the Frame Memory is enabled.
    	//	This command makes no change of contents of frame memory.
    	//	This command does not change any other status
    
    	SysCtlDelay(100 * temp);
    
    	WriteCommand(0x2c);   	//	Memory Write
    	//	This command is used to transfer data from MCU to frame memory. This command makes no change to the other driver
    	//	status. When this command is accepted, the column register and the page register are reset to the Start Column/Start
    	//	Page positions. The Start Column/Start Page positions are different in accordance with MADCTL setting.) Then D [17:0] is
    	//	stored in frame memory and the column register and the page register incremented. Sending any other command can stop
    	//	frame Write. X = Don�t care.
    }
    
    
    //*****************************************************************************
    //
    //! Initializes the display driver.
    //!
    //! This function initializes the ILI9341 display
    //! controller on the panel, preparing it to display data.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    Formike240x320x16_ILI9340Init(void)
    {
        unsigned long ulClockMS;
    
        //
        // Get the current processor clock frequency.
        //
        ulClockMS = SysCtlClockGet() / (3 * 1000);
    
        //
        // Enable the GPIO peripherals used to interface to the ILI934x.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
       	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
       	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
        GPIOPinConfigure(GPIO_PA3_SSI0FSS);
        GPIOPinConfigure(GPIO_PA4_SSI0RX);
        GPIOPinConfigure(GPIO_PA5_SSI0TX);
        GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_5|GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2);
    
        //
        //	The upper 32 - N bits of \e ulData are discarded by the hardware, where N is
        // the data width as configured by SSIConfigSetExpClk(). For example, if the
        // interface is configured for 8-bit data width, the upper 24 bits of \e
        // ulData are discarded.
        //	For our case : 32 - N =23 so N=9
        //
        SSIConfigSetExpClk(SSI0_BASE,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER,10000,9);
        //SSIConfigSetExpClk(SSI0_BASE,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER,10000,16);
        SSIEnable(SSI0_BASE);
    
        //
        // Delay for 10ms.
        //
        SysCtlDelay(10 * ulClockMS);
    
    	Formike240x320x16_ILI9340InitScreen();
    }
    
    
    
    
    //*****************************************************************************
    //
    //! Determines whether an ILI9341 controller is present.
    //!
    //! This function queries the ID of the display controller in use and returns
    //! it to the caller.  This driver supports both ILI9341.
    //! These are very similar but the sense of the long display axis is reversed
    //! in the Formike KWH028Q02-F03 using an ILI9340 relative to the other two
    //! supported displays and this information is needed by the touchscreen driver
    //! to provide correct touch coordinate information.
    //!
    //! \return Returns 0x9340 if an ILI9341 controller is in use.
    //
    //*****************************************************************************
    unsigned short
    Formike240x320x16_ILI9340ControllerIdGet(void)
    {
        unsigned short usController;
    
        //
        // Determine which version of the display controller we are using.
        //
        usController = ReadRegister(0x00);
    
        return(usController);
    }
    
    //*****************************************************************************
    //
    //! Turns on the backlight.
    //!
    //! This function turns on the backlight on the display.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    Formike240x320x16_ILI9340BacklightOn(void)
    {
        //
        // Assert the signal that turns on the backlight.
        //
        //HWREG(LCD_BL_BASE + GPIO_O_DATA + (LCD_BL_PIN << 2)) = LCD_BL_PIN;
        WriteCommand(0x53);		//	Write CTRL Display (53h)
        WriteData(0x24);
    }
    
    //*****************************************************************************
    //
    //! Turns off the backlight.
    //!
    //! This function turns off the backlight on the display.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    Formike240x320x16_ILI9340BacklightOff(void)
    {
        //
        // Deassert the signal that turns on the backlight.
        //
        //HWREG(LCD_BL_BASE + GPIO_O_DATA + (LCD_BL_PIN << 2)) = 0;
        WriteCommand(0x53);		//	Write CTRL Display (53h)
        WriteData(0x00);
    }
    
    //*****************************************************************************
    //
    //! Draws a pixel on the screen.
    //!
    //! \param pvDisplayData is a pointer to the driver-specific data for this
    //! display driver.
    //! \param lX is the X coordinate of the pixel.
    //! \param lY is the Y coordinate of the pixel.
    //! \param ulValue is the color of the pixel.
    //!
    //! This function sets the given pixel to a particular color.  The coordinates
    //! of the pixel are assumed to be within the extents of the display.
    //!
    //! \return None.
    //
    //*****************************************************************************
    static void
    Formike240x320x16_ILI9340PixelDraw(void *pvDisplayData, long lX, long lY,
                                       unsigned long ulValue)
    {
        //
        // Set the X address of the display cursor.
        //
        WriteCommand(0x20);
    #ifdef PORTRAIT
        WriteData(lX);
    #endif
    #ifdef LANDSCAPE
        WriteData(239 - lY);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(239 - lX);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(lY);
    #endif
    
        //
        // Set the Y address of the display cursor.
        //
        WriteCommand(0x21);
    #ifdef PORTRAIT
        WriteData(lY);
    #endif
    #ifdef LANDSCAPE
        WriteData(lX);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(319 - lY);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(319 - lX);
    #endif
    
        //
        // Write the pixel value.
        //
        WriteCommand(0x22);
        WriteData(ulValue);
    }
    
    //*****************************************************************************
    //
    //! Draws a horizontal sequence of pixels on the screen.
    //!
    //! \param pvDisplayData is a pointer to the driver-specific data for this
    //! display driver.
    //! \param lX is the X coordinate of the first pixel.
    //! \param lY is the Y coordinate of the first pixel.
    //! \param lX0 is sub-pixel offset within the pixel data, which is valid for 1
    //! or 4 bit per pixel formats.
    //! \param lCount is the number of pixels to draw.
    //! \param lBPP is the number of bits per pixel; must be 1, 4, or 8.
    //! \param pucData is a pointer to the pixel data.  For 1 and 4 bit per pixel
    //! formats, the most significant bit(s) represent the left-most pixel.
    //! \param pucPalette is a pointer to the palette used to draw the pixels.
    //!
    //! This function draws a horizontal sequence of pixels on the screen, using
    //! the supplied palette.  For 1 bit per pixel format, the palette contains
    //! pre-translated colors; for 4 and 8 bit per pixel formats, the palette
    //! contains 24-bit RGB values that must be translated before being written to
    //! the display.
    //!
    //! \return None.
    //
    //*****************************************************************************
    static void
    Formike240x320x16_ILI9340PixelDrawMultiple(void *pvDisplayData, long lX,
                                               long lY, long lX0, long lCount,
                                               long lBPP,
                                               const unsigned char *pucData,
                                               const unsigned char *pucPalette)
    {
        unsigned long ulByte;
    
        //
        // Set the cursor increment to left to right, followed by top to bottom.
        //
        WriteCommand(0x03);
    #ifdef PORTRAIT
        WriteData(0x0030);
    #endif
    #ifdef LANDSCAPE
        WriteData(0x0028);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(0x0000);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(0x0018);
    #endif
    
        //
        // Set the starting X address of the display cursor.
        //
        WriteCommand(0x20);
    #ifdef PORTRAIT
        WriteData(lX);
    #endif
    #ifdef LANDSCAPE
        WriteData(239 - lY);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(239 - lX);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(lY);
    #endif
    
        //
        // Set the Y address of the display cursor.
        //
        WriteCommand(0x21);
    #ifdef PORTRAIT
        WriteData(lY);
    #endif
    #ifdef LANDSCAPE
        WriteData(lX);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(319 - lY);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(319 - lX);
    #endif
    
        //
        // Write the data RAM write command.
        //
        WriteCommand(0x22);
    
        //
        // Determine how to interpret the pixel data based on the number of bits
        // per pixel.
        //
        switch(lBPP)
        {
            //
            // The pixel data is in 1 bit per pixel format.
            //
            case 1:
            {
                //
                // Loop while there are more pixels to draw.
                //
                while(lCount)
                {
                    //
                    // Get the next byte of image data.
                    //
                    ulByte = *pucData++;
    
                    //
                    // Loop through the pixels in this byte of image data.
                    //
                    for(; (lX0 < 8) && lCount; lX0++, lCount--)
                    {
                        //
                        // Draw this pixel in the appropriate color.
                        //
                        WriteData(((unsigned long *)pucPalette)[(ulByte >>
                                                                 (7 - lX0)) & 1]);
                    }
    
                    //
                    // Start at the beginning of the next byte of image data.
                    //
                    lX0 = 0;
                }
    
                //
                // The image data has been drawn.
                //
                break;
            }
    
            //
            // The pixel data is in 4 bit per pixel format.
            //
            case 4:
            {
                //
                // Loop while there are more pixels to draw.  "Duff's device" is
                // used to jump into the middle of the loop if the first nibble of
                // the pixel data should not be used.  Duff's device makes use of
                // the fact that a case statement is legal anywhere within a
                // sub-block of a switch statement.  See
                // http://en.wikipedia.org/wiki/Duff's_device for detailed
                // information about Duff's device.
                //
                switch(lX0 & 1)
                {
                    case 0:
                        while(lCount)
                        {
                            //
                            // Get the upper nibble of the next byte of pixel data
                            // and extract the corresponding entry from the
                            // palette.
                            //
                            ulByte = (*pucData >> 4) * 3;
                            ulByte = (*(unsigned long *)(pucPalette + ulByte) &
                                      0x00ffffff);
    
                            //
                            // Translate this palette entry and write it to the
                            // screen.
                            //
                            WriteData(DPYCOLORTRANSLATE(ulByte));
    
                            //
                            // Decrement the count of pixels to draw.
                            //
                            lCount--;
    
                            //
                            // See if there is another pixel to draw.
                            //
                            if(lCount)
                            {
                    case 1:
                                //
                                // Get the lower nibble of the next byte of pixel
                                // data and extract the corresponding entry from
                                // the palette.
                                //
                                ulByte = (*pucData++ & 15) * 3;
                                ulByte = (*(unsigned long *)(pucPalette + ulByte) &
                                          0x00ffffff);
    
                                //
                                // Translate this palette entry and write it to the
                                // screen.
                                //
                                WriteData(DPYCOLORTRANSLATE(ulByte));
    
                                //
                                // Decrement the count of pixels to draw.
                                //
                                lCount--;
                            }
                        }
                }
    
                //
                // The image data has been drawn.
                //
                break;
            }
    
            //
            // The pixel data is in 8 bit per pixel format.
            //
            case 8:
            {
                //
                // Loop while there are more pixels to draw.
                //
                while(lCount--)
                {
                    //
                    // Get the next byte of pixel data and extract the
                    // corresponding entry from the palette.
                    //
                    ulByte = *pucData++ * 3;
                    ulByte = *(unsigned long *)(pucPalette + ulByte) & 0x00ffffff;
    
                    //
                    // Translate this palette entry and write it to the screen.
                    //
                    WriteData(DPYCOLORTRANSLATE(ulByte));
                }
    
                //
                // The image data has been drawn.
                //
                break;
            }
        }
    }
    
    //*****************************************************************************
    //
    //! Draws a horizontal line.
    //!
    //! \param pvDisplayData is a pointer to the driver-specific data for this
    //! display driver.
    //! \param lX1 is the X coordinate of the start of the line.
    //! \param lX2 is the X coordinate of the end of the line.
    //! \param lY is the Y coordinate of the line.
    //! \param ulValue is the color of the line.
    //!
    //! This function draws a horizontal line on the display.  The coordinates of
    //! the line are assumed to be within the extents of the display.
    //!
    //! \return None.
    //
    //*****************************************************************************
    static void
    Formike240x320x16_ILI9340LineDrawH(void *pvDisplayData, long lX1, long lX2,
                                       long lY, unsigned long ulValue)
    {
        //
        // Set the cursor increment to left to right, followed by top to bottom.
        //
        WriteCommand(0x03);
    #ifdef PORTRAIT
        WriteData(0x0030);
    #endif
    #ifdef LANDSCAPE
        WriteData(0x0028);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(0x0000);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(0x0018);
    #endif
    
        //
        // Set the starting X address of the display cursor.
        //
        WriteCommand(0x20);
    #ifdef PORTRAIT
        WriteData(lX1);
    #endif
    #ifdef LANDSCAPE
        WriteData(239 - lY);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(239 - lX1);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(lY);
    #endif
    
        //
        // Set the Y address of the display cursor.
        //
        WriteCommand(0x21);
    #ifdef PORTRAIT
        WriteData(lY);
    #endif
    #ifdef LANDSCAPE
        WriteData(lX1);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(319 - lY);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(319 - lX1);
    #endif
    
        //
        // Write the data RAM write command.
        //
        WriteCommand(0x22);
    
        //
        // Loop through the pixels of this horizontal line.
        //
        while(lX1++ <= lX2)
        {
            //
            // Write the pixel value.
            //
            WriteData(ulValue);
        }
    }
    
    //*****************************************************************************
    //
    //! Draws a vertical line.
    //!
    //! \param pvDisplayData is a pointer to the driver-specific data for this
    //! display driver.
    //! \param lX is the X coordinate of the line.
    //! \param lY1 is the Y coordinate of the start of the line.
    //! \param lY2 is the Y coordinate of the end of the line.
    //! \param ulValue is the color of the line.
    //!
    //! This function draws a vertical line on the display.  The coordinates of the
    //! line are assumed to be within the extents of the display.
    //!
    //! \return None.
    //
    //*****************************************************************************
    static void
    Formike240x320x16_ILI9340LineDrawV(void *pvDisplayData, long lX, long lY1,
                                       long lY2, unsigned long ulValue)
    {
        //
        // Set the cursor increment to top to bottom, followed by left to right.
        //
        WriteCommand(0x03);
    #ifdef PORTRAIT
        WriteData(0x0038);
    #endif
    #ifdef LANDSCAPE
        WriteData(0x0020);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(0x0008);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(0x0010);
    #endif
    
        //
        // Set the X address of the display cursor.
        //
        WriteCommand(0x20);
    #ifdef PORTRAIT
        WriteData(lX);
    #endif
    #ifdef LANDSCAPE
        WriteData(239 - lY1);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(239 - lX);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(lY1);
    #endif
    
        //
        // Set the starting Y address of the display cursor.
        //
        WriteCommand(0x21);
    #ifdef PORTRAIT
        WriteData(lY1);
    #endif
    #ifdef LANDSCAPE
        WriteData(lX);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(319 - lY1);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(319 - lX);
    #endif
    
        //
        // Write the data RAM write command.
        //
        WriteCommand(0x22);
    
        //
        // Loop through the pixels of this vertical line.
        //
        while(lY1++ <= lY2)
        {
            //
            // Write the pixel value.
            //
            WriteData(ulValue);
        }
    }
    
    //*****************************************************************************
    //
    //! Fills a rectangle.
    //!
    //! \param pvDisplayData is a pointer to the driver-specific data for this
    //! display driver.
    //! \param pRect is a pointer to the structure describing the rectangle.
    //! \param ulValue is the color of the rectangle.
    //!
    //! This function fills a rectangle on the display.  The coordinates of the
    //! rectangle are assumed to be within the extents of the display, and the
    //! rectangle specification is fully inclusive (in other words, both sXMin and
    //! sXMax are drawn, along with sYMin and sYMax).
    //!
    //! \return None.
    //
    //*****************************************************************************
    static void
    Formike240x320x16_ILI9340RectFill(void *pvDisplayData, const tRectangle *pRect,
                                      unsigned long ulValue)
    {
        long lCount;
    
        //
        // Write the X extents of the rectangle.
        //
        WriteCommand(0x50);
    #ifdef PORTRAIT
        WriteData(pRect->sXMin);
    #endif
    #ifdef LANDSCAPE
        WriteData(239 - pRect->sYMax);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(239 - pRect->sXMax);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(pRect->sYMin);
    #endif
        WriteCommand(0x51);
    #ifdef PORTRAIT
        WriteData(pRect->sXMax);
    #endif
    #ifdef LANDSCAPE
        WriteData(239 - pRect->sYMin);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(239 - pRect->sXMin);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(pRect->sYMax);
    #endif
    
        //
        // Write the Y extents of the rectangle.
        //
        WriteCommand(0x52);
    #ifdef PORTRAIT
        WriteData(pRect->sYMin);
    #endif
    #ifdef LANDSCAPE
        WriteData(pRect->sXMin);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(319 - pRect->sYMax);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(319 - pRect->sXMax);
    #endif
        WriteCommand(0x53);
    #ifdef PORTRAIT
        WriteData(pRect->sYMax);
    #endif
    #ifdef LANDSCAPE
        WriteData(pRect->sXMax);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(319 - pRect->sYMin);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(319 - pRect->sXMin);
    #endif
    
        //
        // Set the display cursor to the upper left of the rectangle.
        //
        WriteCommand(0x20);
    #ifdef PORTRAIT
        WriteData(pRect->sXMin);
    #endif
    #ifdef LANDSCAPE
        WriteData(239 - pRect->sYMin);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(239 - pRect->sXMin);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(pRect->sYMin);
    #endif
        WriteCommand(0x21);
    #ifdef PORTRAIT
        WriteData(pRect->sYMin);
    #endif
    #ifdef LANDSCAPE
        WriteData(pRect->sXMin);
    #endif
    #ifdef PORTRAIT_FLIP
        WriteData(319 - pRect->sYMax);
    #endif
    #ifdef LANDSCAPE_FLIP
        WriteData(319 - pRect->sXMax);
    #endif
    
        //
        // Write the data RAM write command.
        //
        WriteCommand(0x22);
    
        //
        // Loop through the pixels of this filled rectangle.
        //
        for(lCount = ((pRect->sXMax - pRect->sXMin + 1) *
                      (pRect->sYMax - pRect->sYMin + 1)); lCount >= 0; lCount--)
        {
            //
            // Write the pixel value.
            //
            WriteData(ulValue);
        }
    
        //
        // Reset the X extents to the entire screen.
        //
        WriteCommand(0x50);
        WriteData(0x0000);
        WriteCommand(0x51);
        WriteData(0x00ef);
    
        //
        // Reset the Y extents to the entire screen.
        //
        WriteCommand(0x52);
        WriteData(0x0000);
        WriteCommand(0x53);
        WriteData(0x013f);
    }
    
    //*****************************************************************************
    //
    //! Translates a 24-bit RGB color to a display driver-specific color.
    //!
    //! \param pvDisplayData is a pointer to the driver-specific data for this
    //! display driver.
    //! \param ulValue is the 24-bit RGB color.  The least-significant byte is the
    //! blue channel, the next byte is the green channel, and the third byte is the
    //! red channel.
    //!
    //! This function translates a 24-bit RGB color into a value that can be
    //! written into the display's frame buffer in order to reproduce that color,
    //! or the closest possible approximation of that color.
    //!
    //! \return Returns the display-driver specific color.
    //
    //*****************************************************************************
    static unsigned long
    Formike240x320x16_ILI9340ColorTranslate(void *pvDisplayData,
                                            unsigned long ulValue)
    {
        //
        // Translate from a 24-bit RGB color to a 5-6-5 RGB color.
        //
        return(DPYCOLORTRANSLATE(ulValue));
    }
    
    //*****************************************************************************
    //
    //! Flushes any cached drawing operations.
    //!
    //! \param pvDisplayData is a pointer to the driver-specific data for this
    //! display driver.
    //!
    //! This functions flushes any cached drawing operations to the display.  This
    //! is useful when a local frame buffer is used for drawing operations, and the
    //! flush would copy the local frame buffer to the display.  For the ILI934x
    //! driver, the flush is a no operation.
    //!
    //! \return None.
    //
    //*****************************************************************************
    static void
    Formike240x320x16_ILI9340Flush(void *pvDisplayData)
    {
        //
        // There is nothing to be done.
        //
    }
    
    //*****************************************************************************
    //
    //! The graphics library display structure that describes the driver for the
    //! F02, F03 or F05 variants of the Formike Electronic KWH028Q02 TFT panel with
    //! ILI934x controllers.
    //
    //*****************************************************************************
    const tDisplay g_sFormike240x320x16_ILI9340 =
    {
        sizeof(tDisplay),
        0,
    #if defined(PORTRAIT) || defined(PORTRAIT_FLIP)
        240,
        320,
    #else
        320,
        240,
    #endif
        Formike240x320x16_ILI9340PixelDraw,
        Formike240x320x16_ILI9340PixelDrawMultiple,
        Formike240x320x16_ILI9340LineDrawH,
        Formike240x320x16_ILI9340LineDrawV,
        Formike240x320x16_ILI9340RectFill,
        Formike240x320x16_ILI9340ColorTranslate,
        Formike240x320x16_ILI9340Flush
    };
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    
    4885.formike240x320x16_ili9340.h

  • Hello Raphael,

    It seems that the SSI Pin Mux is not correct. It should be the following

    #define GPIO_PA2_SSI0CLK        0x00000802
    #define GPIO_PA3_SSI0FSS        0x00000C02
    #define GPIO_PA4_SSI0RX         0x00001002
    #define GPIO_PA5_SSI0TX         0x00001402

    in the code file for display it is defined 0x0000zz01

    Also when Sending a SSI Data you need to read the Buffer to flush it out.

    Similarly to get a SSI Data you need to write to the Buffer so that it can be pushed out.

    Regards

    Amit

  • Hello Amit,

    I have each signal (Tx, Cs, Fss) for SSI communication on the oscilloscope. So now, the frames are in TxFIFO.

    What is the function to read it ?

    Thanks for you help.

    Regards

  • Hello Raphael,

    I am not sure what you mean by frames? Is it the display frames for the LCD Panel?

    The data in the TXFIFO cannot be read by the CPU. When a CPU does a Read from SSI it gets the last data from RXFIFO.

    Regards

    Amit

  • CS going down, Clk starting, and Tx data starting from the LM4F.

    When I put the LCD_test, there are lines on the displayat the end. If I put the command reset i have the reset screen.

    So I think the LCD get the Data... and thecommunication works.

    But i didn't manage to display 'Hello' for example.

    Regards

  • Hello Raphael,

    I am not familiar with the LCD Panel you have and may be you would need to google some examples. Community members if have worked on it, may be also be able to help.

    Regards

    Amit

  • A quick, most uncertain advisory - not all of those LCD Controllers enable "full" display control via SPI.  (yes - I realize that's counter-intuitive - but our group specializes in displays - and have moved far from these controllers for just that reason!)  (Note - this is not a knock on that controller vendor - multiple such - similar Lcd controllers - disappoint as they provide the SPI feature for many, critical register read/writes - but not for the "pixel populating" of the entire display!)  And this fact is rarely, clearly declared...

    I'd address the Lcd maker directly - asking if the SPI interface - "alone" may be used to create full screen images upon your Lcd.

    Note further that even should SPI enable full, "Pixel Populating of your display" - and should that display be color (w/2 or 3 bytes per pixel) - be prepared for extremely slow screen clears and updates.

    Serial interfaces are attractive due to the reduction in signal interconnect - but like most things in engineering - "trade-offs" are an often encountered, "sidecar."  (i.e. you trade connection ease for "reasonable", screen performance!)  If of interest - our group has migrated to lower cost - controller-less TFTs - which we drive from higher speed ARM MCUs which feature external bus interface & direct TFT control signals...

    One last point - title of this post is of little (i.e. NO) value.  Would not, "SPI control of an Lcd" far better signal what you seek?  I rarely open such posts - lack of care in titling casts grave doubt on your content...  Packaging is important - "packaging" here is your title/subject!  Realize that you're competing here for the time/effort of (perhaps) very skilled/busy others.   You must make some effort to attract & SELL them!  (if you don't care - why should we?)

    I bet you that, "better/proper packaging" will enhance many aspects of your life - will prove most worthwhile...

  • Thanks for your advises.

  • Hello Raphael,

    Without the Data sheet of the panel, it would be tough figuring why the "hello" does not get printed.

    If you can provide the same (as asked earlier), the forum can be more helpful

    Regards

    Amit