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.

EK-TM4C129EXL: LCD code issue

Part Number: EK-TM4C129EXL
Other Parts Discussed in Thread: ENERGIA, EK-TM4C1294XL, EK-TM4C123GXL, BOOSTXL-EDUMKII

Hi team,

Our customer is requesting assistance:

I did not want to have to ask TI for help as I know that they do not support DRM style coding, but after consideration, I do not think that this counts as DRM. I am attempting to code the LCD screen on said board using header 1 of my TM4C129EXL. I found code online for how to do this using the TM4C123 and am porting it over to my MCU. If I could have help seeing where I am going wrong, I would appreciate it. I did post this issue to stack overflow as well but am not getting an answer there: c - TM4C129EXL and BOOSTXL-EDUMKII having some LCD issues - Stack Overflow . I am attaching my code as well as the code I am using as a model (ST7735.c).
LCD_Defines.h

main (2).c
#include <stdint.h>
#include <stdbool.h>
#include "LCD_Defines.h"

void static writeCMD(uint8_t c){
    TFT_CS = TFT_CS_LOW;
    DC = DC_COMMAND;
    SSI2[SSI_DR] = c;
    while ((SSI2[SSI_SR] & 0x10) == 0x10){};
}

void static writeData(uint8_t c){
    while ((SSI2[SSI_SR] & 0x02) == 0){};
    DC = DC_COMMAND;
    SSI2[SSI_DR] = c;
}

void static deselect(void){
    while ((SSI2[SSI_SR] & 0x10) == 0x10){};
    TFT_CS = TFT_CS_HIGH;
}

void static setAddr(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1){
    writeCMD(CASET);
    writeData(0x00);
    writeData(x0+ColStart);
    writeData(0x00);
    writeData(x1+ColStart);

    writeCMD(RASET);
    writeData(0x00);
    writeData(y0+RowStart);
    writeData(0x00);
    writeData(y1+RowStart);

    writeCMD(RAMWR);
}

void static commandList(const uint8_t *addr){
    uint8_t numCommand, numArgs;
    uint16_t ms;

    numCommand = *(addr++);
    while (numCommand--){
        writeCMD(*(addr++));
        numArgs = *(addr++);
        ms = numArgs & DELAY;
        numArgs &= ~DELAY;
        while (numArgs--)
            writeData(*(addr++));

        if (ms){
            ms = *(addr++);
            ms = (ms == 255) ? 500:ms;
            for (int i = 0; i < ms; i++)
                while((SysTick[STCTRL] & 0x10000) == 0){}
        }
    }
}

void setCursor(uint32_t newX, uint32_t newY){
    if((newX > 20) || (newY > 12))
        return;

    StX = newX;
    StY = newY;
}

void fillScreen(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
    uint8_t hi = color >> 8, lo = color;

    if((x >= width) || (y >= height)) return;
    if((x + w - 1) >= width)  w = width  - x;
    if((y + h - 1) >= height) h = height - y;

    setAddr(x, y, x+w-1, y+h-1);

    for(y=h; y>0; y--){
        for(x=w; x>0; x--){
            writeData(hi);
            writeData(lo);
        }
    }

    deselect();
}

