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.

TM4C123G6PM and initialization of the LCD with PCD8544 on assembly lang

Hello everyone!

I need some help in initialization of the popular LCD on PCD8544 chip. I see many sources on C and i want to write this on assembly language just for example.

This init sequence (has already written by  Jonathan Valvano) i used as a guide:

void Nokia5110_Init(void){
  volatile uint32_t 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.33 MHz SSIClk (80 MHz PLL/24)
                                        // SysClk/(CPSDVSR*(1+SCR))
                                        // 80/(24*(1+0)) = 3.33 MHz (slower than 4 MHz)
  SSI0_CPSR_R = (SSI0_CPSR_R&~SSI_CPSR_CPSDVSR_M)+24; // must be even number
  SSI0_CR0_R &= ~(SSI_CR0_SCR_M |       // SCR = 0 (3.33 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
}

And i wrote this:

INIT        

; System clock properties FOR 40 MHz        


; reg RCC2-> bit 30 DIV400=1->SYSDIV2LSB & SYSDIV2 CREATE A 7 BIT DIVISOR USING THE 400 MHz PLL OTPUT        
USE_RCC2    ;reg RCC2->bit 31 USERCC2=1-> THE RCC2 REGISTER FIELDS OVERRIDE THE RCC REGISTER FIELDS
            LDR R1, =SYSCTL_RCC2_R
            LDR R0, [R1]
            ORR R0, #SYSCTL_RCC2_USERCC2
            STR R0, [R1]

;bypass PLL while initializing
BYPASS        ;BYPASS PLL WHILE INITIALIZING
            LDR R1, =SYSCTL_RCC2_R
            LDR R0,[R1]
            ORR R0, #SYSCTL_RCC2_BYPASS2
            STR R0, [R1]
;configure for 16 MHz crystal            
XTAL_16MHZ    ;reg RCC->bit 10-6 XTAL=0XD-> XTAL =16 MHZ
            LDR R1, =SYSCTL_RCC_R
            LDR R0,[R1]
            BIC R0, #0x7C0 ; CLEAR XTAL FIELD
            ORR R0, #0x540 ;16 MHz CRYSTAL
            STR R0, [R1]
;configure for main oscillator source            
MOSC        ;reg RCC2->bit 6-4 OSCSRC2=0-> SELECT INPUT SOURCE FOR THE OSC = MOSC
            LDR R1, =SYSCTL_RCC2_R
            LDR R0,[R1]
            BIC R0, #SYSCTL_RCC2_OSCSRC2_M
            ORR R0, #SYSCTL_RCC2_OSCSRC2_MO
            STR R0, [R1]
;activate PLL by clearing PWRDN
PLL_ON        ;reg RCC2->bit 13 PWRDN2=0-> THE PLL IS ON
            LDR R1, =SYSCTL_RCC2_R
            LDR R0,[R1]
            BIC R0, #0x2000
            STR R0, [R1]
;use 400 MHz PLL    
DIV400    ; reg RCC2-> bit 30 DIV400=1->SYSDIV2LSB & SYSDIV2 CREATE A 7 BIT DIVISOR USING THE 400 MHz PLL OTPUT            
            LDR R1, =SYSCTL_RCC2_R
            LDR R0, [R1]
            ORR R0, #SYSCTL_RCC2_DIV400
            STR R0, [R1]
;configure for 50 MHz clock
SYSDIV2        ;reg RCC2->bit 28-23 SYSDIV2=0x02-> SELECT INPUT SYSTEM CLOCK DIVISOR = 10    
            LDR R1, =SYSCTL_RCC2_R
            LDR R0,[R1]
            BIC R0, #0x1FC00000
            ORR R0, #0x01C00000
            STR R0, [R1]

;wait for the PLL to lock by polling PLLLRIS
PLL_LOCK_WAIT    ;WAIT FOR PLL LOCK                            
            LDR R1, =SYSCTL_PLLSTAT_R
            
READ_PLLSTAT
            LDR R0,[R1]
            CMP R0, #0x01
            BNE READ_PLLSTAT

;enable use of PLL by clearing BYPASS        
CLR_BYPASS2    ;reg RCC2->bit 11 BYPASS2=0-> SYSTEM CLOCK IS USED DIVIDED BY THE DIVISOR SPECIFIED BY SYSDIV2
            LDR R1, =SYSCTL_RCC2_R
            LDR R0,[R1]
            BIC R0, #SYSCTL_RCC2_BYPASS2
            STR R0, [R1]
            
;SPI0    properties - 2,5 MHZ SPH=0 SPO=0


;ACTIVATE SSI0
            MOV R0, #0x01
            LDR R1, =SYSCTL_RCGCSSI_R
            STR R0, [R1]

;ACTIVATE PORT A
            MOV R0, #0x01
            LDR R1, =SYSCTL_RCGCGPIO_R
            STR R0, [R1]

;ALLOW TIME TO FINISH ACTIVATING
            NOP
            NOP
            NOP
            NOP
            NOP

;MAKE PA6,7 OUT
            MOV R0, #0xC0
            LDR R1, =GPIO_PORTA_DIR_R
            STR R0, [R1]

;ENABLE ALT FUCNT ON PA2,3,5
            MOV R0, #0x2C
            LDR R1, =GPIO_PORTA_AFSEL_R
            STR R0, [R1]

;DISABLE ALT FUNCT ON PA6,7
            LDR R1, =GPIO_PORTA_AFSEL_R
            LDR R0, [R1]
            BIC R0, #0xC0
            STR R0, [R1]

;ENABLE DIGITAL IO ON PA2,3,5,6,7
            MOV R0, #0xEC
            LDR R1, =GPIO_PORTA_DEN_R
            STR R0, [R1]

;CONFIGURE PA6,7 AS GPIO; 2,3,6 AS SSI
            LDR R1, =GPIO_PORTA_PCTL_R
            LDR R0, [R1]
            MOV32 R2, #0xFF0F00FF
            AND R0,R0,R2
            MOV32 R2, #0x00202200
            ORR R0, R0, R2
            STR R0, [R1]

;DISABLE ANALOG FUNCTIONALITY ON PA2,3,5,6,7
            LDR R1, =GPIO_PORTA_AMSEL_R
            LDR R0, [R1]
            BIC R0, #0xEC

;DISABLE SSI
            LDR R1, =SSI0_CR1_R
            LDR R0, [R1]
            BIC R0, #SSI_CR1_SSE
            STR R0, [R1]

;MASTER MODE
            LDR R1, =SSI0_CR1_R
            LDR R0, [R1]
            BIC R0, #SSI_CR1_MS
            STR R0, [R1]

;CONFIGURE FOR PLL BAUD CLOCK SOURCE
            LDR R1, =SSI0_CC_R
            LDR R0, [R1]
            BIC R0, #0xF
            STR R0, [R1]

;SYSCLK=40MHZ
;SPICLK=SYSCLK/(CPSRDVSR*(SCR+1))
;SPICLK=40/(4*(3+1))=2.5
;SET CPSRDVSR=4
            MOV R0, #0x04
            LDR R1, =SSI0_CPSR_R
            STR R0, [R1]

;SCR=3
            LDR R1, =SSI0_CR0_R
            LDR R0, [R1]
            BIC R0, #0xFF00
            ORR R0, #0x0300
            STR R0, [R1]

;SPH=0 ;SPO=0
            LDR R1, =SSI0_CR0_R
            LDR R0, [R1]
            BIC R0, #SSI_CR0_SPH
            BIC R0, #SSI_CR0_SPO
            STR R0, [R1]

;FRF=0 FREESCALE SPI
            LDR R1, =SSI0_CR0_R
            LDR R0, [R1]
            BIC R0, #0x30
            STR R0, [R1]

;DSS = 8 BIT DATA
            LDR R1, =SSI0_CR0_R
            LDR R0, [R1]
            BIC R0, #SSI_CR0_DSS_M
            ORR R0, #SSI_CR0_DSS_8
            STR R0, [R1]

;ENABLE SSI
            LDR R1, =SSI0_CR1_R
            LDR R0, [R1]
            ORR R0, #SSI_CR1_SSE
            STR R0, [R1]

;RESET THE LCD TO A KNOWN STATE
            MOV R0, #0x00
            LDR R1, =GPIO_PORTA_DATA_R
            STR R0, [R1]

;DELAY MIN 100 NS
            NOP
            NOP
            NOP
            NOP
            NOP

;RESET HIGH (NEGATIVE LOGIC)
            MOV R0, #0x80
            LDR R1, =GPIO_PORTA_DATA_R
            STR R0, [R1]
            
            NOP
            NOP
            NOP
            NOP
            NOP

;SET LCD Vop
            

            
            MOV R0, #0x21
            LDR R1, =SSI0_DR_R
            STR R0, [R1]
            


;0xB1,0xBF,0x80,0xFF, TWEAKING
            MOV R0, #0xB1
            LDR R1, =SSI0_DR_R
            STR R0, [R1]
            


;SET TEMP COEFFICIENT
            MOV R0, #0x04
            LDR R1, =SSI0_DR_R
            STR R0, [R1]
            


;LCD BIAS MODE
            MOV R0, #0x14
            LDR R1, =SSI0_DR_R
            STR R0, [R1]
            


;WE MUST SEND 0x20 BEFORE MODIFYING THE DISPLAY CONTROLE MODE
            MOV R0, #0x20
            LDR R1, =SSI0_DR_R
            STR R0, [R1]
            


;SET DISPLAY CONTROL TO NORMAL MODE
            
            MOV R0, #0x0D
            LDR R1, =SSI0_DR_R
            STR R0, [R1]

            LDR R1, =GPIO_PORTA_DATA_R
            LDR R0, [R1]
            BIC R0, #0xF0
            ORR R0, #0x40
            STR R0, [R1]
            
            MOV R0, #0x7F
            LDR R1, =SSI0_DR_R
            STR R0, [R1]
LABEL        B LABEL

But the program don't work as i waited. Sometimes the LCD don't start at all. Sometimes screen shows just odd dots and anything alike my simbol.

Help me understand my error.

Regards, Paul.

  • 0000 9999 said:
    i [sic] I want to write this on assembly language just for example.

    Might there exist multiple reasons (why) you see (many) examples - only in "C?"

    ASM does have it's "time/place" yet the set-up/config of a peripheral is not (usually) that place.

    You are aware that your combination of Direct Register and ASM forces, "orders of magnitude" in added complexity, upon your (hapless) helpers - are you not?   And - while your need, "just for example" may be important to you - that may not register as (especially) compelling to many here.

    If it were me - and I really wanted to study/master ASM - would it not make sense to program your display all in "C" - and then review the ASM code-flow which resulted?  

    Further - would not your time be better served by employing ASM where it's "truly needed" - which is other than a basic, display set-up/config?  

    Often it's productive to "Sell your post" to harvest smart/disciplined responders.   "Just for example barely "pings" the radar - don't you (now) agree?

  • Hello cb1

    I agree with you. Use of both DRM and ASM raises the complexity of any useful debug without forum users making an error on the operation.

    Hello 0000 9999,

    Suggest simplifying the approach to C in case the use of DRM and ASM serve no other specific purpose.

    Regards
    Amit
  • Thanks, guys. But i can do this if i want. I know what life is too short so let we forget asm=)
    But someone must write interpreters. I just want to write one good program - have some practice and maybe forget it too.
  • Hello 0000 9999,

    The approach will be to write the program in pure-C and then write it in ASM to be able to code compare...

    Regards
    Amit
  • 0000 9999 said:
    I just want to write one good program

    That's just great - but who does not?

    May I return you to the (gentle) suggestion of, "Writing that one good program in an area where ASM makes the most sense - throws off the most value?"   Clearly - that's not in the set-up/config of a very basic, low performance LCD Controller.

    As a small, tech biz owner - we have some experience in/around "human nature."   Strongly suspect that your efforts to recognize and choose a, "proper Target for ASM" will yield far more - and higher quality responses!   (trust me - that (old) LCD Controller won't "ping" too many radars... a better choice is your best friend...)

  • I am very grateful to you.