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.

Not able to run Nokia5110

Genius 3300 points

Other Parts Discussed in Thread: TM4C123GH6PM

Hi I am running code for Nokia 5110 but unable to see anything on lcd. I took reference code from from Embedded course running on edx website.
However it uses DRM, but I had modified it using library programming. Same code does not work.

Some of difference I noticed between two:
1. Edx code uses DRM , while I use library.
2. SPI speed in edx is 3.125Mhz while i have 3Mhz around.
3. System speed is 50Mhz in edx case while I have 80Mhz.
4. CS pin is used as FSS in edx case while I use CS/CE independently.

I have toggled reset, cs & dc pin & checked on CRO, they are working correctly. Below is my code & then edx code is attached.

#define LCD_COMMAND      0U
#define LCD_DATA         1U


#define RESET_PERIPH    SYSCTL_PERIPH_GPIOA
#define RESET_BASE      GPIO_PORTA_AHB_BASE
#define RESET_PIN       GPIO_PIN_7  

#define RESET_HIGH()                         do{                                                                     \
                                                 HWREG(RESET_BASE + (GPIO_O_DATA + (RESET_PIN << 2))) = RESET_PIN;   \
                                             }while(0)   

#define RESET_LOW()                          do{                                                                   \
                                                 HWREG(RESET_BASE + (GPIO_O_DATA + (RESET_PIN << 2))) = 0;         \
                                             }while(0)  

                                             
#define CE_PERIPH    SYSCTL_PERIPH_GPIOA
#define CE_BASE      GPIO_PORTA_AHB_BASE
#define CE_PIN       GPIO_PIN_3  

#define CE_HIGH()                            do{                                                            \
                                                 HWREG(CE_BASE + (GPIO_O_DATA + (CE_PIN << 2))) = CE_PIN;   \
                                             }while(0)   

#define CE_LOW()                             do{                                                             \
                                                 HWREG(CE_BASE + (GPIO_O_DATA + (CE_PIN << 2))) = 0;         \
                                             }while(0)         

                                             
#define DC_PERIPH    SYSCTL_PERIPH_GPIOA
#define DC_BASE      GPIO_PORTA_AHB_BASE
#define DC_PIN       GPIO_PIN_6  

#define DC_HIGH()                            do{                                                            \
                                                 HWREG(DC_BASE + (GPIO_O_DATA + (DC_PIN << 2))) = DC_PIN;   \
                                             }while(0)   

#define DC_LOW()                             do{                                                             \
                                                 HWREG(DC_BASE + (GPIO_O_DATA + (DC_PIN << 2))) = 0;         \
                                             }while(0)                                                 


void all_tasks_manager(void) 
{     
    uint32_t ready_count;
    
    
/* cs high initially */    
    SysCtlGPIOAHBEnable(CE_PERIPH);
    SysCtlPeripheralEnable(CE_PERIPH);
    
    ready_count = 2000U;
    while( (!(SysCtlPeripheralReady(CE_PERIPH)))  &&  (--ready_count));
    if(0U == ready_count)   /* if periph not ready take action */
    {
    }    
    
    GPIOPinTypeGPIOOutput(CE_BASE, CE_PIN);
    CE_HIGH();      
    
/* reset low initially */    
    SysCtlGPIOAHBEnable(RESET_PERIPH);
    SysCtlPeripheralEnable(RESET_PERIPH);
    
    ready_count = 2000U;
    while( (!(SysCtlPeripheralReady(RESET_PERIPH)))  &&  (--ready_count));
    if(0U == ready_count)   /* if periph not ready take action */
    {
    }    
    
    GPIOPinTypeGPIOOutput(RESET_BASE, RESET_PIN);
    RESET_LOW();    
      
/* dc low initially */    
    SysCtlGPIOAHBEnable(DC_PERIPH);
    SysCtlPeripheralEnable(DC_PERIPH);
    
    ready_count = 2000U;
    while( (!(SysCtlPeripheralReady(DC_PERIPH)))  &&  (--ready_count));
    if(0U == ready_count)   /* if periph not ready take action */
    {
    }    
    
    GPIOPinTypeGPIOOutput(DC_BASE, DC_PIN);
    DC_LOW();        
    
    
    
/* enable SSI0 module */    
    SysCtlPeripheralDisable(SYSCTL_PERIPH_SSI0);
    SysCtlPeripheralReset(SYSCTL_PERIPH_SSI0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    while( (!(SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0)))  &&  (--ready_count));
    if(0U == ready_count)   /* if periph not ready take action */
    {
    }        
    
/* enable clk */
    SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    while( (!(SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)))  &&  (--ready_count));
    if(0U == ready_count)   /* if periph not ready take action */
    {
    }      
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinTypeSSI(GPIO_PORTA_AHB_BASE , GPIO_PIN_2);
    
