Skip to content

Commit

Permalink
SeedStudio SenseCAP D1
Browse files Browse the repository at this point in the history
  • Loading branch information
s-hadinger committed Nov 9, 2024
1 parent 47c05ed commit 0443e24
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 0 deletions.
82 changes: 82 additions & 0 deletions raw/esp32s3/SeedStudio-SenseCAP-D1/PCA9535.be
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#################################################################################
# Generic driver for PCA9535 - solidified
#
# I2C IO Expander, similar to PCA9557
# Datasheet: https://www.nxp.com/docs/en/data-sheet/PCA9535_PCA9535C.pdf
#
# This expander is used in SeedStudio SenseCAP D1
#################################################################################

#@ solidify:PCA9535
class PCA9535 : I2C_Driver
var last_read # time when last read (avoid reading too often)
var input_port # shadow of registers 0+1 with state of input registers
var output_port # shadow of registers 2+3 with known outputs
var inversion_port # shadow of registers 4+5 with input inversion
var config_port # shadow of registers 6+7 with Input/Output configurations

def init(address)
if (address == nil) address = 0x20 end # default address is 0x20
super(self).init("PCA9535", address)
self.last_read = 0
if self.wire
# if detected
self.read_all()
end
end

def read_all()
var now = tasmota.millis()
if (now - self.last_read > 10) # if last read was more than 10 ms in the past
self.input_port = self.read16LE(0x00)
self.output_port = self.read16LE(0x02)
self.inversion_port = self.read16LE(0x04)
self.config_port = self.read16LE(0x06)
self.last_read = tasmota.millis()
if tasmota.loglevel(4)
log(f"I2C: PCA9535 read input(0x{self.input_port:04X}) output(0x{self.output_port:04X}) inversion(0x{self.inversion_port:04X}) config(0x{self.config_port:04X})")
end
end
end

def config_all(v)
self.config_port = int(v)
self.write16LE(0x06, self.config_port)
end
# port: 0..15
# mode: 0=output 1=input
def config_gpio(port, mode)
self.read_all()
if (mode != 0 && mode != 1) raise "value_error", f"mode muste be 0 or 1" end
var config_new = self._bit_set_to(self.config_port, port, mode)
# write only if value changed
if config_new != self.config_port
self.config_all(config_new)
end
end

def read_gpio(port)
self.read_all()
return (self.input_port & (1 << port)) ? 1 : 0
end

def write_gpio(port, v)
self.read_all()
v = (v ? 1 : 0) # ensure we have only 0/1 as values
var output_new = self._bit_set_to(self.output_port, port, v)
if output_new != self.output_port
self.output_port = output_new
self.write16LE(0x02, self.output_port)
end
end

# inspired from https://stackoverflow.com/questions/47981/how-to-set-clear-and-toggle-a-single-bit
# num: int value
# n: bit to change
# x: value 0/1
static def _bit_set_to(num, n, x)
return (num & ~(1 << n)) | (x << n)
end
end

return PCA9535
42 changes: 42 additions & 0 deletions raw/esp32s3/SeedStudio-SenseCAP-D1/PCA9535_SenseCAP_D1.be
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#################################################################################
# Specialized driver for SeedStudio SenseCAP D1 display
#################################################################################

import PCA9535

class PCA9535_SenseCAP_D1 : PCA9535
def init()
super(self).init(0x20)

if self.wire
self.write_gpio(0x05, 1) # set IO0.5 (LCD_RESET) high
self.write_gpio(0x07, 1) # set IO0.7 (TOUCH_RESET) high
self.write_gpio(0x08, 1) # set IO1.0 (RP2040_RESET) high
self.config_gpio(0x05, 0) # configure IO0.5 (LCD_RESET) as output
self.config_gpio(0x07, 0) # configure IO0.7 (TOUCH_RESET) as output
self.config_gpio(0x08, 0) # configure IO1.0 (RP2040_RESET) as output
# reset display at boot
self.reset_display()
end
end

# hardware reset for the MCU RP2040
def reset_RP2040()
self.write_gpio(0x08, 0) # drive RESET Low
tasmota.delay(2) # the recommended delay is 1ms, we take some margin
self.write_gpio(0x08, 1) # drive RESET High
end

# reset both display and touch screen
def reset_display()
self.write_gpio(0x05, 0)
self.write_gpio(0x07, 0)
tasmota.delay(2)
self.write_gpio(0x05, 1)
self.write_gpio(0x07, 1)
tasmota.delay(50)
end

end

return PCA9535_SenseCAP_D1()
64 changes: 64 additions & 0 deletions raw/esp32s3/SeedStudio-SenseCAP-D1/display.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
:H,ST7701,480,480,16,RGB,18,17,16,21,45,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,6
:V,1,10,8,50,1,10,8,20,0
:S,2,1,1,0,40,20
:IS,41,48,-1,-1
FF,5,77,01,00,00,10
C0,2,3B,00
C1,2,0D,02
C2,2,31,05
C7,1,04
CD,1,08
B0,10,00,11,18,0E,11,06,07,08,07,22,04,12,0F,AA,31,18
B1,10,00,11,19,0E,12,07,08,08,08,22,04,11,11,A9,32,18
FF,5,77,01,00,00,11
B0,1,60
B1,1,32
B2,1,07
B3,1,80
B5,1,49
B7,1,85
B8,1,21
C1,1,78
C2,A1,78
E0,3,00,1B,02
E1,B,08,A0,00,00,07,A0,00,00,00,44,44
E2,C,11,11,44,44,ED,A0,00,00,EC,A0,00,00
E3,4,00,00,11,11
E4,2,44,44
E5,10,0A,E9,D8,A0,0C,EB,D8,A0,0E,ED,D8,A0,10,EF,D8,A0
E6,4,00,00,11,11
E7,2,44,44
E8,10,09,E8,D8,A0,0B,EA,D8,A0,0D,EC,D8,A0,0F,EE,D8,A0
EB,7,02,00,E4,E4,88,00,40
EC,2,3C,00
ED,10,AB,89,76,54,02,FF,FF,FF,FF,FF,FF,20,45,67,98,BA
36,1,10
FF,5,77,01,00,00,13
E1,1,E4
FF,5,77,01,00,00,00
21,0
3A,1,60
11,80
29,80
:B,120,02
:UTI,FT5x06,I2,48,-1,-1
RD A8
CP 11
RTF
RD A3
CP 64
RTF
RT
:UTT
RDM 00 16
MV 2 1
RT
:UTX
MV 3 2
SCL 480 -1
RT
:UTY
MV 5 2
SCL 480 -1
RT
#
2 changes: 2 additions & 0 deletions raw/esp32s3/SeedStudio-SenseCAP-D1/init.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Template {"NAME":"SenseCAP Indicator D1","GPIO":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11488,11520,0,6210,0,0,0,0,32,641,609,0,1,1,1,0,1,0,0],"FLAG":0,"BASE":1}
Module 0
1 change: 1 addition & 0 deletions raw/esp32s3/SeedStudio-SenseCAP-D1/preinit.be
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import PCA9535_SenseCAP_D1

0 comments on commit 0443e24

Please sign in to comment.