Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions software/docs/source/commands/structs.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ Set of all available [low-level commands](./low_level_commands.md)
```

### Output Modes
```{eval-rst}
.. autoenum:: obi.commands.structs.OutputEnable
:members:
```

```{eval-rst}
.. autoenum:: obi.commands.structs.OutputMode
:members:
Expand Down
74 changes: 0 additions & 74 deletions software/frametest.py

This file was deleted.

64 changes: 37 additions & 27 deletions software/obi/applet/open_beam_interface/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
PipelinedLoopbackAdapter, BusController, FastBusController,
Supersampler, RasterScanner, CommandParser)

from glasgow.simulation.assembly import SimulationPipe

# Overview of (linear) processing pipeline:
# 1. PC software (in: user input, out: bytes)
# 2. Glasgow software/framework (in: bytes, out: same bytes; vendor-provided)
Expand Down Expand Up @@ -52,7 +54,7 @@ class CommandExecutor(wiring.Component):
blank_enable: Out(1, init=1)

#Input to Serializer
output_mode: Out(2)
output_mode: Out(OutputMode)


def __init__(self, *, out_only:bool=False, adc_latency=8, ext_delay_cyc=960000,
Expand Down Expand Up @@ -90,7 +92,7 @@ def elaborate(self, platform):
vector_stream = stream.Signature(DACStream).create()

raster_mode = Signal()
output_mode = Signal(2)
output_mode = Signal(OutputMode)
command = Signal.like(self.cmd_stream.payload)
with m.If(raster_mode):
wiring.connect(m, self.raster_scanner.dac_stream, self.supersampler.dac_stream)
Expand Down Expand Up @@ -223,21 +225,25 @@ def elaborate(self, platform):
m.d.comb += [
self.raster_scanner.dwell_stream.valid.eq(1),
self.raster_scanner.dwell_stream.payload.dwell_time.eq(command.payload.raster_pixel.dwell_time),
self.raster_scanner.dwell_stream.payload.output_en.eq(command.payload.raster_pixel.output_en),
self.raster_scanner.dwell_stream.payload.blank.eq(sync_blank)
]
with m.If(self.raster_scanner.dwell_stream.ready):
m.d.comb += submit_pixel.eq(1)
with m.If(command.payload.raster_pixel.output_en==OutputEnable.Enabled):
m.d.comb += submit_pixel.eq(1)
m.next = "Fetch"

with m.Case(CmdType.RasterPixelRun):
m.d.comb += raster_mode.eq(1)
m.d.comb += [
self.raster_scanner.dwell_stream.valid.eq(1),
self.raster_scanner.dwell_stream.payload.dwell_time.eq(command.payload.raster_pixel_run.dwell_time),
self.raster_scanner.dwell_stream.payload.output_en.eq(command.payload.raster_pixel_run.output_en),
self.raster_scanner.dwell_stream.payload.blank.eq(sync_blank)
]
with m.If(self.raster_scanner.dwell_stream.ready):
m.d.comb += submit_pixel.eq(1)
with m.If(command.payload.raster_pixel_run.output_en==OutputEnable.Enabled):
m.d.comb += submit_pixel.eq(1)
with m.If(run_length == command.payload.raster_pixel_run.length):
m.d.sync += run_length.eq(0)
m.next = "Fetch"
Expand All @@ -254,7 +260,8 @@ def elaborate(self, platform):
m.d.comb += [
self.raster_scanner.dwell_stream.valid.eq(1),
self.raster_scanner.dwell_stream.payload.dwell_time.eq(command.payload.raster_pixel_fill.dwell_time),
self.raster_scanner.dwell_stream.payload.blank.eq(sync_blank)
self.raster_scanner.dwell_stream.payload.blank.eq(sync_blank),
self.raster_scanner.dwell_stream.payload.output_en.eq(OutputEnable.Enabled),
]


Expand All @@ -263,7 +270,8 @@ def elaborate(self, platform):
m.d.comb += [
self.raster_scanner.roi_stream.payload.eq(raster_region),
self.raster_scanner.dwell_stream.payload.dwell_time.eq(command.payload.raster_pixel.dwell_time),
self.raster_scanner.dwell_stream.payload.blank.eq(sync_blank)
self.raster_scanner.dwell_stream.payload.blank.eq(sync_blank),
self.raster_scanner.dwell_stream.payload.output_en.eq(OutputEnable.Enabled),
]
with m.If(self.cmd_stream.valid):
m.d.comb += self.raster_scanner.abort.eq(1)
Expand All @@ -280,11 +288,15 @@ def elaborate(self, platform):

with m.Case(CmdType.VectorPixel, CmdType.VectorPixelMinDwell):
m.d.comb += vector_stream.valid.eq(1)
m.d.comb += vector_stream.payload.blank.eq(sync_blank)
m.d.comb += vector_stream.payload.delay.eq(inline_delay_counter)
m.d.comb += [
vector_stream.payload.blank.eq(sync_blank),
vector_stream.payload.output_en.eq(command.payload.vector_pixel.output_en),
vector_stream.payload.delay.eq(inline_delay_counter)
]
with m.If(vector_stream.ready):
m.d.sync += inline_delay_counter.eq(0)
m.d.comb += submit_pixel.eq(1)
with m.If(command.payload.vector_pixel.output_en==OutputEnable.Enabled):
m.d.comb += submit_pixel.eq(1)
m.next = "Fetch"

with m.FSM():
Expand Down Expand Up @@ -334,18 +346,15 @@ def elaborate(self, platform):

with m.FSM():
with m.State("High"):
with m.If(self.output_mode == OutputMode.NoOutput):
m.d.comb += self.img_stream.ready.eq(1) #consume and destroy image stream
with m.Else():
m.d.comb += self.usb_stream.payload.eq(self.img_stream.payload[8:16])
m.d.comb += self.usb_stream.valid.eq(self.img_stream.valid)
m.d.comb += self.img_stream.ready.eq(self.usb_stream.ready)
with m.If(self.output_mode == OutputMode.SixteenBit):
m.d.sync += low.eq(self.img_stream.payload[0:8])
with m.If(self.usb_stream.ready & self.img_stream.valid):
m.next = "Low"
with m.If(self.output_mode == OutputMode.EightBit):
m.next = "High"
m.d.comb += self.usb_stream.payload.eq(self.img_stream.payload[8:16])
m.d.comb += self.usb_stream.valid.eq(self.img_stream.valid)
m.d.comb += self.img_stream.ready.eq(self.usb_stream.ready)
with m.If(self.output_mode == OutputMode.SixteenBit):
m.d.sync += low.eq(self.img_stream.payload[0:8])
with m.If(self.usb_stream.ready & self.img_stream.valid):
m.next = "Low"
with m.If(self.output_mode == OutputMode.EightBit):
m.next = "High"

with m.State("Low"):
m.d.comb += self.usb_stream.payload.eq(low)
Expand Down Expand Up @@ -569,6 +578,7 @@ async def flush(self):
await self.pipe.flush()

async def readuntil(self, separator=b'\n', *, flush=True, max_count=False):
self._logger.debug("reading until %s", separator)
def find_sep(buffer, separator=b'\n', offset=0):
if buffer._chunk is None:
if not buffer._queue:
Expand Down Expand Up @@ -596,16 +606,17 @@ def find_sep(buffer, separator=b'\n', offset=0):

# Check if we now have enough data in the buffer for `separator` to fit.
if buflen >= seplen:
self._logger.debug("Looking for the separator in the buffer")
isep = find_sep(self.pipe._in_buffer, separator)
if isep != -1:
print(f"found {isep=}")
# `separator` is in the buffer. `isep` will be used later
# to retrieve the data.
break
else:
while len(self.pipe_in_buffer) < seplen:
print(f"{len(self.pipe._in_tasks)=}")
self._logger.debug("FIFO: need %d bytes", seplen - len(self.lower._in_buffer))
self._logger.debug("Need more data before we can look for the separator")
while len(self.pipe._in_buffer) < seplen:
self._logger.debug("FIFO: need %d bytes", seplen - len(self.pipe._in_buffer))
await self.pipe._in_tasks.wait_one()

async with self.pipe._in_pushback:
Expand Down Expand Up @@ -640,10 +651,9 @@ async def benchmark(self):
sync_cmd = SynchronizeCommand(cookie=123, output=OutputMode.EightBit, raster=True)
flush_cmd = FlushCommand()
await self.pipe.send(bytes(sync_cmd))
await self.pipe.send(bytes(flush_cmd))
await self.pipe.flush()
await self.pipe.recv(4)
print(f"got cookie!")
data = await self.pipe.recv(4)
print(f"got cookie!: {data.tobytes()[2:]}")
commands = bytearray()
print("generating block of commands...")
for _ in range(131072*16):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from amaranth.lib.wiring import In, Out, flipped
from amaranth.lib.fifo import SyncFIFOBuffered

from obi.applet.open_beam_interface.modules.structs import SuperDACStream, BusSignature, BlankRequest, Transforms
from obi.applet.open_beam_interface.modules.structs import SuperDACStream, BusSignature, BlankRequest, Transforms, OutputEnable

class SkidBuffer(wiring.Component):
def __init__(self, data_layout, *, depth):
Expand Down Expand Up @@ -139,7 +139,8 @@ def elaborate(self, platform):
# Transmit blanking state from input stream
m.d.comb += self.inline_blank.eq(self.dac_stream.payload.blank)
# Schedule ADC sample for these DAC codes to be output.
m.d.sync += accept_sample.eq(Cat(1, accept_sample))
with m.If(self.dac_stream.payload.output_en==OutputEnable.Enabled):
m.d.sync += accept_sample.eq(Cat(1, accept_sample))
# Carry over the flag for last sample [of averaging window] to the output.
m.d.sync += last_sample.eq(Cat(self.dac_stream.payload.last, last_sample))
with m.Else():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ def elaborate(self, platform):
m.d.comb += self.cmd_stream.payload.eq(self.command)
self.command_reg = Signal(Command)
array_length = Signal(16)
is_array_command = Signal()

self.is_started = Signal()

with m.FSM() as fsm:
m.d.comb += self.is_started.eq(fsm.ongoing("Type"))
def goto_first_deserialized_state(from_type=self.command.type):
Expand Down Expand Up @@ -58,10 +60,12 @@ def Deserialize(target, state, next_state):
with m.State("Submit"):
m.d.comb += self.command.eq(self.command_reg)
with m.If(self.command.type == CmdType.Array):
m.d.sync += self.command_reg.type.eq(self.command.payload.array.cmdtype)
m.d.sync += self.command_reg.as_value()[4:].eq(0)
# m.d.sync += self.command_reg.eq(self.command.payload.array.command)
m.d.sync += self.command_reg.type.eq(self.command.payload.array.command[4:8])
m.d.sync += self.command_reg.payload.as_value()[0:4].eq(self.command.payload.array.command[0:4])
m.d.sync += self.command_reg.payload.as_value()[8:].eq(self.command.payload.array.command[8:])
m.d.sync += array_length.eq(self.command.payload.array.array_length)
goto_first_deserialized_state(from_type=self.command.payload.array.cmdtype)
goto_first_deserialized_state(from_type=self.command.payload.array.command[4:8])
with m.Else():
with m.If(self.cmd_stream.ready):
m.d.comb += self.cmd_stream.valid.eq(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from amaranth.lib import data, stream, wiring
from amaranth.lib.wiring import In, Out, flipped

from obi.applet.open_beam_interface.modules.structs import RasterRegion, DACStream, DwellTime, BlankRequest
from obi.applet.open_beam_interface.modules.structs import RasterRegion, DACStream, DwellTime, BlankRequest, OutputEnable

class RasterScanner(wiring.Component):
"""
Expand All @@ -23,6 +23,7 @@ class RasterScanner(wiring.Component):
dwell_stream: In(stream.Signature(data.StructLayout({
"dwell_time": DwellTime,
"blank": BlankRequest,
"output_en": OutputEnable
})))

abort: In(1)
Expand All @@ -43,7 +44,8 @@ def elaborate(self, platform):
self.dac_stream.payload.dac_x_code.eq(x_accum >> self.FRAC_BITS),
self.dac_stream.payload.dac_y_code.eq(y_accum >> self.FRAC_BITS),
self.dac_stream.payload.dwell_time.eq(self.dwell_stream.payload.dwell_time),
self.dac_stream.payload.blank.eq(self.dwell_stream.payload.blank)
self.dac_stream.payload.blank.eq(self.dwell_stream.payload.blank),
self.dac_stream.payload.output_en.eq(self.dwell_stream.payload.output_en)
]

with m.FSM():
Expand Down
6 changes: 5 additions & 1 deletion software/obi/applet/open_beam_interface/modules/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

from dataclasses import dataclass

from obi.commands.structs import OutputEnable

class BlankRequest(data.Struct):
enable: 1
request: 1
Expand Down Expand Up @@ -32,6 +34,7 @@ class DACStream(data.Struct):
padding_x: 2
dwell_time: 16
blank: BlankRequest
output_en: OutputEnable
delay: 3


Expand All @@ -41,7 +44,8 @@ class SuperDACStream(data.Struct):
dac_y_code: 14
padding_y: 2
blank: BlankRequest
last: 1
output_en: OutputEnable
last: 1
delay: 3

class RasterRegion(data.Struct):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def elaborate(self, platform):
self.super_dac_stream.payload.dac_x_code.eq(self.dac_stream_data.dac_x_code),
self.super_dac_stream.payload.dac_y_code.eq(self.dac_stream_data.dac_y_code),
self.super_dac_stream.payload.blank.eq(self.dac_stream_data.blank),
self.super_dac_stream.payload.output_en.eq(self.dac_stream_data.output_en),
self.super_dac_stream.payload.delay.eq(self.dac_stream_data.delay),
last.eq(dwell_counter == self.dac_stream_data.dwell_time)
#self.super_dac_stream.payload.last.eq(dwell_counter == self.dac_stream_data.dwell_time),
Expand Down
Loading
Loading