mirror of
https://github.com/im-tomu/foboot.git
synced 2024-09-20 02:40:09 +00:00
a67d13e925
This is an untested block that will replace fomutouch. Signed-off-by: Sean Cross <sean@xobs.io>
152 lines
6.7 KiB
Python
152 lines
6.7 KiB
Python
from migen import Module, TSTriple, Cat, Signal, If, wrap
|
|
from litex.soc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage, CSRField
|
|
from litex.soc.integration.doc import ModuleDoc
|
|
from litex.build.generic_platform import Pins, Subsignal
|
|
from litex.soc.interconnect import csr_eventmanager as ev
|
|
|
|
class CapTouchPads(Module, AutoCSR):
|
|
touch_device = [
|
|
("touch_pads", 0,
|
|
Subsignal("t1", Pins("touch_pins:0")),
|
|
Subsignal("t2", Pins("touch_pins:1")),
|
|
Subsignal("t3", Pins("touch_pins:2")),
|
|
Subsignal("t4", Pins("touch_pins:3")),
|
|
)
|
|
]
|
|
def __init__(self, pads, debugging=False):
|
|
self.intro = ModuleDoc("""Fomu Touchpads
|
|
|
|
Fomu has four single-ended exposed pads on its side. These pads are designed
|
|
to be connected to some captouch block, or driven in a resistive touch mode
|
|
in order to get simple touchpad support.
|
|
|
|
This block attempts to implement capacative touch, while still providing
|
|
backwards-compatibility with the original Fomu touchpad interface.
|
|
|
|
More research will need to be done in order to determine sane defaults for the
|
|
trigger levels.
|
|
""")
|
|
|
|
cap_signal_size = 8
|
|
|
|
touch1 = TSTriple()
|
|
touch2 = TSTriple()
|
|
touch3 = TSTriple()
|
|
touch4 = TSTriple()
|
|
self.specials += touch1.get_tristate(pads.t1)
|
|
self.specials += touch2.get_tristate(pads.t2)
|
|
self.specials += touch3.get_tristate(pads.t3)
|
|
self.specials += touch4.get_tristate(pads.t4)
|
|
ios = [touch1, touch2, touch3, touch4]
|
|
|
|
self.o = CSRStorage(4, description="Output values for pads 1-4", fields=[
|
|
CSRField("o1", description="Output value for pad 1"),
|
|
CSRField("o2", description="Output value for pad 2"),
|
|
CSRField("o3", description="Output value for pad 3"),
|
|
CSRField("o4", description="Output value for pad 4"),
|
|
])
|
|
self.oe = CSRStorage(4, description="Output enable control for pads 1-4", fields=[
|
|
CSRField("oe1", description="Output Enable value for pad 1"),
|
|
CSRField("oe2", description="Output Enable value for pad 2"),
|
|
CSRField("oe3", description="Output Enable value for pad 3"),
|
|
CSRField("oe4", description="Output Enable value for pad 4"),
|
|
])
|
|
self.i = CSRStatus(4, description="Input value for pads 1-4", fields=[
|
|
CSRField("i1", description="Input value for pad 1"),
|
|
CSRField("i2", description="Input value for pad 2"),
|
|
CSRField("i3", description="Input value for pad 3"),
|
|
CSRField("i4", description="Input value for pad 4"),
|
|
])
|
|
self.capen = CSRStorage(4, description="Enable captouch for pads 1-4", fields=[
|
|
CSRField("t1", description="Enable captouch for pad 1"),
|
|
CSRField("t2", description="Enable captouch for pad 2"),
|
|
CSRField("t3", description="Enable captouch for pad 3"),
|
|
CSRField("t4", description="Enable captouch for pad 4"),
|
|
])
|
|
|
|
cper = 524288
|
|
cap_count_len = 20
|
|
if debugging:
|
|
cap_count_len = 32
|
|
self.cper = CSRStorage(cap_count_len, description="""The number of clock cycles for one sample period
|
|
|
|
The hardware will count how many times the touchpad discharges within this sample
|
|
period and reflect that value in the corresponding `count` register.""", reset=524288)
|
|
cper = self.cper.storage
|
|
|
|
self.cstat = CSRStatus(4, description="Current status of the captouch buttons", fields=[
|
|
CSRField("s1", description="State of pad 1"),
|
|
CSRField("s2", description="State of pad 2"),
|
|
CSRField("s3", description="State of pad 3"),
|
|
CSRField("s4", description="State of pad 4"),
|
|
])
|
|
|
|
cpress = 0x0a
|
|
crel = 0x03
|
|
if debugging:
|
|
self.cpress = CSRStorage(cap_signal_size, reset=0x0a, description="Count threshold for triggering a ``press`` event")
|
|
cpress = self.cpress.storage
|
|
self.crel = CSRStorage(cap_signal_size, reset=0x03, description="Count threshold for triggering a ``release`` event")
|
|
crel = self.crel.storage
|
|
if debugging:
|
|
self.c1 = CSRStatus(cap_signal_size, description="Count of events for pad 1")
|
|
self.c2 = CSRStatus(cap_signal_size, description="Count of events for pad 2")
|
|
self.c3 = CSRStatus(cap_signal_size, description="Count of events for pad 3")
|
|
self.c4 = CSRStatus(cap_signal_size, description="Count of events for pad 4")
|
|
|
|
cap_count = Signal(cap_count_len)
|
|
cap1_count = Signal(cap_signal_size)
|
|
cap2_count = Signal(cap_signal_size)
|
|
cap3_count = Signal(cap_signal_size)
|
|
cap4_count = Signal(cap_signal_size)
|
|
|
|
self.submodules.ev = ev.EventManager()
|
|
self.ev.submodules.touch = ev.EventSourcePulse(name="touch", description="""
|
|
Indicates a touch event such as a "press" or "release" has occurred.""")
|
|
self.ev.finalize()
|
|
|
|
ar = []
|
|
syn = []
|
|
cmb = []
|
|
for num, pad in enumerate(ios, start=1):
|
|
print("touch{}".format(num))
|
|
if debugging:
|
|
exec("ar.append(self.c{}.status.eq(cap{}_count))".format(num, num))
|
|
exec("ar.append(cap{}_count.eq(0))".format(num))
|
|
|
|
# Implement a schmitt trigger in Verilog
|
|
# 1: Value is 1 and count > crel OR value is 0 and count > cpress
|
|
# 0: Value is 1 and count < crel OR value is 0 and count < cpress
|
|
exec("""ar.append(self.cstat.fields.s{}.eq(
|
|
(self.cstat.fields.s{} & wrap(cap{}_count > crel)) |
|
|
(~self.cstat.fields.s{} & wrap(cap{}_count > cpress))))""".format(num, num, num, num, num))
|
|
|
|
exec("cmb.append(pad.o.eq(self.o.fields.o{} | self.capen.fields.t{}))".format(num, num))
|
|
exec("cmb.append(self.i.fields.i{}.eq(pad.i))".format(num))
|
|
exec("syn.append(cap{}_count.eq(cap{}_count + (self.capen.fields.t{} & ~pad.i)))".format(num, num, num))
|
|
exec("syn.append(pad.oe.eq(self.oe.fields.oe{} | (self.capen.fields.t{} & ~pad.i)))".format(num, num))
|
|
|
|
# This is used to trigger an interrupt when this value changes
|
|
last_stat = Signal(4)
|
|
|
|
self.sync += [
|
|
self.ev.touch.trigger.eq(0),
|
|
|
|
last_stat.eq(self.cstat.status),
|
|
self.ev.touch.trigger.eq(self.cstat.status != last_stat),
|
|
|
|
*syn,
|
|
|
|
# Perform a captouch tick
|
|
If(cap_count > 0,
|
|
cap_count.eq(cap_count - 1),
|
|
).Else(
|
|
cap_count.eq(cper),
|
|
*ar,
|
|
),
|
|
]
|
|
|
|
self.comb += [
|
|
*cmb,
|
|
]
|