rtl: add fomucaptouch

This is an untested block that will replace fomutouch.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-01-29 10:32:25 +08:00
parent 3844a9a84c
commit a67d13e925

151
hw/rtl/fomucaptouch.py Normal file
View File

@ -0,0 +1,151 @@
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,
]