Share My Creation SD TFT Picture Frame

1.8", 128x160 pixels TFT driven by Arduino Uno or Nano to display pictures from SD card. TFT driver is ST7735.
The SD is interfaced by the main ATMEGA ISP and the TFT interfaced by USART as ISP. The code reads the SD 54 bytes at a time and streams them to the TFT. Inline C is used to set up the USART ISP, the code also initialize the TFT.
The circuit diagram shows an option of using Micro SD module and an option of using the SD card on the back of the TFT module. The 1K resistors are on the TFT module, If you don't have them on your module you have to add them to avoid high currents to the SD inputs.
To setup the SD:
Format the card with FAT32.
Create image file using MS Paint or another program, file size is 61KB, image size 160 pixels high by 128 pixels wide.
Name the files "1.bmp", "2.bmp", etc.
Save the files as 24 bits bmp.
Add the files to the root folder of the card (don't use a directory).
B4X:
Sub Process_Globals
    Private sd As SD
    Public Serial1 As Serial
    Public CStft, CSsd As Pin
    Public DC As Pin
    Public SDA As Pin
    Public SCK, SCKsd As Pin
    Public RST As Pin
    Private miso, mosi As Pin
    Private spires, spidata As Byte

End Sub

Private Sub AppStart
    Serial1.Initialize(9600)
    sd.Initialize(10) '10 is the CS pin

    CStft.Initialize(7, CStft.MODE_OUTPUT)
    DC.Initialize(9, DC.MODE_OUTPUT)    'AO
    RST.Initialize(8, RST.MODE_OUTPUT)
    SDA.Initialize(1, SDA.MODE_OUTPUT)    'MOSI
    SCK.Initialize(4, SCK.MODE_OUTPUT)
 
    mosi.Initialize(11, mosi.MODE_OUTPUT)    'MOSI
    SCKsd.Initialize(13, SCKsd.MODE_OUTPUT)
    CSsd.Initialize(10, CSsd.MODE_OUTPUT)
    miso.Initialize(12, miso.MODE_INPUT)
 
    RunNative ("set_spi",Null)
    TFTinit
    getBMP

End Sub


Sub getBMP
    Do While True
        sd.OpenRead("1.bmp")
        If sd.Exists("1.bmp") Then
            drawTFT
            Delay(10000)
        End If
        sd.OpenRead("2.bmp")
        If sd.Exists("2.bmp") Then
            drawTFT
            Delay(10000)
        End If
        sd.OpenRead("3.bmp")
        If sd.Exists("3.bmp") Then
            drawTFT
            Delay(10000)
        End If
        sd.OpenRead("4.bmp")
        If sd.Exists("4.bmp") Then
            drawTFT
            Delay(10000)
        End If
    
        sd.OpenRead("5.bmp")
        If sd.Exists("5.bmp") Then
            drawTFT
            Delay(10000)
        End If
        sd.OpenRead("6.bmp")
        If sd.Exists("6.bmp") Then
            drawTFT
            Delay(10000)
        End If
    Loop
End Sub


Sub drawTFT
    Dim j As Byte
    Dim i As ULong
    Dim buf1(54) As Byte
 
    area(0,0,127,159)

    DC.DigitalWrite(True)
    CStft.DigitalWrite(False)
    For i=0 To 1138    '1136
        sd.Position=i*54
        sd.Stream.ReadBytes(buf1,0,54)
    
        If i>0 Then
            For j=0 To 53
                spi(buf1(j))
            Next
            Else
                spi(buf1(53))
        End If
    
    Next
    CStft.DigitalWrite(True)
 
End Sub

Sub spi(data As Byte)    'send byte over spi
    spidata=data
    RunNative ("spi",Null)
    Return
End Sub


Sub command(cmd As Byte)
    DC.DigitalWrite(False)    'command Mode
    CStft.DigitalWrite(False)    'Select the LCD (active low)
    spi(cmd)'set up data on bus
    CStft.DigitalWrite(True)    'Deselect LCD (active low)
End Sub

Sub send_data(data As Byte)
    DC.DigitalWrite(True)    'data mode
    CStft.DigitalWrite(False)    'Select the LCD (active low)
    spi(data)    'set up data on bus
    CStft.DigitalWrite(True)    'Deselect LCD (active low)
End Sub



Sub TFTinit
    Dim i As Byte
 
    RST.DigitalWrite(True)    'hardware reset
    Delay(200)
    RST.DigitalWrite(False)
    Delay(10)
    RST.DigitalWrite(True)
    Delay(10)

    command(0x01)    'sw reset
    Delay(200)
    command(0x11)    ' Sleep out
    Delay(200)
 
    command(0x3A)    'color mode
    'send_data(0x05)    '16 bits
    send_data(0x06)    '18 bits

    command(0x36)    'Memory access ctrl (directions)
    send_data(0x40)    '0B1100000=0x60
    'send_data(0x08)    '0x48=left to right,BRG,horizontal   0x40=vertical,RGB
    'command(0x21)    'color inversion on

    command(0x2D)    'color look up table
    send_data(0)
    For i = 1 To 31
        send_data(i * 2)
    Next

    For i = 0 To 63
        send_data(i)
    Next
    send_data(0)
    For i = 1 To 31
        send_data(i * 2)
    Next

    command(0x13)    'Normal display on
    command(0x29)    'Main screen turn on
End Sub

Sub area(x0 As Byte, y0 As Byte,  x1 As Byte, y1 As Byte)
    command(0x2A)    'Column addr set
    send_data(0x00)
    send_data(x0)    ' XSTART
    send_data(0x00)
    send_data(x1)    ' XEND

    command(0x2B)    'Row addr set
    send_data(0x00)
    send_data(y0)    ' YSTART
    send_data(0x00)
    send_data(y1)    ' YEND

    command(0x2C)    'write To RAM
End Sub

    #if C
    void spi(B4R::Object* o)
    {
        while ( !( UCSR0A & (1<<UDRE0)) );    // Wait for empty transmit buffer
        UDR0 = b4r_main::_spidata;        // Put data into buffer, sends the data
        while ( !(UCSR0A & (1<<RXC0)) );        // Wait for data to be received
        b4r_main::_spires = UDR0;    // return received data from buffer
    }
    #End if
 
    #if C
    void set_spi(B4R::Object* o)
    {
        UBRR0 = 0;
        UCSR0C = (1<<UMSEL01)|(1<<UMSEL00)|(1<<UCPHA0)|(1<<UCPOL0); // MSPI mode and SPI data mode 3
        UCSR0B = (1<<RXEN0)|(1<<TXEN0);        // Enable receiver and transmitter
        UBRR0 = 8;    // Set baud rate. must be at the end
    }
    #End if
 

Attachments

  • tft_bmp.zip
    2 KB · Views: 80
  • picture_frame400.jpg
    picture_frame400.jpg
    23.3 KB · Views: 317
  • arduino_sd_tft-2.png
    arduino_sd_tft-2.png
    14.2 KB · Views: 29
Last edited:

Beja

Expert
Licensed User
1.8", 128x160 pixels TFT driven by Arduino Uno or Nano to display pictures from SD card. TFT driver is ST7735.
The SD is interfaced by the main ATMEGA ISP and the TFT interfaced by USART as ISP. The code reads the SD 54 bytes at a time and streams them to the TFT. Inline C is used to set up the USART ISP, the code also initialize the TFT.
The circuit diagram shows an option of using Micro SD module and an option of using the SD card on the back of the TFT module. The 1K resistors are on the TFT module, If you don't have them on your module you have to add them to avoid high currents to the SD inputs.
To setup the SD:
Format the card with FAT32.
Create image file using MS Paint or another program, file size is 61KB, image size 160 pixels high by 128 pixels wide.
Name the files "1.bmp", "2.bmp", etc.
Save the files as 24 bits bmp.
Add the files to the root folder of the card (don't use a directory).
B4X:
Sub Process_Globals
    Private sd As SD
    Public Serial1 As Serial
    Public CStft, CSsd As Pin
    Public DC As Pin
    Public SDA As Pin
    Public SCK, SCKsd As Pin
    Public RST As Pin
    Private miso, mosi As Pin
    Private spires, spidata As Byte

End Sub

Private Sub AppStart
    Serial1.Initialize(9600)
    sd.Initialize(10) '10 is the CS pin

    CStft.Initialize(7, CStft.MODE_OUTPUT)
    DC.Initialize(9, DC.MODE_OUTPUT)    'AO
    RST.Initialize(8, RST.MODE_OUTPUT)
    SDA.Initialize(1, SDA.MODE_OUTPUT)    'MOSI
    SCK.Initialize(4, SCK.MODE_OUTPUT)
 
    mosi.Initialize(11, mosi.MODE_OUTPUT)    'MOSI
    SCKsd.Initialize(13, SCKsd.MODE_OUTPUT)
    CSsd.Initialize(10, CSsd.MODE_OUTPUT)
    miso.Initialize(12, miso.MODE_INPUT)
 
    RunNative ("set_spi",Null)
    TFTinit
    getBMP

End Sub


Sub getBMP
    Do While True
        sd.OpenRead("1.bmp")
        If sd.Exists("1.bmp") Then
            drawTFT
            Delay(10000)
        End If
        sd.OpenRead("2.bmp")
        If sd.Exists("2.bmp") Then
            drawTFT
            Delay(10000)
        End If
        sd.OpenRead("3.bmp")
        If sd.Exists("3.bmp") Then
            drawTFT
            Delay(10000)
        End If
        sd.OpenRead("4.bmp")
        If sd.Exists("4.bmp") Then
            drawTFT
            Delay(10000)
        End If
     
        sd.OpenRead("5.bmp")
        If sd.Exists("5.bmp") Then
            drawTFT
            Delay(10000)
        End If
        sd.OpenRead("6.bmp")
        If sd.Exists("6.bmp") Then
            drawTFT
            Delay(10000)
        End If
    Loop
End Sub


Sub drawTFT
    Dim j As Byte
    Dim i As ULong
    Dim buf1(54) As Byte
 
    area(0,0,127,159)

    DC.DigitalWrite(True)
    CStft.DigitalWrite(False)
    For i=0 To 1138    '1136
        sd.Position=i*54
        sd.Stream.ReadBytes(buf1,0,54)
     
        If i>0 Then
            For j=0 To 53
                spi(buf1(j))
            Next
            Else
                spi(buf1(53))
        End If
     
    Next
    CStft.DigitalWrite(True)
 
End Sub

Sub spi(data As Byte)    'send byte over spi
    spidata=data
    RunNative ("spi",Null)
    Return
End Sub


Sub command(cmd As Byte)
    DC.DigitalWrite(False)    'command Mode
    CStft.DigitalWrite(False)    'Select the LCD (active low)
    spi(cmd)'set up data on bus
    CStft.DigitalWrite(True)    'Deselect LCD (active low)
End Sub

Sub send_data(data As Byte)
    DC.DigitalWrite(True)    'data mode
    CStft.DigitalWrite(False)    'Select the LCD (active low)
    spi(data)    'set up data on bus
    CStft.DigitalWrite(True)    'Deselect LCD (active low)
End Sub



Sub TFTinit
    Dim i As Byte
 
    RST.DigitalWrite(True)    'hardware reset
    Delay(200)
    RST.DigitalWrite(False)
    Delay(10)
    RST.DigitalWrite(True)
    Delay(10)

    command(0x01)    'sw reset
    Delay(200)
    command(0x11)    ' Sleep out
    Delay(200)
 
    command(0x3A)    'color mode
    'send_data(0x05)    '16 bits
    send_data(0x06)    '18 bits

    command(0x36)    'Memory access ctrl (directions)
    send_data(0x40)    '0B1100000=0x60
    'send_data(0x08)    '0x48=left to right,BRG,horizontal   0x40=vertical,RGB
    'command(0x21)    'color inversion on

    command(0x2D)    'color look up table
    send_data(0)
    For i = 1 To 31
        send_data(i * 2)
    Next

    For i = 0 To 63
        send_data(i)
    Next
    send_data(0)
    For i = 1 To 31
        send_data(i * 2)
    Next

    command(0x13)    'Normal display on
    command(0x29)    'Main screen turn on
End Sub

Sub area(x0 As Byte, y0 As Byte,  x1 As Byte, y1 As Byte)
    command(0x2A)    'Column addr set
    send_data(0x00)
    send_data(x0)    ' XSTART
    send_data(0x00)
    send_data(x1)    ' XEND

    command(0x2B)    'Row addr set
    send_data(0x00)
    send_data(y0)    ' YSTART
    send_data(0x00)
    send_data(y1)    ' YEND

    command(0x2C)    'write To RAM
End Sub

    #if C
    void spi(B4R::Object* o)
    {
        while ( !( UCSR0A & (1<<UDRE0)) );    // Wait for empty transmit buffer
        UDR0 = b4r_main::_spidata;        // Put data into buffer, sends the data
        while ( !(UCSR0A & (1<<RXC0)) );        // Wait for data to be received
        b4r_main::_spires = UDR0;    // return received data from buffer
    }
    #End if
 
    #if C
    void set_spi(B4R::Object* o)
    {
        UBRR0 = 0;
        UCSR0C = (1<<UMSEL01)|(1<<UMSEL00)|(1<<UCPHA0)|(1<<UCPOL0); // MSPI mode and SPI data mode 3
        UCSR0B = (1<<RXEN0)|(1<<TXEN0);        // Enable receiver and transmitter
        UBRR0 = 8;    // Set baud rate. must be at the end
    }
    #End if

Thanks for this great creation.. can it play animated GIF file?
 

moty22

Active Member
Licensed User
Thanks for this great creation.. can it play animated GIF file?
Thank you.
It takes about 4 seconds to draw the whole screen, so to draw 10% of the screen area it takes 0.4 sec. The smaller the GIF the faster it loads. You have to convert the GIF to BMP frames and load them to the SD as separate files and change the area (line 78 of the code) to the size of your frames.
If you draw a face and redraw only the eyes it can be quite fast.
 
Top