from machine import Pin, SPI
import time
# ==========================================
# LCD CONNECTIONS
# ==========================================
# SPI communication
spi = SPI(
0,
baudrate=40000000,
polarity=0,
phase=0,
sck=Pin(18),
mosi=Pin(19)
)
# LCD control pins
cs = Pin(17, Pin.OUT)
rst = Pin(16, Pin.OUT)
dc = Pin(20, Pin.OUT)
# ==========================================
# LCD COMMAND FUNCTIONS
# ==========================================
def write_command(command):
dc.value(0)
cs.value(0)
spi.write(bytes([command]))
cs.value(1)
def write_data(data):
dc.value(1)
cs.value(0)
spi.write(bytes(data))
cs.value(1)
# ==========================================
# RESET LCD
# ==========================================
rst.value(0)
time.sleep(0.1)
rst.value(1)
time.sleep(0.1)
# ==========================================
# INITIALIZE ILI9341
# ==========================================
write_command(0x01) # Software reset
time.sleep(0.15)
write_command(0x11) # Sleep out
time.sleep(0.15)
# 16-bit RGB565 color mode
write_command(0x3A)
write_data([0x55])
# Set display orientation/color order.
write_command(0x36)
write_data([0x28])
# Turn display on
write_command(0x29)
print("LCD initialized!")
# ==========================================
# DRAW A SOLID COLOR
# ==========================================
def set_window(x0, y0, x1, y1):
# Tell the LCD which columns we want to draw in.
write_command(0x2A)
write_data([
x0 >> 8,
x0 & 0xFF,
x1 >> 8,
x1 & 0xFF
])
# Tell the LCD which rows we want to draw in.
write_command(0x2B)
write_data([
y0 >> 8,
y0 & 0xFF,
y1 >> 8,
y1 & 0xFF
])
# Tell the LCD we're about to send pixel colors.
write_command(0x2C)
def fill_screen(color):
# ILI9341 resolution is 320 wide × 240 tall.
set_window(0, 0, 319, 239)
# RGB565 uses two bytes per pixel.
high_byte = color >> 8
low_byte = color & 0xFF
pixel = bytes([high_byte, low_byte])
dc.value(1)
cs.value(0)
# Send one row at a time.
row = pixel * 320
for _ in range(240):
spi.write(row)
cs.value(1)
# RGB565 red
RED = 0xF800
def fill_rect(x, y, width, height, color):
# Select the rectangle we want to draw.
set_window(
x,
y,
x + width - 1,
y + height - 1
)
# Convert our RGB565 color into two bytes.
high_byte = color >> 8
low_byte = color & 0xFF
pixel = bytes([high_byte, low_byte])
dc.value(1)
cs.value(0)
# Create one horizontal row of pixels.
row = pixel * width
# Draw that row repeatedly to make the rectangle.
for _ in range(height):
spi.write(row)
cs.value(1)
# ==========================================
# TEST COLORS
# ==========================================
GREEN = 0x07E0
ORANGE = 0xFD20
BLUE = 0x001F
# ==========================================
# FIRST TURBINE GAUGE TEST
# ==========================================
BLACK = 0x0000
# Pretend the submarine currently needs
# about 60% turbine output.
target_turbine = 60
# Width of our gauge.
gauge_x = 20
gauge_y = 90
gauge_width = 280
gauge_height = 60
# Clear the screen.
fill_screen(BLACK)
# Draw the entire gauge orange first.
fill_rect(
gauge_x,
gauge_y,
gauge_width,
gauge_height,
ORANGE
)
# Give the recommended green area a temporary
# width of 20% of the entire gauge.
green_width_percent = 20
# Calculate where the green region starts.
green_start_percent = (
target_turbine - green_width_percent / 2
)
# Convert percentages into screen pixels.
green_x = int(
gauge_x
+ (green_start_percent / 100) * gauge_width
)
green_width = int(
(green_width_percent / 100) * gauge_width
)
# Draw the recommended region.
fill_rect(
green_x,
gauge_y,
green_width,
gauge_height,
GREEN
)
print("Target turbine:", target_turbine, "%")
# ==========================================
# MOVING TURBINE TARGET TEST
# ==========================================
while True:
# Pretend the submarine's electrical load
# changes over time.
for target_turbine in range(10, 91, 5):
# Clear ONLY the gauge area back to orange.
fill_rect(
gauge_x,
gauge_y,
gauge_width,
gauge_height,
ORANGE
)
# Calculate where the green region begins.
green_start_percent = (
target_turbine
- green_width_percent / 2
)
# Convert the percentage into pixels.
green_x = int(
gauge_x
+ (green_start_percent / 100)
* gauge_width
)
# Draw the green recommended region.
fill_rect(
green_x,
gauge_y,
green_width,
gauge_height,
GREEN
)
print(
"Required turbine:",
target_turbine,
"%"
)
time.sleep(0.5)
# Now simulate the submarine load decreasing.
for target_turbine in range(90, 9, -5):
fill_rect(
gauge_x,
gauge_y,
gauge_width,
gauge_height,
ORANGE
)
green_start_percent = (
target_turbine
- green_width_percent / 2
)
green_x = int(
gauge_x
+ (green_start_percent / 100)
* gauge_width
)
fill_rect(
green_x,
gauge_y,
green_width,
gauge_height,
GREEN
)
print(
"Required turbine:",
target_turbine,
"%"
)
time.sleep(0.5)