Using the Raspberry Pi Pico [6] – SPI communication with Micro Python


SPI on the Raspberry Pi Pico
The RP2040 has two independent SPI controllers (SPI0 / SPI1), available on the Raspberry Pi Pico from GP[0] to GP[27] pins. In this article, I tried to use this feature to connect the LCD display and read/write the EEPROM.

Connecting the ATM0130B3 LCD

The ATM0130B3 is a 240x(RGB)x240 1.3-inch full-color graphic LCD. This time, we used Akizuki’s control kit with 2.54mm pitch conversion board to connect it. The pitch conversion board also has a level conversion circuit, so it can be connected directly to the Raspberry Pi Pico.
1.3-inch full-color graphic LCD display
Hardware connections
The following figure shows the wiring between Raspberry Pi Pico’s I/O terminals and the ATM0130B3 conversion board. All the necessary components are mounted on the board. Connect the four SPI pins /CS, D/C, and RES, and the power supply and GND pins, respectively.
Schematics

Connection
Software (Micro Python code)
We will use Micro Python as before, referring to the MicroPython library documentation for examples of using the SPI class for the Serial Peripheral Interface Bus Protocol (SPI).
# Setup the SPI
spi = SPI(0, baudrate=8000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(2), miso=Pin(4), mosi=Pin(3))

# Write the bytes type object contained in buf to the device
spi.write(buff)

# write bytes object in write_buf while reading in read_buf 
# Both buffers can be the same or different, but must have the same length
spi.write_readinto(buff, buff)

The /CS, D/C, and RES signal lines are controlled as GPIOs.
from machine import Pin
from machine import SPI
import time

