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.

Graphics Library Demo for BOOSTXL-K350QVGA-S1 on MSP430F5529LP vs. MSP-EXP432P401R Launchpad?

Hi all,

I have both an MSP430F5529LP and an MSP-EXP432P401R launchpad, along with a BOOSTXL-K350QVGA-S1.  I am using the IAR tools for MSP430 and for ARM Cortex-M respectively.  I am trying to run a comparison of the TI Graphics Library demos from GRLIB_3_21_00_00 on both processors.

First of all, when trying to perform a "screen calibration", I had continuous problems getting xMin and yMin values that were considered "in range" by the validateCalibration() function in touch_P401R.c.  Even using a stylus and trying to hit the dead center of the red dots, I kept getting "INVALID CALIBRATION".  I finally looked at the values in the debugger, and they were very repeatable, so I eventually modified the code to open up the limits a bit so that I could pass the initial calibration.

Next, I expected to see that the MSP432 would "paint" the graphics images on the LCD quite a bit faster, since it's a 32-bit ARM vs. 16-bit MSP430, and is running at 48 MHz for the MSP432 vs. 25 MHz for the MSP430.  Much to my surprise, it seems like the painting of the graphics images is actually slower on the MSP432 than on the MSP430!  I checked optimizations, etc., and it looks like they are all turned off for these demos.

I have not actually measured the execution time to draw the graphics images on the display, but to my untrained eye, I'd say that the MSP432 seems to draw about 50% to 100% slower than the MSP430!  I have to admit that I was pretty shocked.  It's not a show-stopper, and most users might not even notice, but I expected to see exactly the opposite, with the MSP432 doing the work faster than the MSP430.

Have any of you tried similar experiments?  Have you seen similar behavior?  Do you have any suggestions on things to try or configuration changes that might need to be made so that the MSP432 behaves faster than the MSP430?  One suspicion that I have not had time to investigate is whether the SPI interface to the display is being configured to a slower clock rate than on the MSP430.  There could also be differences in the CPU clock or peripheral clock initializations that would affect this behavior, but I did not want to sink a lot of time into this without checking with other Graphics Library users first.

Also, have any of you experienced the same kind of rejection of initial calibration?  If so, what did you do to solve it?  I'm assuming (perhaps incorrectly), that the xMin and yMin values were calculated based on expected ADC readings from the display Booster Pack, but maybe the default range is simply too tight, or has an offset that has not been accounted for.

Any help or suggestions are appreciated.  I have not tried any compiler optimizations for speed, either, since often optimizations will interfere with ease of debugging.

Thanks in advance for your help, Graphics Library gurus!