/* enable rx */
    SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOA);    
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    while( (!(SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)))  &&  (--ready_count));
    if(0U == ready_count)   /* if periph not ready take action */
    {
    }      
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinTypeSSI(GPIO_PORTA_AHB_BASE , GPIO_PIN_4);    
    
/* enable tx */
    SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOA);    
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    while( (!(SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)))  &&  (--ready_count));
    if(0U == ready_count)   /* if periph not ready take action */
    {
    }      
    GPIOPinConfigure(GPIO_PA5_SSI0TX);
    GPIOPinTypeSSI(GPIO_PORTA_AHB_BASE , GPIO_PIN_5);       
    
/* disable SPi first */ 
    SSIDisable(SSI0_BASE);
    SSIDMADisable(SSI0_BASE , SSI_DMA_RX | SSI_DMA_TX);
    SSIIntDisable(SSI0_BASE , SSI_TXFF | SSI_RXFF | SSI_RXTO | SSI_RXOR);
    SSIIntClear(SSI0_BASE , SSI_RXTO | SSI_RXOR);
    
/* SPI clock & congig */    
    SSIClockSourceSet(SSI0_BASE , SSI_CLOCK_SYSTEM);
    SSIConfigSetExpClk(SSI0_BASE , SysCtlClockGet() , SSI_FRF_MOTO_MODE_0 , SSI_MODE_MASTER , 3000000U , 8U);
    SSIEnable(SSI0_BASE);

    
/* init spi */    
    lcd_init();
    lcd_cursor(5U, 2U);
    lcd_string((uint8_t *)"WELL_DONE");
    lcd_clear();
    while(1)
    {       
        lcd_string((uint8_t *)"WELL_DONE");
    }    
    
} /* function ends here */    



void lcd_clear(void)
{
    uint32_t cnt;
    
    for(cnt = 0U; cnt <(84U*48U/8U); cnt++)
    {
        lcdwrite(LCD_DATA, 0xffU);
    }
    lcd_cursor(0U , 0U);
}



void lcd_cursor(uint8_t x_pos, uint8_t y_pos)
{
    if(x_pos > 11U)
    {
        x_pos = 11U;
    }    
    if(y_pos > 5U)
    {
        y_pos = 5U;
    }    
    
// multiply newX by 7 because each character is 7 columns wide
    lcdwrite(LCD_COMMAND, 0x80|(x_pos*7));     // setting bit 7 updates X-position
    lcdwrite(LCD_COMMAND, 0x40|y_pos);         // setting bit 6 updates Y-position
}




void lcd_string(uint8_t *ptr)
{
    while(*ptr)
    {
        lcd_character((uint8_t)*ptr);
        ptr = ptr + 1;
    }
}



void lcd_character(uint8_t data)
{
    uint32_t cnt;
  
    if((data < 0x20U) || (data > 0x7fU))
    {
        data = 0x20U;
    }    
    
    lcdwrite(LCD_DATA, 0x00);                 // blank vertical line padding
  
    for(cnt = 0U; cnt < 5U; cnt++)
    {
        lcdwrite(LCD_DATA, ASCII[data - 0x20][cnt]);
    }
    lcdwrite(LCD_DATA, 0x00);                 // blank vertical line padding
}



void lcd_init(void)
{
    RESET_LOW();
    SysCtlDelay(80);  /* min 100ns delay required, I gave 1000ns */
    RESET_HIGH();
    
    lcdwrite(LCD_COMMAND , 0x21U);
    lcdwrite(LCD_COMMAND , 0xbfU);
    lcdwrite(LCD_COMMAND , 0x04U);
    lcdwrite(LCD_COMMAND , 0x14U);
    lcdwrite(LCD_COMMAND , 0x20U);
    lcdwrite(LCD_COMMAND , 0x0cU);
    
}  



