6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 9:02 pm

All times are UTC




Post new topic Reply to topic  [ 14 posts ] 
Author Message
PostPosted: Mon Nov 06, 2023 8:30 pm 
Offline
User avatar

Joined: Fri Feb 17, 2023 11:59 pm
Posts: 163
Location: Lviv, Ukraine
I've been bit-banging PS/2 for some time (in my Deck65 build, I have PS/2 clock wired to VIA's CB2 with interrupt enabled on falling edge, and PS/2 data wired to one of data pins), but I always wanted a small and optimal hardware solution that would not require me to waste CPU cycles for reading keyboard bit by bit. (Yes, the dreaded 11-bit frames...)

Here's the concept I came up with - a 1-byte register with interrupt flip-flop which is set when PS/2 frame is fully received. Reading the register automatically clears the interrupt.

Attachment:
ps2_reader.png
ps2_reader.png [ 72.57 KiB | Viewed 3472 times ]

Attachment:
File comment: Digital circuit (https://github.com/hneemann/Digital)
ps2_reader.zip [1.44 KiB]
Downloaded 48 times


CLK & DATA should be connected to PS/2 keyboard, /RES - to your reset circuit, /CE - to your address decoder (used to read buffered data from '595) and D0..D7 - to your 6502 data bus.

Few notes:
- '191 counts from 4 to 14 and uses /RC to reset itself back to 4 when 15 is reached. TC is used as overflow signal and sets the interrupt flag. '595 latches the data bits.
- I initially wanted to use '163, but its preset input is synchronous, so I picked '191 since it has asynchronous preset.
- Data register is not cleared during read - only the interrupt flag is cleared.
- Obviously, this is a read-only design (i. e. only device-to-host communication).
- Start/stop/parity bits are ignored - who uses parity anyway?! (c)
- This circuit actually samples PS/2 data on the wrong clock edge (should be rising edge). I did this to save an extra inverter gate and keep total chip count at 5. I think you might be able to get away with it, since (according to some PS/2 oscilloscope readings from the internet) PS/2 data should still be valid even on clock's rising edge, but I'm not sure about this.

Few questions:
- I often find myself designing something and then finding out that I've picked some outdated 74xx chips. Is '190 still being made? Just want to make sure I'm not using anything that's hard to find.
- Do you think it's possible to reduce the number of chips?

_________________
/Andrew

deck65 - 6502 slab with screen and keyboard | ПК-88 - SBC based on KM1810VM88 (Ukrainian i8088 clone) | leo80 - simple Z80 SBC
nice65 - 6502 assembly linter | My parts, footprints & 3D models for KiCad/FreeCAD


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 06, 2023 11:11 pm 
Offline

Joined: Sat Oct 28, 2023 7:57 pm
Posts: 22
Location: Missouri
and3rson wrote:
Few questions:
- I often find myself designing something and then finding out that I've picked some outdated 74xx chips. Is '190 still being made? Just want to make sure I'm not using anything that's hard to find.

A quick check of Mouser seems to show that the CD74HC190 in several variants are in production. Would those be workable for your design?


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 07, 2023 1:03 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Hmmm... what's the symbol you used at 1., Andrew? I'm guessing it's a time delay, wisely included to avoid a race condition as the counter reloads itself.
Attachment:
ps2_reader annotated.png
ps2_reader annotated.png [ 62.23 KiB | Viewed 3436 times ]

As for your question about possibly using fewer chips, you might gain some advantage by using a 74HC4015 (datasheet attached). This dual, 4-bit shift register can easily replace two or more D flipflop sections. And NXP is still making them; they're in stock at Digikey, for example (dunno about in Europe).
Attachment:
alternatives.png
alternatives.png [ 15.35 KiB | Viewed 3436 times ]

But, just thinking out loud, it seems to me that the section at 3. could be eliminated and simply bypassed if you can hasten the arrival of the rising edge on the RCLK input of the '595... that is, have the rising edge on RCLK occur after 9 clocks instead of 11. :idea:

This would entail some changes to the counter, of course. And if you're going to be tinkering with the counter anyway, probably there's a way it could use a synchronous load IC after all. That'd preclude the race condition and eliminate the need for the time delay. However, that might be awkward, negating the reduction in chip count -- dunno. (I'm tempted to play with the puzzle myself, but I already have a backlog of other puzzles waiting!)

-- Jeff


Attachments:
74hc4015 .pdf [270.49 KiB]
Downloaded 62 times

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 07, 2023 1:32 am 
Offline
User avatar

Joined: Fri Feb 17, 2023 11:59 pm
Posts: 163
Location: Lviv, Ukraine
Dr Jefyll wrote:
Hmmm... what's the symbol you used at 1., Andrew? I'm guessing it's a time delay, wisely included to avoid a race condition as the counter reloads itself.

Correct - I've been bit several times by Digital sometimes being too idealistic with simulations, so now I'm adding delays in all places where loops & latches are involved.

Dr Jefyll wrote:
As for your question about possibly using fewer chips, you might gain some advantage by using a 74HC4015 (datasheet attached). This dual, 4-bit shift register can easily replace two or more D flipflop sections. And NXP is still making them; they're in stock at Digikey, for example (dunno about in Europe).

This is awesome, thank you! How could I not think about using a shift register to introduce a delay... And what's even better - it has two of them. It fits perfectly since it merges all my flip-flops into a single chip. Furthermore, I can now replace my ANDs with NANDs (since according to your schematic I'll need inverted reset for interrupt flip-flop), so now I have one spare NAND that I can use to invert the /CLK line! Learning something new every day. :)

