Jump to content

PS/2 Mouse working with ATTINY and I2C


Wavicle
 Share

Recommended Posts

Some more good news to share with everyone... Big shout outs to @Stefan and @ZeroByte for many hours of help with code and debugging both on the ATTINY SMC and KERNAL while getting this working. I haven't yet found a game or application to show off the mouse in action that works on R41, let me know if there's a diamond out there that I've overlooked.

 

  • Like 7
Link to comment
Share on other sites

as quoted from the ides of march status post now we have 2 competing standards:

Quote

As for the keyboard.  Originally we were bit-banging the PS/2 keyboard from one of the 6522 chips.  This presented problems and Michael Steil was not able to get it working reliably, so we tried moving that function over to the little micro-controller that was in charge of the power/reset systems.  We figured we’d talk to the micro-controller via I2C.  Frank was going to get this working for us, but he was having trouble with it, and there hasn’t been any word from him in months.

So, we had a meeting today between me, Kevin, and Adrian Black and brainstormed ideas.  We decided to replace the micro-controller with a larger one that has enough legs to integrate onto the main memory bus.  This way it can appear as 1 or 2 memory address registers.  It can read the PS/2 key up/down signals and place them in a buffer to be read in as bytes from that address.  This should make integration into the kernel much simpler. In reality, this is how the original IBM PC worked, so there’s nothing inappropriate about doing this.

Kevin and I talked about possibly building a small cartridge for the C64 that has the microcontroller and a PS-2 port.  This way kevin could test the microcontroller code and I could write some preliminary 6502 code to prove it all works. Then hopefully somebody could integrate that into the X16 kernel. It’s really hard to test stuff on the X16 when you have to burn a ROM chip every time you want to make a change. That will be solved once we have a working keyboard and file system.

  • PS2 ->Attiny-> I2C-> 6522->main bus-> CPU
  • PS2-> larger micro->main bus->CPU

😨 which direction should we take and how we decide it?

Link to comment
Share on other sites

On 8/9/2022 at 6:53 AM, Fabio said:

as quoted from the ides of march status post now we have 2 competing standards:

  • PS2 ->Attiny-> I2C-> 6522->main bus-> CPU
  • PS2-> larger micro->main bus->CPU

😨 which direction should we take and how we decide it?

I prefer the shorter path personally. Less to go wrong, and doesn't use up 6522 resources.

That being said, we're at the mercy of the team actually building the platform. It appears they've made a decision to go with the larger micro. 

Original post on 

 

On 8/9/2022 at 6:53 AM, Fabio said:

So, we had a meeting today between me, Kevin, and Adrian Black and brainstormed ideas.  We decided to replace the micro-controller with a larger one that has enough legs to integrate onto the main memory bus.

 

Link to comment
Share on other sites

  • Super Administrators
On 8/9/2022 at 6:53 AM, Fabio said:

as quoted from the ides of march status post now we have 2 competing standards:

  • PS2 ->Attiny-> I2C-> 6522->main bus-> CPU
  • PS2-> larger micro->main bus->CPU

😨 which direction should we take and how we decide it?

IMO, all other things being equal, simpler is better. And this won't even be equal, since there are performance and efficiency benefits. Integrating directly onto the system bus means fewer parts, less code, and I'm betting the  data packets can be read in far fewer steps. 

So given the choice, I'd definitely choose the larger micro controller attached directly to the main bus. 

 

Link to comment
Share on other sites

On 8/9/2022 at 9:53 AM, Fabio said:

as quoted from the ides of march status post now we have 2 competing standards:

  • PS2 ->Attiny-> I2C-> 6522->main bus-> CPU
  • PS2-> larger micro->main bus->CPU

😨 which direction should we take and how we decide it?

Note that "ATTiny" and "larger micro" are not strict alternatives, since there are ATTiny processors with more legs than the one used for the power supply controller. AFAIU, the ATTiny family goes as high as 28 GPIO pins.

