Skip to content

Commit

Permalink
applet.interface.gpib_controller: new applet.
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Oct 20, 2023
1 parent 3d8902f commit 2486cea
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/archive
Submodule archive updated 27 files
+ G00059/ina233.pdf
+ G00060/APX811_812_Rev.2.pdf
+ G00061/CAT24M01-D_Rev.5.PDF
+ G00062/BL24C256A_1.91.pdf
+ G00063/DAC081C08x_SNAS449F_Revision_F.pdf
+ G00064/PCA6408A_Rev.1.pdf
+ G00065/sn74lvc1t45_SCES515L_Revision_L.pdf
+ G00066/tlv733p_SBVS320A_Revision_A.pdf
+ G00067/tpd3s0x4_SLVSCP4B_Revision_B.pdf
+ G00068/TPS731xx_SBVS034N_Revision_N.pdf
+ ...014A_CY7C68015A_CY7C68016A_EZ-USB_FX2LP_USB_MICROCONTROLLER_HIGH_SPEED_USB_PERIPHERAL_CONTROLLER_Rev.AC.pdf
+ G00070/iCE40-LP-HX-Family-Data-Sheet_Revision_3.6.pdf
+ G00071/ICETechnologyLibrary_Version_3.0.pdf
+ G00072/Lattice-PCB-Layout-Recommandations-BGA-Packages_Revision_4.4.pdf
+ G00073/iCE40-Programming-Configuration_Revision_3.2.pdf
+ G00074/iCE40-Hardware-Checklist_Revision_1.8.pdf
+ G00075/Lattice-Package-Diagrams_Revision_6.0.pdf
+ G00076/Memory-Usage-Guide-for-iCE40-Devices_Revision_1.7.pdf
+ G00077/iCE40-sysCLOCK-PLL-Design-Usage-Guide_Revision_1.2.pdf
+ G00078/Lattice-Solder-Reflow-Guide-for-Surface-Mount-Devices_Revision_4.2.pdf
+ G00079/Using_Differential_IOLVDS_Sub-LVDS_in_iCE40_Devices_Revision_1.5.pdf
+ G00080/EZ-USB_TECHNICAL_REFERENCE_MANUAL_Revision_G.pdf
+ G00081/ds055.pdf
+ G00082/ds056.pdf
+ G00083/Sensirion_Environmental_Sensor_Node_SEN5x_Datasheet.pdf
+ G00084/TNxxx - STUSB4500 NVM Description_V1.1.pdf
+ G00085/ieee-standard-for-higher-performance-protocol-for-the-standard-d.pdf
168 changes: 168 additions & 0 deletions software/glasgow/applet/interface/gpib_controller/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import logging
from amaranth import *
from amaranth.lib.cdc import FFSynchronizer
from amaranth.lib.wiring import Component, In, Out

from ....support.logging import *
from ... import *


# class GPIBDeviceBus(Component):
# # Data lines
# doe : In()
# do : In(8)
# di : Out(8)




# class GPIBControllerBus(Component):

# # Control lines
# eoi : In() # End or Identify
# dav : In() # Data Valid \
# nrfd : Out() # Not Ready For Data | Handshake bus
# ndac : Out() # No Data Accepted /
# ifc : Signal() # Interface Clear \
# srq : Signal() # Service Request | Management bus
# atn : Signal() # Attention /
# ren : Signal() # Remote Enable


# def __init__(self, pads):
# self.pads = pads

# # Data lines
# self.doe = Signal()
# self.do = Signal(8)
# self.di = Signal(8)

# # Control lines
# self.eoi = Signal() # End or Identify
# self.dav = Signal() # Data Valid \
# self.nrfd = Signal() # Not Ready For Data | Handshake bus
# self.ndac = Signal() # No Data Accepted /
# self.ifc = Signal() # Interface Clear \
# self.srq = Signal() # Service Request | Management bus
# self.atn = Signal() # Attention /
# self.ren = Signal() # Remote Enable

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

# m.d.comb += [
# # Data lines
# self.pads.dio_t.oe.eq(self.doe),
# self.pads.dio_t.o.eq(self.do),
# self.pads.dio_t.i.eq(self.di),

# # Control lines
# self.pads.eoi_t.oe.eq(1),
# self.pads.
# ]

# return m


class GPIBControllerSubtarget(Elaboratable):
def elaborate(self, platform):
m = Module()
return m


class GPIBControllerInterface:
def __init__(self, interface, logger):
self.lower = interface
self._logger = logger
self._level = logging.DEBUG if self._logger.name == __name__ else logging.TRACE