Dr Jefyll wrote:
But, just thinking out loud, it seems to me that the section at 3. could be eliminated and simply bypassed if you can hasten the arrival of the rising edge on the RCLK input of the '595... that is, have the rising edge on RCLK occur after 9 clocks instead of 11. :idea:

This would entail some changes to the counter, of course. And if you're going to be tinkering with the counter anyway, probably there's a way it could use a synchronous load IC after all. That'd preclude the race condition and eliminate the need for the time delay. However, that might be awkward, negating the reduction in chip count -- dunno. (I'm tempted to play with the puzzle myself, but I already have a backlog of other puzzles waiting!)

I like this idea, and it really sounds like an interesting challenge. I think it should be possible to include /RES into the mix and initialize the counter at 6 instead of 4 (by feeding RES - that is, inverted /RES) to D1. (Extra care should be taken to make sure D1 is set BEFORE /PL is triggered, since both are driven by /RES). Then, on overflow, the counter would be set to 4, since /RES is high (RES=0). The process would look as such:
- On reset, '191 is set to 6
- (9 clock cycles - 1 start bit & 8 data bits)
- '191 overflows, triggers RCLK of '595 (which is loaded with clean 8-bit data value), and is reset to 4
- (2 more cycles - stop bit & parity)
- '191 is set to 6 again

_________________
/Andrew

deck65 - 6502 slab with screen and keyboard | ПК-88 - SBC based on KM1810VM88 (Ukrainian i8088 clone) | leo80 - simple Z80 SBC
nice65 - 6502 assembly linter | My parts, footprints & 3D models for KiCad/FreeCAD


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 07, 2023 4:26 am 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 746
Location: Germany
very fancy! i wonder if it would be possible to squeeze all this logic into a single (or maybe 2) 22V10's.
maybe even remove the interrupt logic and instead use an IDT720x FIFO chip after the '595, then you could invert the FIFO's empty flag to use it as an IRQ signal for the CPU.
it would ultimately achive the same thing, but with storage for multiple characters so no keypresses are lost when the CPU cannot respond to an interrupt for a long period of time. (unless the FIFO fills up i guess, but PS/2 is so slow it would take atleast multiple seconds of keyboard activity for that to happen)


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 07, 2023 8:45 am 
Offline
User avatar

Joined: Fri Nov 09, 2012 5:54 pm
Posts: 1431
Long time ago I had built something with a few TTL chips for connecting to a PS/2 keyboard.

I had used a monoflop instead of a Bit counter,
because when using a counter one might consider that the clock pulse for a Bit could get lost during transmission.

Unfortunately I had no 74595 chips at hand, so I went for two 74164 shift registers plus a 74574 latch.

For generating an interrupt, I just had made use of the CA1 input of a 6522.

I'm attaching some pictures, have fun.

Attachment:
ps2kb_1.png
ps2kb_1.png [ 21.51 KiB | Viewed 3391 times ]

Attachment:
ps2kb_2.png
ps2kb_2.png [ 40.19 KiB | Viewed 3391 times ]

Attachment:
ps2kb_brd_components.png
ps2kb_brd_components.png [ 8.36 KiB | Viewed 3391 times ]

Attachment:
ps2kb_brd_top.png
ps2kb_brd_top.png [ 17.8 KiB | Viewed 3391 times ]