void static commonInit(const uint8_t *cmdList){
    ColStart = RowStart = 0;

    SYSCTL[SYSCTL_RCGCGPIO] |= SYSCTL_RCGCGPIO_PORTD;
    SYSCTL[SYSCTL_RCGCGPIO] |= SYSCTL_RCGCGPIO_PORTH;
    SYSCTL[SYSCTL_RCGCGPIO] |= SYSCTL_RCGCGPIO_PORTL;
    SYSCTL[SYSCTL_RCGCGPIO] |= SYSCTL_RCGCGPIO_PORTN;
    SYSCTL[SYSCTL_RCGCGPIO] |= SYSCTL_RCGCGPIO_PORTD;
    SYSCTL[SYSCTL_RCGCGPIO] |= SYSCTL_RCGCGPIO_PORTH;
    SYSCTL[SYSCTL_RCGCGPIO] |= SYSCTL_RCGCGPIO_PORTL;
    SYSCTL[SYSCTL_RCGCGPIO] |= SYSCTL_RCGCGPIO_PORTN;
    SYSCTL[SYSCTL_RCGCSSI] |= 0x4;

    while ((SYSCTL[SYSCTL_PRSSI] & 0x4) == 0){};

    GPIO_PORTD[GPIO_FSEL] |= 0xA;

    GPIO_PORTD[GPIO_PCTL] |= 0xF0F0;

    GPIO_PORTD[GPIO_DEN] |= SPICl;
    GPIO_PORTD[GPIO_DEN] |= SPIMOSI;
    GPIO_PORTH[GPIO_DEN] |= SPIRST;
    GPIO_PORTL[GPIO_DEN] |= SPIREG;
    GPIO_PORTN[GPIO_DEN] |= SPICS;

    GPIO_PORTH[GPIO_DIR] |= SPIRST;
    GPIO_PORTL[GPIO_DIR] |= SPIREG;
    GPIO_PORTN[GPIO_DIR] |= SPICS;

    TFT_CS = TFT_CS_LOW;

    while ((SYSCTL[SYSCTL_SRSSI] & 0x4) == 1){
        RESET = RESET_HIGH;
        for (int i = 0; i < 500; i++)
            while((SysTick[STCTRL] & 0x10000) == 0){}
        RESET = RESET_LOW;
        for (int i = 0; i < 500; i++)
            while((SysTick[STCTRL] & 0x10000) == 0){}
        RESET = RESET_HIGH;
        for (int i = 0; i < 500; i++)
            while((SysTick[STCTRL] & 0x10000) == 0){}
    }

    SYSCTL[SYSCTL_SRSSI] &= ~0x4;

    SSI2[SSI_CR1] &= ~0x2;
    SSI2[SSI_CR1] &= ~0x4;
    SSI2[SSI_CC] &= ~0xF;
    SSI2[SSI_PS] = 30;
    SSI2[SSI_CR0] &= ~(0xFF00 | 0x80 | 0x40);
    SSI2[SSI_CR0] &= ~0x30;
    SSI2[SSI_CR0] = 0x7;
    SSI2[SSI_CR1] |= 0x2;

    if (cmdList)
        commandList(cmdList);
}

void static initS(enum initSFlags option){
    commonInit(Scmd1);

    if (option == INITS_GREENTAB){
        commandList(Scmd2green);
        ColStart = 2;
        RowStart = 3;
    }else
        commandList(Scmd2red);

    commandList(Scmd3);

    if (option == INITS_BLACKTAB) {
      writeCMD(MADCTL);
      writeData(0xC0);
    }

    TabColor = option;
    setCursor(0,0);
    StTextColor = YELLOW;
    fillScreen(0,0,width,height,0);
}

void static pushColor(uint16_t color){
    writeData((uint8_t)(color >> 8));
    writeData((uint8_t)color);
}

void drawPixel(int16_t x, int16_t y, uint16_t color){
    if (x < 0 || x >= width || y < 0 || y >= height) return;
    setAddr(x,y,x,y);
    pushColor(color);
    deselect();
}

void drawVert(int16_t x, int16_t y, int16_t h, uint16_t color) {
  uint8_t hi = color >> 8, lo = color;

  if(x >= width || y >= height) return;
  if((y+h-1) >= height) h = height-y;
  setAddr(x, y, x, y+h-1);

  while (h--) {
    writeData(hi);
    writeData(lo);
  }

  deselect();
}

void drawHor(int16_t x, int16_t y, int16_t w, uint16_t color) {
  uint8_t hi = color >> 8, lo = color;

  if((x >= width) || (y >= height)) return;
  if((x+w-1) >= width)  w = width-x;
  setAddr(x, y, x+w-1, y);

  while (w--) {
    writeData(hi);
    writeData(lo);
  }

  deselect();
}

