Skip to content

General improvements to help with init, touch, and comments #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 32 additions & 23 deletions adafruit_ra8875/ra8875.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import struct
import time

from digitalio import Direction
from adafruit_bus_device import spi_device
import adafruit_ra8875.registers as reg

Expand All @@ -45,7 +44,7 @@
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RA8875.git"


# pylint: disable-msg=invalid-name
# pylint: disable-msg=invalid-name, too-many-statements
def color565(r: int, g: int = 0, b: int = 0) -> int:
"""Convert red, green and blue values (0-255) into a 16-bit 565 encoding."""
try:
Expand Down Expand Up @@ -102,7 +101,7 @@ def __init__(
self.reset()
if self._read_reg(0) == 0x75:
return
self._adc_clk = reg.TPCR0_ADCCLK_DIV16
self._adc_clk = reg.TPCR0_ADCCLK_DIV4

# pylint: enable-msg=invalid-name,too-many-arguments

Expand All @@ -112,6 +111,7 @@ def init(self, start_on: bool = True) -> None:

:param bool start_on: (optional) If the display should start in an On State (default=True)
"""
hsync_finetune = 0
if self.width == 480 and self.height == 82:
self.vert_offset = 190

Expand All @@ -123,6 +123,7 @@ def init(self, start_on: bool = True) -> None:
vsync_nondisp = 32
vsync_start = 23
vsync_pw = 2
self._adc_clk = reg.TPCR0_ADCCLK_DIV16
elif self.width == 480 and self.height in (272, 128, 82):
pixclk = reg.PCSR_PDATL | reg.PCSR_4CLK
hsync_nondisp = 10
Expand All @@ -131,36 +132,41 @@ def init(self, start_on: bool = True) -> None:
vsync_nondisp = 3
vsync_start = 8
vsync_pw = 10
self._adc_clk = reg.TPCR0_ADCCLK_DIV4
else:
raise ValueError("An invalid display size was specified.")

self.pllinit()

self._write_reg(reg.SYSR, reg.SYSR_16BPP | reg.SYSR_MCU8)
self._write_reg(reg.PCSR, pixclk)
time.sleep(0.001)

# Horizontal settings registers
self._write_reg(reg.HDWR, self.width // 8 - 1)
self._write_reg(reg.HNDFTR, reg.HNDFTR_DE_HIGH)
self._write_reg(reg.HNDR, (hsync_nondisp - 2) // 8)
self._write_reg(reg.HNDFTR, reg.HNDFTR_DE_HIGH + hsync_finetune)
self._write_reg(reg.HNDR, (hsync_nondisp - hsync_finetune - 2) // 8)
self._write_reg(reg.HSTR, hsync_start // 8 - 1)
self._write_reg(reg.HPWR, reg.HPWR_LOW + hsync_pw // 8 - 1)
self._write_reg(reg.HPWR, reg.HPWR_LOW + (hsync_pw // 8 - 1))

# Vertical settings registers
self._write_reg16(reg.VDHR0, self.height - 1 + self.vert_offset)
self._write_reg16(reg.VDHR0, (self.height - 1 + self.vert_offset) & 0xFF)
self._write_reg16(reg.VDHR1, (self.height - 1 + self.vert_offset) >> 8)
self._write_reg16(reg.VNDR0, vsync_nondisp - 1)
self._write_reg16(reg.VNDR1, vsync_nondisp >> 8)
self._write_reg16(reg.VSTR0, vsync_start - 1)
self._write_reg16(reg.VSTR1, vsync_start >> 8)
self._write_reg(reg.VPWR, reg.VPWR_LOW + vsync_pw - 1)

# Set active window X
self._write_reg16(reg.HSAW0, 0)
self._write_reg16(reg.HEAW0, self.width - 1)
self._write_reg16(reg.HSAW1, 0)
self._write_reg16(reg.HEAW0, (self.width - 1) & 0xFF)
self._write_reg16(reg.HEAW1, (self.width - 1) >> 8)

# Set active window Y
self._write_reg16(reg.VSAW0, self.vert_offset)
self._write_reg16(reg.VEAW0, self.height - 1 + self.vert_offset)
self._write_reg16(reg.VSAW1, self.vert_offset)
self._write_reg16(reg.VEAW0, (self.height - 1 + self.vert_offset) & 0xFF)
self._write_reg16(reg.VEAW1, (self.height - 1 + self.vert_offset) >> 8)

# Clear the entire window
self._write_reg(reg.MCLR, reg.MCLR_START | reg.MCLR_FULL)
Expand Down Expand Up @@ -216,7 +222,7 @@ def _write_cmd(self, cmd: int) -> None:

def _write_data(self, data: int, raw: bool = False) -> None:
"""
Write a byte or push raw data out
Write a byte or push raw data out using the previously selected register

:param data: The byte to write to the register
:type data: byte or bytearray
Expand Down Expand Up @@ -341,9 +347,8 @@ def touch_init(
:param bool enable: Enable the Touch Functionality as well
"""
if tpin is not None:
tpin.direction = Direction.INPUT
tpin.switch_to_input()
self._tpin = tpin
self._write_reg(reg.INTC2, reg.INTC2_TP)
self.touch_enable(enable)

def touch_enable(self, touch_on: bool) -> None:
Expand All @@ -356,12 +361,13 @@ def touch_enable(self, touch_on: bool) -> None:
self._write_reg(
reg.TPCR0,
reg.TPCR0_ENABLE
| reg.TPCR0_WAIT_4096CLK
| reg.WAITTIME_LUT[self._adc_clk]
| reg.TPCR0_WAKEENABLE
| self._adc_clk,
)
self._write_reg(reg.TPCR1, reg.TPCR1_AUTO | reg.TPCR1_DEBOUNCE)
self._write_data(self._read_reg(reg.INTC1) | reg.INTC1_TP)
self._gfx_mode()
else:
self._write_data(self._read_reg(reg.INTC1) & ~reg.INTC1_TP)
self._write_reg(reg.TPCR0, reg.TPCR0_DISABLE)
Expand All @@ -375,9 +381,12 @@ def touched(self) -> bool:
:rtype: bool
"""
if self._tpin is not None:
self._gfx_mode() # Hack that seems to work
# Hardware interrupt only works in graphics mode
self._gfx_mode()
if self._tpin.value:
return False

# Read the Interrupt Flag
istouched = self._read_reg(reg.INTC2) & reg.INTC2_TP
return istouched

Expand All @@ -388,13 +397,13 @@ def touch_read(self) -> Tuple[int, int]:
:return: The coordinate of the detected touch
:rtype: tuple[int, int]
"""
touch_x = self._read_reg(reg.TPXH)
touch_y = self._read_reg(reg.TPYH)
temp = self._read_reg(reg.TPXYL)
touch_x = touch_x << 2
touch_y = touch_y << 2
touch_x |= temp & 0x03
touch_y |= (temp >> 2) & 0x03
# Read the Touch Coordinates
touch_x_high_bits = self._read_reg(reg.TPXH)
touch_y_high_bits = self._read_reg(reg.TPYH)
touch_xy_low_bits = self._read_reg(reg.TPXYL)
touch_x = touch_x_high_bits << 2 | touch_xy_low_bits & 0x03
touch_y = touch_y_high_bits << 2 | (touch_xy_low_bits >> 2) & 0x03
# Clear the Interrupt Flag
self._write_reg(reg.INTC2, reg.INTC2_TP)
return [touch_x, touch_y]

Expand Down
27 changes: 27 additions & 0 deletions adafruit_ra8875/registers.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@
HPWR_HIGH = 0x80

VDHR0 = 0x19
VDHR1 = 0x1A
VNDR0 = 0x1B
VNDR1 = 0x1C
VSTR0 = 0x1D
VSTR1 = 0x1E
VPWR = 0x1F
VPWR_LOW = 0x00
VPWR_HIGH = 0x80
Expand All @@ -70,10 +73,14 @@
FNCR1 = 0x22

HSAW0 = 0x30
HSAW1 = 0x31
VSAW0 = 0x32
VSAW1 = 0x33

HEAW0 = 0x34
HEAW1 = 0x35
VEAW0 = 0x36
VEAW1 = 0x37

MCLR = 0x8E
MCLR_START = 0x80
Expand Down Expand Up @@ -125,11 +132,22 @@
TPCR0 = 0x70
TPCR0_ENABLE = 0x80
TPCR0_DISABLE = 0x00
TPCR0_WAIT_512CLK = 0x00
TPCR0_WAIT_1024CLK = 0x10
TPCR0_WAIT_2048CLK = 0x20
TPCR0_WAIT_4096CLK = 0x30
TPCR0_WAIT_8192CLK = 0x40
TPCR0_WAIT_16384CLK = 0x50
TPCR0_WAIT_32768CLK = 0x60
TPCR0_WAIT_65536CLK = 0x70
TPCR0_WAKEENABLE = 0x08
TPCR0_WAKEDISABLE = 0x00
TPCR0_ADCCLK_DIV4 = 0x02
TPCR0_ADCCLK_DIV8 = 0x03
TPCR0_ADCCLK_DIV16 = 0x04
TPCR0_ADCCLK_DIV32 = 0x05
TPCR0_ADCCLK_DIV64 = 0x06
TPCR0_ADCCLK_DIV128 = 0x07

TPCR1 = 0x71
TPCR1_AUTO = 0x00
Expand All @@ -152,3 +170,12 @@
INTC2_DMA = 0x08
INTC2_TP = 0x04
INTC2_BTE = 0x02

WAITTIME_LUT = {
TPCR0_ADCCLK_DIV4: TPCR0_WAIT_512CLK,
TPCR0_ADCCLK_DIV8: TPCR0_WAIT_1024CLK,
TPCR0_ADCCLK_DIV16: TPCR0_WAIT_2048CLK,
TPCR0_ADCCLK_DIV32: TPCR0_WAIT_4096CLK,
TPCR0_ADCCLK_DIV64: TPCR0_WAIT_8192CLK,
TPCR0_ADCCLK_DIV128: TPCR0_WAIT_16384CLK,
}
10 changes: 0 additions & 10 deletions examples/ra8875_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,3 @@
display.fill_circle(
int(coords[0] / x_scale), int(coords[1] / y_scale), 4, MAGENTA
)
display.txt_color(WHITE, BLACK)
display.txt_set_cursor(display.width // 2 - 220, display.height // 2 - 20)
display.txt_size(2)
display.txt_write(
"Position ("
+ str(int(coords[0] / x_scale))
+ ", "
+ str(int(coords[1] / y_scale))
+ ")"
)