Scott

  • Hi Scott,

    Scott Whitney80914 said:
    Next, I expected to see that the MSP432 would "paint" the graphics images on the LCD quite a bit faster, since it's a 32-bit ARM vs. 16-bit MSP430, and is running at 48 MHz for the MSP432 vs. 25 MHz for the MSP430.  Much to my surprise, it seems like the painting of the graphics images is actually slower on the MSP432 than on the MSP430!  I checked optimizations, etc., and it looks like they are all turned off for these demos.

    Interesting, maybe the spi clock was not configured correctly. Could you please send me your main.c and HAL_MSP_EXP432P401R_KITRONIX320X240_SSD2119_SPI.c (I would like review the clock configurations).

    Scott Whitney80914 said:
    Also, have any of you experienced the same kind of rejection of initial calibration?  If so, what did you do to solve it?  I'm assuming (perhaps incorrectly), that the xMin and yMin values were calculated based on expected ADC readings from the display Booster Pack, but maybe the default range is simply too tight, or has an offset that has not been accounted for.

     We are in the process of updating this example code, in the meantime I'm putting together an example code that should help you with this calibration. I'll get it ready by tomorrow.

       Best regards,

        David

  • Scott Whitney80914 said:

    Next, I expected to see that the MSP432 would "paint" the graphics images on the LCD quite a bit faster, since it's a 32-bit ARM vs. 16-bit MSP430, and is running at 48 MHz for the MSP432 vs. 25 MHz for the MSP430.  Much to my surprise, it seems like the painting of the graphics images is actually slower on the MSP432 than on the MSP430!

    5529 has CPUX v2 that can execute 20-bit instructions in one cycle. And it can be overclocked without problems.

  • Thanks - good info, but not sure that it completely explains what is happening on the MSP432 for an apples-to-apples comparison.
  • Thanks for the help, David.  I hope the two files have been attached correctly.  It took a bit to discover that I had to enable Rich Text Formatting, and then an "Insert File" button showed up.  If the two files you need aren't available to you, perhaps you could provide me with instructions on the best way to attach a file to my reply.  Best regards,  Scott

    14782.main.c
    /* --COPYRIGHT--,BSD
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    /* DriverLib Includes */
    #include "driverlib.h"
    
    /* Standard Includes */
    #include <stdint.h>
    
    /* GrLib Includes */
    #include "grlib.h"
    #include "button.h"
    #include "imageButton.h"
    #include "radioButton.h"
    #include "checkbox.h"
    #include "LcdDriver/kitronix320x240x16_ssd2119_spi.h"
    #include "images/images.h"
    #include "touch_P401R.h"
    
    //Touch screen context
    touch_context g_sTouchContext;
    Graphics_ImageButton primitiveButton;
    Graphics_ImageButton imageButton;
    Graphics_Button yesButton;
    Graphics_Button noButton;
    
    // Graphic library context
    Graphics_Context g_sContext;
    
    //Flag to know if a demo was run
    bool g_ranDemo = false;
    
    void Delay(uint16_t msec);
    void boardInit(void);
    void clockInit(void);
    void initializeDemoButtons(void);
    void drawMainMenu(void);
    void runPrimitivesDemo(void);
    void runImagesDemo(void);
    void drawRestarDemo(void);
    
    void main(void)
    {
    //	int16_t ulIdx;
        WDT_A_hold(WDT_A_BASE);
    
        /* Initialize the demo. */
        boardInit();
        clockInit();
        initializeDemoButtons();
    
        /* Globally enable interrupts. */
        __enable_interrupt();
    
        // LCD setup using Graphics Library API calls
        Kitronix320x240x16_SSD2119Init();
        Graphics_initContext(&g_sContext, &g_sKitronix320x240x16_SSD2119);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        Graphics_setFont(&g_sContext, &g_sFontCmss20b);
        Graphics_clearDisplay(&g_sContext);
    
        touch_initInterface();
    
        drawMainMenu();
    
        // Loop to detect touch
        while(1)
        {
            touch_updateCurrentTouch(&g_sTouchContext);
    
            if(g_sTouchContext.touch)
            {
                if(Graphics_isImageButtonSelected(&primitiveButton,
                                                  g_sTouchContext.x,
                                                  g_sTouchContext.y))
                {
                    Graphics_drawSelectedImageButton(&g_sContext,&primitiveButton);
                    runPrimitivesDemo();
                }
                else if(Graphics_isImageButtonSelected(&imageButton,
                                                       g_sTouchContext.x,
                                                       g_sTouchContext.y))
                {
                    Graphics_drawSelectedImageButton(&g_sContext,&imageButton);
                    runImagesDemo();
                }
    
                if(g_ranDemo == true)
                {
                    g_ranDemo = false;
                    drawMainMenu();
                }
            }
        }
    }
    
    void initializeDemoButtons(void)
    {
        // Initiliaze primitives Demo Button
        primitiveButton.xPosition = 20;
        primitiveButton.yPosition = 50;
        primitiveButton.borderWidth = 5;
        primitiveButton.selected = false;
        primitiveButton.imageWidth = Primitives_Button4BPP_UNCOMP.xSize;
        primitiveButton.imageHeight = Primitives_Button4BPP_UNCOMP.ySize;
        primitiveButton.borderColor = GRAPHICS_COLOR_WHITE;
        primitiveButton.selectedColor = GRAPHICS_COLOR_RED;
        primitiveButton.image = &Primitives_Button4BPP_UNCOMP;
    
        // Initiliaze images Demo Button
        imageButton.xPosition = 180;
        imageButton.yPosition = 50;
        imageButton.borderWidth = 5;
        imageButton.selected = false;
        imageButton.imageWidth = Primitives_Button4BPP_UNCOMP.xSize;
        imageButton.imageHeight = Primitives_Button4BPP_UNCOMP.ySize;
        imageButton.borderColor = GRAPHICS_COLOR_WHITE;
        imageButton.selectedColor = GRAPHICS_COLOR_RED;
        imageButton.image = &Images_Button4BPP_UNCOMP;
    
        yesButton.xMin = 80;
        yesButton.xMax = 150;
        yesButton.yMin = 80;
        yesButton.yMax = 120;
        yesButton.borderWidth = 1;
        yesButton.selected = false;
        yesButton.fillColor = GRAPHICS_COLOR_RED;
        yesButton.borderColor = GRAPHICS_COLOR_RED;
        yesButton.selectedColor = GRAPHICS_COLOR_BLACK;
        yesButton.textColor = GRAPHICS_COLOR_BLACK;
        yesButton.selectedTextColor = GRAPHICS_COLOR_RED;
        yesButton.textXPos = 100;
        yesButton.textYPos = 90;
        yesButton.text = "YES";
        yesButton.font = &g_sFontCm18;
    
        noButton.xMin = 180;
        noButton.xMax = 250;
        noButton.yMin = 80;
        noButton.yMax = 120;
        noButton.borderWidth = 1;
        noButton.selected = false;
        noButton.fillColor = GRAPHICS_COLOR_RED;
        noButton.borderColor = GRAPHICS_COLOR_RED;
        noButton.selectedColor = GRAPHICS_COLOR_BLACK;
        noButton.textColor = GRAPHICS_COLOR_BLACK;
        noButton.selectedTextColor = GRAPHICS_COLOR_RED;
        noButton.textXPos = 200;
        noButton.textYPos = 90;
        noButton.text = "NO";
        noButton.font = &g_sFontCm18;
    }
    
    void drawMainMenu(void)
    {
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        Graphics_clearDisplay(&g_sContext);
        Graphics_drawStringCentered(&g_sContext, "MSP Graphics Library Demo",
                                    AUTO_STRING_LENGTH,
                                    159,
                                    15,
                                    TRANSPARENT_TEXT);
    
        // Draw TI banner at the bottom of screnn
        Graphics_drawImage(&g_sContext,
                           &TI_platform_bar_red4BPP_UNCOMP,
                           0,
                           Graphics_getDisplayHeight(
                               &g_sContext) - TI_platform_bar_red4BPP_UNCOMP.ySize);
    
        // Draw Primitives image button
        Graphics_drawImageButton(&g_sContext, &primitiveButton);
    
        // Draw Images image button
        Graphics_drawImageButton(&g_sContext, &imageButton);
    }
    
    void runPrimitivesDemo(void)
    {
        int16_t ulIdx;
        uint32_t color;
    
        Graphics_Rectangle myRectangle1 = { 10, 50, 155, 120};
        Graphics_Rectangle myRectangle2 = { 150, 100, 300, 200};
        Graphics_Rectangle myRectangle3 = { 0, 0, 319, 239};
    
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        Graphics_clearDisplay(&g_sContext);
        Graphics_drawString(&g_sContext, "Draw Pixels & Lines", AUTO_STRING_LENGTH,
                            60, 5, TRANSPARENT_TEXT);
        Graphics_drawPixel(&g_sContext, 45, 45);
        Graphics_drawPixel(&g_sContext, 45, 50);
        Graphics_drawPixel(&g_sContext, 50, 50);
        Graphics_drawPixel(&g_sContext, 50, 45);
        Graphics_drawLine(&g_sContext, 60, 60, 200, 200);
        Graphics_drawLine(&g_sContext, 30, 200, 200, 60);
        Graphics_drawLine(&g_sContext, 0, Graphics_getDisplayHeight(
                              &g_sContext) - 1,
                          Graphics_getDisplayWidth(&g_sContext) - 1,
                          Graphics_getDisplayHeight(&g_sContext) - 1);
        Delay(2000);
        Graphics_clearDisplay(&g_sContext);
        Graphics_drawStringCentered(&g_sContext, "Draw Rectangles",
                                    AUTO_STRING_LENGTH, 159, 15, TRANSPARENT_TEXT);
        Graphics_drawRectangle(&g_sContext, &myRectangle1);
        Graphics_fillRectangle(&g_sContext, &myRectangle2);
        // Text won't be visible on screen due to transparency (foreground colors match)
        Graphics_drawStringCentered(&g_sContext, "Normal Text", AUTO_STRING_LENGTH,
                                    225, 120, TRANSPARENT_TEXT);
        // Text draws foreground and background for opacity
        Graphics_drawStringCentered(&g_sContext, "Opaque Text", AUTO_STRING_LENGTH,
                                    225, 150, OPAQUE_TEXT);
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
    
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_RED);
        // Text draws with inverted foreground color to become visible
        Graphics_drawStringCentered(&g_sContext, "Invert Text", AUTO_STRING_LENGTH,
                                    225, 180, TRANSPARENT_TEXT);
        Delay(2000);
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        // Invert the foreground and background colors
        Graphics_fillRectangle(&g_sContext, &myRectangle3);
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_RED);
        Graphics_drawStringCentered(&g_sContext, "Invert Colors",
                                    AUTO_STRING_LENGTH, 159, 15, TRANSPARENT_TEXT);
        Graphics_drawRectangle(&g_sContext, &myRectangle1);
        Graphics_fillRectangle(&g_sContext, &myRectangle2);
        // Text won't be visible on screen due to transparency
        Graphics_drawStringCentered(&g_sContext, "Normal Text", AUTO_STRING_LENGTH,
                                    225, 120, TRANSPARENT_TEXT);
        // Text draws foreground and background for opacity
        Graphics_drawStringCentered(&g_sContext, "Opaque Text", AUTO_STRING_LENGTH,
                                    225, 150, OPAQUE_TEXT);
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        // Text draws with inverted color to become visible
        Graphics_drawStringCentered(&g_sContext, "Invert Text", AUTO_STRING_LENGTH,
                                    225, 180, TRANSPARENT_TEXT);
        Delay(2000);
        Graphics_clearDisplay(&g_sContext);
        Graphics_drawStringCentered(&g_sContext, "Draw Circles", AUTO_STRING_LENGTH,
                                    159, 15, TRANSPARENT_TEXT);
        Graphics_drawCircle(&g_sContext, 100, 100, 50);
        Graphics_fillCircle(&g_sContext, 200, 140, 70);
        Delay(2000);
        Graphics_clearDisplay(&g_sContext);
        // Add some more color
        Graphics_setForegroundColor(&g_sContext, ClrLawnGreen);
        Graphics_setBackgroundColor(&g_sContext, ClrBlack);
        Graphics_clearDisplay(&g_sContext);
        Graphics_drawStringCentered(&g_sContext, "Rainbow of Colored Lines",
                                    AUTO_STRING_LENGTH, 159, 15, TRANSPARENT_TEXT);
        // Draw a quarter rectangle sweep of lines from red to purple.
        for(ulIdx = 128; ulIdx >= 1; ulIdx--)
        {
            // Red Color
            *((uint16_t*) (&color) + 1) = 255;
            // Blue and Green Colors
            *((uint16_t*) (&color)) =
                ((((128 - ulIdx) * 255) >> 7) << ClrBlueShift);
    
            Graphics_setForegroundColor(&g_sContext, color);
            Graphics_drawLine(&g_sContext, 160, 200, 32, ulIdx + 72);
        }
        // Draw a quarter rectangle sweep of lines from purple to blue.
        for(ulIdx = 128; ulIdx >= 1; ulIdx--)
        {
            // Red Color
            *((uint16_t*) (&color) + 1) = (ulIdx * 255) >> 7;
            // Blue and Green Colors
            *((uint16_t*) (&color)) = 255 << ClrBlueShift;
    
            Graphics_setForegroundColor(&g_sContext, color);
            Graphics_drawLine(&g_sContext, 160, 200, 160 - ulIdx, 72);
        }
        // Clear Red Color
        *((uint16_t*) (&color) + 1) = 0;
        // Draw a quarter rectangle sweep of lines from blue to teal.
        for(ulIdx = 128; ulIdx >= 1; ulIdx--)
        {
            // Blue and Green Colors
            *((uint16_t*) (&color)) =
                ((((128 -
                    ulIdx) * 255) >> 7) << ClrGreenShift) | (255 << ClrBlueShift);
    
            Graphics_setForegroundColor(&g_sContext, color);
            Graphics_drawLine(&g_sContext, 160, 200, 288 - ulIdx, 72);
        }
        // Draw a quarter rectangle sweep of lines from teal to green.
        for(ulIdx = 128; ulIdx >= 0; ulIdx--)
        {
            // Blue and Green Colors
            *((uint16_t*) (&color)) =
                (255 << ClrGreenShift) | (((ulIdx * 255) >> 7) << ClrBlueShift);
    
            Graphics_setForegroundColor(&g_sContext, color);
            Graphics_drawLine(&g_sContext, 160, 200, 288, 200 - (ulIdx));
        }
        Delay(2000);
        g_ranDemo = true;
    
        drawRestarDemo();
    }
    
    void runImagesDemo(void)
    {
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        Graphics_clearDisplay(&g_sContext);
        Graphics_drawStringCentered(&g_sContext, "Draw Uncompressed Image",
                                    AUTO_STRING_LENGTH, 159, 200, TRANSPARENT_TEXT);
        Delay(2000);
        // Draw Image on the display
        Graphics_drawImage(&g_sContext, &lcd_color_320x2408BPP_UNCOMP, 0, 0);
        Delay(2000);
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_WHITE);
        Graphics_clearDisplay(&g_sContext);
        Graphics_drawStringCentered(&g_sContext, "Draw RLE4 compressed Image",
                                    AUTO_STRING_LENGTH, 159, 200, TRANSPARENT_TEXT);
        Delay(2000);
        Graphics_drawImage(&g_sContext, &TI_logo_150x1501BPP_COMP_RLE4, 85, 45);
        Delay(2000);
    
        g_ranDemo = true;
    
        drawRestarDemo();
    }
    
    void drawRestarDemo(void)
    {
        g_ranDemo = false;
        Graphics_setForegroundColor(&g_sContext, GRAPHICS_COLOR_RED);
        Graphics_setBackgroundColor(&g_sContext, GRAPHICS_COLOR_BLACK);
        Graphics_clearDisplay(&g_sContext);
        Graphics_drawStringCentered(&g_sContext, "Would you like to go back",
                                    AUTO_STRING_LENGTH,
                                    159,
                                    45,
                                    TRANSPARENT_TEXT);
        Graphics_drawStringCentered(&g_sContext, "to the main menu?",
                                    AUTO_STRING_LENGTH,
                                    159,
                                    65,
                                    TRANSPARENT_TEXT);
    
        // Draw Primitives image button
        Graphics_drawButton(&g_sContext, &yesButton);
    
        // Draw Images image button
        Graphics_drawButton(&g_sContext, &noButton);
    
        do
        {
            touch_updateCurrentTouch(&g_sTouchContext);
            if(Graphics_isButtonSelected(&noButton, g_sTouchContext.x,
                                         g_sTouchContext.y))
            {
                Graphics_drawSelectedButton(&g_sContext, &noButton);
                g_ranDemo = true;
            }
            else
            {
                if(g_ranDemo)
                {
                    Graphics_drawReleasedButton(&g_sContext, &noButton);
                    g_ranDemo = false;
                }
            }
        }
        while(!Graphics_isButtonSelected(&yesButton, g_sTouchContext.x,
                                         g_sTouchContext.y));
    
        Graphics_drawSelectedButton(&g_sContext, &yesButton);
    
        g_ranDemo = true;
        Delay(1000);
    }
    
    void boardInit()
    {
        FPU_enableModule();
    }
    
    void clockInit(void)
    {
        /* 2 flash wait states, VCORE = 1, running off DC-DC, 48 MHz */
        FlashCtl_setWaitState(FLASH_BANK0, 2);
        FlashCtl_setWaitState(FLASH_BANK1, 2);
        PCM_setPowerState(PCM_AM_DCDC_VCORE1);
        CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
        CS_setDCOFrequency(48000000);
        CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, 1);
        CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, 1);
        CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, 1);
    
        return;
    }
    
    void Delay(uint16_t msec){
        uint32_t i = 0;
        uint32_t time = (msec / 1000) * (SYSTEM_CLOCK_SPEED / 15);
    
        for(i = 0; i < time; i++)
        {
            ;
        }
    }
    
    HAL_MSP_EXP432P401R_KITRONIX320X240_SSD2119_SPI.c
    /* --COPYRIGHT--,BSD
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    // TODO update this diagram
    //*****************************************************************************
    //
    // HAL_MSP-EXP430FR5969_Sharp96x96.c
    //
    //*****************************************************************************
    //
    //! \addtogroup display_api
    //! @{
    //
    //*****************************************************************************
    
    #include "grlib.h"
    #include "HAL_MSP_EXP432P401R_KITRONIX320X240_SSD2119_SPI.h"
    #include "kitronix320x240x16_ssd2119_spi.h"
    #include "driverlib.h"
    
    //*****************************************************************************
    //
    //! Initializes the display driver.
    //!
    //! This function initializes the Sharp96x96 display. This function
    //! configures the GPIO pins used to control the LCD display when the basic
    //! GPIO interface is in use. On exit, the LCD has been reset and is ready to
    //! receive command and data writes.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void HAL_LCD_initLCD(void)
    {
        //
        // Configure the pins that connect to the LCD as GPIO outputs.
        //
        GPIO_setAsOutputPin(LCD_RESET_PORT,
                            LCD_RESET_PIN);
    
        GPIO_setOutputLowOnPin(LCD_RESET_PORT,
                               LCD_RESET_PIN);
    
        GPIO_setAsOutputPin(LCD_SDC_PORT,
                            LCD_SDC_PIN);
    
        GPIO_setOutputLowOnPin(LCD_SDC_PORT,
                               LCD_SDC_PIN);
    
        GPIO_setAsOutputPin(LCD_SCS_PORT,
                            LCD_SCS_PIN);
    
        GPIO_setOutputLowOnPin(LCD_SCS_PORT,
                               LCD_SCS_PIN);
    
        //
        // Configure SPI peripheral.
        //
        // Configure LCD_SIMO_PIN
        GPIO_setAsPeripheralModuleFunctionOutputPin(LCD_SDI_PORT,
                                                    LCD_SDI_PIN,
                                                    LCD_SDI_PIN_FUNCTION);
    
        // Configure LCD_CLK_PIN  option select CLK
        GPIO_setAsPeripheralModuleFunctionOutputPin(LCD_SCL_PORT, LCD_SCL_PIN,
                                                    LCD_SCL_PIN_FUNCTION);
    
        eUSCI_SPI_MasterConfig spiMasterConfig =
        {
            EUSCI_B_SPI_CLOCKSOURCE_SMCLK,                      // SMCLK Clock Source
            CS_getSMCLK(),                                  // Get SMCLK frequency
            16000000,                                                // SPICLK = 16 MHz
            EUSCI_B_SPI_MSB_FIRST,                             // MSB First
            EUSCI_B_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,         // Phase
            EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW,         // Low polarity
            EUSCI_B_SPI_3PIN                                   // 3Wire SPI Mode
        };
    
        SPI_initMaster(LCD_EUSCI_MODULE, &spiMasterConfig);
    
        SPI_clearInterruptFlag(LCD_EUSCI_MODULE,
                               EUSCI_B_SPI_RECEIVE_INTERRUPT);
    
        SPI_enableModule(LCD_EUSCI_MODULE);
    
    /*    // Initialize USCI_B1 for SPI Master operation
            EUSCI_B_SPI_initMaster(LCD_EUSCI_BASE,
            EUSCI_B_SPI_CLOCKSOURCE_SMCLK,
                CS_getSMCLK(),
                15000000,
            EUSCI_B_SPI_MSB_FIRST,
            EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT,
            EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_HIGH,
            EUSCI_B_SPI_3PIN);
    
        EUSCI_B_SPI_clearInterrupt(LCD_EUSCI_BASE,
                               EUSCI_B_SPI_RECEIVE_INTERRUPT);
    
        EUSCI_B_SPI_enable(LCD_EUSCI_BASE);*/
    
        //
        // Set the LCD Backlight high to enable
        //
        GPIO_setAsOutputPin(LCD_PWM_PORT,
                            LCD_PWM_PIN);
    
        GPIO_setOutputHighOnPin(LCD_PWM_PORT,
                                LCD_PWM_PIN);
    
        //
        // Set the LCD control pins to their default values.
        //
    
        GPIO_setOutputHighOnPin(LCD_SDC_PORT,
                                LCD_SDC_PIN);
    
        GPIO_setOutputLowOnPin(LCD_SCS_PORT,
                               LCD_SCS_PIN);
    
        //
        // Delay for 1ms.
        //
        HAL_LCD_delay(1);
    
        //
        // Deassert the LCD reset signal.
        //
    
        GPIO_setOutputHighOnPin(LCD_RESET_PORT,
                                LCD_RESET_PIN);
    
        //
        // Delay for 1ms while the LCD comes out of reset.
        //
        HAL_LCD_delay(1);
    }
    
    //*****************************************************************************
    //
    // Writes a command to the UC1701.  This function implements the basic SPI
    // interface to the LCD display.
    //
    //*****************************************************************************
    void HAL_LCD_writeCommand(uint8_t command)
    {
        //
        // Wait for any SPI transmission to complete before setting the LCD_SDC signal.
        //
        while(SPI_isBusy(LCD_EUSCI_MODULE))
        {
            ;
        }
    
        //
        // Set the LCD_SDC signal low, indicating that following writes are commands.
        //
        GPIO_setOutputLowOnPin(LCD_SDC_PORT, LCD_SDC_PIN);
    
        //
        // Transmit the command.
        //
        SPI_transmitData(LCD_EUSCI_MODULE, command);
    
        //
        // Wait for the SPI transmission to complete before setting the LCD_SDC signal.
        //
        while(SPI_isBusy(LCD_EUSCI_MODULE))
        {
            ;
        }
    
        //
        // Set the LCD_SDC signal high, indicating that following writes are data.
        //
        GPIO_setOutputHighOnPin(LCD_SDC_PORT,LCD_SDC_PIN);
    }
    
    //*****************************************************************************
    //
    // Writes a data word to the UC1701.  This function implements the basic SPI
    // interface to the LCD display.
    //
    //*****************************************************************************
    void HAL_LCD_writeData(uint16_t data)
    {
        uint8_t ui8Data;
    
        //
        // Calculate the high byte to transmit.
        //
        ui8Data = (uint8_t)(data >> 8);
    
        //
        // Wait for the transmit buffer to become empty.
        //
        while(!SPI_getInterruptStatus(LCD_EUSCI_MODULE,
                                      EUSCI_B_SPI_TRANSMIT_INTERRUPT))
        {
            ;
        }
    
        //
        // Transmit the high byte.
        //
        SPI_transmitData(LCD_EUSCI_MODULE,ui8Data);
    
        //
        // Calculate the low byte to transmit.
        //
        ui8Data = (uint8_t)(data & 0xff);
    
        //
        // Wait for the transmit buffer to become empty.
        //
        while(!SPI_getInterruptStatus(LCD_EUSCI_MODULE,
                                      EUSCI_B_SPI_TRANSMIT_INTERRUPT))
        {
            ;
        }
    
        //
        // Transmit the high byte.
        //
        SPI_transmitData(LCD_EUSCI_MODULE,ui8Data);
    }
    
    //*****************************************************************************
    //
    // Clears CS line
    //
    // This macro allows to clear the Chip Select (CS) line
    //
    // \return None
    //
    //*****************************************************************************
    
    void HAL_LCD_selectLCD(){
        //
        // Wait for any SPI transmission to complete before setting the LCD_SCS signal.
        //
        while(SPI_isBusy(LCD_EUSCI_MODULE))
        {
            ;
        }
    
        GPIO_setOutputLowOnPin(LCD_SCS_PORT, LCD_SCS_PIN);
    }
    
    //*****************************************************************************
    //
    // Set CS line
    //
    // This macro allows to set the Chip Select (CS) line
    //
    // \return None
    //
    //*****************************************************************************
    
    void HAL_LCD_deselectLCD(){
        //
        // Wait for any SPI transmission to complete before setting the LCD_SCS signal.
        //
        while(SPI_isBusy(LCD_EUSCI_MODULE))
        {
            ;
        }
    
        GPIO_setOutputHighOnPin(LCD_SCS_PORT, LCD_SCS_PIN);
    }
    
    //*****************************************************************************
    //
    // Generates delay of
    //
    // \param cycles number of cycles to delay
    //
    // \return None
    //
    //*****************************************************************************
    void HAL_LCD_delay(uint16_t msec)
    {
        uint32_t i = 0;
        uint32_t time = (msec / 1000) * (SYSTEM_CLOCK_SPEED / 15);
    
        for(i = 0; i < time; i++)
        {
            ;
        }
    }
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    

  • Hi Scott,

      Please update your HAL_MSP_EXP432P401R_KITRONIX320X240_SSD2119_SPI.c with this one. The display FPS (320x240 16bpp) should improve from ~1.5 to ~5.4, almost 3x.

    A couple of comments:

    1. The new touch screen calibration that we are working on, was developed according to the algorithm  described by Carlos E. Videles in the June 2002 issue of Embedded Systems Design. It can be found online at http://www.embedded.com/story/OEG20020529S0046

    2. We are also working on a DMA implementation of this SPI driver, and it should give us around 20FPS (320x240 16bpp). Please let me know if this is something that you would be interested for your application.

    #1 and #2 are part of a different framework (example code) that will be released soon. I'm discussing internally to find out what would be the best way to share this code with you.

     Best regards,

       David

  • Hi David,

    This modified driver is WAY faster than before!  Thank you very much - I'm pleased to see such an improvement.  Can you describe what was modified to get this kind of performance gain?  I have not done an extensive analysis of the code.

    Thank you also for the comments.  Some less frustrating way of doing screen calibration would be most welcomed.  It's still hit or miss, even with limits that I opened up and trying to be very careful about hitting the center of the red dots using a pointer/stylus.

    A DMA implementation of the SPI driver would be excellent, and I can certainly see it being useful not only in my application but for others out there using the Graphics Library.

    Looking forward to finding out how you can share the new example code.  I'm happy to try them out as you can share them.  I sincerely appreciate the effort to address this issue quickly, and I'm impressed at how much faster the screen draw occurs.

    Let me know if you need any other information from me, or would like me to perform other experiments.

    Best regards and many thanks,

    Scott

  • Hi Scott,

     I'm very happy that I was able to help.

    Scott Whitney80914 said:
     Can you describe what was modified to get this kind of performance gain?  I have not done an extensive analysis of the code.

    I substituted all the driverlib API's with register level  calls. For example:

    From:

    	while(SPI_isBusy(LCD_EUSCI_MODULE));
    

    To:

    	while (UCB0STATW & UCBUSY);

     BTW I missed one in HAL_LCD_writeCommand, line #195 and this should make it a little bit faster.

     Best regards,

       David

  • Hi David,

    That's really incredible.  I guess that it's safe to say that there is a definite performance price to pay for the convenience of using the DriverLib API!  Never assume that just because the code has  been put into a ROM that it's truly been optimized.

    I'll take a look at the other line you mentioned, but the performance improvement I observed was very impressive.  Hoping that this information also helps other users of GRLIB and the MSP432.

    Thanks again for your efforts to address and explain this, and I'm looking forward to other updates to the Graphics Library.

    Best regards,

    Scott

  • Hi David,

    I have one other question.  In main.c, clockInit() actually initializes the Flash wait states to 2.  From a recent discussion with my local FAE, it appears that the silicon on the Rev 2.0 Launchpad should run  at 1 wait state.  Is that correct?  Seems like there would be a bit of a speed gain from that as well.

    Also, I think that read buffering can be enabled to do a pre-fetch of instructions/data, which can help offset the wait state delays a bit if things run in sequence.  Does that make sense?  clockInit() doesn't do that currently, either.

    Thanks again for your help and your advice!

    Scott

  • Scott,
    Yes what you are suggesting makes sense, and you are probably already aware of the FlashCtl_enableReadBuffering API.

    Scott, David,
    I am going to close this due to inactivity.

    Thanks and Regards,
    Chris

**Attention** This is a public forum