void lcdwrite(uint32_t data_or_com , uint8_t data)
{
    
/* pull pin DC */    
    if(LCD_COMMAND == data_or_com)
    {
        DC_LOW();
    }    
    else
    {
        DC_HIGH();
    }    
    
/* tx data */    
    CE_LOW();
    SysCtlDelay(80);             /* min 100ns delay required, I gave 1000ns */
    while(SSIBusy(SSI0_BASE));
    SSIDataPut(SSI0_BASE , (uint32_t)data);
    SysCtlDelay(80);             /* min 100ns delay required, I gave 1000ns */
    CE_HIGH();
    
    
}    

// Nokia5110.c
// Runs on LM4F120/TM4C123
// Use SSI0 to send an 8-bit code to the Nokia5110 48x84
// pixel LCD to display text, images, or other information.
// Daniel Valvano
// September 16, 2013

// Font table, initialization, and other functions based
// off of Nokia_5110_Example from Spark Fun:
// 7-17-2011
// Spark Fun Electronics 2011
// Nathan Seidle
// http://dlnmh9ip6v2uc.cloudfront.net/datasheets/LCD/Monochrome/Nokia_5110_Example.pde

/* This example accompanies the book
   "Embedded Systems: Real Time Interfacing to Arm Cortex M Microcontrollers",
   ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2013

 Copyright 2013 by Jonathan W. Valvano, valvano@mail.utexas.edu
    You may use, edit, run or distribute this file
    as long as the above copyright notice remains
 THIS SOFTWARE IS PROVIDED "AS IS".  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.
 VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 For more information about my classes, my research, and my books, see
 http://users.ece.utexas.edu/~valvano/
 */

// Blue Nokia 5110
// ---------------
// Signal        (Nokia 5110) LaunchPad pin
// Reset         (RST, pin 1) connected to PA7
// SSI0Fss       (CE,  pin 2) connected to PA3
// Data/Command  (DC,  pin 3) connected to PA6
// SSI0Tx        (Din, pin 4) connected to PA5
// SSI0Clk       (Clk, pin 5) connected to PA2
// 3.3V          (Vcc, pin 6) power
// back light    (BL,  pin 7) not connected, consists of 4 white LEDs which draw ~80mA total
// Ground        (Gnd, pin 8) ground

// Red SparkFun Nokia 5110 (LCD-10168)
// -----------------------------------
// Signal        (Nokia 5110) LaunchPad pin
// 3.3V          (VCC, pin 1) power
// Ground        (GND, pin 2) ground
// SSI0Fss       (SCE, pin 3) connected to PA3
// Reset         (RST, pin 4) connected to PA7
// Data/Command  (D/C, pin 5) connected to PA6
// SSI0Tx        (DN,  pin 6) connected to PA5
// SSI0Clk       (SCLK, pin 7) connected to PA2
// back light    (LED, pin 8) not connected, consists of 4 white LEDs which draw ~80mA total

#include "Nokia5110.h"

#define DC                      (*((volatile unsigned long *)0x40004100))
#define DC_COMMAND              0
#define DC_DATA                 0x40
#define RESET                   (*((volatile unsigned long *)0x40004200))
#define RESET_LOW               0
#define RESET_HIGH              0x80
#define GPIO_PORTA_DIR_R        (*((volatile unsigned long *)0x40004400))
#define GPIO_PORTA_AFSEL_R      (*((volatile unsigned long *)0x40004420))
#define GPIO_PORTA_DEN_R        (*((volatile unsigned long *)0x4000451C))
#define GPIO_PORTA_AMSEL_R      (*((volatile unsigned long *)0x40004528))
#define GPIO_PORTA_PCTL_R       (*((volatile unsigned long *)0x4000452C))
#define SSI0_CR0_R              (*((volatile unsigned long *)0x40008000))
#define SSI0_CR1_R              (*((volatile unsigned long *)0x40008004))
#define SSI0_DR_R               (*((volatile unsigned long *)0x40008008))
#define SSI0_SR_R               (*((volatile unsigned long *)0x4000800C))
#define SSI0_CPSR_R             (*((volatile unsigned long *)0x40008010))
#define SSI0_CC_R               (*((volatile unsigned long *)0x40008FC8))
#define SSI_CR0_SCR_M           0x0000FF00  // SSI Serial Clock Rate
#define SSI_CR0_SPH             0x00000080  // SSI Serial Clock Phase
#define SSI_CR0_SPO             0x00000040  // SSI Serial Clock Polarity
#define SSI_CR0_FRF_M           0x00000030  // SSI Frame Format Select
#define SSI_CR0_FRF_MOTO        0x00000000  // Freescale SPI Frame Format
#define SSI_CR0_DSS_M           0x0000000F  // SSI Data Size Select
#define SSI_CR0_DSS_8           0x00000007  // 8-bit data
#define SSI_CR1_MS              0x00000004  // SSI Master/Slave Select
#define SSI_CR1_SSE             0x00000002  // SSI Synchronous Serial Port
                                            // Enable