uint16_t color565(uint8_t r, uint8_t g, uint8_t b) {
  return ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3);
}

uint16_t swapColor(uint16_t x) {
  return (x << 11) | (x & 0x07E0) | (x >> 11);
}

void drawBMP(int16_t x, int16_t y, const uint16_t *image, int16_t w, int16_t h){
    int16_t skipC = 0;
    int16_t originalWidth = w;
    int i = w*(h - 1);

    if((x >= width) || ((y - h + 1) >= height) || ((x + w) <= 0) || (y < 0)) return;

    if (w > width || h > height) return;

    if((x + w - 1) >= width){
        skipC = (x + w) - width;
        w = width - x;
    }
    if((y - h + 1) < 0){
        i -= (h - y - 1)*originalWidth;
        h = y + 1;
    }
    if(x < 0){
        w += x;
        skipC = -1*x;
        i -= x;
        x = 0;
    }
    if(y >= height){
      h -= (y - height + 1);
      y = height - 1;
    }

    setAddr(x, y-h+1, x+w-1, y);

    for(y=0; y<h; y++){
      for(x=0; x<w; x++){
        writeData((uint8_t)(image[i] >> 8));
        writeData((uint8_t)image[i]);
        i++;
      }
      i += skipC;
      i -= 2*originalWidth;
    }

    deselect();
}

void drawChar(int16_t x, int16_t y, char c, int16_t textColor, int16_t bgColor, uint8_t size){
    uint8_t line;
    int32_t col, row, i, j;

    if(((x + 6*size - 1) >= width)  || ((y + 8*size - 1) >= height) || ((x + 6*size - 1) < 0) || ((y + 8*size - 1) < 0)) return;

    setAddr(x, y, x+6*size-1, y+8*size-1);

    line = 0x1;

    for(row=0; row<8; row++){
        for(i=0; i<size; i++){
            for(col=0; col<5; col++){
                if(Font[(c*5)+col]&line){
                    for(j=0; j<size; j++)
                        pushColor(textColor);
                }else{
                    for(j=0; j<size; j++)
                        pushColor(bgColor);
                }
            }
            for(j=0; j<size; j++)
                pushColor(bgColor);
            }
        line <<= 1;
    }

    deselect();
}

uint32_t drawString(uint16_t x, uint16_t y, char *pt, int16_t textColor){
    uint32_t count = 0;

    if(y>12) return 0;

    while(*pt){
        drawChar(x*6, y*10, *pt, textColor, BLACK, 1);
        pt++;
        x++;
        if(x>20) return count;
        count++;
    }
    return count;
}

void fillMessage(uint32_t n){
    if(n >= 10){
        fillMessage(n/10);
        n %= 10;
    }
    Message[Messageindex] = (n+'0');
    if(Messageindex<11) Messageindex++;
}

void fillMessage4(uint32_t n){
    if(n>9999) n=9999;

    if(n>=1000)
        Messageindex = 0;
    else if(n>=100){
        Message[0] = ' ';
        Messageindex = 1;
    }else if(n>=10){
        Message[0] = ' ';
        Message[1] = ' ';
        Messageindex = 2;
    }else{
        Message[0] = ' ';
        Message[1] = ' ';
        Message[2] = ' ';
        Messageindex = 3;
    }
    fillMessage(n);
}

void fillMessage5(uint32_t n){
    if(n>99999) n=99999;

    if(n>=10000)
        Messageindex = 0;
    else if(n>=1000){
        Message[0] = ' ';
        Messageindex = 1;
    }else if(n>=100){
        Message[0] = ' ';
        Message[1] = ' ';
        Messageindex = 2;
    }else if(n>=10){
        Message[0] = ' ';
        Message[1] = ' ';
        Message[2] = ' ';
        Messageindex = 3;
    }else{
        Message[0] = ' ';
        Message[1] = ' ';
        Message[2] = ' ';
        Message[3] = ' ';
        Messageindex = 4;
    }
  fillMessage(n);
}