chars = [0x00, 0x00, 0x00, 0x00, 0x00,  0x21, 0x08, 0x40, 0x10, 0x00,  0x52, 0x94, 0x00, 0x00, 0x00,  0x52, 0x95, 0xF5, 0x7D, 0x4A,  0x23, 0xE8, 0xE2, 0xF8, 0x80,  0xC6, 0x44, 0x44, 0x4C, 0x60,  0x64, 0xA8, 0x8A, 0xC9, 0xA0,  0x61, 0x10, 0x00, 0x00, 0x00,  0x11, 0x10, 0x84, 0x10, 0x40,  0x41, 0x04, 0x21, 0x11, 0x00,  0x01, 0x2A, 0xEA, 0x90, 0x00,  0x01, 0x08, 0xE2, 0x10, 0x00,  0x00, 0x00, 0x06, 0x11, 0x00,  0x00, 0x01, 0xF0, 0x00, 0x00,  0x00, 0x00, 0x00, 0x63, 0x00,  0x00, 0x44, 0x44, 0x40, 0x00,  0x74, 0x67, 0x5C, 0xC5, 0xC0,  0x23, 0x08, 0x42, 0x11, 0xC0,  0x74, 0x42, 0x22, 0x23, 0xE0,  0xF8, 0x88, 0x20, 0xC5, 0xC0,
      0x11, 0x95, 0x2F, 0x88, 0x40,  0xFC, 0x3C, 0x10, 0xC5, 0xC0,  0x32, 0x11, 0xE8, 0xC5, 0xC0,  0xF8, 0x44, 0x44, 0x21, 0x00,  0x74, 0x62, 0xE8, 0xC5, 0xC0,  0x74, 0x62, 0xF0, 0x89, 0x80,  0x03, 0x18, 0x06, 0x30, 0x00,  0x03, 0x18, 0x06, 0x11, 0x00,  0x11, 0x11, 0x04, 0x10, 0x40,  0x00, 0x3E, 0x0F, 0x80, 0x00,  0x41, 0x04, 0x11, 0x11, 0x00,  0x74, 0x42, 0x22, 0x00, 0x80,  0x74, 0x42, 0xDA, 0xD5, 0xC0,  0x74, 0x63, 0x1F, 0xC6, 0x20,  0xF4, 0x63, 0xE8, 0xC7, 0xC0,  0x74, 0x61, 0x08, 0x45, 0xC0,  0xE4, 0xA3, 0x18, 0xCB, 0x80,  0xFC, 0x21, 0xE8, 0x43, 0xE0,  0xFC, 0x21, 0xE8, 0x42, 0x00,  0x74, 0x61, 0x78, 0xC5, 0xE0,
      0x8C, 0x63, 0xF8, 0xC6, 0x20,  0x71, 0x08, 0x42, 0x11, 0xC0,  0x38, 0x84, 0x21, 0x49, 0x80,  0x8C, 0xA9, 0x8A, 0x4A, 0x20,  0x84, 0x21, 0x08, 0x43, 0xE0,  0x8E, 0xEB, 0x58, 0xC6, 0x20,  0x8C, 0x73, 0x59, 0xC6, 0x20,  0x74, 0x63, 0x18, 0xC5, 0xC0,  0xF4, 0x63, 0xE8, 0x42, 0x00,  0x74, 0x63, 0x1A, 0xC9, 0xA0,  0xF4, 0x63, 0xEA, 0x4A, 0x20,  0x74, 0x20, 0xE0, 0x87, 0xC0,  0xF9, 0x08, 0x42, 0x10, 0x80,  0x8C, 0x63, 0x18, 0xC5, 0xC0,  0x8C, 0x63, 0x18, 0xA8, 0x80,  0x8C, 0x63, 0x5A, 0xD5, 0x40,  0x8C, 0x54, 0x45, 0x46, 0x20,  0x8C, 0x62, 0xA2, 0x10, 0x80,  0xF8, 0x44, 0x44, 0x43, 0xE0,  0x72, 0x10, 0x84, 0x21, 0xC0,
      0x8A, 0xBE, 0x4F, 0x90, 0x80,  0x70, 0x84, 0x21, 0x09, 0xC0,  0x22, 0xA2, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x03, 0xE0,  0x41, 0x04, 0x00, 0x00, 0x00,  0x00, 0x1C, 0x17, 0xC5, 0xE0,  0x84, 0x2D, 0x98, 0xC7, 0xC0,  0x00, 0x1D, 0x08, 0x45, 0xC0,  0x08, 0x5B, 0x38, 0xC5, 0xE0,  0x00, 0x1D, 0x1F, 0xC1, 0xC0,  0x32, 0x51, 0xC4, 0x21, 0x00,  0x03, 0xE3, 0x17, 0x85, 0xC0,  0x84, 0x2D, 0x98, 0xC6, 0x20,  0x20, 0x18, 0x42, 0x11, 0xC0,  0x10, 0x0C, 0x21, 0x49, 0x80,  0x84, 0x25, 0x4C, 0x52, 0x40,  0x61, 0x08, 0x42, 0x11, 0xC0,  0x00, 0x35, 0x5A, 0xC6, 0x20,  0x00, 0x2D, 0x98, 0xC6, 0x20,  0x00, 0x1D, 0x18, 0xC5, 0xC0,
      0x00, 0x3D, 0x1F, 0x42, 0x00,  0x00, 0x1B, 0x37, 0x84, 0x20,  0x00, 0x2D, 0x98, 0x42, 0x00,  0x00, 0x1D, 0x07, 0x07, 0xC0,  0x42, 0x38, 0x84, 0x24, 0xC0,  0x00, 0x23, 0x18, 0xCD, 0xA0,  0x00, 0x23, 0x18, 0xA8, 0x80,  0x00, 0x23, 0x1A, 0xD5, 0x40,  0x00, 0x22, 0xA2, 0x2A, 0x20,  0x00, 0x23, 0x17, 0x85, 0xC0,  0x00, 0x3E, 0x22, 0x23, 0xE0,  0x11, 0x08, 0x82, 0x10, 0x40,  0x21, 0x08, 0x42, 0x10, 0x80,  0x41, 0x08, 0x22, 0x11, 0x00,  0x00, 0x11, 0x51, 0x00, 0x00]

spi = SPI(0, baudrate=8000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(2), miso=Pin(4), mosi=Pin(3))
print(spi)
cs =  Pin(5, Pin.OUT)
dc =  Pin(14, Pin.OUT)
res = Pin(15, Pin.OUT)
led = Pin(25, Pin.OUT)

fig_color = 0
cxahar_color = 0
char_color_bg = 0
char_x = 0
char_y = 0
queue = [0, 0, 0, 0, 0]

def putPixel(color):
    writeData(color >> 8)
    writeData(color & 0xFF)

def setWindow(x, y, w, h):
    writeReg(0x2A)
    writeData(0x00)
    writeData(x)
    writeData(0x00)
    writeData(x + w - 1)

    writeReg(0x2B)
    writeData(0x00)
    writeData(y)
    writeData(0x00)
    writeData(y + h - 1)

    writeReg(0x2c)

def writeCharQueue():
    global char_x
    global char_y
    global char_color
    global char_color_bg

    setWindow(char_x, char_y, 5, 8);
    for i in range(5):
        for j in range(8):
            if ((queue[i] & (0x80 >> j)) > 0):
                putPixel(char_color)
            else:
                putPixel(char_color_bg)

    setWindow(char_x + 5, char_y, 1, 8);
    for i in range(8):
        putPixel(char_color_bg);

def setCharQueue(ch):
    global chars
    if ((ord(ch) >= 0x20) and (ord(ch) <= 0x7E)) :
        c = ord(ch) - 0x20
        for i in range(5) :
            queue[i] = chars[5 * c + i]
    else:
        for i in range(5) :
            queue[i] = 0xFF
    #print(str(queue))