#define SSI_SR_BSY              0x00000010  // SSI Busy Bit
#define SSI_SR_TNF              0x00000002  // SSI Transmit FIFO Not Full
#define SSI_CPSR_CPSDVSR_M      0x000000FF  // SSI Clock Prescale Divisor
#define SSI_CC_CS_M             0x0000000F  // SSI Baud Clock Source
#define SSI_CC_CS_SYSPLL        0x00000000  // Either the system clock (if the
                                            // PLL bypass is in effect) or the
                                            // PLL output (default)
#define SYSCTL_RCGC1_R          (*((volatile unsigned long *)0x400FE104))
#define SYSCTL_RCGC2_R          (*((volatile unsigned long *)0x400FE108))
#define SYSCTL_RCGC1_SSI0       0x00000010  // SSI0 Clock Gating Control
#define SYSCTL_RCGC2_GPIOA      0x00000001  // port A Clock Gating Control

enum typeOfWrite{
  COMMAND,                              // the transmission is an LCD command
  DATA                                  // the transmission is data
};
// The Data/Command pin must be valid when the eighth bit is
// sent.  The SSI module has hardware input and output FIFOs
// that are 8 locations deep.  Based on the observation that
// the LCD interface tends to send a few commands and then a
// lot of data, the FIFOs are not used when writing
// commands, and they are used when writing data.  This
// ensures that the Data/Command pin status matches the byte
// that is actually being transmitted.
// The write command operation waits until all data has been
// sent, configures the Data/Command pin for commands, sends
// the command, and then waits for the transmission to
// finish.
// The write data operation waits until there is room in the
// transmit FIFO, configures the Data/Command pin for data,
// and then adds the data to the transmit FIFO.

// This is a helper function that sends an 8-bit message to the LCD.
// inputs: type     COMMAND or DATA
//         message  8-bit code to transmit
// outputs: none
// assumes: SSI0 and port A have already been initialized and enabled
void static lcdwrite(enum typeOfWrite type, char message){
  if(type == COMMAND){
                                        // wait until SSI0 not busy/transmit FIFO empty
    while((SSI0_SR_R&SSI_SR_BSY)==SSI_SR_BSY){};
    DC = DC_COMMAND;
    SSI0_DR_R = message;                // command out
                                        // wait until SSI0 not busy/transmit FIFO empty
    while((SSI0_SR_R&SSI_SR_BSY)==SSI_SR_BSY){};
  } else{
    while((SSI0_SR_R&SSI_SR_TNF)==0){}; // wait until transmit FIFO not full
    DC = DC_DATA;
    SSI0_DR_R = message;                // data out
  }
}