However, also note that it seems more like a performance question: there is a CPU <-> main bus <-> 6522 <-> I2C <-> RTC path already in the design, so having the ATTiny on the I2C bus does not means more parts and is unlikely to mean substantially more code. However, the performance of access to the RTC has a lot less system-wide impact than the performance of access to the keyboard and mouse.

Edited by BruceMcF
Link to comment
Share on other sites

A microcontroller that could interface with a 6502 bus is a tall order. I don't know that there is one that could do so reliably with an 8MHz 6502 and those that could aren't usually tolerant of 5V IO.

The simplest and lowest cost way to reduce the performance impact of scanning the keyboard and mouse every VSYNC is to give the host CPU the ability to determine the source of an interrupt. That way the host only needs to query the ATTINY over I2C when there is something for it. This can be accomplished with the leftover gates on the proto 3 hardware and a single 74ACT563 IC. I've already proven that this approach works on hardware, it's now a matter of getting another design change in. That will be hard to do at this point in the design process, as it should be. I'm going to try asking/encouraging Kevin to route the IRQ wires to an appropriate footprint on the proto 4 board so that if the opportunity presents itself, it can be capitalized on by inserting a $1 chip.

  • Like 1
Link to comment
Share on other sites

On 8/9/2022 at 10:14 PM, Stefan said:

Just of curiosity, what timing requirements are there, if you would like to put a SMC on the data bus? Must the state of a pin be changed within half a clock cycle 1/8,000,000/2 = 62.5 ns? But there's also the clock stretching...

Here's the timing diagram I worked out for memory reads, same essentially goes for anything responding to read cycles from the CPU.

image.thumb.png.191551055a20ef4f513c9aceaae9728b.png

In theory the total access time is 85ns, but more realistically most devices will have to wait until the rising edge of PHI2 to be sure that they are being addressed. Data needs to be stable 10ns before the next falling edge, so about 52.5 ns to respond. Assuming the clock of the microcontroller is independent of the host clock, it may have to give up almost one full clock before detecting the access condition. Assuming a 100MHz microcontroller with a 10ns cycle time, that works out to 4, possibly 5, cycles to respond.
 

Link to comment
Share on other sites

On 8/9/2022 at 10:28 PM, Wavicle said:

A microcontroller that could interface with a 6502 bus is a tall order. ...

It depends on the interface, doesn't it? If you have the means to let the MCU know that you want to talk to it (REQUEST) and a means for the MCU to signal whether its ready to give/receive a byte (ACK), then the access protocol can be designed to work with the speed of the MCU. It works best if the REQUEST and ACK signals show up in specific spots in an I/O slot, but if some of that logic can be done with spare gates already present in the design, it might be doable with little or no additional glue logic.

Link to comment
Share on other sites

On 8/10/2022 at 2:36 PM, BruceMcF said:

It depends on the interface, doesn't it? If you have the means to let the MCU know that you want to talk to it (REQUEST) and a means for the MCU to signal whether its ready to give/receive a byte (ACK), then the access protocol can be designed to work with the speed of the MCU. It works best if the REQUEST and ACK signals show up in specific spots in an I/O slot, but if some of that logic can be done with spare gates already present in the design, it might be doable with little or no additional glue logic.

Will that kind of solution require you to slow down the 65C02 clock? How would you do that?

Link to comment
Share on other sites

On 8/10/2022 at 9:48 AM, Stefan said:

Will that kind of solution require you to slow down the 65C02 clock? How would you do that?

(1) You don't necessarily have to slow down the clock. If a write to a particular address triggers an interrupt in the MCU (REQUEST), and the MCU can set a GPIO that shows up at an address as low when the MCU is not ready and high when it is ready (or visa versa) (ACK), then the protocol can check that the MCU is ready for the next step in the protocol. After all, you are programming for an MCU routine that you have also programmed, so you don't have to hit arbitrary times specified in a pre-existing protocol.

Note that ACK could actually only be a single GPIO output connected through to D7 (when reading the correct address in that I/O slot), so that "BIT MCURDY" can put the state into the sign flag for BPL / BMI to use. With that design, you don't actually have to put a BIT mask into the accumulator, because you don't care what the state of the Z flag is after the BIT operation.