def print_str(str):
    global char_x
    global char_y

    if (char_x > 235):
        char_x = 0
        char_y += 8

    if (char_y > 232):
        char_x = 0
        char_y = 0
    else :
        index = 0
        for item in str:
            setCharQueue(str[index])
            cs.value(0)
            writeCharQueue()
            char_x += 6
            cs.value(1)
            index += 1

def setCharPlace(x, y):
    global char_x
    global char_y
    char_x = x;
    char_y = y;

def setFigColor(r, g, b):
    global fig_color
    color = 0;
    color = b >> 3;
    color |= ((g & 0xFC) << 3)
    color |= ((r & 0xF8) << 8)
    fig_color = color
    #print('figcolor : ' + hex(fig_color))

def setCharColor(r, g, b):
    global char_color
    color = 0;
    color = b >> 3;
    color |= ((g & 0xFC) << 3)
    color |= ((r & 0xF8) << 8)
    char_color = color
    #print('char_color : ' + hex(char_color))

def setCharColorBG(r, g, b):
    global char_color_bg
    color = 0;
    color = b >> 3;
    color |= ((g & 0xFC) << 3)
    color |= ((r & 0xF8) << 8)
    char_color_bg = color
    #print('char_color_bg : ' + hex(char_color_bg))

def writeReg(reg):
    dc.value(0)
    buff = bytearray(1)
    buff[0] = reg
    spi.write(buff)
    #print('writeReg ' + hex(buff[0]))

def writeData(data):
    dc.value(1)
    buff = bytearray(1)
    buff[0] = data
    spi.write(buff)
    #print('writeData ' + hex(buff[0]))

def drawRectangle(x, y, w, h):
    global fig_color
    led.value(1)
    loop = w * h
    colorH = fig_color >> 8
    colorL = fig_color & 0x00FF
    
    #print('ColorH = ' + hex(colorH))
    #print('ColorL = ' + hex(colorL))
    #color  = 240
    #colorH = 255
    #colorL = 255
    cs.value(0)

# set window
    writeReg(0x2A)
    writeData(0x00)
    writeData(x)
    writeData(0x00)
    writeData(x + w - 1)

    writeReg(0x2B)
    writeData(0x00)
    writeData(y)
    writeData(0x00)
    writeData(y + h - 1)

    writeReg(0x2c);

    dc.value(1)

    for i in range(loop):
        buff = bytearray(1)
        buff[0] = colorH
        spi.write(buff)
        buff[0] = colorL
        spi.write(buff)
        #spi.write(hex(colorH))
        #spi.write(hex(colorL))
        #writeData(colorH)
        #writeData(colorL)
        #print(i)

    cs.value(1)
    led.value(0)
    print('draw finished')

def begin():
    cs.value(1)
    res.value(1)
    time.sleep(0.02)
    res.value(0)
    time.sleep(0.02)
    res.value(1)
    time.sleep(0.02)
    print('Reset')
    
    cs.value(0)
    led.value(1)

    writeReg(0x11)
    time.sleep(0.1)

    writeReg(0x36)
    writeData(0x00)

    writeReg(0x3A)
    writeData(0x55)

    ##--------------------------------ST7789V Frame rate

    writeReg(0xb2)
    writeData(0x0c)
    writeData(0x0c)
    writeData(0x00)
    writeData(0x33)
    writeData(0x33)

    time.sleep(0.002)

    writeReg(0xb7)
    writeData(0x75)

    time.sleep(0.002)

    ##---------------------------------ST7789V Power

    writeReg(0xc2)
    writeData(0x01)

    time.sleep(0.002)

    writeReg(0xc3)
    writeData(0x10)

    time.sleep(0.002)

    writeReg(0xc4)
    writeData(0x20)

    time.sleep(0.002)

    writeReg(0xc6)
    writeData(0x0f)

    writeReg(0xb0)
    writeData(0x00)
    writeData(0xf0); # RRRR RGGGG GGGB BBBB

    time.sleep(0.002)

    writeReg(0xD0)
    writeData(0xA4)
    writeData(0xA1)
    time.sleep(0.002)

    ## --------------------------------ST7789V gamma

    writeReg(0x21)

    time.sleep(0.002)

    writeReg(0xbb)
    writeData(0x3b)

    time.sleep(0.002)

    writeReg(0xE0)    # Set Gamma
    writeData(0xF0)
    writeData(0x0b)
    writeData(0x11)
    writeData(0x0e)
    writeData(0x0d)
    writeData(0x19)
    writeData(0x36)
    writeData(0x33)
    writeData(0x4b)
    writeData(0x07)
    writeData(0x14)
    writeData(0x14)
    writeData(0x2c)
    writeData(0x2e)

    time.sleep(0.002)

    writeReg(0xE1)   # Set Gamma
    writeData(0xF0)
    writeData(0x0d)
    writeData(0x12)
    writeData(0x0b)
    writeData(0x09)
    writeData(0x03)
    writeData(0x32)
    writeData(0x44)
    writeData(0x48)
    writeData(0x39)
    writeData(0x16)
    writeData(0x16)
    writeData(0x2d)
    writeData(0x30)

    writeReg(0x2A)
    writeData(0x00)
    writeData(0x00)
    writeData(0x00)
    writeData(0xEF)

    writeReg(0x2B)
    writeData(0x00)
    writeData(0x00)
    writeData(0x00)
    writeData(0xEF)

    writeReg(0x29)    # Display on

    time.sleep(0.002)
    writeReg(0x2c)

    cs.value(1)
    led.value(0)
    print('Init finished')

