recipes/rc2014/sdcard: make spi relay design multi-devices
Also, fix the SPI relay driver to properly AND-away the result of the CTL read. Tested with a real prototype, works fine.
This commit is contained in:
parent
7dc00179f7
commit
495d2819d2
2
blk/596
2
blk/596
@ -2,7 +2,7 @@ CODE (spix) ( n -- n )
|
||||
HL POP, chkPS, A L LDrr,
|
||||
SPI_DATA OUTiA,
|
||||
( wait until xchg is done )
|
||||
BEGIN, SPI_CTL INAi, A ORr, JRNZ, AGAIN,
|
||||
BEGIN, SPI_CTL INAi, 1 ANDi, JRNZ, AGAIN,
|
||||
SPI_DATA INAi,
|
||||
L A LDrr,
|
||||
HL PUSH,
|
||||
|
@ -1,12 +1,5 @@
|
||||
# Accessing a MicroSD card
|
||||
|
||||
Warning: this recipe is temporarily broken. The schema below hasn't yet been
|
||||
updated to work with the new SPI relay protocol. If you've already built an
|
||||
old design, use an earlier commit or work around it in the SPI driver it should
|
||||
only be a matter of testing the input value for zero-ness to decide whether we
|
||||
ping the CSLOW or CSHIGH port. If you haven't, wait a little bit before building
|
||||
one: the upcoming design is better.
|
||||
|
||||
SD cards are great because they are accessible directly. No supporting IC is
|
||||
necessary. The easiest way to access them is through the SPI protocol.
|
||||
|
||||
@ -25,57 +18,57 @@ subsystem (B420) to drive a SD card.
|
||||
* A proto board + header pins with 39 positions so we can make a RC2014 card.
|
||||
* Diodes, resistors and stuff
|
||||
* 40106 (Inverter gates)
|
||||
* 4011 (NAND gates)
|
||||
* 74xx139 (Decoder)
|
||||
* 74xx138 (Decoder)
|
||||
* 74xx375 (Latches)
|
||||
* 74xx125 (Buffer)
|
||||
* 74xx161 (Binary counter)
|
||||
* 74xx165 (Parallel input shift register)
|
||||
* 74xx595 (Shift register)
|
||||
|
||||
## Building the SPI relay
|
||||
|
||||
The [schematic][schematic] supplied with this recipe works well with the SD
|
||||
Card subsystem (B420). Of course, it's not the only possible design that
|
||||
works, but I think it's one of the most straighforwards.
|
||||
![SPI relay](spirelay.jpg)
|
||||
|
||||
The basic idea with this relay is to have one shift register used as input,
|
||||
loaded in parallel mode from the z80 bus and a shift register that takes the
|
||||
serial input from `MISO` and has its output wired to the z80 bus.
|
||||
The schematic above works well with the SD Card subsystem (B420). Of course,
|
||||
it's not the only possible design that works, but I think it's one of the most
|
||||
straighforwards.
|
||||
|
||||
These two shift registers are clocked by a binary counter that clocks exactly
|
||||
8 times whenever a write operation on port `4` occurs. Those 8 clocks send
|
||||
data we've just received in the `74xx165` into `MOSI` and get `MISO` into the
|
||||
`74xx595`.
|
||||
This relay communicates through the z80 bus with 2 ports, `DATA` and `CTL` and
|
||||
allows up to 4 devices to be connected to it at once, although only one device
|
||||
can ever be active at once. This schema only has 2 (and the real prototype I've
|
||||
built from it), but the '375 has room for 4. In this schema, `DATA` is port 4,
|
||||
`CTL` is port `5`.
|
||||
|
||||
The `74xx139` then takes care of activating the right ICs on the right
|
||||
combinations of `IORQ/WR/RD/Axx`.
|
||||
We activate a device by sending a bitmask to `CTL`, this will end up in the
|
||||
'375 latches and activate the `SS` pin of one of the device, or deactivate them
|
||||
all if `0` is sent.
|
||||
|
||||
The rest of the ICs is fluff around this all.
|
||||
You then initiate a SPI exchange by sending a byte to send to the `DATA` port.
|
||||
This byte will end up in the '165 and the '161 counter will be activated,
|
||||
triggering a clock for the SPI exchange. At each clock, a bit is sent to `MOSI`
|
||||
from the '161 and received from `MISO` into the '595, which is the byte sent to
|
||||
the z80 bus when we read from `DATA`.
|
||||
|
||||
My first idea was to implement the relay with an AVR microcontroller to
|
||||
minimize the number of ICs, but it's too slow. We have to be able to respond
|
||||
within 300ns! Following that, it became necessary to add a 595 and a 165, but
|
||||
if we're going to add that, why not go the extra mile and get rid of the
|
||||
microcontroller?
|
||||
When the '161 is wired to the system clock, as it is in the schema, two `NOP`s
|
||||
are a sufficient delay between your `DATA` write and subsequent `DATA` read.
|
||||
|
||||
To that end, I was heavily inspired by [this design][inspiration].
|
||||
However, if you build yourself some kind of clock override and run the '161 at
|
||||
something slower than the system clock, those 2 `NOP`s will be too quick. That's
|
||||
where that '125 comes into play. When reading `CTL`, it spits `RUNNING` into
|
||||
`D0`. This allows you to know when the result of the SPI exchange is ready to be
|
||||
fetched. Make sure you `AND` away other bits, because they'll be garbage.
|
||||
|
||||
This board uses port `4` for SPI data, port `5` to pull `CS` low and port `6`
|
||||
to pull it high. Port `7` is unused but monopolized by the card.
|
||||
The '138 is to determine our current IORQ mode (`DATA`/`CTL` and `WR/RO`), the
|
||||
'106 is to provide for those `NOT`s sprinkled around.
|
||||
|
||||
Advice 1: If you make your own design, double check propagation delays!
|
||||
Some NAND gates, such as the 4093, are too slow to properly respond within
|
||||
a 300ns limit. For example, in my own prototype, I use a 4093 because that's
|
||||
what I have in inventory. For the `CS` flip-flop, the propagation delay doesn't
|
||||
matter. However, it *does* matter for the `SELECT` line, so I don't follow my
|
||||
own schematic with regards to the `M1` and `A2` lines and use two inverters
|
||||
instead.
|
||||
Please note that this design is inspired by [this design][inspiration].
|
||||
|
||||
Advice 2: Make `SCK` polarity configurable at all 3 endpoints (the 595, the 165
|
||||
Advice 1: Make `SCK` polarity configurable at all 3 endpoints (the 595, the 165
|
||||
and SPI connector). Those jumpers will be useful when you need to mess with
|
||||
polarity in your many tinkering sessions to come.
|
||||
|
||||
Advice 3: Make input `CLK` override-able. SD cards are plenty fast enough for us
|
||||
to use the system clock, but you might want to interact with devices that
|
||||
Advice 2: Make input `CLK` override-able. SD cards are plenty fast enough for
|
||||
us to use the system clock, but you might want to interact with devices that
|
||||
require a slower clock.
|
||||
|
||||
## Building your binary
|
||||
@ -85,15 +78,14 @@ assemble a binary with those drivers. To do so, you'll modify the xcomp unit
|
||||
of the base recipe. Look at `xcomp.fs`, you'll see that we load a block. That's
|
||||
our xcomp block (likely, B599). Open it.
|
||||
|
||||
First, we need drivers for the SPI relay. This is done by declaring `SPI_DATA`,
|
||||
`SPI_CSLOW` and `SPI_CSHIGH`, which are respectively `4`, `5` and `6` in our
|
||||
relay design. We also need to define SPI_DELAY, which we keep to 2 NOPs because
|
||||
we use the system clock:
|
||||
First, we need drivers for the SPI relay. This is done by declaring `SPI_DATA`
|
||||
and `SPI_CTL`, which are respectively `4` and `5` in our relay design.
|
||||
|
||||
: SPI_DELAY NOP, NOP, ;
|
||||
You also need to tell the SDC subsystem which SPI device to activate by defining
|
||||
the `SDC_DEVID` (1, 2, 4, 8 for device 0, 1, 2 or 3)
|
||||
|
||||
You can then load the driver with `596 LOAD`. This driver provides
|
||||
`(spix)`, `(spie)` and `(spid)` which are then used in the SDC driver.
|
||||
`(spix)` and `(spie)` which are then used in the SDC driver.
|
||||
|
||||
The SDC driver is at B420. It gives you a load range. This means that what
|
||||
you need to insert in `xcomp` will look like:
|
||||
@ -139,5 +131,4 @@ Very easy. You see that `/cvm/blkfs` file? You dump it to your raw device.
|
||||
For example, if the device you get when you insert your SD card is `/dev/sdb`,
|
||||
then you type `cat emul/blkfs | sudo tee /dev/sdb > /dev/null`.
|
||||
|
||||
[schematic]: spirelay.pdf
|
||||
[inspiration]: https://www.ecstaticlyrics.com/electronics/SPI/fast_z80_interface.html
|
||||
|
BIN
recipes/rc2014/spirelay.jpg
Normal file
BIN
recipes/rc2014/spirelay.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 166 KiB |
Binary file not shown.
Loading…
Reference in New Issue
Block a user