This takes about 2.2us for a read cycle and 1.9us for a write cycle.
I figure roughly 2us more to add the use of address bits to access an array of locations
and to use hub memory instead of cog memory.
If we were to set this up for block moves (known byte count), we really don't have to decode
any further addresses (from the Z80).
So you were obviously talking about addressing an array in the Prop. (Gotcha now)
Kinda like: (it HAS been a long time since I did Z80 coding)
Me too, eh eh:cool:
I forcefully rejected anything but assembly, irrespective to the processor i'm coding for. I simply love stitching bits togheter!
Its the cause i feel so passionate by Propellers. A loom with its automated needle that weaves the strands coming from the peripheral cogs.
About holding the clock. That's realy about frequency modulating the clock signal.
Studying the available timing diagrams for every operation, memory or I/O, read or write, instruction, data or address fetch, you can choose at wich level you should temporary hold the clock generator.
Since all control signals are refered to some activating clock edge, even the tight ones could benefit from that strategy.
Another approach might be to use the Busreq/busack signals to stop things for a moment.
Maybe off of the IO port address decoder?
With a release controlled by the Prop.
The Z80 stores video info in regular ram memory somewhere.
The Prop suspends Z80 ops via /Busreq and reads the contents of that memory and
moves it to the prop video buffer.
If there were a simple way to sync to Vsync this could be done between frames.
Downside is that the prop dedicates a lot of pins to addressing Z80 ram.
But the idea of stopping time via busreq makes a lot of sense...
Stopping the Z80's clock is a good idea to stall it while decoding IO in the prop - especially since the prop can be in control of this signal already. Or you could try to use the the real Z80 !WAIT signal and force it low from the prop as soon as the waitpeq operation detects !IORQ going low, thereby buying yourself any number of wait states needed for the operation to complete in the prop. I think there was just about enough time at 4MHz clock rates for doing this when I checked timing diagrams a while ago and was considering implementing this approach on an old Z80 microbee system I had plans for - but for any faster Z80's probably not. The downside of course is that it needs another prop pin to drive it....
Also, about the I2C clock being shared with the Z80 clock. It might be slightly against the spec but I have a feeling you can toggle the SCL clock line while holding SDA high the whole time and it won't do too much harm because it won't issue a start command on the bus causing other devices to decode/respond. But I haven't confirmed this 100% so treat it with a grain of salt. Certainly in a single master system with just a I2C bootrom present on the I2C bus I'd expect it should be fine.
For IO operations why not have an external flip flop arrangement that immediately drives WAIT on all IO accesses.
At the same time the Prop gets the IORQ, it then takes it's time doing whatever it has to do to satisfy the IO operation and the clears the flip flop allowing the Z80 to continue.
With this would allow using any speed of Z80 and saves messing around with the clock speed.
I did this back in the day on the 8085. It was for a multi-8085 system sharing some RAM. Kind of a Propeller made from 8085s:) I seem to remember the signal I used was HOLD but the idea is the same.
When idle, both lines are high. To start a transaction, SDA is pulled low while SCL remains high. Releasing SDA to float high again would be a stop marker, signalling the end of a bus transaction. Although legal, this is typically pointless immediately after a start, so the next step is to pull SCL low.
Except for the start and stop signals, the SDA line only changes while the clock is low; transmitting a data bit consists of pulsing the clock line high while holding the data line steady at the desired level.
While SCL is low, the transmitter (initially the master) sets SDA to the desired value and (after a small delay to let the value propagate) lets SCL float high. The master then waits for SCL to actually go high; this will be delayed by the finite rise-time of the SCL signal (the RC time constant of the pull-up resistor and the parasitic capacitance of the bus), and may be additionally delayed by a slave's clock stretching.
Once SCL is high, the master waits a minimum time (4 μs for standard speed I²C) to ensure the receiver has seen the bit, then pulls it low again. This completes transmission of one bit.
After every 8 data bits in one direction, an "acknowledge" bit is transmitted in the other direction. The transmitter and receiver switch roles for one bit and the erstwhile receiver transmits a single 0 bit (ACK) back. If the transmitter sees a 1 bit (NACK) instead, it learns that:
(If master transmitting to slave) The slave is unable to accept the data. No such slave, command not understood, or unable to accept any more data.
(If slave transmitting to master) The master wishes the transfer to stop after this data byte.
After the acknowledge bit, the master may do one of three things:
Prepare to transfer another byte of data: the transmitter set SDA, and the master pulses SCL high..
Send a "Stop": Set SDA low, let SCL go high, then let SDA go high. This releases the I²C bus.
Send a "Repeated start": Set SDA high, let SCL go high, and pull SDA low again. This starts a new I²C bus transaction without releasing the bus.
What would a clock be translated as if the clock line was toggling and SDA was held high?
@heater, using a flip flop on the wait line is a more traditional way of doing things. My gut feeling is the prop is more than fast enough to detect an iorq and then stop the clock. Bottom line is it saves a flip flop.
What would a clock be translated as if the clock line was toggling and SDA was held high?
In my take it should be ignored if devices have not already detected any start condition. But there is probably someone from Philips (sorry NXP) screaming no at me...
Attached minimalist circuit idea. One ram chip, one Z80 and one 74HC125.
VGA or TV, Keyboard, SD card, Audio out. Boot up the Z80 using the VGA pins then turn on the display.
Pins - 12 for talking to the Z80, 4 for SD card, 8 for display, 2 for keyboard, 2 for audio, 2 for I2C bus, 2 for download and then as a serial port.
Could it work?
Yeah looks nice, I reckon it could be coaxed into working if the clock stopping and 3.3V operation reliably works on your Z80 chip, that's probably the biggest unknown in my opinion (at least for me). If you have all the main chips handy, why not breadboard it up first and give it a go? Then build up a real PCB if it all works out.
[EDIT] I noticed your pin numbers on the SD interface block are not P12-P15 - don't get that bit wrong.
Ultimately I want to build something almost the same as you have designed here, but luckily I can probably live with S-video (or 4 pin RGBS) instead of VGA and in that case I would get the luxury of 8 prop pins to hook up to the Z80 control lines allowing me to then pick !RD, !WR, A0, !IORQ, !WAIT, CLK, !RESET and maybe !M1 (or !INT/!NMI) for maximum versatility in interfacing to the Z80 for I/O. Just need the time to do it...
Yes with TV there are 5 spare pins. That would save a chip.
Someone earlier wondered if it would be possible to lose the 74HC125 chip - and still do VGA?
I've been pondering this. One option is to replace the 125 with a MCP23008 on the I2C bus and use one of the output pins of the 23008 to run the Z80 reset line. That gives you 7 spare I/O pins, or 15 spare pins if you use a MCP23017. Same chip count but more I/O.
But is it possible to do this without the 125?
Consider - the 125 is taking one propeller pin so you get that pin back. So there are 4 propeller pins available for control. For bootup control I think that means Z80 clock, /WR, /RD and /IORQ. But there might be other combinations.
Could you get a reset line from somewhere? I'm thinking about a diode and a RC network onto the Propeller reset line. When the propeller is reset (with a download, or powerup, or with a pushbutton), the Z80 also is reset but the RC network keeps the Z80 reset line low for about a second which is enough time for the Spin program to get started and to start running a clock. I think the Z80 needs at least 3 clock cycles with the reset line held low in order to register a reset.
Or get a reset from somewhere else - a pin combination that never comes up ordinarily (eg maybe on the VGA line) - but then you need a gate to detect that combination.
The /CS line on the SD card is a possibility but I think some of the SD driver code needs control of this.
Yes with TV there are 5 spare pins. That would save a chip.
Someone earlier wondered if it would be possible to lose the 74HC125 chip - and still do VGA?
I've been pondering this. One option is to replace the 125 with a MCP23008 on the I2C bus and use one of the output pins of the 23008 to run the Z80 reset line. That gives you 7 spare I/O pins, or 15 spare pins if you use a MCP23017. Same chip count but more I/O.
But is it possible to do this without the 125?
Consider - the 125 is taking one propeller pin so you get that pin back. So there are 4 propeller pins available for control. For bootup control I think that means Z80 clock, /WR, /RD and /IORQ. But there might be other combinations.
Could you get a reset line from somewhere? I'm thinking about a diode and a RC network onto the Propeller reset line. When the propeller is reset (with a download, or powerup, or with a pushbutton), the Z80 also is reset but the RC network keeps the Z80 reset line low for about a second which is enough time for the Spin program to get started and to start running a clock. I think the Z80 needs at least 3 clock cycles with the reset line held low in order to register a reset.
Or get a reset from somewhere else - a pin combination that never comes up ordinarily (eg maybe on the VGA line) - but then you need a gate to detect that combination.
The /CS line on the SD card is a possibility but I think some of the SD driver code needs control of this.
I'll keep thinking about this!
Looks really good, Doc.
Some other things to think about?
What is the Prop going to do with that byte that is written to it?
Put it on screen, right? But where?
It's time to consider a protocol for this set-up, Doc.
Allocate one more pin attached to Z80 A0.
Use that so the Prop to determine if the byte written is a control byte or data.
Z80A0 = 0 for access to the data register.
Z80A1 = 1 for the control register.
Control bytes can be used to tell the Prop what to do, or what to do with the next data byte(s).
But a single data register can't pick put something like a control function from a binary stream.
And I would NOT want to try to implement ANSII escape sequences for this!
Also this protocol can be used so that the Prop can return touch screen events, SD data, etc?
Just about anything that you want to do with this circuit.
Such as (in no particular order)
XX = control byte (value of 0 to 255)
Write to Display:
00 - reset the control register and terminate any pending operation (reset the control function)
01 - write the next byte TTY style (print character and move cursor to next position, maybe with wrap)
02 - Write a zero terminated string (prop watches for binary zero to indicate end of string)
03 - write a string of (N) bytes; N indicated by next byte written to control register.
04 - locate cursor X (next byte)
05 - locate cursor Y (next byte)
(oops - maybe the above should be relocated so that normal ASCII codes work right?)
06
07 - Beep
10 - cr
11 - FF
12 - LF
13 - cr-lf
Backlight on/off/intensity. etc
...
Access SD card:
S0 - reset the SD card?
S1 - open file
S2 - read
S3 - write
Sn - etc
Read Keyboard:
k0 - clear key buffer
k1 - get key - no wait
k2 - get key - wait
k3 - ?
Read Mouse:
Etc:
All of this will have to be done somehow, and to me, this is just the simplest way.
Yeah there are plenty more ways to free pins. Some sacrifices may be okay in some cases.
Mono audio instead of stereo buys another pin, and the fun to use sound objects like SIDCog/AYCog are only outputing mono anyway on their two output channels.
Some type of delayed reset approach could work out, if there is enough time given for the prop to boot first and start the clock before the Z80 is taken out of reset and if you can use a method (like the stack approach I'd mentioned earlier) which doesn't require resetting the Z80 a second time to fire up the boot code. That's another pin freed.
Someone (I think Cluso) had a 1 pin PS/2 KBD driver. But personally I'd prefer the regular method for best compatibility with keyboards.
One more pin is free if the i2c clock and Z80 clock are sharable which I think they can be.
Also didn't someone else here once also figure out a good way to reuse the Prop's I2C boot pins as part of an SD card interface a while back? I think it was SPI !CS = SCL and SPI MOSI = SDA or some such thing like that. The SD card won't be uspet while it gets selected when doing I2C accesses because you don't clock it (your keep its own dedicated SCLK high with a pullup when doing I2C), and the I2C bootrom won't respond if you don't ever issue a start condition on the bus by keeping SDA (MOSI) high while you drop the !CS line, and make sure to bring it high again before raising !CS during the SD accesses. I'm pretty confident something like that is possible where you can do two things with the same pins at different times. Yeah it might be technically unsupported by the specs but I think for hobby grade stuff it may still work ok, particularly if you don't touch I2C again after bootup. That method actually frees 2 more pins which is really nice.
Certainly only needing S-video instead of VGA buys 4 more free pins, or composite video buys 5 more pins over regular 8 bit VGA as you mentioned. By then it's real luxury with I/O pins galore.
But I still say having at least one address pin from the Z80 feeding into the prop will be useful for I/O register decode. Yeah you could get around it by breaking a single 8 bit R/W I/O port down into smaller bits or using various escape sequences in the stream of bytes going back and forth over a single I/O port to multiplex audio/video console/keyboard/SD/UART etc but it is not as convenient as indexed registers for all the different functions supplied by the propeller and that makes it a bit harder to develop the software sooner. Also if there are extra spare pins freed, the !WAIT line is very useful and could avoid Z80 clock stopping trickiness.
It's got me all interested again now so I really gotta dig my spare eeZee Prop board out of its bag and a Z80 and 128k DIP SRAM wired up on a breadboard and try some of this. I probably already have all the parts sitting around at home ready to try something. Hacking up some Z80 asm test code will likely be the biggest challenge - haven't touched one in ages, it's oldschool now but I was all over it as a kid so some of it might come back with any luck.
Based on the above discussion here's a minimal way to connect things in order to keep VGA and ditch the 74HC125. It of course relies on the combination of I2C and SD cards working together which I now want to try out.
Z80 Prop Usage
---------------------------------
D0-D7 P0-P7 Data bus
A0 P8 Z80 I/O port decode
!RD P9 Read strobe to prop
!WR P10 Write strobe to prop
!IORQ P11 I/O Request to prop
CLOCK P12 Z80 clock from prop
!RESET P13 Z80 reset from prop
!WAIT P14 Wait signal for I/O from prop
P15 Mono PWM audio output
P16-P23 VGA port (64 colors)
P24-P25 PS/2 keyboard
P26 SPI_SCLK
P27 SPI_MISO (input to prop)
P28 I2C_SCL / SPI_CS
P29 I2C_SDA / SPI_MOSI
P30-P31 UART TX+RX
Pullups on all SD pins and appropriate Z80 signals
Either run the Z80 at 3.3V or use current limiting resistors or other voltage translation methods between a 5V Z80 and 3.3V prop
So tonight I've gone and wired up my breadboard with my eeZee prop and an SD socket on pins 26-29 and an audio output pin to RC network, will doublecheck wiring and try to test it tomorrow in better light. Hate working under poor lighting at night with breadboard wiring. It sucks hard and makes it all too easy to get something wrong and then fry something.
I'll probably test it out with some simple WAV file playback code reading from the SD card after booting up via the I2C ROM, proving they can be used together in that order after bootup. I'll need to first check the sequence of the SPI driver's pin control to make sure it is compatible with the SDA and SCL transition requirements on the shared pins, and modify it a bit if needed. But that shouldn't be too difficult.
I just put pullups on the extra SD pins for MISO and SCLK (used a 4.7k network I had lying around) and will rely on the 10k ones already fitted on the eeZee prop board for I2C.
If this SD card approach works, then I'll be confident there'd be enough prop pins free for the rest of the Z80 interfacing proposed above without further changes. I also found I had an old NMOS based Z80 (SGS Z8400AB1 chip) which can run at 4MHz. Not sure about running these NMOS ones at 3.3V. But I can try it and if it's not working, run with 5V and use a bunch of limiting resistors - I know that already works well on my AVR to Prop setup with 2.2k ohm resistors at 5MHz. The Z80's Vih logic threshold level at 2V will be fine for the prop to directly drive for clock/reset/wait signals and on the data bus itself for IO reads so that shouldn't be an issue. Input capacitance is rated at 5pF on Z80 inputs - am hoping that shouldn't be too bad for a reasonable signal to still get through the limiting resistor network even though I know the signal edges won't be too square. Can always underclock the CPU for testing I guess if it looks a little flakey.
and to answer cavelamb, yes, once the basics are working with booting a z80 and getting a tiny bootstrap program running, that is the sort of thing what would be very useful. Add standard propeller objects like display, keyboard, SD card, and then use your simple protocol. Add more numbers as needed.
Addit: More thoughts.
Let's assume that hardware solutions will work, and also, let's assume there will be a number of hardware solutions. Some will use /wait, some will not. Some will use a DMA style of comms, some will send bytes one at a time. Roger is building some clever parallel comms hardware. And right now I have an older version that is much slower and is using just 4 propeller pins for a serial protocol. All of these will work and more.
cavelamb is onto something really clever in post #72, because what we can do is think about a software protocol that will work with lots of different hardware. Maybe there is a tiny bit of code to change parallel to serial, or insert a wait state, or stop a clock, but the bulk of the software can be the same. I've been having a mental block about this and I think cavelamb has proposed a solution.
Take it further, one thing that has been troubling me is what happens if you use just numbers, and say that service number 0 to 10 is keyboard, and then 11 to 20 is mouse, and 20 to 30 is the display and then you suddenly think of two more keyboard routines? It is a bit messy to now have 0-10 and also 30-31 as being keyboard.
cavelamb proposes this
Access SD card:
S0 - reset the SD card?
S1 - open file
S2 - read
S3 - write
Sn - etc
so if you think of more SD routines, add them to the "S" group. So the K group is keyboard, T for TV, V for VGA etc.
Next thing - one might want to send different numbers of bytes. So S0 might be reset the SD card and that is two bytes. But S1 might need some more bytes because that is opening a file, so you might want to make that 14 bytes eg S1FILENAME.TXT Each of these routines will likely correspond with a routine in an existing Obex object. We just number them as it is quicker than sending the name each time. So in a simplistic way, take each Obex file, eg the keyboard, and number each of the PUB routines and that is a place to start.
Then it is a matter of working out how many bytes each routine uses. I suspect they may all be different. How to work through that? Rather than rigidly saying that each message must be x bytes, I have a feeling it may be easier to be flexible, and simply say that each routine is going to need a different number of bytes, but if we write the Spin interface code at the same time as the Z80 code, they will both be compatible. So cavelamb says that K1 is get a keypress with no wait, and that is going to send two bytes and receive one byte.
Many people can work on this at the same time. Say, for some silly reason, I really wanted a routine that fetched ten keypresses at once. I would look at what cavelamb has done, note that he wrote the code for K0 to K2, and then I add my silly routine at K3 and let him know I have used K3.
Taking a look at all the Obex code for keyboard, display and SD card, and numbering them this way, and then taking a look at the CP/M source code, suddenly about 90% of the CP/M routines are already written.
The idea that I'd like to explore is that CP/M gets expanded. Using the concept above, one can add a set of routines for a touchscreen. Or a propeller ethernet adapter or all the clever I2C and SPI objects that are in the Obex. From a program inside CP/M, say BDS C (which is an older subset of Catalina and GCC), these new calls would be accessible from within a program.
I need to think about this some more. The general concept is that one has a 'software' layer and a 'hardware' layer and that with some simple tweaks, the software layer is the same for lots of different hardware configurations.
If one were to include "true" 3.3V / 5V level shifting, what would be the "proper" method to do that? 74xx245? Or 74xx4245 74CBT3245, or something completely different?
Update: Tried to do some research.. it looks like the 74CBT3245 is good for translating 5V to 3.3V, but not the other way, so it'll work OK if the 3.3 V levels are good enough for the 5V device. Then there's the 74LVC4245 which is powered by both 5V and 3.3V (and thus needs more pins than the '245 layout). It is fully bi-directionally 5V - 3.3V converting. And there's also a very similar 74LVC8T245 which is more flexible w.r.t. voltage ranges and can accommodate everything between 1.65V to 5.5V (and thus overkill here)
Not sure if I'm even on the right track, this is the first time I've looked into what exists of chip support for combining different logic level families.
Dr_A, the result of my I/O pin saving experiment is in.
It worked!
I was able to boot up and then playback some SIDCog audio file from an SD card when sharing two pins with the i2c bootrom. I have SCL = !CS and SDA = MOSI. I used the ExampleSidDumpPlay code (from Ahle2 I think) for testing.
I know this is not an exhaustive test but at least it proves the basic concept you can indeed share the pins if you are careful about it.
All I did was:
1) modify the pin setup order of the fsrw.spin mount method by flipping the last two pins relative to the base to force SCL=!CS=P28, and SDA=MOSI=P29 and set the basepin to pin 26.
2) in the underlying mb_spi.spin file I reversed the order of initial writes to outa and dira to make sure I setup the output pins at the high level before enabling the dira register, so it would not drop all the output signals low briefly during this initialization which could possible have triggered an unwanted I2C start if there was a slight amount of skew.
When I viewed the SPI bus transitions during SD card accesses with my logic analyzer I would always see that !CS signal remained low during high to low transitions of the shared SDA pin. This means that the start pattern is not happening on the I2C bus and in my opinion the attached devices should therefore not decode their address or respond and interfere with the MOSI/CS pins used by SPI.
I like it! :thumb:
Speaking of logic translation I wonder in my case with an old NMOS Z80 if I can cheat a bit and run the Z80 at 5V but not use any current limiting resistors into the propeller inputs given that NMOS already has very limited output drive capability for logic high and shouldn't be sourcing directly via a transistor from the 5V rail but via some passive resistor or equivalent instead. When connected into the protection diodes of the propeller, I suspect the output voltage will drop down to a safe level and the current will be rather low. Maybe I will try a test with the Z80 !HALT signal connected to 3.3V via a diode and see what current it sources when powered on and logic high - shouldn't be very much. Only real issue I see is other CMOS devices on the same data bus (eg SRAM) which still could drive the signals rather hard from 5V. I guess I'll not want to risk burning out my prop so I will still need to put them on the data bus at least once I try to test with a real Z80 at 5V.
The SRAMs used on the DracBlades etc (as6c4008-55) are rated to be 5V or 3.3V, @ the full 55nS speed, so these would allow for more flexibility on their power source.
Ah, the NMOS Z80! Proof of operation was gauge able by the surface temperature, more than 10 seconds of finger holding (whilst retaining finger print) = all is well. Bless.
Wow, some great progress here. Ok, that saves 2 pins, so that allows 6 control pins for the Z80? eg reset, clock, iorq, wr, rd and then there is a spare pin, which could be A0 or /wait or something else again.
Re 5V into the propeller, it is only the cost of a few resistors, right? Or changing to a Z80 that the author of the mini80 has shown will work at 3V3.
It is cool this can be done with no support chips - just a Z80 and ram.
One immediate thing this could be is a smart memory peripheral for the propeller. Instead of needing lots of control latches or counters, the Z80 has enough smarts to dump out bytes using all sorts of protocols. I think the very fastest ram driver we have is Cluso's which just connects all the ram pins to a propeller, but that leaves no propeller pins free. With a 20mhz Z80, I wonder if this could be the second fastest?
Yeah with this you could use 6 control pins (or 7 with mono audio). If you use clock stopping the wait line is not so important. Without the clock stopping method during I/O decode and boot load reads you will want a wait signal. But having an address line like A0 is really important in my view - I really think you will want it.
I would say that using mono audio is not that big of a deal. How much benefit will having mono duplicated over stereo channels (like SIDCOG etc do) get you really? May as well just do it by coupling left and right channels together electrically. Will sound about the same either way. Plus a lot of retro stuff from back then would have been mono anyway I imagine.
Many people can work on this at the same time. Say, for some silly reason, I really wanted a routine that fetched ten keypresses at once. I would look at what cavelamb has done, note that he wrote the code for K0 to K2, and then I add my silly routine at K3 and let him know I have used K3.
Taking a look at all the Obex code for keyboard, display and SD card, and numbering them this way, and then taking a look at the CP/M source code, suddenly about 90% of the CP/M routines are already written.
The idea that I'd like to explore is that CP/M gets expanded. Using the concept above, one can add a set of routines for a touchscreen. Or a propeller ethernet adapter or all the clever I2C and SPI objects that are in the Obex. From a program inside CP/M, say BDS C (which is an older subset of Catalina and GCC), these new calls would be accessible from within a program.
I need to think about this some more. The general concept is that one has a 'software' layer and a 'hardware' layer and that with some simple tweaks, the software layer is the same for lots of different hardware configurations.
I was actually thinking those codes would be a single binary byte, Doc.
And they would be written to a different address than the data stream.
Set aside ranges of numbers for the different functions, and yes, leave room for expansion of each.
Two hundred and fifty six functions oughtt to be enough for anybody
But you may have misinterpreted it into a better scheme - one that may not need to
supply an address pin to differentiate between data control registers.
If the two processors (Z80 and Prop) can stay together and not get out of sync (ever!)
Interesting.
I have to think about this some more too...
I was actually thinking those codes would be a single binary byte, Doc.
And they would be written to a different address than the data stream.
All moving so fast. rogloh just gave us a solution that frees up an address pin. So now it <is> possible to write to a different address than the data stream. Makes your protocol even easier.
I'd be hoping the prop and the Z80 could be coded so they never get out of sync. A cog in a tight pasm loop that does both the clock and polls for /iorq each clock cycle shouldn't miss anything.
It is cool this can be done with no support chips - just a Z80 and ram.
One immediate thing this could be is a smart memory peripheral for the propeller. Instead of needing lots of control latches or counters, the Z80 has enough smarts to dump out bytes using all sorts of protocols. I think the very fastest ram driver we have is Cluso's which just connects all the ram pins to a propeller, but that leaves no propeller pins free. With a 20mhz Z80, I wonder if this could be the second fastest?
Dr_Acula
I do know nothing about Cluso's solution, but a Z80@20MHz can move data from one place to another, either RAM or peripheral I/O, at a cost of 21 clock cycles per moved byte (16 for the last one) , or ~1,05uS per byte. This stands for a bit less than 1MB/s.
I believe that someone else has implemented the following solution before, but, for the sake of clarity I will mention it and try to describe its operation.
An obvious approach is to use the Z80 to produce 'tweaked' address and control signals (slaved to the Propeller, so it controls the Z80) to allow RAM reading or writing at solely 04 clock cycles per byte moved, or 5MB/s@20MHz clock rate. But clocking the Z80 this high, can't be done by the Prop 1 and simultaneously be in Sync with the data stream.
I'm not sure, but I believe that you must use at least two cogs, one to clock and sync the Z80 control signage and the other, in a tight loop in sync with the other COG, to transfer data to/from the bus.
Sure you must code the Prop to stuff a JUMP instruction followed by two bytes to set the initial move to or from address into the Z80-side data bus. Then a Z80 NOP is to be stuffed at the registered transceiver, this will be a one time operation for the entire dataset.
A Prop pin will be used to 'convert' the /RD coming from the Z80 during instruction 'fetch' to RAM /RD or /WR, depending on the direction of the intended data flow.
The Z80 will be blindly executing a NOP for each transfered byte, and it's address bus will be moving upwards.
In fact, the limit will be stablished by the Propeller, since it will be feeding the RAM data bus with data, or receiving it from the Ram data bus at this time.
This implies the use of a 'LVC543 style registered transceiver and a couple of 'LVC style quad gates, but since it also solves completely the problem of having different voltages at the data bus and lets the Z80 run at full speed@5Vdc, I think it can be a cheap solution.
I have another idea. Last year averagejoe and I built a touchscreen controller using the propeller, and one of the things we found was that for games we needed to dump data out very quickly from a ram chip. After trying many solutions, including using other propeller chips, the best solution turned out to be five 74HC161 clock chips to do the ram address lines. But with Yanomani's idea, you could use a Z80 as the counter - and use it in a completely different way to its original intended use as a microprocessor.
Add a touchscreen with no extra chips? I'm going to cheat a bit here and say yes - the touchscreen has 8 data lines, /rd, /wr, /rs, /reset /cs. And there are 4 pins for the SPI touch interface. If a design is using a touchscreen then VGA is likely not needed, so can use the VGA pins to talk to the 4 spi pins and the /rs and /cs lines. I'll draw a schematic tonight.
@rogloh - would you be kind enough to check this schematic - is it what you have done? Specifically, the SD pins
P28 SD CS
P29 SD MOSI (data into the SD card)
P27 SD CLK
P26 SD MISO (data out of SD card)
Thanks Dr_Acula, but as I said before, i believe that someone else had the same idea, or at least as similar as it can be, that one can view them as twins.
I have another idea. Last year averagejoe and I built a touchscreen controller using the propeller, and one of the things we found was that for games we needed to dump data out very quickly from a ram chip. After trying many solutions, including using other propeller chips, the best solution turned out to be five 74HC161 clock chips to do the ram address lines.
I realized that, when you and averagejoe were doing your controller. you were constrained by the operational speed of the choosen Z80. But now, a faster CPU can be used, like the 'H or even the 'C0020 versions.
Fancier clocking options can be now be tested, and the best one selected.
In the next hours I'll be busy, elaborating a bit on the 'stuffing' sequencing protocol, including the use of a Z80 CALL instruction, wich I'm wondering if its better suited since, when properly done, will does not disrupt 'normal' programs workflow as a unlinked JUMP can do.
Stuffing a JUMP could be better suited if one uses a Propeller pin to control and extend the Z80 /RESET period. Then the synced Propeller PASM routines could handle the job on filling the RAM with proper gathered data from a SD card or another serial channel, for example, using the Z80 as a 'mule beast' address carrier.
There is also the possibility to 'sync' both processors by the use of an interlocked protocol, like /HALT then /INT or even /NMI, whichever will be better suited for the intended results.
@rogloh, this is a the relevant schematic of your SD/I2C sharing idea.
To clarify how it works.
1) From the SD card's point of view, if the I2C bus is running, the SD card will see /CS and MOSI toggling randomly, but the SD Clock will not be changing. I think that means no data will be clocked into the SD card so it will not respond?
2) From an I2C device point of view, if the SD card is running, like you say, the /SD_CS stays low which is also I2C clock so no data can be clocked into the I2C device.
Is there a possibility that each time the SD card is enabled, the I2C clock line goes from high to low and that very slowly something does get clocked to an I2C chip? Or do I2C devices have a timeout? Or is there a way of clearing the I2C bus?
Would a solution be to send a formal "stop bit" on the I2C bus each time the SD card is disabled eg, from wikipedia
Send a "Stop": Set SDA low, let SCL go high, then let SDA go high. This releases the I²C bus.
@rogloh, this is a the relevant schematic of your SD/I2C sharing idea.
To clarify how it works.
1) From the SD card's point of view, if the I2C bus is running, the SD card will see /CS and MOSI toggling randomly, but the SD Clock will not be changing. I think that means no data will be clocked into the SD card so it will not respond?
2) From an I2C device point of view, if the SD card is running, like you say, the /SD_CS stays low which is also I2C clock so no data can be clocked into the I2C device.
Is there a possibility that each time the SD card is enabled, the I2C clock line goes from high to low and that very slowly something does get clocked to an I2C chip? Or do I2C devices have a timeout? Or is there a way of clearing the I2C bus?
Would a solution be to send a formal "stop bit" on the I2C bus each time the SD card is disabled eg, from wikipedia
Send a "Stop": Set SDA low, let SCL go high, then let SDA go high. This releases the I²C bus.
Yes you have the correct schematic with the same pinout as I used. I also used some pullups on SCLK and MISO.
For (1) yes if there is no SPI clock toggling it can't drive anything into the SD card to control it so the SD can't do anything. Having been chip selected yes it might drive a single high or low output voltage level into MISO but that is a separate pin and so won't upset anything on the I2C pins. SPI devices should cancel their transactions if the /CS line goes high. Certainly in my case with a common SanDisk branded SDHC card it was all fine in my simple test and I could reset the system over and over and it would recover and reboot and start playing audio each time I pressed reset. I would hope that is the typical behaviour for all cards since SanDisk pretty much wrote the spec.
The I2C boot rom should not decode anything until it sees a start on the bus which is a falling edge of SDA while SCLK is high and this won't happen if you keep MOSI high when you drop SPI /CS. That's why the SPI driver needs to be careful with what it does and why I wanted to tweak it slightly for my test to ensure there were no I2C start sequences created during SPI access.
As far as I2C bus cleanup goes I know that there is a general way to reset the I2C bus, if for example you had reset the microcontroller system while in the middle of an I2C transaction and had not reset the I2C device. Can't remember all the details here now (just google it) but I recall you need to issue some minimum number of clocks to complete and then a stop. I know without this there was a chance of I2C device lockup - have seen this in some embedded systems I've worked on in the past.
I suspect this reset is already done during boot but have not looked at Chip's initial I2C bootup sequence on the logic analyzer. Parallax probably/hopefully added a similar cleanup sequence at the first access after boot if they wanted to make sure it would be reliable after all resets.
UPDATE: googling for "i2c bus cleanup" finds the Analog Devices "Implementing an I2C Reset" Application Note as its first hit - it appears to have some useful information.
You are a dynamo of activity, Dr_A! I don't know how in the world you manage to hold down a practice, raise a family, and still tackle (and finish!) new projects all the time. You must be some sort of Homo novus. In any event, my hat is off to you.
Comments
If we were to set this up for block moves (known byte count), we really don't have to decode
any further addresses (from the Z80).
So you were obviously talking about addressing an array in the Prop. (Gotcha now)
Is there an auto-increment trick in Pasm?
Me too, eh eh:cool:
I forcefully rejected anything but assembly, irrespective to the processor i'm coding for. I simply love stitching bits togheter!
Its the cause i feel so passionate by Propellers. A loom with its automated needle that weaves the strands coming from the peripheral cogs.
About holding the clock. That's realy about frequency modulating the clock signal.
Studying the available timing diagrams for every operation, memory or I/O, read or write, instruction, data or address fetch, you can choose at wich level you should temporary hold the clock generator.
Since all control signals are refered to some activating clock edge, even the tight ones could benefit from that strategy.
Yanomani
Maybe off of the IO port address decoder?
With a release controlled by the Prop.
But Vega256 took a different approach...
http://forums.parallax.com/showthread.php/131957-Z80-Driven-Propeller-Update
The Z80 stores video info in regular ram memory somewhere.
The Prop suspends Z80 ops via /Busreq and reads the contents of that memory and
moves it to the prop video buffer.
If there were a simple way to sync to Vsync this could be done between frames.
Downside is that the prop dedicates a lot of pins to addressing Z80 ram.
But the idea of stopping time via busreq makes a lot of sense...
Also, about the I2C clock being shared with the Z80 clock. It might be slightly against the spec but I have a feeling you can toggle the SCL clock line while holding SDA high the whole time and it won't do too much harm because it won't issue a start command on the bus causing other devices to decode/respond. But I haven't confirmed this 100% so treat it with a grain of salt. Certainly in a single master system with just a I2C bootrom present on the I2C bus I'd expect it should be fine.
Roger.
At the same time the Prop gets the IORQ, it then takes it's time doing whatever it has to do to satisfy the IO operation and the clears the flip flop allowing the Z80 to continue.
With this would allow using any speed of Z80 and saves messing around with the clock speed.
I did this back in the day on the 8085. It was for a multi-8085 system sharing some RAM. Kind of a Propeller made from 8085s:) I seem to remember the signal I used was HOLD but the idea is the same.
What would a clock be translated as if the clock line was toggling and SDA was held high?
@heater, using a flip flop on the wait line is a more traditional way of doing things. My gut feeling is the prop is more than fast enough to detect an iorq and then stop the clock. Bottom line is it saves a flip flop.
Back to Eagle to draw up a minimalist circuit...
VGA or TV, Keyboard, SD card, Audio out. Boot up the Z80 using the VGA pins then turn on the display.
Pins - 12 for talking to the Z80, 4 for SD card, 8 for display, 2 for keyboard, 2 for audio, 2 for I2C bus, 2 for download and then as a serial port.
Could it work?
In my take it should be ignored if devices have not already detected any start condition. But there is probably someone from Philips (sorry NXP) screaming no at me...
Yeah looks nice, I reckon it could be coaxed into working if the clock stopping and 3.3V operation reliably works on your Z80 chip, that's probably the biggest unknown in my opinion (at least for me). If you have all the main chips handy, why not breadboard it up first and give it a go? Then build up a real PCB if it all works out.
[EDIT] I noticed your pin numbers on the SD interface block are not P12-P15 - don't get that bit wrong.
Ultimately I want to build something almost the same as you have designed here, but luckily I can probably live with S-video (or 4 pin RGBS) instead of VGA and in that case I would get the luxury of 8 prop pins to hook up to the Z80 control lines allowing me to then pick !RD, !WR, A0, !IORQ, !WAIT, CLK, !RESET and maybe !M1 (or !INT/!NMI) for maximum versatility in interfacing to the Z80 for I/O. Just need the time to do it...
Someone earlier wondered if it would be possible to lose the 74HC125 chip - and still do VGA?
I've been pondering this. One option is to replace the 125 with a MCP23008 on the I2C bus and use one of the output pins of the 23008 to run the Z80 reset line. That gives you 7 spare I/O pins, or 15 spare pins if you use a MCP23017. Same chip count but more I/O.
But is it possible to do this without the 125?
Consider - the 125 is taking one propeller pin so you get that pin back. So there are 4 propeller pins available for control. For bootup control I think that means Z80 clock, /WR, /RD and /IORQ. But there might be other combinations.
Could you get a reset line from somewhere? I'm thinking about a diode and a RC network onto the Propeller reset line. When the propeller is reset (with a download, or powerup, or with a pushbutton), the Z80 also is reset but the RC network keeps the Z80 reset line low for about a second which is enough time for the Spin program to get started and to start running a clock. I think the Z80 needs at least 3 clock cycles with the reset line held low in order to register a reset.
Or get a reset from somewhere else - a pin combination that never comes up ordinarily (eg maybe on the VGA line) - but then you need a gate to detect that combination.
The /CS line on the SD card is a possibility but I think some of the SD driver code needs control of this.
I'll keep thinking about this!
Looks really good, Doc.
Some other things to think about?
What is the Prop going to do with that byte that is written to it?
Put it on screen, right? But where?
It's time to consider a protocol for this set-up, Doc.
Allocate one more pin attached to Z80 A0.
Use that so the Prop to determine if the byte written is a control byte or data.
Z80A0 = 0 for access to the data register.
Z80A1 = 1 for the control register.
Control bytes can be used to tell the Prop what to do, or what to do with the next data byte(s).
But a single data register can't pick put something like a control function from a binary stream.
And I would NOT want to try to implement ANSII escape sequences for this!
Also this protocol can be used so that the Prop can return touch screen events, SD data, etc?
Just about anything that you want to do with this circuit.
Such as (in no particular order)
XX = control byte (value of 0 to 255)
Write to Display:
00 - reset the control register and terminate any pending operation (reset the control function)
01 - write the next byte TTY style (print character and move cursor to next position, maybe with wrap)
02 - Write a zero terminated string (prop watches for binary zero to indicate end of string)
03 - write a string of (N) bytes; N indicated by next byte written to control register.
04 - locate cursor X (next byte)
05 - locate cursor Y (next byte)
(oops - maybe the above should be relocated so that normal ASCII codes work right?)
06
07 - Beep
10 - cr
11 - FF
12 - LF
13 - cr-lf
Backlight on/off/intensity. etc
...
Access SD card:
S0 - reset the SD card?
S1 - open file
S2 - read
S3 - write
Sn - etc
Read Keyboard:
k0 - clear key buffer
k1 - get key - no wait
k2 - get key - wait
k3 - ?
Read Mouse:
Etc:
All of this will have to be done somehow, and to me, this is just the simplest way.
Unless someone has a better suggestion?
Yeah there are plenty more ways to free pins. Some sacrifices may be okay in some cases.
Mono audio instead of stereo buys another pin, and the fun to use sound objects like SIDCog/AYCog are only outputing mono anyway on their two output channels.
Some type of delayed reset approach could work out, if there is enough time given for the prop to boot first and start the clock before the Z80 is taken out of reset and if you can use a method (like the stack approach I'd mentioned earlier) which doesn't require resetting the Z80 a second time to fire up the boot code. That's another pin freed.
Someone (I think Cluso) had a 1 pin PS/2 KBD driver. But personally I'd prefer the regular method for best compatibility with keyboards.
One more pin is free if the i2c clock and Z80 clock are sharable which I think they can be.
Also didn't someone else here once also figure out a good way to reuse the Prop's I2C boot pins as part of an SD card interface a while back? I think it was SPI !CS = SCL and SPI MOSI = SDA or some such thing like that. The SD card won't be uspet while it gets selected when doing I2C accesses because you don't clock it (your keep its own dedicated SCLK high with a pullup when doing I2C), and the I2C bootrom won't respond if you don't ever issue a start condition on the bus by keeping SDA (MOSI) high while you drop the !CS line, and make sure to bring it high again before raising !CS during the SD accesses. I'm pretty confident something like that is possible where you can do two things with the same pins at different times. Yeah it might be technically unsupported by the specs but I think for hobby grade stuff it may still work ok, particularly if you don't touch I2C again after bootup. That method actually frees 2 more pins which is really nice.
Certainly only needing S-video instead of VGA buys 4 more free pins, or composite video buys 5 more pins over regular 8 bit VGA as you mentioned. By then it's real luxury with I/O pins galore.
But I still say having at least one address pin from the Z80 feeding into the prop will be useful for I/O register decode. Yeah you could get around it by breaking a single 8 bit R/W I/O port down into smaller bits or using various escape sequences in the stream of bytes going back and forth over a single I/O port to multiplex audio/video console/keyboard/SD/UART etc but it is not as convenient as indexed registers for all the different functions supplied by the propeller and that makes it a bit harder to develop the software sooner. Also if there are extra spare pins freed, the !WAIT line is very useful and could avoid Z80 clock stopping trickiness.
It's got me all interested again now so I really gotta dig my spare eeZee Prop board out of its bag and a Z80 and 128k DIP SRAM wired up on a breadboard and try some of this. I probably already have all the parts sitting around at home ready to try something. Hacking up some Z80 asm test code will likely be the biggest challenge - haven't touched one in ages, it's oldschool now but I was all over it as a kid so some of it might come back with any luck.
Roger.
So tonight I've gone and wired up my breadboard with my eeZee prop and an SD socket on pins 26-29 and an audio output pin to RC network, will doublecheck wiring and try to test it tomorrow in better light. Hate working under poor lighting at night with breadboard wiring. It sucks hard and makes it all too easy to get something wrong and then fry something.
I'll probably test it out with some simple WAV file playback code reading from the SD card after booting up via the I2C ROM, proving they can be used together in that order after bootup. I'll need to first check the sequence of the SPI driver's pin control to make sure it is compatible with the SDA and SCL transition requirements on the shared pins, and modify it a bit if needed. But that shouldn't be too difficult.
I just put pullups on the extra SD pins for MISO and SCLK (used a 4.7k network I had lying around) and will rely on the 10k ones already fitted on the eeZee prop board for I2C.
If this SD card approach works, then I'll be confident there'd be enough prop pins free for the rest of the Z80 interfacing proposed above without further changes. I also found I had an old NMOS based Z80 (SGS Z8400AB1 chip) which can run at 4MHz. Not sure about running these NMOS ones at 3.3V. But I can try it and if it's not working, run with 5V and use a bunch of limiting resistors - I know that already works well on my AVR to Prop setup with 2.2k ohm resistors at 5MHz. The Z80's Vih logic threshold level at 2V will be fine for the prop to directly drive for clock/reset/wait signals and on the data bus itself for IO reads so that shouldn't be an issue. Input capacitance is rated at 5pF on Z80 inputs - am hoping that shouldn't be too bad for a reasonable signal to still get through the limiting resistor network even though I know the signal edges won't be too square. Can always underclock the CPU for testing I guess if it looks a little flakey.
Roger.
and to answer cavelamb, yes, once the basics are working with booting a z80 and getting a tiny bootstrap program running, that is the sort of thing what would be very useful. Add standard propeller objects like display, keyboard, SD card, and then use your simple protocol. Add more numbers as needed.
Addit: More thoughts.
Let's assume that hardware solutions will work, and also, let's assume there will be a number of hardware solutions. Some will use /wait, some will not. Some will use a DMA style of comms, some will send bytes one at a time. Roger is building some clever parallel comms hardware. And right now I have an older version that is much slower and is using just 4 propeller pins for a serial protocol. All of these will work and more.
cavelamb is onto something really clever in post #72, because what we can do is think about a software protocol that will work with lots of different hardware. Maybe there is a tiny bit of code to change parallel to serial, or insert a wait state, or stop a clock, but the bulk of the software can be the same. I've been having a mental block about this and I think cavelamb has proposed a solution.
Take it further, one thing that has been troubling me is what happens if you use just numbers, and say that service number 0 to 10 is keyboard, and then 11 to 20 is mouse, and 20 to 30 is the display and then you suddenly think of two more keyboard routines? It is a bit messy to now have 0-10 and also 30-31 as being keyboard.
cavelamb proposes this
so if you think of more SD routines, add them to the "S" group. So the K group is keyboard, T for TV, V for VGA etc.
Next thing - one might want to send different numbers of bytes. So S0 might be reset the SD card and that is two bytes. But S1 might need some more bytes because that is opening a file, so you might want to make that 14 bytes eg S1FILENAME.TXT Each of these routines will likely correspond with a routine in an existing Obex object. We just number them as it is quicker than sending the name each time. So in a simplistic way, take each Obex file, eg the keyboard, and number each of the PUB routines and that is a place to start.
Then it is a matter of working out how many bytes each routine uses. I suspect they may all be different. How to work through that? Rather than rigidly saying that each message must be x bytes, I have a feeling it may be easier to be flexible, and simply say that each routine is going to need a different number of bytes, but if we write the Spin interface code at the same time as the Z80 code, they will both be compatible. So cavelamb says that K1 is get a keypress with no wait, and that is going to send two bytes and receive one byte.
Many people can work on this at the same time. Say, for some silly reason, I really wanted a routine that fetched ten keypresses at once. I would look at what cavelamb has done, note that he wrote the code for K0 to K2, and then I add my silly routine at K3 and let him know I have used K3.
Taking a look at all the Obex code for keyboard, display and SD card, and numbering them this way, and then taking a look at the CP/M source code, suddenly about 90% of the CP/M routines are already written.
The idea that I'd like to explore is that CP/M gets expanded. Using the concept above, one can add a set of routines for a touchscreen. Or a propeller ethernet adapter or all the clever I2C and SPI objects that are in the Obex. From a program inside CP/M, say BDS C (which is an older subset of Catalina and GCC), these new calls would be accessible from within a program.
I need to think about this some more. The general concept is that one has a 'software' layer and a 'hardware' layer and that with some simple tweaks, the software layer is the same for lots of different hardware configurations.
Update: Tried to do some research.. it looks like the 74CBT3245 is good for translating 5V to 3.3V, but not the other way, so it'll work OK if the 3.3 V levels are good enough for the 5V device. Then there's the 74LVC4245 which is powered by both 5V and 3.3V (and thus needs more pins than the '245 layout). It is fully bi-directionally 5V - 3.3V converting. And there's also a very similar 74LVC8T245 which is more flexible w.r.t. voltage ranges and can accommodate everything between 1.65V to 5.5V (and thus overkill here)
Not sure if I'm even on the right track, this is the first time I've looked into what exists of chip support for combining different logic level families.
-Tor
It worked!
I was able to boot up and then playback some SIDCog audio file from an SD card when sharing two pins with the i2c bootrom. I have SCL = !CS and SDA = MOSI. I used the ExampleSidDumpPlay code (from Ahle2 I think) for testing.
I know this is not an exhaustive test but at least it proves the basic concept you can indeed share the pins if you are careful about it.
All I did was:
1) modify the pin setup order of the fsrw.spin mount method by flipping the last two pins relative to the base to force SCL=!CS=P28, and SDA=MOSI=P29 and set the basepin to pin 26.
2) in the underlying mb_spi.spin file I reversed the order of initial writes to outa and dira to make sure I setup the output pins at the high level before enabling the dira register, so it would not drop all the output signals low briefly during this initialization which could possible have triggered an unwanted I2C start if there was a slight amount of skew.
When I viewed the SPI bus transitions during SD card accesses with my logic analyzer I would always see that !CS signal remained low during high to low transitions of the shared SDA pin. This means that the start pattern is not happening on the I2C bus and in my opinion the attached devices should therefore not decode their address or respond and interfere with the MOSI/CS pins used by SPI.
I like it! :thumb:
Speaking of logic translation I wonder in my case with an old NMOS Z80 if I can cheat a bit and run the Z80 at 5V but not use any current limiting resistors into the propeller inputs given that NMOS already has very limited output drive capability for logic high and shouldn't be sourcing directly via a transistor from the 5V rail but via some passive resistor or equivalent instead. When connected into the protection diodes of the propeller, I suspect the output voltage will drop down to a safe level and the current will be rather low. Maybe I will try a test with the Z80 !HALT signal connected to 3.3V via a diode and see what current it sources when powered on and logic high - shouldn't be very much. Only real issue I see is other CMOS devices on the same data bus (eg SRAM) which still could drive the signals rather hard from 5V. I guess I'll not want to risk burning out my prop so I will still need to put them on the data bus at least once I try to test with a real Z80 at 5V.
Roger.
Ah, the NMOS Z80! Proof of operation was gauge able by the surface temperature, more than 10 seconds of finger holding (whilst retaining finger print) = all is well. Bless.
Re 5V into the propeller, it is only the cost of a few resistors, right? Or changing to a Z80 that the author of the mini80 has shown will work at 3V3.
It is cool this can be done with no support chips - just a Z80 and ram.
One immediate thing this could be is a smart memory peripheral for the propeller. Instead of needing lots of control latches or counters, the Z80 has enough smarts to dump out bytes using all sorts of protocols. I think the very fastest ram driver we have is Cluso's which just connects all the ram pins to a propeller, but that leaves no propeller pins free. With a 20mhz Z80, I wonder if this could be the second fastest?
I would say that using mono audio is not that big of a deal. How much benefit will having mono duplicated over stereo channels (like SIDCOG etc do) get you really? May as well just do it by coupling left and right channels together electrically. Will sound about the same either way. Plus a lot of retro stuff from back then would have been mono anyway I imagine.
I was actually thinking those codes would be a single binary byte, Doc.
And they would be written to a different address than the data stream.
Set aside ranges of numbers for the different functions, and yes, leave room for expansion of each.
Two hundred and fifty six functions oughtt to be enough for anybody
But you may have misinterpreted it into a better scheme - one that may not need to
supply an address pin to differentiate between data control registers.
If the two processors (Z80 and Prop) can stay together and not get out of sync (ever!)
Interesting.
I have to think about this some more too...
All moving so fast. rogloh just gave us a solution that frees up an address pin. So now it <is> possible to write to a different address than the data stream. Makes your protocol even easier.
I'd be hoping the prop and the Z80 could be coded so they never get out of sync. A cog in a tight pasm loop that does both the clock and polls for /iorq each clock cycle shouldn't miss anything.
Dr_Acula
I do know nothing about Cluso's solution, but a Z80@20MHz can move data from one place to another, either RAM or peripheral I/O, at a cost of 21 clock cycles per moved byte (16 for the last one) , or ~1,05uS per byte. This stands for a bit less than 1MB/s.
I believe that someone else has implemented the following solution before, but, for the sake of clarity I will mention it and try to describe its operation.
An obvious approach is to use the Z80 to produce 'tweaked' address and control signals (slaved to the Propeller, so it controls the Z80) to allow RAM reading or writing at solely 04 clock cycles per byte moved, or 5MB/s@20MHz clock rate. But clocking the Z80 this high, can't be done by the Prop 1 and simultaneously be in Sync with the data stream.
I'm not sure, but I believe that you must use at least two cogs, one to clock and sync the Z80 control signage and the other, in a tight loop in sync with the other COG, to transfer data to/from the bus.
Sure you must code the Prop to stuff a JUMP instruction followed by two bytes to set the initial move to or from address into the Z80-side data bus. Then a Z80 NOP is to be stuffed at the registered transceiver, this will be a one time operation for the entire dataset.
A Prop pin will be used to 'convert' the /RD coming from the Z80 during instruction 'fetch' to RAM /RD or /WR, depending on the direction of the intended data flow.
The Z80 will be blindly executing a NOP for each transfered byte, and it's address bus will be moving upwards.
In fact, the limit will be stablished by the Propeller, since it will be feeding the RAM data bus with data, or receiving it from the Ram data bus at this time.
This implies the use of a 'LVC543 style registered transceiver and a couple of 'LVC style quad gates, but since it also solves completely the problem of having different voltages at the data bus and lets the Z80 run at full speed@5Vdc, I think it can be a cheap solution.
Yanomani
I have another idea. Last year averagejoe and I built a touchscreen controller using the propeller, and one of the things we found was that for games we needed to dump data out very quickly from a ram chip. After trying many solutions, including using other propeller chips, the best solution turned out to be five 74HC161 clock chips to do the ram address lines. But with Yanomani's idea, you could use a Z80 as the counter - and use it in a completely different way to its original intended use as a microprocessor.
Add a touchscreen with no extra chips? I'm going to cheat a bit here and say yes - the touchscreen has 8 data lines, /rd, /wr, /rs, /reset /cs. And there are 4 pins for the SPI touch interface. If a design is using a touchscreen then VGA is likely not needed, so can use the VGA pins to talk to the 4 spi pins and the /rs and /cs lines. I'll draw a schematic tonight.
P28 SD CS
P29 SD MOSI (data into the SD card)
P27 SD CLK
P26 SD MISO (data out of SD card)
I realized that, when you and averagejoe were doing your controller. you were constrained by the operational speed of the choosen Z80. But now, a faster CPU can be used, like the 'H or even the 'C0020 versions.
Fancier clocking options can be now be tested, and the best one selected.
In the next hours I'll be busy, elaborating a bit on the 'stuffing' sequencing protocol, including the use of a Z80 CALL instruction, wich I'm wondering if its better suited since, when properly done, will does not disrupt 'normal' programs workflow as a unlinked JUMP can do.
Stuffing a JUMP could be better suited if one uses a Propeller pin to control and extend the Z80 /RESET period. Then the synced Propeller PASM routines could handle the job on filling the RAM with proper gathered data from a SD card or another serial channel, for example, using the Z80 as a 'mule beast' address carrier.
There is also the possibility to 'sync' both processors by the use of an interlocked protocol, like /HALT then /INT or even /NMI, whichever will be better suited for the intended results.
More on that subject at a latter time!
Yanomani
@rogloh, this is a the relevant schematic of your SD/I2C sharing idea.
To clarify how it works.
1) From the SD card's point of view, if the I2C bus is running, the SD card will see /CS and MOSI toggling randomly, but the SD Clock will not be changing. I think that means no data will be clocked into the SD card so it will not respond?
2) From an I2C device point of view, if the SD card is running, like you say, the /SD_CS stays low which is also I2C clock so no data can be clocked into the I2C device.
Is there a possibility that each time the SD card is enabled, the I2C clock line goes from high to low and that very slowly something does get clocked to an I2C chip? Or do I2C devices have a timeout? Or is there a way of clearing the I2C bus?
Would a solution be to send a formal "stop bit" on the I2C bus each time the SD card is disabled eg, from wikipedia
Send a "Stop": Set SDA low, let SCL go high, then let SDA go high. This releases the I²C bus.
Yes you have the correct schematic with the same pinout as I used. I also used some pullups on SCLK and MISO.
For (1) yes if there is no SPI clock toggling it can't drive anything into the SD card to control it so the SD can't do anything. Having been chip selected yes it might drive a single high or low output voltage level into MISO but that is a separate pin and so won't upset anything on the I2C pins. SPI devices should cancel their transactions if the /CS line goes high. Certainly in my case with a common SanDisk branded SDHC card it was all fine in my simple test and I could reset the system over and over and it would recover and reboot and start playing audio each time I pressed reset. I would hope that is the typical behaviour for all cards since SanDisk pretty much wrote the spec.
The I2C boot rom should not decode anything until it sees a start on the bus which is a falling edge of SDA while SCLK is high and this won't happen if you keep MOSI high when you drop SPI /CS. That's why the SPI driver needs to be careful with what it does and why I wanted to tweak it slightly for my test to ensure there were no I2C start sequences created during SPI access.
As far as I2C bus cleanup goes I know that there is a general way to reset the I2C bus, if for example you had reset the microcontroller system while in the middle of an I2C transaction and had not reset the I2C device. Can't remember all the details here now (just google it) but I recall you need to issue some minimum number of clocks to complete and then a stop. I know without this there was a chance of I2C device lockup - have seen this in some embedded systems I've worked on in the past.
I suspect this reset is already done during boot but have not looked at Chip's initial I2C bootup sequence on the logic analyzer. Parallax probably/hopefully added a similar cleanup sequence at the first access after boot if they wanted to make sure it would be reliable after all resets.
UPDATE: googling for "i2c bus cleanup" finds the Analog Devices "Implementing an I2C Reset" Application Note as its first hit - it appears to have some useful information.
Roger.