# SPDX-FileCopyrightText: Copyright (c) 2023 Lady Ada for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

"""Capture an images from the camera and display on a ST7789 with
displayio.

This demo is designed to run on the Raspberry Pi Pico, but you can adapt it
to other boards by changing the constructors for `bus` and `cam`
appropriately.

Remember to take the lens cap off!
"""

import time

import board
import busio
import digitalio
from adafruit_ov7670 import OV7670, OV7670_SIZE_DIV1, OV7670_SIZE_DIV16
from adafruit_st7789 import ST7789
from displayio import (
    Bitmap,
    ColorConverter,
    Colorspace,
    FourWire,
    Group,
    TileGrid,
    release_displays,
)

# Set up the display (You must customize this block for your display!)
release_displays()
spi = busio.SPI(clock=board.GP2, MOSI=board.GP3)
display_bus = FourWire(spi, command=board.GP0, chip_select=board.GP1, reset=None)
display = ST7789(display_bus, width=240, height=240, rowstart=80, rotation=270)


# Ensure the camera is shut down, so that it releases the SDA/SCL lines,
# then create the configuration I2C bus

with digitalio.DigitalInOut(board.GP10) as reset:
    reset.switch_to_output(False)
    time.sleep(0.001)
    bus = busio.I2C(board.GP9, board.GP8)

# Set up the camera (you must customize this for your board!)
cam = OV7670(
    bus,
    data0=board.GP12,  # [16]     [org]
    clock=board.GP11,  # [15]     [blk]
    vsync=board.GP7,  # [10]     [brn]
    href=board.GP21,  # [27/o14] [red]
    mclk=board.GP20,  # [16/o15]
    shutdown=None,
    reset=board.GP10,
)  # [14]

width = display.width
height = display.height

# cam.test_pattern = OV7670_TEST_PATTERN_COLOR_BAR_FADE
bitmap = None
# Select the biggest size for which we can allocate a bitmap successfully, and
# which is not bigger than the display
for size in range(OV7670_SIZE_DIV1, OV7670_SIZE_DIV16 + 1):
    cam.size = size
    if cam.width > width:
        continue
    if cam.height > height:
        continue
    try:
        bitmap = Bitmap(cam.width, cam.height, 65535)
        break
    except MemoryError:
        continue

print(width, height, cam.width, cam.height)
if bitmap is None:
    raise SystemExit("Could not allocate a bitmap")

g = Group(scale=1, x=(width - cam.width) // 2, y=(height - cam.height) // 2)
tg = TileGrid(bitmap, pixel_shader=ColorConverter(input_colorspace=Colorspace.RGB565_SWAPPED))
g.append(tg)
display.root_group = g

t0 = time.monotonic_ns()
display.auto_refresh = False
while True:
    cam.capture(bitmap)
    bitmap.dirty()
    display.refresh(minimum_frames_per_second=0)
    t1 = time.monotonic_ns()
    print("fps", 1e9 / (t1 - t0))
    t0 = t1
