Processor comms to hardware?
Processor comms to hardware?
Hi guys. First, hope ya'll don't mind my large amount of topics but well.. anyway, if you don't know by now, I am working on designing a "simple" processor which is a bit of a ramped up version of the 6502. So, as a bit of background, if any of you play minecraft and play with mods, you may have heard of a mod called RedPower2. This mod added its own custom processor called the 65EL02 which is a 6502 and a few other processors together. In the code for the emulator, there is a fairly simple system for the processor to communicate with hardware devices. In my emulator I could easily create something like this however as far as hardware goes I am a bit clueless. My main question is how would I go about implementing some sort of hardware communication system? Like I said, I could EASILY create a system in the emulator but as far as the hardware (real hardware not virtual) goes, I'm not sure at all...
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Processor comms to hardware?
The most common I/O IC to connect to a 6502 is the 6522 (or preferably, the 65c22) VIA. It lives up to its name, "Versatile Interface Adapter."
I've use the synchronous-serial port for many things including a 9-level PWM which was quite adequate for generating DTMF (for phone tone pairs for dialing) and even voice audio without a D/A converter. I have a lot of tips on things you can do with this IC in my Tip of the Day topic, and in the 6502 primer, particularly in the circuit potpourri page. The best way to learn the VIA is just to read the data sheet.
The next most common one to interface to a 6502 might be the 6551 (or preferably the 65c51) ACIA, or Asynchronous Communications Interface Adapter (basically the same as a UART, or Universal Asynchronous Reciever/Transmitter), which is commonly used for RS-232 (TIA-232) or similar. The NMOS one had a bug, or maybe just a dumb design feature, that was corrected in the CMOS version, so I recommend the latter. I have used it with no problems, including for MIDI (musical instrument digital interface) which runs at 31.25kbps [Edit, 6/12/20: and more recently used it at 115.2kbps]. There are other popular UARTs like the 16550, the 2692, and one I have exercised but not put into actual service, the 14-pin-DIP SPI-interfaced MAX3100.
You'll see in my links above that I've bit-banged SPI on the VIA which is very easy but if you want maximum speed with less processor overhead you can use Daryl's 65SPI chip.
My I/O ICs page lists many others, most of which are no longer in production; but there are ways to interface almost anything on the market. The displays page mentions some video & display options, and for anything that doesn't need absolute maximum speed, you can go through the VIA for SPI or I²C and do almost anything, as there are thousands of ICs on the market available with those interfaces to do more functions than you can shake a stick at.
- It has two 8-bit parallel ports
- with additional read & write hardware handshake lines you can optionally use for something like a printer port,
- each bit of the parallel ports is individually programmable to be input or output,
- it has two timer/counters with lots of modes of operation,
- a synchronous-serial port with seven modes of operation,
- and seven sources of interrupts (individually enableable),
- including negative or positive active edges on particular lines.
I've use the synchronous-serial port for many things including a 9-level PWM which was quite adequate for generating DTMF (for phone tone pairs for dialing) and even voice audio without a D/A converter. I have a lot of tips on things you can do with this IC in my Tip of the Day topic, and in the 6502 primer, particularly in the circuit potpourri page. The best way to learn the VIA is just to read the data sheet.
The next most common one to interface to a 6502 might be the 6551 (or preferably the 65c51) ACIA, or Asynchronous Communications Interface Adapter (basically the same as a UART, or Universal Asynchronous Reciever/Transmitter), which is commonly used for RS-232 (TIA-232) or similar. The NMOS one had a bug, or maybe just a dumb design feature, that was corrected in the CMOS version, so I recommend the latter. I have used it with no problems, including for MIDI (musical instrument digital interface) which runs at 31.25kbps [Edit, 6/12/20: and more recently used it at 115.2kbps]. There are other popular UARTs like the 16550, the 2692, and one I have exercised but not put into actual service, the 14-pin-DIP SPI-interfaced MAX3100.
You'll see in my links above that I've bit-banged SPI on the VIA which is very easy but if you want maximum speed with less processor overhead you can use Daryl's 65SPI chip.
My I/O ICs page lists many others, most of which are no longer in production; but there are ways to interface almost anything on the market. The displays page mentions some video & display options, and for anything that doesn't need absolute maximum speed, you can go through the VIA for SPI or I²C and do almost anything, as there are thousands of ICs on the market available with those interfaces to do more functions than you can shake a stick at.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Processor comms to hardware?
sci4me wrote:
My main question is how would I go about implementing some sort of hardware communication system? Like I said, I could EASILY create a system in the emulator but as far as the hardware (real hardware not virtual) goes, I'm not sure at all...
The 6502 family (among others) uses Memory Mapped I/O. That is, is treats I/O just like it does memory. If you want to determine the values of something (like switches), you read a byte. If you want to change the values (like LEDs), you write a byte.
In contrast, the Intel family of processor historically have specialized IN and OUT instructions, and control pins on the CPU to drive I/O devices.
So, on a 6502, if you wanted to read the value of a serial port, you'd just do something like LDA $1234, where $1234 is the address of the serial port. On an Intel device, you would do something like IN $12, which would read device mapped to $12.
The chips that Garth was referencing are the devices that turn those "memory" references in to real work. For assorted reasons, you don't want to just hang I/O things (like switches and LEDs) straight on the address and data bus, so there are other chips that make that much easier and simpler.
As far as implementing I/O in a simulator, it's quite simple. You have code in your low level memory read and write routines and then handle the I/O. You can do this simply, on my simulator, I have a byte mapped for reading the keyboard and one for displaying a character on the terminal. When the simulator does a STA $C001, my memory write routine checks for the special address and simply calls the internal "display character" routine, that handles the screen address, scrolling, etc.
Normally, a memory write is simply setting an array value: memory[address] = value. When the special address is encountered, it calls the appropriate routine. A downside of my technique is that from a clock time perspective, writes to the character output byte take "longer". The CPU increments the correct number of cycles, but actual, wall clock time, is much longer than setting an array value, it does a lot more actual work in the simulator.
This is fine for my purposes, I don't have strict timing, but you can see that if you did, you'd have to compensate for that somehow.
I also have Disk I/O in the same way. Put the start address in two special bytes of memory, set the disk block number in two other bytes (65536 total blocks), and then store a 1 or a 2 in to the control byte, and, magically a 512 byte block of memory is written to disk, or read from it. Super simple.
Here's the fragment from my Forth:
Code: Select all
0270 c000 CHAR_READY = $C000
0271 c001 CHAR_IN = $C001
0272 c002 CHAR_OUT = $C002
0273 030f
0274 030f ad 00 c0 GETKEY LDA CHAR_READY
0275 0312 f0 fb BEQ GETKEY
0276 0314 ad 01 c0 LDA CHAR_IN
0277 0317 60 RTS
0278 0318
0279 0318 8d 02 c0 OUTCHAR STA CHAR_OUT
0280 031b 60 RTS
Here's the Forth using the Disk I/O
Code: Select all
3403 1715 ;
3404 1715 ; Disk Control addresses
3405 1715 ;
3406 c003 DSK_SEC_LO = $c003 ; Low byte of disk sector
3407 c004 DSK_SEC_HI = $c004 ; High byte
3408 c005 DSK_SEC_COUNT = $c005 ; Number of sectors to operate on
3409 c006 DSK_ADDR_LO = $c006 ; Low byte of memory address
3410 c007 DSK_ADDR_HI = $c007 ; High byte
3411 c008 DSK_RESULT = $c008 ; Operation result code
3412 c009 DSK_MODE = $c009 ; Operation mode: 1=READ, 2 = WRITE
3413 c00a DSK_CTL = $c00a ; Write non-zero to start operation
3451 1763 ;: R/W ( addr sec f )
3452 1763 ; 0= IF 2 ELSE 1 THEN R> ( Push read flag on to return stack )
3453 1763 ; DSK_SEC_LO ! ( store sector, no need to range check -- 0-65535 )
3454 1763 ; DSK_ADDR_LO ! ( store buffer )
3455 1763 ; R> DSK_MODE C! ( store r/w flag )
3456 1763 ; 1 DSK_SEC_COUNT C! ( 1 sector )
3457 1763 ; 1 DSK_CTL C! ( perform transfer )
3458 1763 ; DSK_RESULT C@ 1- 8 ?ERROR;
Why did I pick this scheme for Disk I/O? Seemed like the thing to do at the time, it's not based on anything. Why did I map my I/O at $C000? Same reason.
Now you can make your simulator more accurate, do interrupt processing for I/O, etc. I haven't. My needs haven't been that strict. But you can certainly go there.
Re: Processor comms to hardware?
So now I need to try to understand how the mapping works... In my simulator, I have an (java stuff ahead) interface called IRAM which has ramRead, ramWrite and reset in it, this is the memory i use inside the processor, is this also where i would do the peripheral interface? If so then it shouldn't be named IRAM any more but more like IBus or something like that right?
And by the way, thanks for the responses, very informative!
And by the way, thanks for the responses, very informative!
Re: Processor comms to hardware?
sci4me wrote:
So now I need to try to understand how the mapping works... In my simulator, I have an (java stuff ahead) interface called IRAM which has ramRead, ramWrite and reset in it, this is the memory i use inside the processor, is this also where i would do the peripheral interface? If so then it shouldn't be named IRAM any more but more like IBus or something like that right?
Code: Select all
public interface Memory {
public int fetchByte(int addr);
public void putByte(int addr, int value);
public int fetchWord(int addr);
public void putWord(int addr, int value);
}
Code: Select all
public int fetchByte(int addr) {
if (addr == CHAR_READY) {
return terminal.hasKey() ? 1 : 0;
}
if (addr == CHAR_DATA_IN) {
return terminal.getKey();
}
return ram[addr];
}
Re: Processor comms to hardware?
Okay, thats similar to mine I suppose. I think I got it... btw is your simulator OS? If so, gimme XD for reference.. also I am interested in playing with it. But I still have the question (which may be stupid of me at this point) of how you actually map the device to the processor.. how you tell the processor how to talk to the device.. The way it was done in the 65EL02 is basically each device has an ID and it used a MMU to map the id to the actual device and send commands to it.. is this a realistic way to implement it? If so i'll just do it that way..
Re: Processor comms to hardware?
sci4me wrote:
But I still have the question (which may be stupid of me at this point) of how you actually map the device to the processor.. how you tell the processor how to talk to the device..
Once you have a chip on the data- and address-bus you can use it to communicate to other hardware "indirectly" by using f.i a VIA I/O to drive a LCD Display.
One example: I'm playing currently with are 74HC574 octal D-flipflop chips. They can be easily used as input and output device for 8 I/O lines.
These chips have 8 input-lines that I connected directly to the data bus. The 8 output-lines are driving 8 LEDs for a visual effect. The 74HC574 has also a /OE line, which is called "Output Enable". The "/" before the name is important, because it tells you that this line is "low" active. This means if the line is pulled down to GND the chip is active, otherwise not. The chip has also a "LE" Input (Latch enable) that is high-active. If this input gets an LOW-to-HIGH change it takes the data from the 8 input lines and present it on the output lines (permanently as long as the /OE line is LOW).
To talk to my 74HC574 as device on the bus I use my address-decoding logic that generates the "LOW-HIGH-LOW" pulse for the LE input of my device, whenever the address $a000 is set to the address-bus.
So my 65C02 does not now about this special device, it only writes a byte to the specific address $a000 and the bit-pattern of the bytes shoes up on the output lines of the 74HC574, because the chip is activated by the address $a000.
For all other memory mapped chips its the same. You generate a Chip-enable signal for the peripheral chip to activate it for specific addresses. Then the chip itself is responsible for reading or writing data to the databus.
This is really simple and clever, because you do not need special I/O commands to hook almost any device that supports "chip-enable" to your MPU.
For your emulator you can create a "base class" the provides that simple mechanism. It could "register" itself on your address-bus and whenever a byte is read or written to a specific address an instance of this device has registered to, you can delegate this read/write to this instance. This follows the hardware concept straight forward. From the base-class you can then derive any I/O device you'd like to implement.
Mario.
How should I know what I think, until I hear what I've said.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Processor comms to hardware?
Quote:
I still have the question (which may be stupid of me at this point) of how you actually map the device to the processor. How you tell the processor how to talk to the device.
I'll add another example of register addresses beyond what's shown in my address-decoding page for I/O IC addresses. As the others pointed out, the 6502 uses memory-mapped I/O. So suppose you have a VIA whose base address is at $6000. It has 16 registers, and they will be at addresses $6000 to $600F in the memory map, and as far as the processor is concerned, they might as well be memory. It doesn't care. It just does its job, and the VIA does its job, and things happen as they should. Your code will include something like:
Code: Select all
VIA1: EQU $6000 ; Base address of VIA 1
VIA1_PB: EQU $6000 ; port B
VIA1_PA: EQU $6001 ; port A
VIA1_DDRB: EQU $6002 ; data direction register B
VIA1_DDRA: EQU $6003 ; data direction register A
VIA1_T1CL: EQU $6004 ; timer 1 counter low byte
VIA1_T1CH: EQU $6005 ; timer 1 counter high byte
VIA1_T1LL: EQU $6006 ; timer 1 latch low byte
VIA1_T1LH: EQU $6007 ; timer 1 latch high byte
VIA1_T2CL: EQU $6008 ; timer 2 counter low byte
VIA1_T2CH: EQU $6009 ; timer 2 counter high byte
VIA1_SR: EQU $600A ; shift register
VIA1_ACR: EQU $600B ; auxiliary control register
VIA1_PCR: EQU $600C ; peripheral control register
VIA1_IFR: EQU $600D ; interrupt flag register
VIA1_IER: EQU $600E ; interrupt enable register
VIA1_PANOHS: EQU $600F ; port A, but with no handhshakingSo let's say you want to set up port B for all outputs except bits 7 and 6. You would do:
Code: Select all
LDA #00111111B
STA VIA1_DDRBThen suppose you want to set the output bits to 010110B. You might have relay drivers, lights, audio muting, or something else connected to each bit. You could do:
Code: Select all
LDA #010110B
STA VIA1_PBYou just wrote zeroes to bits 7 and 6, but it will have no effect at this time since they are inputs, not outputs. If you read them, they will show what's being input from the pins, not what you just wrote to the port. (If/when you change those bits to outputs, then they will take on the values you wrote to them.)
If you had a relay driver connected to bit 0 and a high output would actuate the relay and that's what you wanted to do, you could do:
Code: Select all
LDA VIA1_PB
ORA #1
STA VIA1_PBor, if you knew for sure that bit 0 was already a 0, you just increment it to a 1 without affecting the other bits:
Code: Select all
INC VIA1_PBThe data-direction register turns out to be a nice thing for the equivalent of an open-drain output, which is how I do the I²C interface. You just leave a 0 in the output latch, pull it up with a resistor from the outside, and then change the bit's direction by writing to the data-direction register (DDRA or DDRB). When you make it an output, it pulls it low. When it's an input, you can read it to find out if something else is pulling the line low, or if the pull-up resistor is being allowed to pull it up to Vcc.
That of course only addresses the two parallel ports and their data-direction registers; but the addressing works the same way for the other registers too. (The operation is slightly different on the interrupt-enable register, so you can enable or disable an interrupt source without reading and ANDing or ORing a bit in or out.)
There's a load of applications, interfaces to real-world circuits, plus in many cases code to go with it, on the circuit potpourri page of the 6502 primer.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Processor comms to hardware?
Okay, I think I understand now. My next question is about the addresses of devices... are the addresses hardcoded? If so, don't some devices overlap?
Re: Processor comms to hardware?
Typically, you arrange for devices to not overlap, although there are some schemes where devices are... "incompletely decoded" (meaning that the device "doesn't care" what some of the address lines are), but each have a preferred base address, and specific combinations of "don't care" address bits can be used to select multiple devices at once... Though you'd only want to do this for writing, not for reading. Bus contention isn't fun.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Processor comms to hardware?
sci4me wrote:
Okay, I think I understand now. My next question is about the addresses of devices... are the addresses hardcoded? If so, don't some devices overlap?
You determine their base addresses when you design your address-decoding circuit. The simplest address-decoding schemes will cause "mirrors," meaning that some devices may show up at more than one address; but that's ok, as long as there are addresses that let you talk to each device individually and there's no bus contention. Beginners tend to make it much more complex than it needs to be, leading to more work, parts, and board space, plus excessive propagation delays, limiting the speed the system can work at.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Processor comms to hardware?
To be honest, I think it is a lot simpler than it seems. For some reason though, it seems confusing to me. IDK why.. but like I said, I think i got it now.
Re: Processor comms to hardware?
Sorry to bump, but I just realized something. I was being a total idiot. Not really sure why it took me until just now as I am testing the first version of my emulator to realize that you can do something like this:
to (in my case atm) write an A to the terminal. I feel stupid.
Code: Select all
LDA #65
STA #8800
- BigDumbDinosaur
- Posts: 9428
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Processor comms to hardware?
sci4me wrote:
Sorry to bump, but I just realized something. I was being a total idiot. Not really sure why it took me until just now as I am testing the first version of my emulator to realize that you can do something like this:
to (in my case atm) write an A to the terminal. I feel stupid.
Code: Select all
LDA #65
STA #8800
x86? We ain't got no x86. We don't NEED no stinking x86!
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Processor comms to hardware?
IOW, if the port register is at address $8800, just remove the # and make it STA $8800.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?