Interfacing a microcontroller to a microprocessor

benryves

Senior Member
I was wondering if anyone here has found a practical way to interface a microcontroller to a microprocessor circuit. Even at the assembly level I don't think a PIC micro is going to be fast enough to reliably respond to a microprocessor's read/write cycle directly.

I currently perform a number of tasks (eg keyboard, mouse and I²C) entirely in software on the main microprocessor, which bogs down the main CPU when polling for input. Being able to attach a microcontroller to handle these tasks and feed the results back to the CPU as and when they are available would make things a lot smoother.

The most obvious solution I could think of would be some sort of FIFO memory. When I wanted to send a byte from the microcontroller to the microprocessor I would clock some data into the FIFO, and the microcontroller could then dequeue it at its own leisure (ideally the FIFO could also have an output pin that indicated when there was at least one byte of data stored in it, and this pin could trigger an interrupt on the microprocessor). Unfortunately, such FIFO memories don't appear to exist - at least not with an 8-bit word size.

An alternative solution may be to use another part which incorporates a FIFO as part of some other functionality - such as a UART - between the microprocessor and microcontroller, but this seems to be overkill for the task, and complicates code at both ends.
 

BeanieBots

Moderator
You say you already have I2C, then that is the obvious solution for connecting to PICAXE. PICAXE can be slave OR master.

The 28X2 has blindingly fast dedicated hardware interrupt pins.

Can't remember the part number but I've used 8bit*256 FIFO chips on Z80s in the past. (might be obsolete now).
 

benryves

Senior Member
The microprocessor (a Z80) is performing I²C in software too, which also adds quite a bit of overhead - though the PICAXE's excellent support of I²C is one of the reasons I added the hardware and routines to support it. :) I need to be polling the keyboard during program execution to detect Escape key presses and the like (I'm using BBC BASIC as the main working environment on this machine); ideally all it'd take is a single IN instruction and comparison.

I suppose another alternative would be to have a bistable that the microcontroller could set to indicate there is data available. The microprocessor could check this quickly, and if it's set it could then perform some "slow" data exchange with the microcontroller. That still feels a little messy, though.
 

BeanieBots

Moderator
Aha, the wonderful Z80.
THE processor for hooking up to hardware.
Been the best part 20 years since I did anything serious with one but I do remember how simple it was to interface with 'extras' (64k of them!).

The Z80 was specifically designed for hardware interrupts.
Polling is well, how can I put this, an insult to it's designer.

You should be able to set it up for interrupt mode 2 (IM 2) and have a 28X2 supply the address for it to run for the interrupt routine. (might need to buffer the 28X2 via a 74HC244 or similar so that the Z80 has control of the tri-state on the data bus.

Alternatively, there are (were) countless peripheral chips available including keyboard buffers.

I don't want to put you off using PICAXE but IMHO you would be better off on a Z80 forum.

Oh, happy memories:)
 

benryves

Senior Member
I agree that using interrupts would be the right thing to do, but it's the rapid control of the bus that's causing me the most headaches. I suppose that the 74HC244 latch would do the trick, plus a bistable to assert one of the Z80's interrupt pins.

Thanks for the help! :)
 

MFB

Senior Member
When I needed to exchange bytes at high speed between the buses of two different types of microprocessor, I simple cross-connected parallel interface adaptor chips from their respective families. For example, in order to link a 6502 to an 8086 the required interface chips would be the 6522 and 8055 respectively. No need to deal with bus architecture and timing differences as both parallel I/O ports worked asynchronously. Of course, this was all a very long time ago!
 

BeanieBots