//********Nokia5110_Init*****************
// Initialize Nokia 5110 48x84 LCD by sending the proper
// commands to the PCD8544 driver.  One new feature of the
// LM4F120 is that its SSIs can get their baud clock from
// either the system clock or from the 16 MHz precision
// internal oscillator.  If the system clock is faster than
// 50 MHz, the SSI baud clock will be faster than the 4 MHz
// maximum of the Nokia 5110.
// inputs: none
// outputs: none
// assumes: system clock rate of 50 MHz or less
void Nokia5110_Init(void){
  volatile unsigned long delay;
  SYSCTL_RCGC1_R |= SYSCTL_RCGC1_SSI0;  // activate SSI0
  SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOA; // activate port A
  delay = SYSCTL_RCGC2_R;               // allow time to finish activating
  GPIO_PORTA_DIR_R |= 0xC0;             // make PA6,7 out
  GPIO_PORTA_AFSEL_R |= 0x2C;           // enable alt funct on PA2,3,5
  GPIO_PORTA_AFSEL_R &= ~0xC0;          // disable alt funct on PA6,7
  GPIO_PORTA_DEN_R |= 0xEC;             // enable digital I/O on PA2,3,5,6,7
                                        // configure PA2,3,5 as SSI
  GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R&0xFF0F00FF)+0x00202200;
                                        // configure PA6,7 as GPIO
  GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R&0x00FFFFFF)+0x00000000;
  GPIO_PORTA_AMSEL_R &= ~0xEC;          // disable analog functionality on PA2,3,5,6,7
  SSI0_CR1_R &= ~SSI_CR1_SSE;           // disable SSI
  SSI0_CR1_R &= ~SSI_CR1_MS;            // master mode
                                        // configure for system clock/PLL baud clock source
  SSI0_CC_R = (SSI0_CC_R&~SSI_CC_CS_M)+SSI_CC_CS_SYSPLL;
                                        // clock divider for 3.125 MHz SSIClk (50 MHz PIOSC/16)
  SSI0_CPSR_R = (SSI0_CPSR_R&~SSI_CPSR_CPSDVSR_M)+16;
  SSI0_CR0_R &= ~(SSI_CR0_SCR_M |       // SCR = 0 (3.125 Mbps data rate)
                  SSI_CR0_SPH |         // SPH = 0
                  SSI_CR0_SPO);         // SPO = 0
                                        // FRF = Freescale format
  SSI0_CR0_R = (SSI0_CR0_R&~SSI_CR0_FRF_M)+SSI_CR0_FRF_MOTO;
                                        // DSS = 8-bit data
  SSI0_CR0_R = (SSI0_CR0_R&~SSI_CR0_DSS_M)+SSI_CR0_DSS_8;
  SSI0_CR1_R |= SSI_CR1_SSE;            // enable SSI

  RESET = RESET_LOW;                    // reset the LCD to a known state
  for(delay=0; delay<10; delay=delay+1);// delay minimum 100 ns
  RESET = RESET_HIGH;                   // negative logic

  lcdwrite(COMMAND, 0x21);              // chip active; horizontal addressing mode (V = 0); use extended instruction set (H = 1)
                                        // set LCD Vop (contrast), which may require some tweaking:
  lcdwrite(COMMAND, CONTRAST);          // try 0xB1 (for 3.3V red SparkFun), 0xB8 (for 3.3V blue SparkFun), 0xBF if your display is too dark, or 0x80 to 0xFF if experimenting
  lcdwrite(COMMAND, 0x04);              // set temp coefficient
  lcdwrite(COMMAND, 0x14);              // LCD bias mode 1:48: try 0x13 or 0x14

  lcdwrite(COMMAND, 0x20);              // we must send 0x20 before modifying the display control mode
  lcdwrite(COMMAND, 0x0C);              // set display control to normal mode: 0x0D for inverse
}

//********Nokia5110_OutChar*****************
// Print a character to the Nokia 5110 48x84 LCD.  The
// character will be printed at the current cursor position,
// the cursor will automatically be updated, and it will
// wrap to the next row or back to the top if necessary.
// One blank column of pixels will be printed on either side
// of the character for readability.  Since characters are 8
// pixels tall and 5 pixels wide, 12 characters fit per row,
// and there are six rows.
// inputs: data  character to print
// outputs: none
// assumes: LCD is in default horizontal addressing mode (V = 0)
void Nokia5110_OutChar(unsigned char data){
  int i;
  lcdwrite(DATA, 0x00);                 // blank vertical line padding
  for(i=0; i<5; i=i+1){
    lcdwrite(DATA, ASCII[data - 0x20][i]);
  }
  lcdwrite(DATA, 0x00);                 // blank vertical line padding
}

//********Nokia5110_OutString*****************
// Print a string of characters to the Nokia 5110 48x84 LCD.
// The string will automatically wrap, so padding spaces may
// be needed to make the output look optimal.
// inputs: ptr  pointer to NULL-terminated ASCII string
// outputs: none
// assumes: LCD is in default horizontal addressing mode (V = 0)
void Nokia5110_OutString(char *ptr){
  while(*ptr){
    Nokia5110_OutChar((unsigned char)*ptr);
    ptr = ptr + 1;
  }
}

