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.