Adafruit_Learning_System_Gu.../OV5640_Breakout/CircuitPython_Kaluga-jpeg/code.py

151 lines
4.5 KiB
Python

# SPDX-FileCopyrightText: Copyright (c) 2023 Jeff Epler for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
This demo is designed for the Kaluga development kit version 1.3 with the
ILI9341 display. It requires CircuitPython 8.
This demo needs reserved psram properly configured in settings.toml:
CIRCUITPY_RESERVED_PSRAM=1048576
This example also requires an SD card breakout wired as follows:
* IO18: SD Clock Input
* IO17: SD Serial Output (MISO)
* IO14: SD Serial Input (MOSI)
* IO12: SD Chip Select
Insert a CircuitPython-compatible SD card before powering on the Kaluga.
Press the "BOOT" button to take a photo in BMP format.
"""
import os
import ssl
import struct
import board
import busio
import displayio
import espcamera
import espidf
import keypad
import sdcardio
import socketpool
import storage
print("Initializing display")
displayio.release_displays()
spi = busio.SPI(MOSI=board.LCD_MOSI, clock=board.LCD_CLK)
display_bus = displayio.FourWire(
spi,
command=board.LCD_D_C,
chip_select=board.LCD_CS,
reset=board.LCD_RST,
baudrate=80_000_000,
)
_INIT_SEQUENCE = (
b"\x01\x80\x80" # Software reset then delay 0x80 (128ms)
b"\xEF\x03\x03\x80\x02"
b"\xCF\x03\x00\xC1\x30"
b"\xED\x04\x64\x03\x12\x81"
b"\xE8\x03\x85\x00\x78"
b"\xCB\x05\x39\x2C\x00\x34\x02"
b"\xF7\x01\x20"
b"\xEA\x02\x00\x00"
b"\xc0\x01\x23" # Power control VRH[5:0]
b"\xc1\x01\x10" # Power control SAP[2:0];BT[3:0]
b"\xc5\x02\x3e\x28" # VCM control
b"\xc7\x01\x86" # VCM control2
b"\x36\x01\x40" # Memory Access Control
b"\x37\x01\x00" # Vertical scroll zero
b"\x3a\x01\x55" # COLMOD: Pixel Format Set
b"\xb1\x02\x00\x18" # Frame Rate Control (In Normal Mode/Full Colors)
b"\xb6\x03\x08\x82\x27" # Display Function Control
b"\xF2\x01\x00" # 3Gamma Function Disable
b"\x26\x01\x01" # Gamma curve selected
b"\xe0\x0f\x0F\x31\x2B\x0C\x0E\x08\x4E\xF1\x37\x07\x10\x03\x0E\x09\x00" # Set Gamma
b"\xe1\x0f\x00\x0E\x14\x03\x11\x07\x31\xC1\x48\x08\x0F\x0C\x31\x36\x0F" # Set Gamma
b"\x11\x80\x78" # Exit Sleep then delay 0x78 (120ms)
b"\x29\x80\x78" # Display on then delay 0x78 (120ms)
)
display = displayio.Display(display_bus, _INIT_SEQUENCE, width=320, height=240)
if espidf.get_reserved_psram() < 1047586:
print("""Place the following line in CIRCUITPY/settings.toml, then hard-reset the board:
```
CIRCUITPY_RESERVED_PSRAM=1048576
```
""")
raise SystemExit
print("Initializing SD card")
sd_spi = busio.SPI(clock=board.IO18, MOSI=board.IO14, MISO=board.IO17)
sd_cs = board.IO12
sdcard = sdcardio.SDCard(sd_spi, sd_cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")
print("Initializing camera")
cam = espcamera.Camera(
data_pins=board.CAMERA_DATA,
external_clock_pin=board.CAMERA_XCLK,
pixel_clock_pin=board.CAMERA_PCLK,
vsync_pin=board.CAMERA_VSYNC,
href_pin=board.CAMERA_HREF,
pixel_format=espcamera.PixelFormat.RGB565,
frame_size=espcamera.FrameSize.QVGA,
i2c=board.I2C(),
external_clock_frequency=20_000_000,
framebuffer_count=1)
print("initialized")
display.auto_refresh = False
def exists(filename):
try:
os.stat(filename)
return True
except OSError:
return False
_image_counter = 0
def open_next_image(extension="jpg"):
global _image_counter # pylint: disable=global-statement
while True:
filename = f"/sd/img{_image_counter:04d}.{extension}"
_image_counter += 1
if exists(filename):
continue
print("#", filename)
return open(filename, "wb") # pylint: disable=consider-using-with
ow = (display.width - cam.width) // 2
oh = (display.height - cam.height) // 2
k = keypad.Keys([board.IO0], value_when_pressed=False)
while True:
frame = cam.take(1)
display_bus.send(42, struct.pack(">hh", ow, cam.width + ow - 1))
display_bus.send(43, struct.pack(">hh", oh, cam.height + ow - 1))
display_bus.send(44, frame)
if (e := k.events.get()) is not None and e.pressed:
cam.reconfigure(
pixel_format=espcamera.PixelFormat.JPEG,
frame_size=espcamera.FrameSize.SVGA,
)
frame = cam.take(1)
if isinstance(frame, memoryview):
jpeg = frame
print(f"Captured {len(jpeg)} bytes of jpeg data")
with open_next_image() as f:
f.write(jpeg)
cam.reconfigure(
pixel_format=espcamera.PixelFormat.RGB565,
frame_size=espcamera.FrameSize.QVGA,
)