Attachment:
ps2kb_brd_bot.png
ps2kb_brd_bot.png [ 18.11 KiB | Viewed 3391 times ]


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 07, 2023 11:17 am 
Offline
User avatar

Joined: Tue Apr 03, 2018 2:10 pm
Posts: 125
Ben Eater did a simple interface with a 74x14 and two 74x595s. It uses an RC circuit to generate an interrupt. I've tried it out & it works fine, although I've now added an Atmega328P to convert PS/2 keycodes into ASCII codes. This makes it a programmable interface that I thought I might use with multiple projects. Anyway, Ben's version is here: https://www.youtube.com/watch?v=w1SB9Ry8_Jg

_________________
I like it when things smoke.
BlogZolatron 64 project


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 07, 2023 12:07 pm 
Offline

Joined: Fri Jul 09, 2021 10:12 pm
Posts: 741
Using a VIA, I think I'd be inclined to lean heavily on its capabilities - counting pulses to generate an interrupt at the right time, for example, and using the internal shift register to receive the data.

But without a VIA, using only 74-series logic with direct connection to a shared bus and IRQ support, this was my thought:
Attachment:
ps2keyboard_74xxx.png
ps2keyboard_74xxx.png [ 15.52 KiB | Viewed 3364 times ]

Reading from the port resets everything - U3A gets set, U3B and U2 get cleared. Now when the keyboard sends data, the start bit enters U3A, then feeds through the shift register U2 and U3B - but note that it gets inverted going from U3A to U2. So when it arrives at U3B we see a rising edge. This asserts /IRQ, and also clocks the storage register of the '595 (U2). The CPU should now read the data, and when it does everything is reset again.

The keyboard will send one more clock pulse, for the stop bit. If the CPU has already read the data then this is a no-op - it feeds 1 into U3A, matching its existing state, and U3A's inverted output is 0, matching the reset state of the 595. If the CPU hasn't read the data yet then this next clock pulse might clear U3B and reset /IRQ, which is undesirable. So better read the data within 100us. Failing that, it would be possible to use a separate D flipflop for /IRQ, so that it's sticky.

I originally intended to use 74HCT175 (quad D flip-flop). To do this you need to invert the keyboard data on the way in, and use the uninverted output of U3A to feed U2 - because 74HCT175 can only clear all its flipflops (asynchronous reset), it has no ability to set one but clear the rest. So this costs one more inverter - but the advantage is, we have two extra flipflops and can for example make /IRQ be driven by the next one, only triggering after the stop bit arrives, and maybe taking a little time pressure off the CPU.

I drew a PARITY connection in, but it's not tristate so the CPU can't really read it. If you want to check parity, you could use a JK flipflop for that, or just give the CPU some tristate way to read this signal - maybe replace all the DFFs with an 8-bit register like 74HCT574.


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 07, 2023 1:16 pm 
Offline

Joined: Fri Dec 21, 2018 1:05 am
Posts: 1117
Location: Albuquerque NM USA
My PS2 CPLD does similar thing described here. There are a couple differences:
1. When a byte of keyboard data is received, it does not generate interrupt but assert a data ready status flag instead. It also pull the PS2 clock low to inhibit keyboard from sending anymore data until the current data is read.
2. When PS2 clock is high for 300uS or longer, it reset the bit-counting state machine. This re-synchronize the state machine in case there are spurious glitches on PS2 clock.

I did have CPLD resource to decode parity, start, stop bits to determine whether the data is valid, but I've not found them to be necessary.

Bill


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 07, 2023 5:24 pm 
Offline

Joined: Fri Jul 09, 2021 10:12 pm
Posts: 741
plasmo wrote:
When a byte of keyboard data is received, it does not generate interrupt but assert a data ready status flag instead. It also pull the PS2 clock low to inhibit keyboard from sending anymore data until the current data is read.

That's interesting approach, I hadn't realised that behaviour was for flow control but it seems obvious now!

I think that you could fairly easily do something similar with my circuit above, if you extended it with an extra flipflop as I discussed - then you could use the output of that last flipflop to drive /IRQ or a "data ready" signal, and also use that output through a diode to pull the PS/2 clock low until the read takes place. The existing reset-on-read behaviour would clear that condition.

