mirror of https://github.com/arendst/Tasmota.git
Berry drivers for PCA9535 (generic and in SenseCAP D1) (#22451)
This commit is contained in:
parent
3bc90175db
commit
a5c33eba5e
|
@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Support deep sleep (standby) for VL53L0X (#22441)
|
||||
- Support for MS5837 pressure and temperature sensor (#22376)
|
||||
- Berry add I2C read16/write16 supporting Little Endian (#22448)
|
||||
- Berry drivers for PCA9535 (generic and in SenseCAP D1)
|
||||
|
||||
### Breaking Changed
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/********************************************************************
|
||||
* Tasmota LVGL lv_signal_bars widget
|
||||
* Drivers for AXP192 and AXP202 I2C Solidified
|
||||
*******************************************************************/
|
||||
#include "solidify/solidified_i2c_axp192.h"
|
||||
#include "solidify/solidified_i2c_axp202.h"
|
||||
|
|
|
@ -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
|
|
@ -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()
|
Loading…
Reference in New Issue