News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

Interfacing CPC with a microcontroller

Started by joska, 11:27, 11 July 14

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

joska

I want to connect an Arduino or similar to my CPC in order to let the CPC interact with the outside world. I've had Z80-computers since the early 80's (Sharp MZ and MSX) but I've never worked with the Z80 at this level before.

I found this interesting MSX project: Coding Laboratory: Virtual MSX disk drive

Basically it has a simple address decoder that pulls the WAIT/READY line low to force the Z80 to wait until the microcontroller has either read the databus or written to it. Then the microcontroller release WAIT/READY and the Z80 continues.

This looks rather easy, but can the same concept be used on the CPC?

Bryce

As long as you don't hold the wait signal low for too long it should be fine.

Bryce.

joska


Nilquader

Take a look at the CPC Booster+ - That's an ATMEGA connected to the CPC Bus. CPC Booster - CPCWiki
--
Nilquader of SPRING
http://www.nilquader.net/

MacDeath

#4
I already asked this.

to have such stuff woud need :
=cabling properly the Arduino to CPC.
=have some library on both the arduino and CPC to have them do stuff together.

good point with arduino :
you can get the ethernet shield and its micro-SD card plug used as ethernet/internet, or mass data storage...

with such a shield, you may emulate an HDD or Floppy dfisk or even ROMs perhaps, or get online.
the arduino could also be used to perform some additional tasks or functions I guess, like arithmetic functions or whatever...

yeah the ethernet shield doesn't allows to use both the SD card or the ethernet at the same time, not a big deal...

Really I don't understand why no coder-hobbyist did stuff like that.


Anyway, would be cool if TotO could create the cable to plug an Arduino Mega a theses models have a lot of I/O so you may put both an ethernet shield and the CPC) into his MotherX4... had to be the perfect combo and the way to properly use the 4th slot.

lemme check :
MotherX4 : done.
=plAY-CiTy : soon.
=X-MEM : done.
=Booster : done
=empty slot for Arduino then... :P

joska

Quote from: Nilquader on 12:00, 11 July 14
Take a look at the CPC Booster+ - That's an ATMEGA connected to the CPC Bus. CPC Booster - CPCWiki

Thank you! Very useful. I just took a look at the schematics and it looks like I only need to implement a subset of the CPCBooster to do exactly what I need :)

steve


Bryce

Quote from: joska on 11:47, 11 July 14
So how long would "too long" be?

The RAM isn't being refreshed while the /WAIT signal is held low, so more than a couple of milliseconds will cause the RAM to become corrupted or deleted completely.

@Steve: Yeah sure.

Bryce.

MacDeath

#8
QuoteYou could link the CPC to a RPi.
yeah, the CPC being some sort of fancy terminal : big Video Display, soundcard and control/keyboard card...
:laugh:

QuoteSo how long would "too long" be?
this would be something like 33 bit or even more...65.537 would be enough to be "too long".
;)

steve

I saw a blog where someone had connected one to a C64 if I find the post again I will provide a link here.
There is no difference (conceptually) between connecting a CPC to an RPi and connecting a PC to a server.

joska

Quote from: MacDeath on 12:21, 11 July 14
I already asked this.

to have such stuff woud need :
=cabling properly the Arduino to CPC.

Basically you need two TTL logic chips to create the address decoder and a 74245 to buffer the databus.

Quote from: MacDeath on 12:21, 11 July 14
good point with arduino :
you can get the ethernet shield and its micro-SD card plug used as ethernet/internet, or mass data storage...

It would be very easy to use the Arduino/whatever to interface with an SD-card, giving the CPC either direct access to individual SD card sectors or even file system access (FAT driver on the Arduino). However, that would require a custom DOS on the CPC, which if far beyond my capabilities.

Quote from: MacDeath on 12:21, 11 July 14
with such a shield, you may emulate an HDD or Floppy dfisk or even ROMs perhaps, or get online.

Depending on the microcontroller I guess it would be rather straightforward to emulate the FDC. But I don't think it would be very practical to emulate a ROM-card.

Quote from: MacDeath on 12:21, 11 July 14
yeah the ethernet shield doesn't allows to use both the SD card or the ethernet at the same time, not a big deal...

I don't see the problem at all. True, both SD-cards and the various ethernet-modules use the SPI-interface, but the SPI-bus can be shared.

Anyway, my goal is not to create some sort of super-expansion for the CPC. I just want to learn something new. I might create a Symbiface compatible mouse (which would be useful to me), but I might also end up with nothing usable at all.

MacDeath

QuoteHowever, that would require a custom DOS on the CPC, which if far beyond my capabilities.
pretty sure FutureOS could handle that... :D

joska

Quote from: steve on 12:35, 11 July 14You could link the CPC to a RPi.

I could, but that would be overkill for my needs. Also, it would cost 10 times as much as a simple Arduino-clone. Btw. what would you use the RPi for?

joska

Quote from: Bryce on 12:38, 11 July 14
The RAM isn't being refreshed while the /WAIT signal is held low, so more than a couple of milliseconds will cause the RAM to become corrupted or deleted completely.

I see. A simple ATmega 328 would perform 16000 instructions in 1ms at 16MHz, so I don't think that would be a problem.

steve

Quote from: joska on 12:52, 11 July 14
I could, but that would be overkill for my needs. Also, it would cost 10 times as much as a simple Arduino-clone. Btw. what would you use the RPi for?