def colorBar():
    for i in range(8):
        g = 255 * (1 - ((i & 0x04) >> 2))
        r = 255 * (1 - ((i & 0x02) >> 1))
        b = 255 * (1 - ((i & 0x01)))
        setFigColor(r, g, b)
        drawRectangle(i * 30, 0, 30, 180)

    for i in range(240):
        setFigColor(i, i, i)
        drawRectangle(i, 180, 1, 60)

begin()
setFigColor(0, 0, 0)
drawRectangle(0, 0, 240, 240)
colorBar()

setCharPlace(0, 160)
setCharColor(0, 0, 0)
setCharColorBG(255, 255, 255)

print_str('https://mytoolbox.tech/tec')
Results
The execution result is shown below. The color bar and character string are displayed correctly.
Color bar

Connecting EEPROM

Next, let’s try to connect to serial EEPROM with SPI interface. The device used is the BR25L320 device manufactured by ROHM.(The picture below shows the device mounted on the pitch conversion board.)
BR25L320
Hardware connection
Below is the wiring between the I/O pins of the Raspberry Pi Pico and the BR25L320, including the SPI, power and GND pins, and the /WP and HOLD signals for write protection control.
Schematics

Connection

Software (Micro Python code)
from machine import Pin
from machine import SPI
import time

spi = SPI(0, baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(2), miso=Pin(4), mosi=Pin(3))
print(spi)
cs   = Pin(5, Pin.OUT)
wp   = Pin(0, Pin.OUT)
hold = Pin(1, Pin.OUT)

cs.value(1)
wp.value(0)
hold.value(0)

def enablewrite():
    cs.value(0)
    wp.value(1)
    hold.value(1)
    
    wen = bytearray(1)
    wen[0] = 0x06
    spi.write(wen)
    print("Write enabled(" + hex(wen[0]) + ").")
    
    cs.value(1)
    wp.value(0)
    hold.value(0)

def disablewrite():
    cs.value(0)
    wp.value(1)
    hold.value(1)
    
    wen = bytearray(1)
    wen[0] = 0x04
    spi.write(wen)
    print("Write disabled(" + hex(wen[0]) + ").")
    
    cs.value(1)
    wp.value(0)
    hold.value(0)

def writeData(addr, data):
    cs.value(0)
    wp.value(1)
    hold.value(1)
    
    buff = bytearray(4)
    buff[0] = 0x02
    buff[1] = (addr & 0xFF00) >> 8
    buff[2] = (addr & 0x00FF)
    buff[3] = (data & 0xFF)
    spi.write(buff)
    print("W : " + hex(buff[0]))
    print("W : " + hex(buff[1]))
    print("W : " + hex(buff[2]))
    print("W : " + hex(buff[3]))
    
    cs.value(1)
    wp.value(0)
    hold.value(0)
    

def readData(addr):
    cs.value(0)
    wp.value(1)
    hold.value(1)
    
    buff = bytearray(4)
    buff[0] = 0x03
    buff[1] = (addr & 0xFF00) >> 8
    buff[2] = (addr & 0x00FF)
    buff[3] = 0x00
    
    spi.write_readinto(buff, buff)
    print("R : " + hex(buff[3]))
    
    cs.value(1)
    wp.value(0)
    hold.value(0)

enablewrite()
writeData(0x0A1B, 0xAA)
disablewrite()
print("----------------")
readData(0x0A1B)
print("----------------")

Results
Results

The following are the waveforms for writing and reading.
Pulse View Waveform (Write Enable command issued)
Pulse View Waveform (Write)
Pulse View Waveform (Write Disable command issued)
Pulse View Waveform (Read)

References

Full Color LCD Control Kit using ATM0130B3 (JAPANESE site)
MicroPython Library Documentation (JAPANESE site)
BR25L320 Devices

Leave a Reply

Your email address will not be published. Required fields are marked *