First thought on an interface (to use Paleolithic DROM)

For discussing the 65xx hardware itself or electronics projects.
Post Reply
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by barnacle »

BruceRMcF wrote:
Note that the issue still exists of the "lda keypad,y" using the expiration of some bits on the address bus to generate a latch signal while one of the latches is trying to latch some other expiring address bus bits.
I don't think so, Bruce; you write to the LED addresses using ,Y as a 0-7 index, that latches the column, and it stays there until the next write. Reading keypad doesn't touch the LED addresses, and the encoding is done with a couple of '00 NAND gates from the latched and decoded column.

It's a busy board, but it looks like it will fit on a two-layer Eurocard, as the DROM. Then the link to the DROM can either be a below-board socket, or a short length of IDC cable.

At the moment I'm worried that the LEDs are going to be bright enough; I think I need to reduce the drive current to limit what gets sunk by the latch...

Neil
BruceRMcF
Posts: 388
Joined: 21 Aug 2019

Re: First thought on an interface (to use Paleolithic DROM)

Post by BruceRMcF »

barnacle wrote:
BruceRMcF wrote:
Note that the issue still exists of the "lda keypad,y" using the expiration of some bits on the address bus to generate a latch signal while one of the latches is trying to latch some other expiring address bus bits.
I don't think so, Bruce; you write to the LED addresses using ,Y as a 0-7 index, that latches the column, ...
What I am looking at is whether it does latch the column. It doesn't look like it would. Look at the clock cycle ...
65c02_timing.jpg
Some gate delays after tADS the /led select goes low somewhere in the dashed blue oval. As a transparent latch, the decoder will be putting the correct row out.

Then some gate delays after tAH, somewhere in the right of the red dashed oval, /led goes high, and the current state of the address bus is latched by the latching decoder.

And as the tAH expires, the transparent latch starts reflecting the new state of the address base when address is indeterminate before the new opcode address is asserted in the following memory cycle, so when /leds rises some gate delays after tAH expires, what is latched looks like it is indeterminate. There's is a lag for the decoder inputs, especially since they are Schmitt Triggers, but with two gate delays on the select line, it seems that the the bottom three address bits read by the decoder may well be in the indeterminate phase of the address bus.

The 6522 is designed for the 65xx bus, so it respects PHI2 (what is input into the 65C02 as well, or what you call PH0 using the old NMOS pin labels), the UART can be made to respect it, and the keypad driver doesn't have to respect it because it is the 65C02 that is latching the keypad data in its read cycle during the tDHR period following PHI2 falling at the end of the memory cycle (the line below the address timing line).

Two lines below is the write timing line, and the tDHW period is per datasheet the same hold period after PHI2 falls, so the segment latch has the same potential problem as the latching decode if it goes on nothing but the state of some bits in the address line.

Now, the latching of the row has the address select rising on the same bus state as the information being latched, so that looks like it is definitely an issue. The segment is latching signals on a parallel bus state, and whether the actual write hold lasts enough longer than the actual address bus state to allow it to work is an open question ... the datasheet promises at least 10ns on each, but the silicon delivers what it delivers.

But there's no need to worry about that, because a clocked D-latch and a active low transparent latch can be latched by the same rising end of an active low select, so the issue only needs to be solved once to not have to worry about the issue for either.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by barnacle »

Screenshot from 2025-06-17 19-58-45.png
The write to the segment and the column latch is qualified by RnW, which is the thing that's happening fastest. So it rises before (for some small value of before) the address and data disappear.

Neil