(2) If you want to slow down the clock, you can use the RDY line. It should still have some support circuitry doing that, so that the RDY line setting by the MCU only connects through to the CPU when the MCU I/O address space is accessed. Unlike the NMOS 6502, the RDY line on the 65C02 holds the CPU for both reads and writes.

Stretching the clock is indeed a general option (and with a counter based clock circuit, you can even get an "unstretched" clock output for the VIAs so that the VIA clock input remains steady), but since the 65C02 clock circuit is presently using a binary counter and jumpers to allow setting the clock to 1MHz / 2MHz / 4MHz / 8MHz, it seems like a clock stretching circuit for the CX16 would be more complex than if the inputs to the binary counter are not already put to use in the circuit for something else.

Edited by BruceMcF
Link to comment
Share on other sites

On 8/10/2022 at 6:55 PM, BruceMcF said:

(1) You don't necessarily have to slow down the clock. If a write to a particular address triggers an interrupt in the MCU (REQUEST), and the MCU can set a GPIO that shows up at an address as low when the MCU is not ready and high when it is ready (or visa versa) (ACK), then the protocol can check that the MCU is ready for the next step in the protocol. After all, you are programming for an MCU routine that you have also programmed, so you don't have to hit arbitrary times specified in a pre-existing protocol.

Note that ACK could actually only be a single GPIO output connected through to D7 (when reading the correct address in that I/O slot), so that "BIT MCURDY" can put the state into the sign flag for BPL / BMI to use. With that design, you don't actually have to put a BIT mask into the accumulator, because you don't care what the state of the Z flag is after the BIT operation.

(2) If you want to slow down the clock, you can use the RDY line. It should still have some support circuitry doing that, so that the RDY line setting by the MCU only connects through to the CPU when the MCU I/O address space is accessed. Unlike the NMOS 6502, the RDY line on the 65C02 holds the CPU for both reads and writes.

Stretching the clock is indeed a general option (and with a counter based clock circuit, you can even get an "unstretched" clock output for the VIAs so that the VIA clock input remains steady), but since the 65C02 clock circuit is presently using a binary counter and jumpers to allow setting the clock to 1MHz / 2MHz / 4MHz / 8MHz, it seems like a clock stretching circuit for the CX16 would be more complex than if the inputs to the binary counter are not already put to use in the circuit for something else.

Seems reasonable you could use the RDY pin for this purpose, if it can halt all operations as you describe.

The first option---doing this without clock stretching---I do not fully understand. If the SMC is to drive the data bus without clock stretching, even to put just a one bit ready signal there, mustn't that be done within the strict timing limits that @Wavicle discussed above? And if the SMC was to drive the data bus outside those timing limits, wouldn't that corrupt the data bus?

EDIT: Another thing. In (2) I suppose the SMC must drive the RDY line within the 65C02 timing limits, that is 4--5 clock cycles for a microcontroller doing 100 MHz, according to @Wavicle above. Could that be a problem, as the SMC has several interrupt driven tasks it's running in parallel---being a host=slave for two PS/2 devices? The SMC could easily spend more than 5 clock cycles handling an incoming PS/2 bit at the same time the 65C02 wants to read a value.

Edited by Stefan
  • Like 1
Link to comment
Share on other sites

On 8/10/2022 at 12:22 PM, Stefan said:

Seems reasonable you could use the RDY pin for this purpose, if it can halt all operations as you describe.

The first option---doing this without clock stretching---I do not fully understand. If the SMC is to drive the data bus without clock stretching, even to put just a one bit ready signal there, mustn't that be done within the strict timing limits that @Wavicle discussed above? And if the SMC was to drive the data bus outside those timing limits, wouldn't that corrupt the data bus?

EDIT: Another thing. In (2) I suppose the SMC must drive the RDY line within the 65C02 timing limits, that is 4--5 clock cycles for a microcontroller doing 100 MHz, according to @Wavicle above. Could that be a problem, as the SMC has several interrupt driven tasks it's running in parallel---being a host=slave for two PS/2 devices? The SMC could easily spend more than 5 clock cycles handling an incoming PS/2 bit at the same time the 65C02 wants to read a value.