It wouldn't work without that extra flipflop though, because in that case there's still one more clock pulse to go (for the stop bit).


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 09, 2023 4:47 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
and3rson wrote:
... I like this idea, and it really sounds like an interesting challenge. I think it should be possible to include /RES into the mix and initialize the counter at 6 instead of 4 (by feeding RES - that is, inverted /RES) to D1. (Extra care should be taken to make sure D1 is set BEFORE /PL is triggered, since both are driven by /RES). Then, on overflow, the counter would be set to 4, since /RES is high (RES=0). The process would look as such:
- On reset, '191 is set to 6
- (9 clock cycles - 1 start bit & 8 data bits)
- '191 overflows, triggers RCLK of '595 (which is loaded with clean 8-bit data value), and is reset to 4
- (2 more cycles - stop bit & parity)
- '191 is set to 6 again


If using a '595 with its separate parallel port, I wonder whether one could run a 4bit binary counter starting at 0 and use a NAND to generate the required end pulse. If the counter is reset when the serial shift register is read, and the counter is tied to the original PS2CLK (that is, not the same inverted clock as the serial shift register), the serial is shifted (x=don't care, start=s, d=data, p=parity, stop=e), and then the counter increments a half clock cycle later:

  • 1: %xxxxxxxs/%0001
  • 2: %xxxxxxsd/%0010
  • 3: %xxxxxsdd/%0011
  • 4: %xxxxsddd/%0100
  • 5: %xxxsdddd/%0101
  • 6: %xxsddddd/%0110
  • 7: %xsdddddd/%0111
  • 8: %sddddddd/%1000
  • 9: %dddddddd/%1001
  • 10: %dddddddp/%1010
  • 11: %ddddddpe/%1011

So if you have a quad 2-input NAND:

/PS2CLK := NAND(PS2CLK,VCC)
/RCLK := NAND(COUNT_Q3,COUNT_Q1)
RCLK := NAND(/RCLK,VCC)
/END := NAND(RCLK,Q2)

Note that a race between the '595 serial shift register settling and the transfer to the parallel storage register that Ben Eater avoids by driving RCLK through two inverters is avoided here by clocking the '595 to /PS2CLK while the counter is clocked to PS2CLK. Also, the /END signal occurs at the conclusion of stop bit clock pulse, and not at it's outset.

Edit: Scratch that, it reloads the parallel register at the end. This approach needs an inverter and a triple 3-input NAND (or quad 2-input, if it's a 74x00 that is at hand):

/PS2CLK := NOT(PS2CLK)
/Q2 := NOT(Q2)
/RCLKC = NAND(Q1,/Q2,Q4)
RCLKC = NOT(/RCLK)
/END = NAND(Q1,Q2,Q4)

If it's a hex inverter, it leaves 3 inverter gates and one 3-input NAND for other use or use by the /END circuit, so unless the 3input NAND is doing a lot of good with the /END circuit, the game probably isn't worth the candle.

I will note, though, that I was looking at the version of /END that leaves a /Ready signal and pulls the clock low until the byte is read, so it needs an open-drain buffer/driver. If that is an open drain octal driver (as might be used to do voltage translation to a +3.3v Flash) rather than a dual driver, that also offers the possibility of wired-OR's that can be used for the /END circuit, which gives 7 open collectors free for wire-ANDs -- eg, a 3-input and a couple of 2-input ANDs.

If the counter is dual simple 4-bit binary counter, perhaps COUNT2 can be used to drive the pull down of the PS2CLK, clearing when the /END state is entered and counting up to 1 by using the SSR /OE as the clock pulse.


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 11, 2023 4:11 pm 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
BruceRMcF wrote:
... If using a '595 with its separate parallel port, I wonder whether one could run a 4bit binary counter starting at 0 and use a NAND to generate the required end pulse. If the counter is reset when the serial shift register is read, and the counter is tied to the original PS2CLK (that is, not the same inverted clock as the serial shift register), the serial is shifted (x=don't care, start=s, d=data, p=parity, stop=e), and then the counter increments a half clock cycle later:

  • 1: %xxxxxxxs/%0001
  • 2: %xxxxxxsd/%0010
  • 3: %xxxxxsdd/%0011
  • 4: %xxxxsddd/%0100
  • 5: %xxxsdddd/%0101
  • 6: %xxsddddd/%0110
  • 7: %xsdddddd/%0111
  • 8: %sddddddd/%1000
  • 9: %dddddddd/%1001
  • 10: %dddddddp/%1010
  • 11: %ddddddpe/%1011

So if you have a quad 2-input NAND:

/PS2CLK := NAND(PS2CLK,VCC)
/RCLK := NAND(COUNT_Q3,COUNT_Q1)
RCLK := NAND(/RCLK,VCC)
/END := NAND(RCLK,Q2)