Fileserver, internet connection, attach a camera and convert the pictures to some format that could be used as graphics in your programs.

nicf82

I'm having a go at implementing something similar to this for my first hardware project  :o

So I have managed to implement the address decoder, which after consulting this page to check for a free port, is working on port F300 and is implemented using NANDs and ORs as per the diagram attached.

I have a program running on the Arduino which will read the value at /G on the 74245 and if its low, it'll print out the byte on the data bus. The weird thing is that if I send an OUT &F300, 1, I dont see any output - but if I run a loop sending the same value, I see a lot of 0x80 (not 1??) values received. I'm assuming it might be something to do with timing, and more specifically maybe I need to hold the WAIT/READY low while I read from it. I tried connecting an Arduino pin to WAIT/READY, defaulted to HIGH, so i can pull it low when needed, but it just crashes the CPC - I'm assuming because it should not be constantly HIGH. The OP pointed to a tutorial written for an MSX where the guy ANDs his /G and his Arduino WaitEnable pin, but I'm struggling to follow the logic there. If anyone has any help on what is going on there that would me much appreciated!

Bryce

I assume you are using an interrupt to react to /G? Anything else might be too slow (depending on the clock speed of µP).

Bryce.

nicf82

Ah! Thanks Bryce. No actually I'm just doing a digital read in a tight loop - I'll check out how to implement an interrupt. Its an ATMEGA328 which I think is running at 20Mhz.
The concern in the back of my mind is even if I react to /G very quickly, by the time I have read the D0-D7 pins they could have changed - so presumably that is the purpose of the WAIT/READY signal?

Bryce

If D0 to D7 are all connected to the same port of the 328 you can read them with a single command immediately within the interrupt. /G should be connected to a different pin of the AVR and used to trigger the interrupt. At 20Mhz that shouldn't be an issue.

Bryce.

nicf82

Brilliant, I'm getting there thanks! - I've implemented it as an interrupt and now its responding every time, not only when I put it in a loop to bombard it with data!
Yes I remember reading you can read them as a single byte using PINB, ill try that next! The only problem I can think of is that interrupts only work on pins 2 and 3 which are part of the large 8 pin port I'd need to use to read a byte in one go. I'll try and come up with a solution

CheersNic

pelrun

The 328 also has pin-change interrupts on each pin, so you're not restricted to just the INT0/1 pins.

nicf82

Thanks pelrun, I got the pin change interrupt working, only as it's pin change it gets fired twice going low then going back high. Also still not getting the correct data off the data bus! Will keep on persevering though...

nicf82

OK, got it working finally!

What I did was basically the same as the first example in this thread - I connected G to an OR gate along with a signal from the Arduino I called FORCE_READY (maybe it should be called FORBID_WAIT or something). FORCE_READY sits low normally so the only thing keeping /WAIT high is G. As soon as G drops low, it pulls /WAIT low with it to give me time to read the bus, then once I have the data I set FORCE_READY high which makes /WAIT go high, the Z80 will move to next instruction so /G will be HIGH again, which I wait for, then set FORCE_READY low to wait for the next interrupt.

Next steps will be to figure out how to send data, but I can see there are a few clues in the first example again  :)

Thanks for all the help and pointers!


Nic

nicf82

I managed to get sending from device to the CPC working, I was not too difficult in the end, just needed to add an AND gate to handle either /WR or /RD going low then as described by Raul use the /RD signal to control the 74245's DIR pin.

One weird think I have noticed, and could do with some clarification on, is that when I plug in my DDI5, the data received is incorrect. I'm sending 255, but the CPC is getting 223 - seems bit 5 on the data bus is being held low for some reason. Removing the DDI5 fixes the problem, so guessing that the IO address I'm using (0xF100) has some conflict with it.

I went over to the IO Port Summary page again to check, but the DDI5 isn't listed, so I figure that the addresses for the 765 FDC which presumably it is emulating will be the same or at least compatible. My main question is around the Decoded As column on this page - if I'm understanding this correctly, it only actually looks at 4 bits in the address bus here to determine the address - seems like that is a lot of potential for conflict? E.G to find I/O requests to #FB7E, it ignores the majority of the bits and only checks 0,7,8 and 10 %xxxxx0x1 0xxxxxx0 is that right? Could that be why I'm seeing issues - my address F100 in binary is  %11110001 00000000 so it would actually match that pattern. The reason I'm questioning it is because I'm sure I must have misunderstood something here because surely that would conflict with loads of devices?

pelrun

#24
Yup, partial decoding is the norm rather than the exception as far as CPC internal devices go. While most addresses in the 16-bit IO space are conflicted due to the partial decoding, there is always at least one address for each device that unambiguously addresses it. So it's the responsibility of the code to avoid the ambigious ones. Basically that means putting 1's in every don't care bit position, which (unsurprisingly) results in the "standard" address for that device.
To find a free address for a new peripheral, it's necessary to start from an IO address with all 5 highest bits set (i.e. 0b11111xxx xxxxxxxx or ANDed with 0xF800). All the standard internal devices have at least one of those five bits set to 0. After that it's just a matter of picking an address that doesn't collide with an existing peripheral, which is still pretty easy if you're doing full decoding and only after a couple of addresses.

Powered by SMFPacks Menu Editor Mod