//********Nokia5110_OutUDec*****************
// Output a 16-bit number in unsigned decimal format with a
// fixed size of five right-justified digits of output.
// Inputs: n  16-bit unsigned number
// Outputs: none
// assumes: LCD is in default horizontal addressing mode (V = 0)
void Nokia5110_OutUDec(unsigned short n){
  if(n < 10){
    Nokia5110_OutString("    ");
    Nokia5110_OutChar(n+'0'); /* n is between 0 and 9 */
  } else if(n<100){
    Nokia5110_OutString("   ");
    Nokia5110_OutChar(n/10+'0'); /* tens digit */
    Nokia5110_OutChar(n%10+'0'); /* ones digit */
  } else if(n<1000){
    Nokia5110_OutString("  ");
    Nokia5110_OutChar(n/100+'0'); /* hundreds digit */
    n = n%100;
    Nokia5110_OutChar(n/10+'0'); /* tens digit */
    Nokia5110_OutChar(n%10+'0'); /* ones digit */
  }
  else if(n<10000){
    Nokia5110_OutChar(' ');
    Nokia5110_OutChar(n/1000+'0'); /* thousands digit */
    n = n%1000;
    Nokia5110_OutChar(n/100+'0'); /* hundreds digit */
    n = n%100;
    Nokia5110_OutChar(n/10+'0'); /* tens digit */
    Nokia5110_OutChar(n%10+'0'); /* ones digit */
  }
  else {
    Nokia5110_OutChar(n/10000+'0'); /* ten-thousands digit */
    n = n%10000;
    Nokia5110_OutChar(n/1000+'0'); /* thousands digit */
    n = n%1000;
    Nokia5110_OutChar(n/100+'0'); /* hundreds digit */
    n = n%100;
    Nokia5110_OutChar(n/10+'0'); /* tens digit */
    Nokia5110_OutChar(n%10+'0'); /* ones digit */
  }
}

//********Nokia5110_SetCursor*****************
// Move the cursor to the desired X- and Y-position.  The
// next character will be printed here.  X=0 is the leftmost
// column.  Y=0 is the top row.
// inputs: newX  new X-position of the cursor (0<=newX<=11)
//         newY  new Y-position of the cursor (0<=newY<=5)
// outputs: none
void Nokia5110_SetCursor(unsigned char newX, unsigned char newY){
  if((newX > 11) || (newY > 5)){        // bad input
    return;                             // do nothing
  }
  // multiply newX by 7 because each character is 7 columns wide
  lcdwrite(COMMAND, 0x80|(newX*7));     // setting bit 7 updates X-position
  lcdwrite(COMMAND, 0x40|newY);         // setting bit 6 updates Y-position
}

//********Nokia5110_Clear*****************
// Clear the LCD by writing zeros to the entire screen and
// reset the cursor to (0,0) (top left corner of screen).
// inputs: none
// outputs: none
void Nokia5110_Clear(void){
  int i;
  for(i=0; i<(MAX_X*MAX_Y/8); i=i+1){
    lcdwrite(DATA, 0x00);
  }
  Nokia5110_SetCursor(0, 0);
}

//********Nokia5110_DrawFullImage*****************
// Fill the whole screen by drawing a 48x84 bitmap image.
// inputs: ptr  pointer to 504 byte bitmap
// outputs: none
// assumes: LCD is in default horizontal addressing mode (V = 0)
void Nokia5110_DrawFullImage(const char *ptr){
  int i;
  Nokia5110_SetCursor(0, 0);
  for(i=0; i<(MAX_X*MAX_Y/8); i=i+1){
    lcdwrite(DATA, ptr[i]);
  }
}

  • Hi!

    Which TIVA board are you using?
  • TM4C123GH6PM launchpad
  • Okay. Your code looks quite complex  to me and it seems you mix DRM with Tivaware at some points. You may try to make it more simple by implementing the spi_master example from TivaWare/examples/peripherals/ssi folder.  Here is a working one:

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/ssi.h"
    
    // Define SPI here
    #define SPIPERIPHERIAL						SYSCTL_PERIPH_SSI0
    #define SPIPINPERIPHERIAL					SYSCTL_PERIPH_GPIOA
    #define SPIPERIPHERIALBASE					SSI0_BASE
    #define SPIPINPERIPHERIALBASE				GPIO_PORTA_BASE
    #define SPISCLKPINTYPE						GPIO_PA2_SSI0CLK
    #define SPISFSSPINTYPE						GPIO_PA3_SSI0FSS
    #define SPISOMIPINTYPE						GPIO_PA4_SSI0RX
    #define SPISIMOPINTYPE						GPIO_PA5_SSI0TX
    #define SPISCLKPIN							GPIO_PIN_2
    #define SPISFSSPIN							GPIO_PIN_3
    #define SPISOMIPIN							GPIO_PIN_4
    #define SPISIMOPIN							GPIO_PIN_5
    
    // Define SPI chip select (CS) pin here
    // CS: PE0
    #define SPICSPINPERIPHERIAL					SYSCTL_PERIPH_GPIOE
    #define SPICSPINPERIPHERIALBASE				GPIO_PORTE_BASE
    #define SPICSPIN 
    
    void board_spi_assert_cs(void) {
    	ROM_GPIOPinWrite(SPICSPINPERIPHERIALBASE, SPICSPIN, 0); // Assert 
    }
    
    void board_spi_deassert_cs(void) {
    	ROM_GPIOPinWrite(SPICSPINPERIPHERIALBASE, SPICSPIN, SPICSPIN); // Deassert 
    }
    
    uint32_t board_spi_transfer_byte(uint8_t data) {
    	uint32_t retval;
    	ROM_SSIDataPut(SPIPERIPHERIALBASE, (uint32_t) data);
    
    	while(ROM_SSIBusy(SPIPERIPHERIALBASE))
    		;
    	ROM_SSIDataGet(SPIPERIPHERIALBASE, &retval);
    
    	return retval;
    }
    
    static void board_init_spi(void) {
    	uint32_t tempbuffer;
    
        // Enable Peripherals
        ROM_SysCtlPeripheralEnable(SPIPERIPHERIAL);
        ROM_SysCtlPeripheralEnable(SPIPINPERIPHERIAL);
    
        // Set the pin muxing
        ROM_GPIOPinConfigure(SPISCLKPINTYPE);
        // GPIOPinConfigure(SPISFSSPINTYPE);
        ROM_GPIOPinConfigure(SPISOMIPINTYPE);
        ROM_GPIOPinConfigure(SPISIMOPINTYPE);
        ROM_GPIOPinTypeSSI(SPIPINPERIPHERIALBASE, SPISCLKPIN | SPISOMIPIN | SPISIMOPIN);
    
        ROM_SSIConfigSetExpClk(SPIPERIPHERIALBASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 10000, 8);
        ROM_SSIEnable(SPIPERIPHERIALBASE);
    
        // Read residual
        while(ROM_SSIDataGetNonBlocking(SPIPERIPHERIALBASE, &tempbuffer))
        	;
    }
    
    static void board_configure_cs(void) {
        ROM_SysCtlPeripheralEnable(SPICSPINPERIPHERIAL);
        ROM_GPIOPinTypeGPIOOutput(SPICSPINPERIPHERIALBASE, SPICSPIN);
        ROM_GPIOPinWrite(SPICSPINPERIPHERIALBASE, SPICSPIN, SPICSPIN); // Deassert 
    }
    
    void board_configure_spi(void) {
    	board_init_spi();
    	board_configure_cs();
        
    }							
  • As one past in the display biz - I know (somewhat) of those displays.

    Now we note that your post reports, "Same code does not work." While crystal clear to you - none here are comforted by that overly broad, oft-used, "Does not work!"

    Does anything work? Or is it only a single character - (missing its full (lower case) descender) [for example] which, "Does not work." We can't possibly know - can we?

    The diagnostic effort demands some precision by the presenting "patient" or "poster."

    Often - it is only the absence of correct contrast voltage - which prevents the display from "bringing its pixels into view."
  • Adding delay in CS low & high has worked. Any delay below 15us does not work. Dont know why is it so, datasheet doesnt say so.

    CE_LOW();
    wait_delay_us(15);
    SSIDataPut(SSI0_BASE , (uint32_t)data);
    wait_delay_us(15);
    CE_HIGH();

  • Strange that data-sheet avoids that - have you presented it for forum review?   If memory serves - multiple versions of that display were issued - employing different (display) controllers - such (in addition to the writing below) may explain.

    As to, "success" w/addition of delay.   That's predictable - is it not.

    Your Cortex M4 runs rings around the outclassed Arduino - thus timings which worked w/the "lesser device" are likely to fail when modern (i.e. real) MCU enters the scene...   (and runs much faster)