Moderator
The 244 is just a tri-state buffer. 373 & 374 are latches. (one is transparent, the other is clocked but I can't rember which is which).

You don't need a bistable for the interrupt input. Just blip it.

The Z80 can run at DC (unless you are using DRAM) so if someting can't keep up, either use latches or hold the lines for a uS or two.

Not sure what you are concerned about with the timing:confused:
A 64Mhz 28X2 not keeping up with a 4Mhz Z80?
 

benryves

Senior Member
When I needed to exchange bytes at high speed between the buses of two different types of microprocessor, I simple cross-connected parallel interface adaptor chips from their respective families. For example, in order to link a 6502 to an 8086 the required interface chips would be the 6522 and 8055 respectively. No need to deal with bus architecture and timing differences as both parallel I/O ports worked asynchronously. Of course, this was all a very long time ago!
That's a good idea. Thus far I've been cobbling together I/O ports out of latches, which is rather tedious and impractical. I'm not sure what the Z80 equivalent would be (8255?) but I'll look into that.

The 244 is just a tri-state buffer. 373 & 374 are latches. (one is transparent, the other is clocked but I can't rember which is which).
Point taken. :)
You don't need a bistable for the interrupt input. Just blip it.
Most interrupt-generating hardware I've dealt with sets a flag to assert /INT which is then cleared to acknowledge the interrupt; in this case, the microcontroller could check that the flag had been cleared so that it knew it could generate the next interrupt.
That said, none of the Z80 machines I've used have done anything meaningful with the data bus when interrupting (IM 1 only), so checking these flags is the only way to work out which bit of hardware generated the interrupt request.

The Z80 can run at DC (unless you are using DRAM) so if someting can't keep up, either use latches or hold the lines for a uS or two.
I've been "cheating" and using SRAMs. :)

Not sure what you are concerned about with the timing:confused:
A 64Mhz 28X2 not keeping up with a 4Mhz Z80?
Would a 64MHz PICAXE be able to react to the read/write cycles of a 10MHz Z80? I wouldn't have thought it likely (and the fastest PICAXE I have is only 8MHz in any case!)
 

BeanieBots

Moderator
If you are asking if a PICAXE could pretend to be a memory location on the Z80 bus and respond to read/write pulses by placing data on the bus, then it's a categoric NO if the Z80 is running at anything over a few hundred hertz.

If you map it onto the I/O space via a '244, it could set up the command, address or whatever is required, THEN interrupt the Z80, which then reads the data by enabling the '244.

If you are not using IM 2, then you will need to use both '244 and '373 to map it onto a memory location and read it that way.

Alternatively, get a Z80 PIO chip which does all that in hardware in one 40 pin chip. It can be configured to interrupt on any combination of any inputs on any of the ports. Your interrupt mode will determine what happens next.
The PICAXE can then chat away at leasure to the PIO and vice versa.

Can you use a PICAXE to replace the PIO, NO. (unless you underclock the Z80)
 

moxhamj

New Member
What a fascinating discussion. To add to the excellent points already mentioned above, maybe head on over to the N8VEM forum as this is being actively discussed. There are some circuits around using the Propellor to trap rd/wr pulses in real time and the prop runs at 80mhz, so maybe a 64Mhz 28x2 can do it too?

Re the keyboard, I've got some Z80 assembler reading a keyboard. The trick is to poll the keyboard only infrequently and ask if it has any output. It is all a compromise but I've found skipping 199 out of 200 checks is a good compromise between potentially missing keys vs slowing down other programs. Code is on the N8VEM forum.

244 is great for input. 373 for output. Or 8255 - it probably isn't important which one you use.

Picaxe and Z80 both have strengths and weaknesses so there are some fantastic synergies. I'm using picaxes for all real world input/output and using a standard comms system of RS232 at 1200 baud, though picaxes can of course go faster. Z80 is good for having an operating system and the ability to load and run different programs, so a board can contain 20 differerent programs and you can run the one you want.

Then there are cunning techniques like daisy chain interrupts or using /busrq to take control of the busses and write directly to the memory.

Do you have some schematics/photos of your setup? Maybe we can exchange some code too - eg swap I2C code for keyboard code?

Addit: found your website - looks very interesting...
 
Last edited:

benryves

Senior Member
If you are asking if a PICAXE could pretend to be a memory location on the Z80 bus and respond to read/write pulses by placing data on the bus, then it's a categoric NO if the Z80 is running at anything over a few hundred hertz.
I assumed as much.

Alternatively, get a Z80 PIO chip which does all that in hardware in one 40 pin chip. It can be configured to interrupt on any combination of any inputs on any of the ports. Your interrupt mode will determine what happens next.
The PICAXE can then chat away at leasure to the PIO and vice versa.
The Z84C2010PEG looks like the easiest solution, then, though it'll probably have to be imported from the US. Many thanks for your help!

What a fascinating discussion. To add to the excellent points already mentioned above, maybe head on over to the N8VEM forum as this is being actively discussed. There are some circuits around using the Propellor to trap rd/wr pulses in real time and the prop runs at 80mhz, so maybe a 64Mhz 28x2 can do it too?
Thanks for the suggestion, I'll take a look there.
Re the keyboard, I've got some Z80 assembler reading a keyboard. The trick is to poll the keyboard only infrequently and ask if it has any output. It is all a compromise but I've found skipping 199 out of 200 checks is a good compromise between potentially missing keys vs slowing down other programs. Code is on the N8VEM forum.
I've been inhibiting data transfers from the keyboard/mouse by holding the clock line low and releasing it when I want to poll. It seems to work relatively well, though I do occasionally get duplicated keys if I press them too quickly - I assume I'm missing the "break" byte somewhere along the line.
Do you have some schematics/photos of your setup? Maybe we can exchange some code too - eg swap I2C code for keyboard code?
My I²C code is not very robust (hard-coded timing) or extensively tested, but if you're interested I'd be happy to drop you a copy. This page has the keyboard and mouse code, but I don't have any schematics for the system itself (I haven't worked on it in ages, due to work constraints!)
 

moxhamj

New Member
Yes if you are getting duplicated keys then you can tweak some delay variables - see routine below.

There is also the other option of using a picaxe 18X as the keyboard interface chip, and the 18X could also probably handle a display as well and ?? a mouse.

Or a PockeTerm (Briel Computers) that uses a Propeller and runs a VGA screen/keyboard and talks via stardard RS232.

So there are a few options.

BTW I like the work you have done with the graphics displays! (That ought to be picaxe-able).

Code:
;-----------------------------------------------
; wait for a byte - tests a number of times if there is a keyboard input,
; overwrites all registers, returns byte in a
;-----------------------------------------------
; if make the time too short, sends two characters instead of 1 as misses the F0 of keyup
; this was written with a clock of 3.68Mhz - may need to increase value in b if errors
; if the waitbyte counter is too short then this manifests as two letters per keypress
; because it misses the F0 keyup character
; at 8Mhz works with hl=250, fails at 175. Make it 500 to be sure
waitbyte:	
		call	clockhigh	; turn on keyboard
		ld 	hl,500		; number of times to check 200=slow TYPE , 10=error, 25 ?error 50 ok - this delay has to be there otherwise weird keyup errors
wb1:		push 	hl		; store counter
		call 	readbits	;test for a low on the clock line
		pop 	hl		; get the counter back
		cp	0		; test for a zero back from readbits
		jr	nz,wb2		; if not a zero then must have a byte ie a keyboard press
		ld	de,1		; load with 1
		sbc 	hl,de		; subtract 1
		jr	nz,wb1		; loop waiting for a response
wb2:		push 	af		; store the value in a
		call 	clocklow	; turn off keyboard
		pop af			; get back byte as clocklow erased it
		ret
 
Last edited:

Brietech

Senior Member
I'm not sure what your hardware background is like, but I was able to successfully interface a Spartan3 FPGA into the system bus of my Kaypro 2/84 (a Z80 machine) quite easily, and then you can add *whatever* you want (including multiple 'soft' Z80s, that you could probably run closer to 75 MHz!!).
 

Attachments

moxhamj

New Member
Say what?! 75Mhz? The propeller guys have emulated a Z80 on a Prop. What is next, emulating a superfast picaxe on a FGPA?

Nice setup. How much are FGPA chips?
 

BeanieBots

Moderator
A very good point about the Z80 bus request.
As Gwillo is using SRAM, there's no reason why a 28X2 could not request the bus and shove whatever straight into RAM. Might need a few logic tricks to get the address bus sorted but that would depend largely on the existing decoding method used.

Thinking more about it, the 28X2 @64Mhz just might be quick enough.
It could certainly respond to the data request in a timely manner by using the hardware interrupt pins but the issue would be if it could present data to the bus quick enough. Maybe a clever little bit of logic to reduce the Z80 clock speed while the 28X2 does its stuff.

Still think a Z80 PIO is the way to go. It's all done for you in one chip.
It's well... it's what they were designed for. Bit of a no brainer really!
Same with keyboards. Get a keyboard chip complete with buffer and just map it to that wopping 64k of IO space the Z80 gives you. These are the reasons I love the Z80 so much.

EDIT: There is (was?) also a Z80 specific dual port RAM chip.
 
Last edited:

MFB

Senior Member
BeanieBots, Quite agree about the PIO approach. That’s what I meant by “no need to deal with bus architecture and timing differences as both parallel I/O ports worked asynchronously”. The PIO had an automatic handshake mode that overcomes many bus-timing issues. Btw, is the 8055 still available?
 

Brietech

Senior Member
Most starter FPGA boards are in the $99-$200 range. The one wired into my kaypro in that picture (I actually just found a socket for a missing PIO chip and sort of emulated one) could emulate about ~1 million "gates," and also included 32MB of SDRAM, and a built in resistor-network DAC to a VGA port.
 

benryves

Senior Member
I definitely think I'll go down the PIO route now, so thanks for the suggestion - though the idea of writing directly into RAM is certainly interesting!

I haven't really worked with any sort of programmable logic in any great detail, so this would seem like a good place to give it a try - though it's quite a bit more expensive a solution than using a PIO, and would also feel a little like cheating. ;-)

Regarding a buffered "keyboard chip", does anyone have any part numbers or links on that? I haven't been able to find anything myself.

Cheers for the advice!
 

benryves

Senior Member
My intention was to use an existing (unmodified) PS/2 (or AT) keyboard, and as far as I can tell that particular IC is designed to scan a keyboard matrix and generate AT/XT signals. Sorry if I'm reading that incorrectly!
 

BeanieBots

Moderator
Correct, it is a Z80 specific keyboard scanner.
Sorry, don't know of anything that could be used to buffer PS/2 type data stream. (besides a PICAXE + PIO or DMA).
 
Top