B4R Question ST7920 graphics LCD

Mostez

Active Member
Licensed User
Hello,
I tried this code example to drive ST7920 128x64 graphics LCD in SPI mode, it worked well. I need to convert the C code into B4R code. I tried SPI code module to send data to LCD with no luck.

the problem is, this type of LCD requires to send data in 24-bit format not byte by byte and actually this is the main problem(timing). I checked SPI signals by logic analyzer and there is a different between SPI signals generated by arduino IDE and signals generated by SPI code module.

Thanks
 

Mostez

Active Member
Licensed User
sure, I also attached signal analysis screenshots for both codes

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public Serial1 As Serial
    
    Private LCD_CLEAR_SCREEN  As Byte = 0x01    ' Clear screen
    Private LCD_ADDRESS_RESET  As Byte = 0x02    ' The address counter is reset
    Private LCD_BASIC_FUNCTION  As Byte = 0x30    ' Basic instruction set
    Private LCD_EXTEND_FUNCTION  As Byte = 0x34    ' Extended instruction set
    
    Private ST7920_SS As Pin 'data/command pin on LCD is now SS(slave select)
    Private ST7920_RST As Pin 'reset
    
'    Private SPI_MODE0 As Byte = 0
'    Private SPI_MODE1 As Byte = 1
'    Private SPI_MODE2 As Byte = 2
'    Private SPI_MODE3 As Byte = 3
'   
'    Private SPI_LSBFIRST As Byte = 0
'    Private SPI_MSBFIRST As Byte = 1
'   
    Private LOW As Boolean = False
    Private HIGH As Boolean = True
    
End Sub

Private Sub AppStart
    
    Serial1.Initialize(115200)
    Log("AppStart")
    ST7920_SS.Initialize (10,ST7920_SS.MODE_OUTPUT)
    ST7920_RST.Initialize(8,ST7920_RST.MODE_OUTPUT)
    SPI.begin
    ST7920_SS.DigitalWrite(LOW)
    STN7920_init
    SetGraphicsMode(True)
    SetGraphicsMode(False)
'    ST7920_DisplayString("hello world",1)
    ST7920_Write(0x93,True)
    ST7920_Write(0x20,False) 'space
    ST7920_Write(0x41,False) 'letter A

End Sub

private Sub ST7920_Write(LCDdata As Byte, Command As Boolean)
    Dim tArray (3) As Byte
    If Command Then
        tArray(0) = (0xFA)
    Else
        tArray(0)= (0xF8)
    End If
    tArray (1) = (Bit.And(LCDdata,0xF0))
    tArray (2) =(Bit.And(Bit.ShiftLeft(LCDdata,4) ,0xF0))
    SPI.BeginTransaction(2000000,SPI.MSBFIRST,SPI.SPI_MODE(3))
    ST7920_SS.DigitalWrite(HIGH)
    For m = 0 To 2
        SPI.Transfer(tArray(m))
    Next
    ST7920_SS.DigitalWrite(LOW)
    SPI.EndTransaction
    
'    SPI.BeginTransaction(2000000,SPI.MSBFIRST,SPI.SPI_MODE(3))
'    ST7920_SS.DigitalWrite(HIGH)
'    If Command Then
'        SPI.Transfer(0xFA)
'    Else
'        SPI.Transfer(0xF8)
'       
'    End If
'    SPI.Transfer(Bit.And(LCDdata,0xF0))
'    SPI.Transfer(Bit.And(Bit.ShiftLeft(LCDdata,4) ,0xF0))
'    'Log (LCDdata,"-",(Bit.And(LCDdata,0xF0)),"-",(Bit.And(Bit.ShiftLeft(LCDdata,4) ,0xF0)))
'    ST7920_SS.DigitalWrite(LOW)
'    'SPI.EndTransaction
End Sub
    
private Sub STN7920_init()
    ST7920_RST.DigitalWrite(LOW)
    Delay(100)
    ST7920_RST.DigitalWrite(HIGH)
    ST7920_Write(LCD_BASIC_FUNCTION,True)
    ST7920_Write(LCD_CLEAR_SCREEN,True)
    ST7920_Write(0x06,True)
    ST7920_Write(0x0C,True)
End Sub

private Sub SetGraphicsMode(Enabled As Boolean)
    If Enabled Then
        ST7920_Write(LCD_EXTEND_FUNCTION,True)
        ST7920_Write(Bit.Or(LCD_EXTEND_FUNCTION,0x02),True)
    Else
        ST7920_Write(LCD_BASIC_FUNCTION,True)
    End If
End Sub

private Sub ST7920_DisplayString(StrData() As Byte, Row As Byte)

Dim Addr As Byte

Select Row
    Case 1
        Addr = 0x90
    Case 2
        Addr = 0x88
    Case 3
        Addr = 0x98
    Case Else
        Addr = 0x80
End Select
ST7920_Write(Addr,True)

Dim Length As Byte = StrData.Length
For i = 0 To Length - 1
    ST7920_Write(StrData(i),False)
Next

End Sub
 

Attachments

Mostez

Active Member
Licensed User
after spending long time analyzing signals and compare data from both codes, here is the final code, works perfect :)
unfortunately SPI module did work, I modified SPI code from NOKIA 5110 module to work with my code.