void static fillMessage2_10(uint32_t n){
    if(n>999) n=999;

    if(n>=100){
        Message[0] = (n/100+'0');
        n %= 100;
    }else
        Message[0] = ' ';

    Message[1] = (n/10+'0');
    n %= 10;
    Message[2] = '.';
    Message[3] = (n+'0');
    Message[4] = 0;
}
void static fillMessage2_Hex(uint32_t n){
    char digit;

    if(n>255){
        Message[0] = '*';
        Message[1] = '*';
    }else{
        digit = n/16;
        if(digit<10)
            digit += '0';
        else
            digit = digit+'A'-10;
        Message[0] = digit;
        digit = n%16;
        if(digit<10)
            digit += '0';
        else
            digit += 'A'-10;
        Message[1] = digit;
    }
    Message[2] = ',';
    Message[3] = 0;
}

void outUDec(uint32_t n, int16_t textColor){
    Messageindex = 0;
    fillMessage(n);
    Message[Messageindex] = 0;
    drawString(StX,StY,Message,textColor);
    StX += Messageindex;
    if(StX>20){
        StX = 20;
        drawChar(StX*6,StY*10,'*',RED,BLACK, 1);
    }
}

void outUDec4(uint32_t n, int16_t textColor){
    Messageindex = 0;
    fillMessage4(n);
    Message[Messageindex] = 0;
    drawString(StX,StY,Message,textColor);
    StX += Messageindex;
    if(StX>20){
        StX = 20;
        drawChar(StX*6,StY*10,'*',RED,BLACK, 1);
    }
}

void outUDec5(uint32_t n, int16_t textColor){
    Messageindex = 0;
    fillMessage5(n);
    Message[Messageindex] = 0;
    drawString(StX,StY,Message,textColor);
    StX += Messageindex;
    if(StX>20){
        StX = 20;
        drawChar(StX*6,StY*10,'*',RED,BLACK, 1);
    }
}

void outUFix2_10(uint32_t n, int16_t textColor){
    fillMessage2_10(n);
    drawString(StX,StY,Message,textColor);
    StX += 4;
    if(StX>20){
        StX = 20;
        drawChar(StX*6,StY*10,'*',RED,BLACK, 1);
    }
}

void outUHex2(uint32_t n, int16_t textColor){
    fillMessage2_Hex(n);
    drawString(StX,StY,Message,textColor);
    StX += 3;
    if(StX>20){
        StX = 20;
        drawChar(StX*6,StY*10,'*',RED,BLACK, 1);
    }
}

void drawAxes(uint16_t axisColor, uint16_t bgColor, char *xLabel, char *yLabel1, uint16_t label1Color, char *yLabel2, uint16_t label2Color, int32_t ymax, int32_t ymin){
    int i;

    Ymax = ymax;
    Ymin = ymin;
    Yrange = Ymax - Ymin;
    TimeIndex = 0;
    PlotBGColor = bgColor;
    fillScreen(0, 17, 111, 111, bgColor);
    drawHor(10, 117, 101, axisColor);
    drawVert(10, 17, 101, axisColor);

    for(i=20; i<=110; i=i+10)
        drawPixel(i, 118, axisColor);
    for(i=17; i<117; i=i+10)
        drawPixel(9, i, axisColor);

    i = 50;
    while((*xLabel) && (i < 100)){
        drawChar(i, 120, *xLabel, axisColor, bgColor, 1);
        i += 6;
        xLabel++;
    }
    if(*yLabel2){
        i = 26;
        while((*yLabel2) && (i < 50)){
          drawChar(0, i, *yLabel2, label2Color, bgColor, 1);
          i = i + 8;
          yLabel2++;
        }
        i = 82;
    }else
        i = 42;

    while((*yLabel1) && (i < 120)){
        drawChar(0, i, *yLabel1, label1Color, bgColor, 1);
        i += 8;
        yLabel1++;
    }
}

