1
0
Fork 0

drivers: cst816s: optimize for power saving and responsiveness

Signed-off-by: Fuji Pebri <pebri86@gmail.com>
[daniel@redfelineinja.org.uk: removed leading underscore from method
arguments, removed redundant state tracking, adopt i2c.writeto_mem]
Signed-off-by: Daniel Thompson <daniel@redfelineninja.org.uk>
This commit is contained in:
Fuji Pebri 2020-06-09 17:18:27 +07:00 committed by Daniel Thompson
parent acf318c122
commit df9d80f6f7
4 changed files with 61 additions and 35 deletions

View file

@ -81,7 +81,7 @@ try:
Signal(Pin('USB_PWR', Pin.IN), invert=True)) Signal(Pin('USB_PWR', Pin.IN), invert=True))
i2c = I2C(1, scl='I2C_SCL', sda='I2C_SDA') i2c = I2C(1, scl='I2C_SCL', sda='I2C_SDA')
accel = BMA421(i2c) accel = BMA421(i2c)
touch = CST816S(i2c) touch = CST816S(i2c, Pin('TP_INT', Pin.IN), Pin('TP_RST', Pin.OUT, value=0))
vibrator = Vibrator(Pin('MOTOR', Pin.OUT, value=0), active_low=True) vibrator = Vibrator(Pin('MOTOR', Pin.OUT, value=0), active_low=True)
# Release flash from deep power-down # Release flash from deep power-down

View file

@ -13,6 +13,7 @@ def print_exception(exc, file=sys.stdout):
sys.print_exception = print_exception sys.print_exception = print_exception
import draw565 import draw565
import array
from machine import I2C from machine import I2C
from machine import Pin from machine import Pin

View file

@ -6,6 +6,8 @@
""" """
import array import array
import time
from machine import Pin
class CST816S: class CST816S:
"""Hynitron CST816S I2C touch controller driver. """Hynitron CST816S I2C touch controller driver.
@ -13,15 +15,44 @@ class CST816S:
.. automethod:: __init__ .. automethod:: __init__
""" """
def __init__(self, bus): def __init__(self, bus, intr, rst):
"""Specify the bus used by the touch controller. """Specify the bus used by the touch controller.
:param machine.I2C bus: I2C bus for the CST816S. :param machine.I2C bus: I2C bus for the CST816S.
""" """
self.i2c = bus self.i2c = bus
self.tp_int = intr
self.tp_rst = rst
self.dbuf = bytearray(6) self.dbuf = bytearray(6)
self.event = array.array('H', (0, 0, 0)) self.event = array.array('H', (0, 0, 0))
self._reset()
self.tp_int.irq(trigger=Pin.IRQ_FALLING, handler=self.get_touch_data)
def _reset(self):
self.tp_rst.off()
time.sleep_ms(5)
self.tp_rst.on()
time.sleep_ms(50)
def get_touch_data(self, pin_obj):
"""Receive a touch event by interrupt.
Check for a pending touch event and, if an event is pending,
prepare it ready to go in the event queue.
"""
dbuf = self.dbuf
event = self.event
try:
self.i2c.readfrom_mem_into(21, 1, dbuf)
except OSError:
return None
event[0] = dbuf[0] # event
event[1] = ((dbuf[2] & 0xf) << 8) + dbuf[3] # x coord
event[2] = ((dbuf[4] & 0xf) << 8) + dbuf[5] # y coord
def get_event(self): def get_event(self):
"""Receive a touch event. """Receive a touch event.
@ -30,38 +61,32 @@ class CST816S:
:return: An event record if an event is received, None otherwise. :return: An event record if an event is received, None otherwise.
""" """
dbuf = self.dbuf if self.event[0] == 0:
event = self.event
# TODO: check the interrupt pin
try:
self.i2c.readfrom_mem_into(21, 1, dbuf)
except OSError:
return None return None
# Skip junk events return self.event
if dbuf[0] == 0:
return None
x = ((dbuf[2] & 0xf) << 8) + dbuf[3] def reset_touch_data(self):
y = ((dbuf[4] & 0xf) << 8) + dbuf[5] """Reset touch data.
swipe_start = dbuf[2] & 0x80
# Skip identical events... when the I2C interface comes alive Reset touch data, call this function after processing an event.
# we can still get back stale events """
if dbuf[0] == event[0] and x == event[1] and y == event[2] \ self.event[0] = 0
and not swipe_start:
return None
# This is a good event, lets save it def wake(self):
event[0] = dbuf[0] """Wake up touch controller chip.
event[1] = x
event[2] = y
# Do not forward swipe start events Just reset the chip in order to wake it up
if dbuf[2] & 0x80: """
event[0] = 0 self._reset()
return None
return event def sleep(self):
"""Put touch controller chip on sleep mode to save power.
"""
# Before we can sent the sleep command we have to reset the
# panel to get the I2C hardware running again...
self._reset()
self.i2c.writeto_mem(21, 0xa5, b'\x03')
# Ensure get_event() cannot return anything
self.event[0] = 0

View file

@ -232,6 +232,7 @@ class Manager():
self.switch(self.quick_ring[0]) self.switch(self.quick_ring[0])
self.app.sleep() self.app.sleep()
watch.display.poweroff() watch.display.poweroff()
watch.touch.sleep()
self._charging = watch.battery.charging() self._charging = watch.battery.charging()
self.sleep_at = None self.sleep_at = None
@ -241,9 +242,7 @@ class Manager():
watch.display.poweron() watch.display.poweron()
self.app.wake() self.app.wake()
watch.backlight.set(self._brightness) watch.backlight.set(self._brightness)
watch.touch.wake()
# Discard any pending touch events
_ = watch.touch.get_event()
self.keep_awake() self.keep_awake()
@ -277,6 +276,7 @@ class Manager():
self.navigate(event[0]) self.navigate(event[0])
elif event[0] == 5 and self.event_mask & EventMask.TOUCH: elif event[0] == 5 and self.event_mask & EventMask.TOUCH:
self.app.touch(event) self.app.touch(event)
watch.touch.reset_touch_data()
def _tick(self): def _tick(self):
"""Handle the system tick. """Handle the system tick.