thanks everyone for help.
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public Serial1 As Serial
    
    Private LCD_CLEAR_SCREEN  As Byte = 0x01    ' Clear screen
    Private LCD_ADDRESS_RESET  As Byte = 0x02    ' The address counter is reset
    Private LCD_BASIC_FUNCTION  As Byte = 0x30    ' Basic instruction set
    Private LCD_EXTEND_FUNCTION  As Byte = 0x34    ' Extended instruction set
    
    Private ST7920_SS As Pin 'data/command pin on LCD is now SS(slave select)
    Private ST7920_RST As Pin 'reset
    
    Private LOW As Boolean = False
    Private HIGH As Boolean = True
'    Private COMMAND As Boolean = True
'    Private DATA As Boolean = False
    
    Private clockPin As Int = 13
    Private dataPin As Int = 11
    
    Private sPin, cPin, dPin As Pin
    Private bitOrder As Boolean =  False
    Private SPIdata As Byte = 0
    
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    cPin.Initialize(clockPin, cPin.MODE_OUTPUT)
    dPin.Initialize(dataPin, dPin.MODE_OUTPUT)
    
    ST7920_SS.Initialize (10,ST7920_SS.MODE_OUTPUT)
    ST7920_RST.Initialize(8,ST7920_RST.MODE_OUTPUT)
    
    ST7920_SS.DigitalWrite(LOW)
    cPin.DigitalWrite(LOW)
    dPin.DigitalWrite(HIGH)
    STN7920_init
    SetGraphicsMode(True)
    ST7920_ClearGraphicMem
    SetGraphicsMode(False)
    ST7920_DisplayString("Hello World",0)
    ST7920_DisplayString("Greetings B4R",1)
    ST7920_DisplayString("B4R is great",2)
End Sub


Private Sub SPI_MasterTransmit(cByte As Byte)
    Dim n=8 As Byte
    cPin.DigitalWrite(False)
    Do While n > 0
        If Bit.And(cByte,0x80)>0 Then
            Write(True)
        Else
            Write(False)
        End If
        cByte=Bit.ShiftLeft(cByte,1)
        n = n - 1
    Loop
    cPin.DigitalWrite(False)
End Sub

Private Sub Write(state As Boolean)
    cPin.DigitalWrite(False)
    If state Then
        dPin.DigitalWrite(True)
    Else
        dPin.DigitalWrite(False)
    End If
    cPin.DigitalWrite(True)
End Sub

private Sub ST7920_Write(LCDdata As Byte, isCMD As Boolean)
    Dim tArray (3) As Byte
    If isCMD Then
        tArray(0)= (0xF8)
    Else
        tArray(0) = (0xFA)
    End If
    tArray (1) = (Bit.And(LCDdata,0xF0))
    tArray (2) =(Bit.And(Bit.ShiftLeft(LCDdata,4) ,0xF0))
    
    ST7920_SS.DigitalWrite(HIGH) 'low for test only
    
    SPI_MasterTransmit(tArray(0))
    SPI_MasterTransmit(tArray(1))
    SPI_MasterTransmit(tArray(2))

    ST7920_SS.DigitalWrite(LOW)
    dPin.DigitalWrite(LOW)
End Sub
    
private Sub STN7920_init()
    ST7920_RST.DigitalWrite(LOW)
    Delay(100)
    ST7920_RST.DigitalWrite(HIGH)
    ST7920_Write(LCD_BASIC_FUNCTION,True)
    ST7920_Write(LCD_CLEAR_SCREEN,True)
    ST7920_Write(0x06,True)
    ST7920_Write(0x0C,True)
End Sub

private Sub SetGraphicsMode(Enabled As Boolean)
    If Enabled Then
        ST7920_Write(LCD_EXTEND_FUNCTION,True)
        ST7920_Write(Bit.Or(LCD_EXTEND_FUNCTION,0x02),True)
    Else
        ST7920_Write(LCD_BASIC_FUNCTION,True)
    End If
End Sub

private Sub ST7920_ClearGraphicMem()
For X = 0 To 15
    For Y = 0 To 31
            ST7920_Write(Bit.Or(Y,0x80),True)
            ST7920_Write(0x00,False)
    Next
        ST7920_Write(Bit.Or(X,0x80),True)
        ST7920_Write(0x00,False)
Next
End Sub

private Sub ST7920_DisplayString(StrData() As Byte, Row As Byte)

Dim Addr As Byte

Select Row
    Case 1
        Addr = 0x90
    Case 2
        Addr = 0x88
    Case 3
        Addr = 0x98
    Case Else
        Addr = 0x80
End Select
ST7920_Write(Addr,True)

Dim Length As Byte = StrData.Length
For i = 0 To Length - 1
    Dim X As Byte = StrData(i)
    ST7920_Write(x,False)
Next

End Sub
 

Attachments

Mostez

Active Member
Licensed User
while testing the LCD, random dots displayed even if no text on screen. the reason was ST7920_ClearGraphicMem sub. I did not translate C++ code correctly, here is the correct sub:
B4X:
private Sub ST7920_ClearGraphicMem()
    For X = 0 To 15
        For Y = 0 To 31
            ST7920_Write(Bit.Or(Y,0x80),True)
            ST7920_Write(Bit.Or(X,0x80),True)
            ST7920_Write(0x00,False)
            ST7920_Write(0x00,False)
        Next
    Next
End Sub
 
Last edited:

emexes

Well-Known Member
Licensed User
... length in a byte ... cannot handle more than 127 bytes ...
all you need is just 16 char per line
No worries, then :)

Given that it is a 128x64 graphics LCD, it seemed plausible that it might also have a bitmapped graphics mode, and a full screen of 8192 pixels = 1024 bytes of data might be sent to the module in one transfer.
 
Top