void plotPoint(int32_t data1, uint16_t color1){
    data1 = ((data1 - Ymin)*100)/Yrange;
    if(data1 > 98){
        data1 = 98;
        color1 = RED;
    }
    if(data1 < 0){
        data1 = 0;
        color1 = RED;
    }
    drawPixel(TimeIndex + 11, 116 - data1, color1);
    drawPixel(TimeIndex + 11, 115 - data1, color1);
}

void plotInc(void){
    TimeIndex++;
    if(TimeIndex > 99){
    TimeIndex = 0;
    }
    drawVert(TimeIndex + 11, 17, 100, PlotBGColor);
}

void pll(void){
    uint32_t tmp;

    SYSCTL[SYSCTL_MOSCCTL] &= ~(SYSCTL_MOSCCTL_NOXTAL | SYSCTL_MOSCCTL_PWRDN);
    if (!(SYSCTL[SYSCTL_MOSCCTL] & SYSCTL_MOSCCTL_OSCRNG)){
        SYSCTL[SYSCTL_MOSCCTL] |= SYSCTL_MOSCCTL_OSCRNG;
        while (!(SYSCTL[SYSCTL_RIS] & SYSCTL_RIS_MOSCPUPRIS));
    }
    SYSCTL[SYSCTL_MISC] = SYSCTL_MISC_MOSCPUMIS;
    SYSCTL[SYSCTL_RSCLKCFG] |= SYSCTL_RSCLKCFG_OSCSRC_MOSC | SYSCTL_RSCLKCFG_PLLSRC_MOSC;
    SYSCTL[SYSCTL_PLLFREQ0] = (96 << SYSCTL_PLLFREQ0_MINT_S) | (0 << SYSCTL_PLLFREQ0_MFRAC_S);
    SYSCTL[SYSCTL_PLLFREQ1] = 4;

    tmp = SYSCTL[SYSCTL_MEMTIM0];
    tmp &= ~(SYSCTL_MEMTIM0_EBCHT_M | SYSCTL_MEMTIM0_EWS_M | SYSCTL_MEMTIM0_EBCE);
    tmp |= SYSCTL_MEMTIM0_FBCHT_3_5 | SYSCTL_MEMTIM0_EWS_6;
    tmp &= ~(SYSCTL_MEMTIM0_FBCHT_M | SYSCTL_MEMTIM0_FWS_M | SYSCTL_MEMTIM0_FBCE);
    tmp |= SYSCTL_MEMTIM0_FBCHT_3_5| SYSCTL_MEMTIM0_FWS_6;
    SYSCTL[SYSCTL_MEMTIM0] = tmp;

    SYSCTL[SYSCTL_PLLFREQ0] |= SYSCTL_PLLFREQ0_PLLPWR;
    SYSCTL[SYSCTL_RSCLKCFG] |= SYSCTL_RSCLKCFG_NEWFREQ;
    while (!SYSCTL[SYSCTL_PLLSTAT]);

    tmp = SYSCTL[SYSCTL_RSCLKCFG];
    tmp = (tmp & ~SYSCTL_RSCLKCFG_PSYSDIV_M) | SYSCTL_RSCLKCFG_PSYSDIV_3;
    tmp |= SYSCTL_RSCLKCFG_USEPLL | SYSCTL_RSCLKCFG_MEMTIMU;
    SYSCTL[SYSCTL_RSCLKCFG] = tmp;
}

void main(void)
{
    pll();

    SysTick[STCTRL] = 0;
    SysTick[STCURRENT] = 0;
    SysTick[STRELOAD] = 0x1D4BF;
    SysTick[STCTRL] = 0x5;

    initS(INITS_GREENTAB);

    while(true){

    }
}

ST7735.c

Thank you,

 