Note that a race between the '595 serial shift register settling and the transfer to the parallel storage register that Ben Eater avoids by driving RCLK through two inverters is avoided here by clocking the '595 to /PS2CLK while the counter is clocked to PS2CLK. Also, the /END signal occurs at the conclusion of stop bit clock pulse, and not at it's outset.

Edit: Scratch that, it reloads the parallel register at the end. This approach needs an inverter and a triple 3-input NAND (or quad 2-input, if it's a 74x00 that is at hand):

/PS2CLK := NOT(PS2CLK)
/Q2 := NOT(Q2)
/RCLKC = NAND(Q1,/Q2,Q4)
RCLKC = NOT(/RCLK)
/END = NAND(Q1,Q2,Q4)

If it's a hex inverter, it leaves 3 inverter gates and one 3-input NAND for other use or use by the /END circuit, so unless the 3input NAND is doing a lot of good with the /END circuit, the game probably isn't worth the candle.

I will note, though, that I was looking at the version of /END that leaves a /Ready signal and pulls the clock low until the byte is read, so it needs an open-drain buffer/driver. If that is an open drain octal driver (as might be used to do voltage translation to a +3.3v Flash) rather than a dual driver, that also offers the possibility of wired-OR's that can be used for the /END circuit, which gives 7 open collectors free for wire-ANDs -- eg, a 3-input and a couple of 2-input ANDs.

If the counter is dual simple 4-bit binary counter, perhaps COUNT2 can be used to drive the pull down of the PS2CLK, clearing when the /END state is entered and counting up to 1 by using the SSR /OE as the clock pulse.


For a circuit to be polled by a 60 ticks per second /NMI routine, first check if its ready, then read the PS/2 and update the keyboard buffer, in a vaguely Ben Eater style memory mapped IO where reading the IO page generates IO (active high) and four IO slots are A7, A6, A5 and A4 low, I get this approach with a '595 shift register, a '393 dual 4bit counter, a triple AND, a quad NAND, an octal inverter, and two Shottkey diodes, for the pull down of the PS2CLK when the SSR is waiting to be read and to put the /Ready? status on D7 when polling for the port to be ready to be read.

So the game is probably not worth the candle, especially if breadboarding, since I'm not sure that a '393 is available in a through hole part.


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 13, 2023 3:56 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
gfoot wrote:
Using a VIA, I think I'd be inclined to lean heavily on its capabilities - counting pulses to generate an interrupt at the right time, for example, and using the internal shift register to receive the data.

But without a VIA, using only 74-series logic with direct connection to a shared bus and IRQ support, this was my thought:
Attachment:
ps2keyboard_74xxx.png

Reading from the port resets everything - U3A gets set, U3B and U2 get cleared. Now when the keyboard sends data, the start bit enters U3A, then feeds through the shift register U2 and U3B - but note that it gets inverted going from U3A to U2. So when it arrives at U3B we see a rising edge. This asserts /IRQ, and also clocks the storage register of the '595 (U2). The CPU should now read the data, and when it does everything is reset again.

The keyboard will send one more clock pulse, for the stop bit. If the CPU has already read the data then this is a no-op - it feeds 1 into U3A, matching its existing state, and U3A's inverted output is 0, matching the reset state of the 595. If the CPU hasn't read the data yet then this next clock pulse might clear U3B and reset /IRQ, which is undesirable. So better read the data within 100us. Failing that, it would be possible to use a separate D flipflop for /IRQ, so that it's sticky.


Again thinking in terms of polled rather than /IRQ PS/2, could the dual 4bit SR 74HC4015 (DSR1 & DSR2) that Dr. Jefyll referred to above be used for counting to two clock pulses after the data is stored to register?

This idea would lose parity, because it would involve stalling the SSR ('595) clock after the inverted start bit reaches QH:
DSR1_SCLK := SSR_SCLK := NAND(SSR_QH',PS2CLK)
SSR_RCLK := SSR_QH.

DSR1 is used as a one cycle delay, using a NOT gate to invert DSR1_QA for the '595 serial input:
DSR1_CLR := NOT(/READ)
DSR1_SER := PS2DAT
/SSR_CLR := /READ
/SSR_OE := /READ
SSR_SER := NOT(DSR1_SER)

DSR2 runs directly off the PS2CLK, so it trails by half a phase. Since it resets to 0, it is fed SSR_QH, so all outputs remain 0 until the inverted start bit arrives at SSR_QH during the MSbit Data phase, and the SSR stalls there, so SSR_QH remains high. In Parity phase, 1 arrives at DSR2_QA. In stop phase, 1 arrives at DSR2_QB. This is used to pull the PS2CLK low for flow control until the byte is read, which resets the shift register and releases the PS2CLK:
DSR2_E := NOT(/READ)
DSR2_CLK := PS2CLK
DSR2_SER := SSR_QH
NOT(DSR2_QB) =: -DIODE+ PS2CLK := pullup+5v

/READYQ is the active low to read the ready signal, which is an open collector held high unless the PS2CLK is being held low:

NAND(NOT(DSR2_QB),/READYQ) =: -DIODE+ =: BUS_D7 := pullup+VCC

PS2 is lsbit first, so D0 inverted is SSR_QG, through to D6 inverted at SSR_QA, and D7 inverted at NOT(DSR1_QA), but the last is not tri-stated, so it also needs to be an open collector/drain:

NAND(DSR1_QA,NOT(/READ)) =: -DIODE+ =: BUS_D7 := pullup+VCC

IIUC, as open collector/drain outputs, a single pullup on BUS_D7 suffices ... either one added or an existing pull-up bus terminator.

Then in the polling timed /IRQ routine, "BIT PS2RDY : BMI READKBD" would check the ready bit and "LDA #$FF : EOR PS2DATA" would read the data.

The decoding of the two active low selects is additional overhead, but this adds 3 NOTs and 3 two-input NANDs, so if there is a free OR gate, a common /PS2 could give OR(/PS2,A0) as /READ and NAND(NOT(/PS2),A0) as /READYQ, leaving two gates free from a hex inverter.

An upgrade to that one would be to have the resets happen at system reset as well as /Read.


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 14, 2023 4:29 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
and3rson wrote:
... I like this idea, and it really sounds like an interesting challenge. I think it should be possible to include /RES into the mix and initialize the counter at 6 instead of 4 (by feeding RES - that is, inverted /RES) to D1. (Extra care should be taken to make sure D1 is set BEFORE /PL is triggered, since both are driven by /RES). Then, on overflow, the counter would be set to 4, since /RES is high (RES=0). The process would look as such:
- On reset, '191 is set to 6
- (9 clock cycles - 1 start bit & 8 data bits)
- '191 overflows, triggers RCLK of '595 (which is loaded with clean 8-bit data value), and is reset to 4
- (2 more cycles - stop bit & parity)
- '191 is set to 6 again


(1) Adding RESET into the mix requires inverting /RESET, so assume a hex inverter.
(2) The remaining latch when the pair of latches (or single quad shift register) [3] is removed can be replaced by a simple /S /R latch, if instead of triggering CLK with TC, you trigger /Reset with /RC and use Q as /IRQ. Then the existing /CLR can be the /S /R latch /Set.
(3) You have two AND's, a simple /S /R latch can be made with two NANDS, and a hex inverter has been added, which has plenty of free gates to turn two NANDs into two ANDs. ... So:
NOT_1A := /RESET
NOT_1Y =: RESET =: COUNT_D1 =: NOT_2A ; to lag /PL
NOT_2A := NOT_1Y ; /RESET2
NOT_2Y =: NAND_1A
NOT_2A := NAND_1Y ; COUNT_PL
NOT_2Y =: /COUNT_PL
NOT_3A := NAND_4Y ; IRQ_SET
NOT_3Y =: NAND_3A ; /IRQ_SET

NAND_1A := NOT_2Y ; /RESET2
NAND_1B := /COUNT_RC
NAND_1Y =: NOT_2A

NAND_4A := /RESET
NAND_4B := /CE
NAND_4Y =: NOT_3A ; IRQ_CLEAR (Set High)

NAND_2A := NAND_4Y ; /IRQ_CLEAR
NAND_2B := NAND_3Y (pin 8 to pin 5)
NAND_2Y =: NAND_3A =: /IRQ

NAND_3A := NAND_2Y (pin 6 to pin 9)
NAND_3B := /COUNT_RC ; /IRQ_TRIGGER
NAND_3Y =: NAND_2B

That puts one inverter gate delay between falling /RESET and /PL, and three inverter gate delays and one NAND gate delay between falling /RESET and PL. This also has a spare gate to invert PS2_SCL to, so that the shift register shifts on the first PS2CLK edge and the counter counts on the second edge, avoiding any race between SSR_SCLK and SSR_RCLK, since they occur half a PS2 clock cycle apart.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 40 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: