Skip to content

Commit

Permalink
gateware: ApolloAdvertiser generates rising edges now
Browse files Browse the repository at this point in the history
Ditch the old UART transmitter approach.
  • Loading branch information
mndza committed Jun 3, 2024
1 parent 0ee9034 commit ee569fb
Showing 1 changed file with 19 additions and 23 deletions.
42 changes: 19 additions & 23 deletions apollo_fpga/gateware/advertiser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
""" Controllers for communicating with Apollo through the FPGA_ADV pin """

from amaranth import Elaboratable, Module, Signal, Mux
from amaranth_stdio.serial import AsyncSerialTX

from luna.gateware.usb.usb2.request import USBRequestHandler
from usb_protocol.types import USBRequestType, USBRequestRecipient
Expand All @@ -17,45 +16,42 @@ class ApolloAdvertiser(Elaboratable):
""" Gateware that implements a periodic announcement to Apollo using the FPGA_ADV pin.
Currently it is used to tell Apollo that the gateware wants to use the CONTROL port.
Apollo will keep the port switch connected to the FPGA after a reset as long as this
Apollo will keep the port switch connected to the FPGA after a reset as long as this
message is received periodically.
Once the port is lost, Apollo will ignore further messages until a specific vendor
Once the port is lost, Apollo will ignore further messages until a specific vendor
request is called.
I/O ports:
I: stop -- Advertisement messages are stopped if this line is asserted.
"""
def __init__(self):
self.stop = Signal()
def __init__(self, pad=None, clk_freq_hz=None):
self.pad = pad
self.clk_freq_hz = clk_freq_hz
self.stop = Signal()

def default_request_handler(self, if_number):
return ApolloAdvertiserRequestHandler(if_number, self.stop)

def elaborate(self, platform):
m = Module()

clk_freq = platform.DEFAULT_CLOCK_FREQUENCIES_MHZ["sync"] * 1e6
# Handle default values.
if self.pad is None:
self.pad = platform.request("int")
if self.clk_freq_hz is None:
self.clk_freq_hz = platform.DEFAULT_CLOCK_FREQUENCIES_MHZ["sync"] * 1e6

# Communication is done with a serial transmitter (unidirectional)
baudrate = 9600
divisor = int(clk_freq // baudrate)
fpga_adv = AsyncSerialTX(divisor=divisor, data_bits=8, parity="even")
m.submodules += fpga_adv

# Counter with 50ms period
period = int(clk_freq * 50e-3)
# Generate clock with 40ms period.
period = int(self.clk_freq_hz * 10e-3)
timer = Signal(range(period))
clk = Signal()
m.d.sync += timer.eq(Mux(timer == period-1, 0, timer+1))
with m.If((timer == 0) & (~self.stop)):
m.d.sync += clk.eq(~clk)

# Drive the FPGA_ADV pin with the generated clock signal.
m.d.comb += self.pad.o.eq(clk)

# Trigger announcement when the counter overflows
m.d.comb += [
fpga_adv.data .eq(ord('A')),
fpga_adv.ack .eq((timer == 0) & ~self.stop),
]

# Drive the FPGA_ADV pin with the serial transmitter
m.d.comb += platform.request("int").o.eq(fpga_adv.o)

return m


Expand Down

0 comments on commit ee569fb

Please sign in to comment.