Drew

  • Hi,

      Doing some search, the mentioned LCD in the attached code is ST7735 which is a 1.8″ display with a resolution of 128×160 pixels while the LCD (CFAF128128B-0145T) on the Educational Boosterpack MKII is a 1.45" color 128x128-pixel TFT LCD from Crystalfontz. The resolution between the two displays are not the same. You can't port the code without taking the the resolution into account. 

      Having saying that, this is a 3rd party code downloaded from internet that we cannot support. TivaWare provides a graphic library and several examples for TM4C129 that can be found in C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl-boostxl-kentec-s1 These examples are based on Kentec320x240 LCD display. You are free to use third party code if you don't want to use TivaWare library, In that case, I will suggest you use the scope/logic analyzer to look at SPI pins that connect to the LCD.  Check if correct commands/data are sent out on SPI pins. 

  • Hi Charles,

    I got the response from customer:

    Hello Charles,

         I did consider the resolution difference and thought that to correct this was to just change the height variable of the LCD screen.  Is there something else I need to do?  I did also use the LCD code from EmbeddedSystems.Playground/BSP.c at master · glennlopez/EmbeddedSystems.Playground · GitHub from line 611 and on.

         I do not have a logic analyzer as I am not in a real lab and cannot afford a real scope.  Can my code be diagnosed by TI, or because I sourced it from a 3rd party, TI cannot help me with that?

    Thank you,

    Drew

  • Hi Chong, Drew,

      A scope or especially a low cost Logic analyzer will be really handy to debug communication bus such as SPI, UART and etc. I think it is worthy investment but that is your decision to make. If these 3rd party code intended for ST7735 LCD display works on TM4C123 then I will suggest you use the same LCD display to test it out on TM4C123. If it works then you can easily port to TM4C129. It is important to verify these 3rd party code works in the first place. Please also read through the ST7735S datasheet which I found on vendor's website.

     ST7735S_v1.3.pdf

  • Hi Charles,

    I got the response from customer:

    Hello Charles,

    I would definitely buy a scope if I could. I would test it out on the TM4C123, but I do not own one and know that I would have to desolder 2 resistors on the board to make it work. I made sure the LCD works by using Energia and the LCD does work. I do not know if I am porting it over correctly. I will look through the data sheet, but is there anything you can do, or advise me to do? I do not know where my code is going wrong.

    Thank you,

    Drew

  • Hi,

      As I suggested, a logic analyzer or a scope is the best way to look at the signals. If you can get TM4C123 to work with ST7735 LCD then you can view the waveforms on the SSI interface. Once you port the example to TM4C129, you can compare the waveforms to see any subtle differences that might explain why it is not working. 

      There are 2737 lines of your 3rd party code that I can't really help you debug what is working and not working. With a quick look, there is a comment that says it is using PA4 on TM4C123 for chip select. PA4 on EK-TM4C123GXL is at different boosterpack location compared to EK-TM4C1294XL. 

  • Hi Charles,

    I got the response from customer:

    I will look into a logic analyzer. I do not have a TM4C123, only a TM4C129EXL.

    I understand that it is not your job, nor your obligation to help with 3rd party code, I was just hoping. I know that PA4 is not on the same spot as my board. I am using the pins according to the quick start guide of the BOOSTXL-EDUMKII. For my booster pack heading, it would be PD1 (MOSI), PD3 (CL), PH3 (RST), PL3 (RS) and PN2 (CS). I have not seen anything to say that this is wrong. Both PDX pins are set to SSI mode and the other 3 are GPIO. If that is wrong, please let me know. I have been using the wrong pins this whole time if I am wrong.

    Thank you,

    Drew

  • it would be PD1 (MOSI), PD3 (CL), PH3 (RST), PL3 (RS) and PN2 (CS).

    I think the pins you use looks correct to me. Sorry, but I can't help you on your code. 

  • Hi Charles,

    I got the response from customer:

    That is what I thought. As you are not able to help me, aside from Stack Overflow, where else can I look for help with my code? I do not know where else to look.

    Thank you,

    Drew

  • Hi,

     I think once you have the scope/logic analyzer it will be easier for you to troubleshoot. 

  • Hi Charles,

    I got the response from customer:

    Ok. I will find a scope to use and hopefully solve my problems from there. Thank you for your help. If you do know anyone though that can help with my code, please let them know of my issue. I always like to have more than one possible solution.

    Thank you,

    Drew