(I haven't posted complete diagrams for a while. Perhaps I should.)
BruceRMcF
Posts: 388
Joined: 21 Aug 2019

Re: First thought on an interface (to use Paleolithic DROM)

Post by BruceRMcF »

barnacle wrote:
Screenshot from 2025-06-17 19-58-45.png
The write to the segment and the column latch is qualified by RnW, which is the thing that's happening fastest. So it rises before (for some small value of before) the address and data disappear. ...
As I said, I don't know what is physically happening fastest, but on the datasheet, R/W is no faster than the address bus.

Your "PH0" is at the start of the hold period (PHI2 in the WDC datasheet, because WDC changed the pin naming a good while back, perhaps to emphasize that the days of making a clock by tying a crystal, a resister, and a cap in a circuit with the clock input and two clock outputs should be in the past, even as the rusty old control boards segment of the market they were supporting forced them to keep the output pins in place to support boards designed in that past) ...

... R/W changing is at the end of the hold (it's part of the same timing line as the Address lines, SYNC and VPB), and then gets to the latches after two gate delays.

Again, datasheet timings, not physical measurements, but the address lines into A, B and C are not delayed by gates ... on the guaranteed datasheet minimums on the holds, the transition of A, B and C happens before the gate-delayed effect of R/W.

I'm saying on a 65Cxx bus, where the R/W line is intended to persist through the hold period of the start of the following memory cycle, instead of common latch line, "/latch = /LE = ↑CLK" being:

/latch <= NOT(NAND(/leds,R/W))

... it should be:

/latch <= NAND(PHI2,NOT(/leds))

Same gates, but do the standard 65Cxx PHI2* qualification of a latch signal in place of the not strictly needed R/W qualification that doesn't do as much to help the timing of the latch signal. Even if the R/W qualification works out with one IC, the datasheet says there's no guarantee it will work with the next one, which isn't an issue to hand to the hardware "absolute beginner" target audience.

While to my mind, for a target audience who may be moving from a breadboard to picking up the soldering gun, I reckon "don't read from this address range, this is write-only hardware" is fine.
_______
NB. *actual CMOS PHI2, not CMOS PHI2O
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by barnacle »

I am feeling particularly stupid in my old age :mrgreen: At least that's an easy change.

Here's the current diagrams (two pages)
6502_minimal.pdf
(869.92 KiB) Downloaded 21 times
Neil
BruceRMcF
Posts: 388
Joined: 21 Aug 2019

Re: First thought on an interface (to use Paleolithic DROM)

Post by BruceRMcF »

barnacle wrote:
I am feeling particularly stupid in my old age
There's a fine excuse that can be saved on a nearby shelf ... "Oh, wait, it's a 6502, not a Z80" ... as Z80 /WR rises in the middle of the final t-cycle, with the CPU asserting the databus past the rise ... and then finally after the databus output expires, its PHI1 rises.
Last edited by BruceRMcF on Wed Jun 18, 2025 3:42 pm, edited 2 times in total.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by barnacle »

Ah, the benefit of a four-phase clock :D
BruceRMcF
Posts: 388
Joined: 21 Aug 2019

Re: First thought on an interface (to use Paleolithic DROM)

Post by BruceRMcF »

Retaining all of the changes made to save bytes to support the 3x8 keyboard, the d7=1 Key Pressed flag, etc, it comes in at 122 bytes with four functions ... GO and CR are at the locations indicated by the datasheet, PageForward next to CR and RV at the opposite side to Go.

And addr0 is back in the IRQ/BRK vector spot, so the option to serve as a crude break point monitor is restored.

Code: Select all

	code
	org $ff80	; +16
LED_PATTERNS:
	db 0b00111111	;0
	db 0b00000110	;1
	db 0b01011011	;2
	db 0b01001111	;3
	db 0b01100110	;4
	db 0b01101101	;5
	db 0b01111101	;6
	db 0b00000111	;7
	db 0b01111111	;8
	db 0b01101111	;9
	db 0b01011111	;a
	db 0b00111100	;b
	db 0b00101000	;c
	db 0b01011110	;d
	db 0b01111101	;e
	db 0b01110001	;f

exec:	jmp addr0	; +3

start:			; +6
	; Set base address, this is also "review"
	lda #>addr0
	sta W+1
	stz W		; start address addr0, page aligned

loop_main:		; +19
	; current state to leds
	; put W and (W) into leds
	; [x][x][x][x][x][x][ ][ ]
	;
	ldx #0
	lda W+1
	jsr to_leds
	lda W
	jsr to_leds
	lda (W)
	jsr to_leds

	; Initialize the display count
	; Need to drive six leds for display
	; The sixth is redundant for 4x5 "keyboard"
	; Top two leds are never driven, so dark
	ldy #5
	
loop_digit:		; +10
	; for each LED digit (right to left)...
	lda leds,y
	sta led_addr,y	; display bit pattern
	lda keys
		; d7 = NOR( row1, row2, row3)
	bmi loop_99	; no key pressed

			; +10
	; do stuff to sort out the key value	
	; a hex key if below smallest command code
	; in circuit diagram, this is the GO key
	cmp #KEY_GO
	bmi loop_hex	; enter hex value
	beq exec	; return addr0 to review
	cmp #KEY_PF	; test 2nd largest command code
	beq loop_pf	; increment W high byte	
	bpl start	; reset W to addr0

			; +8
	; remaining special key is return
	inc W
	bne loop_90
loop_pf:
	inc W+1
	bra loop_90

loop_hex:		; +14
	; else shuffle key value into (W)
	; In this version, d7=NOT(Press)
	; so d7 clear if hex key
	pha
	lda (W)
	asl a
	asl a
	asl a
	asl a
	sta (W)
	pla 
	ora (W)
	sta (W)	

loop_90:		; +4
	; wait for key to be released
	; this will cause display glitch, but...
	lda keys
	bmi loop_90

loop_99:		; +5
	dey    ; underflows after 0th column
	bpl loop_digit
	bra loop_main ; will reset Y to 5
	
to_leds:		; +23
	; unpack byte into two adjacent LED patterns
	; x has character position
	pha
	and #$0f		; low nibble
	tay
	lda LED_PATTERNS,y	; index into the patterns
	sta leds+1,x		; and output into the LED array
	pla
	lsr a
	lsr a
	lsr a
	lsr a			; high nibble
	tay
	lda LED_PATTERNS,y
	sta leds,x		; this byte goes on the left
	inx
	inx
	rts		
		; 6 byte gap

	org $fffc	; +4 
	dw start
	dw start	; BRK restarts micro-monitor
In the micro-monitor role, if it is desired that it not be "blind" to the zero page and stack page, there is this modification which fits into the available six bytes:

Code: Select all

restart:		; +6
	; Reset base address to ZP unless already ZP
	lda #0
	cmp W+1
	bne restart_zp 

start:			; +6
	; Set base address, this is also "review stage 2"
	lda #>addr0
restart_zp: 
In this version, "RV" from anywhere outside of the zero page starts at $0000, but from inside the zero page is start at addr0.

Or if simpler mode free command keys are preferred, restart goes to $0000, as two taps of page forward would take you to $0200, but the previous one takes you straight to $0200 in another tap of PreView even after having a look at what your code has been doing in its page zero variables:

Code: Select all

restart:		; +4
	; Reset base address to ZP
	lda #0
	bra restart_zp 

start:			; +6
	; Set base address
	lda #>addr0
restart_zp: 
If they are to be available as desolder & resolder patches, it is between the end of the the exec jump and "start" that the spare space would go, and the patch would also involve patching the two vectors at the end.

However, since the branch to restart is via a "BPL", the easiest to "diode patch" version is to start with:

Code: Select all

restart:		; +4
	; Restore base address to addr0
	bmi start
	lda #0 ; {code if bmi patched to bpl}
	bra restart_zp ; {set base address to $0000.}

start:			; +6
	; Set base address
	lda #>addr0
restart_zp: 
... where the "bmi" opcode is $30, %00110000, so that if it is desired for ReView to start at $0000 instead, patch on bit to:

Code: Select all

restart:		; +4
	; Reset base address to ZP
	bpl start
	lda #0
	bra restart_zp 

start:			; +6
	; Set base address
	lda #>addr0
restart_zp: 
... where the "bpl" opcode is $10, %00010000.

For programmable memory that erases to $FF and are programmed by resetting the bits that should be 0, that would work as a programmable memory patch as well as a DROM patch. Mind, in the context of the DROM, there may be a way to install a push button switch to make that patch a pushbutton setting.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by barnacle »

It was a busy board; I don't usually choose DIP for glue logic; it's surprisingly restrictive. Perhaps I should make some footprints (feetprints?) that allow two 0.2mm tracks between pins. It would need 1mm space between the pins, and a pad width of 1.54mm, so it's a bit tight - but I believe Garth has mentioned that he's done that successfully.
Screenshot from 2025-06-18 10-47-07.png
Bruce - the keys are arranged in the original four column by five row arrangement and the value read is given by the key number minus one; bit 7 is high when there is no key pressed.

I'll sit and think on this a couple of days, but then I might order the boards.

Neil

p.s. Mesolithic because it's a bridge between old and new stone age :mrgreen:
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by GARTHWILSON »

barnacle wrote:
It was a busy board; I don't usually choose DIP for glue logic; it's surprisingly restrictive. Perhaps I should make some footprints (feetprints?) that allow two 0.2mm tracks between pins. It would need 1mm space between the pins, and a pad width of 1.54mm, so it's a bit tight - but I believe Garth has mentioned that he's done that successfully.
What you might be thinking of is at viewtopic.php?p=80938#p80938, with a picture.  It says, " This is with pads .045"x.055" and .006"/.006" trace/space:," which in metric is 1.14x1.40mm pads and .152mm trace/space.
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?
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by barnacle »

That may well have been it, thanks. I tend to default to 0.200mm trace and space (8 thou) because I _know_ that JLC can produce reliable boards at that resolution. But it's worth considering 0.150mm (6 thou)... or even smaller; I have an idea JLC can do 4 thou without issue. But it leaves the traces a bit vulnerable on the board, maybe.

Neil
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by barnacle »

Hmm, without changing the pads on a standard dip socket, two 6 thou tracks will go between the pins without violating any constraints. To get smaller tracks, you need to edit the constraints to allow closer tracks.

Neil
BruceRMcF
Posts: 388
Joined: 21 Aug 2019

Re: First thought on an interface (to use Paleolithic DROM)

Post by BruceRMcF »

barnacle wrote:
Bruce - the keys are arranged in the original four column by five row arrangement and the value read is given by the key number minus one; bit 7 is high when there is no key pressed. ...
That fits my code just above in the sense that it now matches the Go and CR key marking, but I hadn't caught the "+" and "-" being there, so that had "preview" as "+" and "page forward" as "-".

Page Forward has always been because it was a function that can be added with a single branch and no additional bytes, but rather than tinkering with "go back to addr0 and see if something was punched in wrong", it would be more benefit in context to page back to get a more local "oops, what was that again?" option.

... Well, actually, it would be more benefit in context to step back one step, but there aren't that many bytes available, while there are the bytes available to decrement the high byte of the memory pointer.

Now "-" makes some sense, and "+" may just be read as "AND once more from the beginning".

At 126 bytes, there is slightly more flexibility in examples, since the full six NMI:Reset:BRK/IRQ can be filled in without over-writing the program punch bootstrap routine. In that sense, this fills the space available with no bytes to spare.

Code: Select all

VERSION = $00
REVISION = $05 ; 2025-06-18

; 126  total
; main: 83
; to_leds: 23
; vectors: 4
; table: 16

; Keyboard Note:
; 4x5 key matrix
; GO & CR allocated in original version
; the special key row goes to d4
; d7 is !(row1 # row2 # row3)
; so NO need to clean up hex key before "or" op.
; For branching to work, need to what order keys are:
; Key $10 = "Go", Go key (execute origin)
; Key $11 = "CR", CR key, next address
; Key $12 = "-", PB key (page back)
; Key $13 = "+", RV key, "+ once more from the top"

; Mesolithic
keypad		= $9000
led_addr	= $9800
addr0		= $0200

; Neolithic
;led_addr	= $0200 ; Write
;keys 		= $0200 ; Read
;addr0		= $0400

memptr		= $F8 
leds 		= $FA

; 2 bytes are saved by d7 = !(Row1#Row2#Row3) 

; All four command keys used
KEY_GO		= $10 ; %00010000
KEY_CR		= $11 ; %00010001
KEY_PB		= $12 ; %00010010 "-"
KEY_RV 		= $13 ; %00010011 "+"

	code
	org $ff80	; +16
LED_PATTERNS:
	db 0b00111111	;0
	db 0b00000110	;1
	db 0b01011011	;2
	db 0b01001111	;3
	db 0b01100110	;4
	db 0b01101101	;5
	db 0b01111101	;6
	db 0b00000111	;7
	db 0b01111111	;8
	db 0b01101111	;9
	db 0b01011111	;a
	db 0b00111100	;b
	db 0b00101000	;c
	db 0b01011110	;d
	db 0b01111101	;e
	db 0b01110001	;f

exec:	jmp addr0	; +3

start:			; +6
	; Set base address, this is also "review"
	lda #>addr0
	sta memptr+1
	stz memptr		; start address addr0, page aligned

loop_main:		; +19
	; current state to leds
	; put memptr and (memptr) into leds
	; [x][x][x][x][x][x][ ][ ]
	;
	ldx #0
	lda memptr+1
	jsr to_leds
	lda memptr
	jsr to_leds
	lda (memptr)
	jsr to_leds

	; Initialize the display count
	; Need to drive six leds for display
	; The sixth is redundant for 4x5 "keyboard"
	; Top two leds are never driven, so dark
	ldy #5
	
loop_digit:		; +10
	; for each LED digit (right to left)...
	lda leds,y
	sta led_addr,y	; display bit pattern
	lda keys
		; d7 = (row1 # row2 # row3)
	bmi loop_99	; no key pressed

			; +10
	; do stuff to sort out the key value	
	; a hex key if below smallest command code
	; per circuit design, set up to be KEY_GO
	cmp #KEY_GO
	bmi loop_hex	; enter hex value
	beq exec	; execute routine stored at addr0
	cmp #KEY_PB	; test 2nd largest command code
	beq loop_pb	; "-": decrement memptr high byte	
	bpl start	; reset memptr to addr0

			; +8
	; remaining special key is return
	inc memptr
	bne loop_90
	inc memptr+1
	bra loop_90

loop_pb:		; +4
	dec memptr+1
	bra loop_90

loop_hex:		; +14
	; else shuffle key value into (memptr)
	; In this version, d7=/Press
	; so d7 clear if hex key
	pha
	lda (memptr)
	asl a
	asl a
	asl a
	asl a
	sta (memptr)
	pla 
	ora (memptr)
	sta (memptr)	

loop_90:		; +4
	; wait for key to be released
	; this will cause display glitch, but...
	lda keys
	bmi loop_90

loop_99:		; +5
	dey
	bpl loop_digit
	bra loop_main
	
to_leds:		; +23
	; unpack byte into two successive LED patterns
	; x has character position
	pha
	lsr a
	lsr a
	lsr a
	lsr a			; high nibble
	tay
	lda LED_PATTERNS,y
	sta leds,x		; this byte comes first
	inx			; advance char position
	pla
	and #$0f		; low nibble
	tay
	lda LED_PATTERNS,y	; index into the patterns
	sta leds,x		; and this byte comes next
	inx			; advance char position
	rts

	; should be at $fffa 
	; NMI vector unallocated

	org $fffc	; +4
	dw start
	dw start	; BRK to program punch routine
Last edited by BruceRMcF on Wed Jun 18, 2025 4:53 pm, edited 1 time in total.
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: First thought on an interface (to use Paleolithic DROM)

Post by barnacle »

The + and - were completely arbitrary and can be changed at a stroke of the silk screen, if that helps you...

(You'll have seen that the switch numbers are somewhat jumbled to get the KB layout; it made the traces between them interesting. Getting eight data lines and seven address lines through it didn't help, either.)

Neil
BruceRMcF
Posts: 388
Joined: 21 Aug 2019

Re: First thought on an interface (to use Paleolithic DROM)

Post by BruceRMcF »

barnacle wrote:
The + and - were completely arbitrary and can be changed at a stroke of the silk screen, if that helps you...

(You'll have seen that the switch numbers are somewhat jumbled to get the KB layout; it made the traces between them interesting. Getting eight data lines and seven address lines through it didn't help, either.)

Neil
Yes, while all the code cares about is the generated keycode, that's fancier than what I would have aimed for. 8)

No need to change the silkscreen, the + and - are more generic for other applications ... the micro-monitor is, presumably, just the launch pad, and not the be-all and end-all.

"AND now to go back and check" is a little hokey, but switching to the slightly more functional Page Back that squeezing a few bytes out has allowed means the "-" is now intuitive.

Indeed, for an EEPROM stage only "mini-monitor" that takes up the full top page, except for the vectors ... or even more! :shock: "-" could be don't accept entered byte and go one step back, and "+" could be the function select, putting an "F." in the not-yet-used LED#7 and having up to 16 functions available based on what hex is entered into the not-yet-used LED#8.

A part of the progression could be having a timer going in the VIA and an interrupt routine putting the segment definitions in an eight byte array in zp up in an ongoing cycle, with a "most recent key entered" byte as well anytime a "d7=0" keycode is read in the process, so the one key keyboard "buffer" can be reset by simply stuffing it with $80.

Then applications are free to do whatever 8x7seg graphics they want, can do a "BIT readkey" to see whether a key is waiting, and can wait for a key or reset the keyboard with a choice of two BIOS calls:

Code: Select all

KEY: ; wait for key, then return it
-       LDA readkey
        BMI -

CLRKEY: ; reset state to NonPressed
        LDX $80
        STX readkey
        RTS
Since there would be a "current LED being driven" value also retained in ZP, I guess the equivalent of "chase the beam" programming would be "chase the digit countdown".
Post Reply