This is where the glue logic I mentioned would come in ... in (2) the MCU starts with the GPIO pin that asserts the RDY already in the state to hold the CPU in RDY state, and the circuit connects that pin TO the CPU RDY line in the cycle that that I/O select is asserted with that address selected. Then the MCU does its stuff, and when it is finished and either the data is read by the MCU (if its a 6502 Write cycle) or the data is latched and available at the MCU (in a 6502 Read cycle), it releases the RDY state and the CPU keeps going where it left off. The code that is accessing the MCU would be written with the knowledge of how long after the RDY is released that the RDY will be back in the hold state, so it just wouldn't access that address "too early".

In (1), again, there could be a hardware circuit that only connects the ACK line to D7 during the read cycle of the appropriate address. So the ACK starts out in the "no acknowledge" state, and when the MCU has received an handshake signal from the CPU and is ready to process it, it puts the ACK GPIO into the "acknowledge" state. As far as which state is ACK and which is NO-ACK, you design the protocol so that the state it comes up in after a reset is the NO-ACK state, so that positive action is required by the MCU in order to put it into ACK state.

Link to comment
Share on other sites

On 8/10/2022 at 8:55 AM, BruceMcF said:

(1) You don't necessarily have to slow down the clock. If a write to a particular address triggers an interrupt in the MCU (REQUEST), and the MCU can set a GPIO that shows up at an address as low when the MCU is not ready and high when it is ready (or visa versa) (ACK), then the protocol can check that the MCU is ready for the next step in the protocol. After all, you are programming for an MCU routine that you have also programmed, so you don't have to hit arbitrary times specified in a pre-existing protocol.

Note that ACK could actually only be a single GPIO output connected through to D7 (when reading the correct address in that I/O slot), so that "BIT MCURDY" can put the state into the sign flag for BPL / BMI to use. With that design, you don't actually have to put a BIT mask into the accumulator, because you don't care what the state of the Z flag is after the BIT operation.

(2) If you want to slow down the clock, you can use the RDY line. It should still have some support circuitry doing that, so that the RDY line setting by the MCU only connects through to the CPU when the MCU I/O address space is accessed. Unlike the NMOS 6502, the RDY line on the 65C02 holds the CPU for both reads and writes.

Stretching the clock is indeed a general option (and with a counter based clock circuit, you can even get an "unstretched" clock output for the VIAs so that the VIA clock input remains steady), but since the 65C02 clock circuit is presently using a binary counter and jumpers to allow setting the clock to 1MHz / 2MHz / 4MHz / 8MHz, it seems like a clock stretching circuit for the CX16 would be more complex than if the inputs to the binary counter are not already put to use in the circuit for something else.

I've done the clock stretching circuit that works with the clock divider and delivers an unstretched clock to the VIAs. It was needed to enable reading from the YM2151 at 8MHz. At max stretch, it slows the high phase of PHI2 to an effective speed of 2MHz.

I had designed a circuit for interfacing a microcontroller to the 6502 bus. It doesn't assert RDY but does have the ATTN/ACK signals in bits 6 and 7. It's a bit out of date, but the principal is still valid. It required 6 ICs. That would be a big architectural change. The design for it is up on GitHub here: jburks/X16-Simple-Intf: A very simple X16 to microcontroller interface. (github.com).

With any change at this point the biggest questions become: Is the architectural risk justified by what it returns? How much does it increase complexity / the ability of the average enthusiast to understand the overall design (the "VIC-20" standard)? We have a working keyboard and mouse solution; what does the change proposed get us? Querying SMC over I2C every VSYNC has a performance hit of ~3% (30ms spent performing I2C transactions per second). There are some protocol tricks that could shave a little bit of time off of that (e.g. have a combined keyboard + mouse transaction instead of a transaction for each), but if we ignore those and just consider the 3% number - what will we gain from throwing more hardware at the problem? A 3% hit to an 8MHz 8-bit retro system still leaves us with a screaming fast retro system.

  • Like 4
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use