async def reset(self):
self._logger.debug("GPIB: reset")
await self.lower.reset()


class GPIBControllerApplet(GlasgowApplet):
logger = logging.getLogger(__name__)
help = "control, talk, and listen to devices on the GPIB (née HP-IB) instrumentation bus"
description = """
Control, talk, and listen to devices on the IEEE 488.1 bus, known as GPIB or HP-IB. This bus
is typically used to remotely control instrumentation, such as multimeters, oscilloscopes,
frequency generators, and so on, though it is also used for some historic computer peripherals.
The GPIB connector is wired as follows (front view of plug/cable side):
::
_______________________________________________________________________
\\ /
\\ DIO1 DIO2 DIO3 DIO4 EOI DAV NRFD NDAC IFC SRQ ATN Shld /
\\ 1 2 3 4 5 6 7 8 9 10 11 12 /
\\ 24 23 22 21 20 19 18 17 16 15 14 13 /
\\ GND GND GND GND GND GND GND REN DIO8 DIO7 DIO6 DIO5 /
\\___________________________________________________________/
With the default pin configuration for this applet, the device pins 1..16 should be wired to
the male GPIB connector pins in this sequence:
1, 2, 3, 4, 13, 14, 15, 16, 6, 7, 8, 9, 11, 5, 10, 17
"""
required_revision = "C0"

__pins = ("dav", "nrfd", "ndac", "ifc", "atn", "eoi", "srq", "ren")
__pin_sets = ("dio",)

@classmethod
def add_build_arguments(cls, parser, access):
super().add_build_arguments(parser, access)

# IEEE Std 488.1-2003 §7.1:
# Selection of a minimum set of interface functions from Clause 4 leads to the following
# minimum set of signal lines in order to be system compatible:
# a) DIO 1–7
# b) DAV, NRFD, NDAC
# c) IFC and ATN (unnecessary in systems without a controller)

# Required pins first.
access.add_pin_set_argument(parser, "dio", range(7, 9), default=8, required=True)
access.add_pin_argument(parser, "dav", default=True, required=True)
access.add_pin_argument(parser, "nrfd", default=True, required=True)
access.add_pin_argument(parser, "ndac", default=True, required=True)
# Non-required pins second.
access.add_pin_argument(parser, "ifc", default=True)
access.add_pin_argument(parser, "atn", default=True)
access.add_pin_argument(parser, "eoi", default=True)
access.add_pin_argument(parser, "srq", default=True)
access.add_pin_argument(parser, "ren", default=True)

def build(self, target, args):
self.mux_interface = iface = target.multiplexer.claim_interface(self, args)
iface.add_subtarget(GPIBControllerSubtarget(
pads=iface.get_pads(args, pins=self.__pins, pin_sets=self.__pin_sets),
out_fifo=iface.get_out_fifo(),
in_fifo=iface.get_in_fifo()
))

@classmethod
def add_run_arguments(cls, parser, access):
pass # None of the parameters are configurable.

async def run(self, device, args):
# Although running GPIB on 3.3 V would be in-spec, none of the devices likely to have it
# will use anything but 5 V, and so we don't need this to be configurable.
await device.set_voltage(args.port, 5.0)

iface = await device.demultiplexer.claim_interface(
self, self.mux_interface, args,
# Strictly speaking only NRFD, NDAC, and SRQ need to be pulled up; however there is no
# harm in enabling the built-in ~10k pullups on every line, and this can help avoid
# glitches in the complicated GPIB message coding state machines.
pull_high=self.__pins + self.__pin_sets)
gpib_iface = GPIBControllerInterface(iface, self.logger)
return gpib_iface


# -------------------------------------------------------------------------------------------------

class GPIBControllerAppletTestCase(GlasgowAppletTestCase, applet=GPIBControllerApplet):
@synthesis_test
def test_build(self):
self.assertBuilds()
1 change: 1 addition & 0 deletions software/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jtag-pinout = "glasgow.applet.interface.jtag_pinout:JTAGPinoutApplet"
jtag-probe = "glasgow.applet.interface.jtag_probe:JTAGProbeApplet"
jtag-openocd = "glasgow.applet.interface.jtag_openocd:JTAGOpenOCDApplet"
jtag-svf = "glasgow.applet.interface.jtag_svf:JTAGSVFApplet"
gpib-controller = "glasgow.applet.interface.gpib_controller:GPIBControllerApplet"
ps2-host = "glasgow.applet.interface.ps2_host:PS2HostApplet"
sbw-probe = "glasgow.applet.interface.sbw_probe:SpyBiWireProbeApplet"

Expand Down

0 comments on commit 2486cea

Please sign in to comment.