Showing posts with label retro computing. Show all posts
Showing posts with label retro computing. Show all posts

Monday, June 20, 2022

The RIBBBITN3RDing BitPump


The RIBBBITN3RDing BitPump


The RIBBBITN3RDing BitPump r0.1


A little bit of background 

I've been trying quite a few new things with my RIBBBIT65 designs, and I'm running into issues which aren't making a lot of sense.  I've also been having some trouble isolating issues (e.g. "known good" components or circuits don't work *here*... and it turns out "known good" wasn't)  I wanted to have a way that I could repeatably, and quickly, put a bunch of R65 Bus signal configurations ... snapshots, if you will... on the bus to confirm the thing is behaving the way I expect.  Rather than coding something up in 6502 Assembly for every different testing scenario - and, in the process, intoroducing the possibilty that the CORE board I'm using has a problem, I thought it would be better to do something like my TTL Busy Boxes, but on steroids.  The Busy Boxes are just boards with switches and/ or lights that let you do some multiple of 8 worth of switching and/or indicating.  The first one I designed has an 8-position DIP switch, 8 mini-tac switches, and a 10-segment LED bar graph.  That's great for, say, the data bus.  There's still the address bus (16 bits) and all the control signals.  Well, controlling 32 (or more) signals via DIP switches and/or Mini-Tac switches through 20 or 30 cycles (to test an ACIA or a VIA) just seemed like a nightmare.  ...if only there was a way to repeatably send out pre-defined bit patterns over regular time intervals...


The BitPump

The RIBBBITN3RDing BitPump is intended to be an easily reconfigurable digital signal generator which can provide the bit patterns necessary for in-circuit testing of subsystems which interface with 8-bit microcomputers.  


The BitPump, configured for use with the RIBBBIT65 provides:

  • an 8-bit bidirectional Data Bus
  • a 16-bit output-only Address Bus
  • 4 jumpered CPU Control signals (VPB, RWB, MLB, SYNC)
  • Jumpered Pull-ups for 5 CPU Control Inputs (SOB,RDY,BE,NMIB,IRWB,RSTB)
  • 8 bits of completely manual switching, both latching and momentary on each bit, with indicator LEDs
  • 1 "bus clock" driven by a separate IO pin from the bit pattern

The BitPump uses a RaspberryPi Pico (or simlar) to drive a set of four serial-to-parallel shift registers.  

The lower 8 bits (which in the original configuration are wired to the data bus) are bidirectional, and the data direction is controlled by the same "control bit" which drives the R65's RWB (Read, Not-Write) line.  In "Read" mode, the data lines from the bus are displayed on the LEDs.

Since the BitPump is driven by a RaspberryPi Pico (or equivalent), the user has the ability to easily re-program the device to send whatever bit patterns are desired at whatever speed is desired (within the confines of 74HCTXX switching speeds and the capabilities of the sytem under test).


Uses of the BitPump

I'm planning to use the BitPump to see what's going on with my Mini-ITX design.  There's definitely something rotten in Denmark.... hopefully I'll be able to use the BitPump's lower speed, and "known good" bit patterns to isolate the problem(s).  Similar story on the "CORE Daugher Support" board, which is basically supposed to provide a serial console, IO selects, pull-ups and a few other things to the CORE Daughter board I designed for the ITX MoBo, to just make it minimally interactive and runnable.  I plan to troubleshoot both these boards using bit pattern sets delivered by the BitPump.

After that , I plan to use the BitPump to test out different ways of running the 40x4 character LCDs I have.

I can also use it for direct testing of IO and memory chips, since the "data bus" is bidirectional.

What can you use it for?  I dunno.  You could build one and try it out.


Possible updates to the BitPump

One thing I think might be nice is a knob to control the "clock speed".  This could be done easily with a pot and one of the PWM inputs on the Pico.

Another thing that might be nice is a manually controlled "RUN/STOP/STEP" thing that could be done with a couple digital inputs on the Pico.

Do you have any ideas?

Wednesday, March 30, 2022

RIBBBIT65 on Mini-ITX: The Pre-Dawn Chill

RIBBBIT65 on Mini-ITX: The Pre-Dawn Chill

Good news, everyone! I've taught the toaster to feel love!

Also, the design of r0.1 of the Mini-ITX version of the RIBBBIT65 is frozen!  After six months and at least a dozen "clear all tracks" re-works, switching the WDC chips from PDIPs to PLCCs to QFPs, changing all the TTLs and passives to SMT and a myriad other second-guessings and but-what-ifs, first light is in sight.

The board's ID block

The board has 1 ACIA (the serial console, as socketed PLCC), 3 VIAs (2 general pupose, and one "internal" for the LCD character display - as QFPs), and support chips to cover power, reset, PROM select, and IO select.  There are 5 DB9 serial ports and 2 DB25 connectors providing access to the general pupose VIAs.  ACIAs (with MAX232s) are available on "Serial Twin" daughter boards, and the system "core" is provided by a mezzanine board.

PROM and IO select signals, as well as IRQ lines for integrated peripherals are available on headers.

The top of the board, favoring the rear IO
The board is powered by a standard 24-pin ATX-style connector, and has an ATX-style pin header to support power and reset switches, and a power LED.

The top of the board, favoring the front edge
If everything goes according to plan, I should be able to just drop this board into one of a handful of Mini-ITX cases I have around, and cook.

The "core mezzanine board" has already been designed, fabbed, and assembled, and I'm pretty sure it's good to go.  The "serial twins" cards have been fabbed, and I've assembled one of them, so that's a plus.
"Core mezzanine board" with EEPROM address decoding

"Serial Twins" card with 2 MAX232s and PLCC sockets for 2 W65C51s 


...so, now, it's off to review proofs, fix any issues, and then off to manufacturing!


The back of the board, favoring the rear IO


I'm planning on streaming the assembly of this board, as this will likely be quite the educational experience for me, and hopefully you can learn something too, or at least be entertained by my hamfisted efforts!  Check out the RIBBBITN3RDing YouTube channel - subscribe and click the notify bell if you'd like to catch the streams live.  Eventually, I plan to edit the assembly down to a single video with boring bots cut out and tedious soldering sped up... but that will likely take a while.



Tuesday, January 4, 2022

RIBBBIT65 On Mini-ITX: The Before Times

 RIBBBIT65 On Mini-ITX: The Before Times


I've been ruminating and mulling on the possibility of implementing the RIBBBIT65 in a Mini-ITX form factor.  My goal for this is to fit the "CORE" and SystemIO functionality in a Mini-ITX footprint, make use of rear panel IO and front panel lights and switches, and be supplied by a standard ATX power supply connector.

My first pass at the design study was arranging paper cutouts on a cardboard Mini-ITX sized blank.  I quickly discovered that I could not fit the myriad functions I wanted on a Mini-ITX board using PDIP ICs.  This was the impetus for trying to implement the address decoding using an EEPROM.  I then toyed with a few variations on the theme of mezzanine boards... putting the CORE and primary peripherals on the motherboard, and "secondary" peripherals on the mez... putting the main peripherals on the main board, and the CORE on a mez... I settled on putting the CORE on a mezzanine, in large part, because its conversation with the IO is isolated to 8 address lines, 8 data lines, and an AD line.  Sure, you need clock, RW, IRQ and so on... but... that simplifies routing immensely on the motherboard.  It also permits me to use the CORE mezzanine in other applications if I want/need.

Goals

My first goal was trying to make a CORE mezzanine board.  I figured making that fit on something I could stack on a Mini-ITX board would be something of an accomplishment.  It would also give me something solid and tangible I could design against.


PotatoCam view of r0.1 of the CORE mezzanine card
for the RIBBBIT65 Mini-ITX 

KiCAD 3D render of in-progress r0.1 of the
RIBBBIT65 Mini-ITX Motherboard

Above is my second layout of the RIBBBIT65 Mini-ITX, and I think this might be the best I can do under the circumstances.  I don't know if this version of the RIBBBIT65 Mini-ITX is ever going to go to manufacturing. There's just so many compromises. I wanted to at least do a PCB layout to get a sense of the issues I was facing. I may send it out to manufacturing just to validate the integration... work out any bugs before I switch to PLCCs and SMT, but I really think PLCCs for the WDC chips and SMT for the passives and jellybean logic is going to have to be the way forward for the Mini-ITX form factor if I'm going to fit everything I want on there.

The journey continues...


Wednesday, December 15, 2021

CrapDASM Demo (et al) Video!

Just posted a new video to the YouTube channel -- Mostly covers the CrapDASM disassembler.  



One thing I didn't mention (because I forgot in the moment) among the things I want to fix/improve on the CrapDASM (and, yeah, I think that's going to be the name) is "decorations" for the mnemonics.  For example,  indicating vectors, indexed offsets, and stuff like that.  Right now, you can't just take the disassembler output, type it into an assembler, and go...  and while that may never actually be a thing, I'd like to get a little closer to understanding what's going on by reading the disassembler output.  Decorations are distinct based on opcode, and there is a finite and small list of decorations (basically one for each addressing mode).  

I also discovered (after posting the video) and issue with the routine that increments the the vector to the current OpCode.  Moar debugging!

Anyway,  progress is being made, so, hooray!

Sunday, December 12, 2021

Avengers! Disassemble!

 

Disassembler, disassemble yourself!

So, I thought it would be a good exercise to write a disassembler for the RIBBBIT65.  My plan is to integrate this into the CoreROM, but I have a few fixes and tweaks I want to do first.  As it is now, this starts as $1000 and references some constants and code in the CoreROM (e.g. CIOH), so, unfortunately, this won't really output anything without that, but you could stuff your own output routines in there if you were so inclined.  

...and, yes, I realize there's a bunch of stuff in here that's redundant... and some hard-coded addresses (rather than constants)... but I thought it might be nice to get something out there.

Originally, I had written this with its own "private" buffer, that it would then copy to the CIOH output buffer, but then I realized that was dumb, and just made this write directly to the CIOH output buffer.  Unfortunately, there are still some vestiges of the "private buffer" business in here (constants and such).

Anyway... here it is.

; START BNW CONSTANTS
DBUTIL0 = $50
DBUTIL1 = $51
DBUTIL2 = $52
DBUTIL3 = $53
DBUTIL4 = $54
VWMSGSYS = $0090  ; System Message Vector
VWMSGPRG = $0092  ; Program Message Vector
VWMSGSPC = $0094  ; Special Message Vector
DBCPBTERM = $6237  ; Current Peripheral Buffer Terminate Value
CBSERBRDM = $6238  ; Serial Baud Rate Delay MultiplierDFCLCDLB0 = $6d00  ; Character LCD Line Buffer 0
DFCLCDLB1 = $6d30  ; Character LCD Line Buffer 1
DFCLCDLB2 = $6d60  ; Character LCD Line Buffer 2
DFCLCDLB3 = $6d90  ; Character LCD Line Buffer 3
DFCLCDLB4 = $6dc0  ; Character LCD Line Buffer 4
pfciohobufappendbytestart = $b264 ;EXPR(45668=0xb264) ABS 
pfsetcurpstart = $b1c0 ; EXPR(45504=0xb1c0) ABS 
pfciohstdentry = $b27f ; EXPR(45695=0xb27f) ABS 
pfciohobufinitstart = $b23d ; EXPR(45629=0xb23d) ABS 
; END BNW CONSTANTS


VWLDASMSTARTVEC = $b0   ; Vector to beginning of space to disassemble
VWLDASMENDVEC = $b2     ; Vector to end of space to disassemble
VWLDASMCUROCVEC = $b4   ; Vector to the current "working" OpCode
DBLDASMOBWP = $ba       ; Output Buffer Write Pointer (offset)
DBLDASMOBRP = $bb       ; Output Buffer Read Pointer (offset)
DBLDASMOCVINCCNT = $bc  ; Number of times to increment VWLDASMCUROCVEC
DBLDASMDONEFLG = $bd    ; Done Flag -- Anything other than $00 means done
DBLDASOCWRKCPY = $be    ; Working copy of the current OpCode





DBBTHSRC = $21
;DWBTHRES = $22
DWBTHRES = $72
PFBYTETOASCII = $e14f

;BTHRESL EXPR(115=0x73) EQU 
;BTHRESH EXPR(114=0x72) EQU

    .org $1000
pfbdasmentry:

    ;;;; Tell the CLCD we're streaking
    lda #<$c200 ; dfr65msg001 ; $c200 ; dfr65msg001
    sta $0090 ; VWMSGSYS ; $0090 ; VWMSGSYS
    lda #>$c200 ; dfr65msg001 ; $c200 ; dfr65msg001
    sta $0090 + 1 ; VWMSGSYS + 1 ; $0090 + 1 ; VWMSGSYS + 1
    lda #pfbdasmclcdmsg ; twmesg   ;;;;   <<<======LOCAL MESSAGE
    sta $0092 + 1 ; VWMSGPRG + 1 ; $0092 + 1 ; VWMSGPRG + 1
    jsr $ce17 ; pflcd162spmsgtobufstart ; $ce17 ; pflcd162spmsgtobufstart
    jsr $bd00 ; pfclcd162l1bufstart ; $bd00 ; pfclcd162l1bufstart
    
    
    ;; INITIALIZE THE THINGS
    lda #$00
    sta DBLDASMDONEFLG
    clc
    lda VWLDASMSTARTVEC
    sta VWLDASMCUROCVEC
    lda VWLDASMSTARTVEC + 1
    sta VWLDASMCUROCVEC + 1
    
    jsr pfbdasmserportinit
    
;;;; HERE BEGINS THE BIG OUTER LOOP
pfbdasmmainlooptop:

    ;; Save a working copy of the current OpCode
    ldy #$00                  ; Copy the Current OC Vector to "Working Copy"
    lda (VWLDASMCUROCVEC),y
    sta DBLDASOCWRKCPY
    
    ; Initialize the things
    lda #$00
    sta DBLDASMOBWP       ; Output Buffer Write Pointer (offset)
    sta DBLDASMOBRP       ; Output Buffer Read Pointer (offset)
    
    ; Clear the Output Buffer
    jsr pfciohobufinitstart

    ; Call the POC Disassembler
    jsr pfpocdasmentry
    
    ; Write the Serial Buffer out to the port
    jsr pfbdasmserportwrite
    
    ;;; Increment the "Current OpCode Vector" the correct number of 
    ;;; times for the "length" of the OpCode
    jsr pfbdasmcurocvecincstart

    lda DBLDASMDONEFLG        ; Get the "DONE" flag
    cmp #$00                  ; $00 == Keep going
    bne pfbdasmexit           ; Bail out if != 0
    
    jmp pfbdasmmainlooptop
    
pfbdasmexit:
    rts
    
    
    
    
    
;;;;;; INITIALIZE THE SERIAL PORT
pfbdasmserportinit:
    ; preserve the registers
    pha
    txa
    pha
    tya
    pha
    ; Initialize the SIO4 device
    ;; Set baud rate write delay
    lda #$08
    sta CBSERBRDM ; CBSERBRDM
    ;; Set terminate character
    lda #$00
    sta DBCPBTERM ; DBCPBTERM
    ;lda #$04 ;;; 
    lda #$05
    jsr pfsetcurpstart
    lda #$10
    jsr pfciohstdentry
    ;restore the registers
    pla
    tay
    pla
    tax
    pla
    rts


;;;;;; WRITE TO THE SERIAL PORT
pfbdasmserportwrite:
    ;;;; START WRITE TO SERIAL PORT MAYBE
    ; Preserve the registers
    pha
    tya
    pha
    txa
    pha
    
    ;lda #$04 ;;;;
    lda #$05
    jsr pfsetcurpstart
    lda #$62
    jsr pfciohstdentry
        
    ;;;; END WRITE TO SERIAL PORT MAYBE
    ; Restore the registers
    pla
    tax
    pla
    tay
    pla
    rts

;;;;;;;;NEW INCREMENT CURRENT OPCODE VECTOR
pfbdasmcurocvecincstart:
    pha
    txa
    pha
    tya
    pha
    
    ldy DBLDASOCWRKCPY
    lda dfopcdarglut,y
    sta DBUTIL3 ; TMP copy of OpCode length
    ; Get the c lsb
    lda VWLDASMCUROCVEC
    ; eor with $ff to see how many steps til carry
    eor #$ff
    sta DBUTIL4 ; tmp holding spot for "steps til carry"
    lda DBUTIL4
    cmp DBUTIL3 ; compare with opcode length
    bcs pfbdasmcurocvecincinclsbonly ; no carry expected
    lda DBUTIL3 ; Opcode Length
    sbc DBUTIL4 ; tmp holding spot for "steps til carry"
    sta VWLDASMCUROCVEC
    clc
    lda VWLDASMCUROCVEC + 1
    adc #$01
    sta VWLDASMCUROCVEC + 1
    jmp pfbdasmcurocvecinccheckgt
    nop
    
pfbdasmcurocvecincinclsbonly:
    clc
    lda VWLDASMCUROCVEC
    adc DBUTIL3
    sta VWLDASMCUROCVEC
    nop
  
pfbdasmcurocvecinccheckgt:
    lda VWLDASMCUROCVEC + 1  ; 80
    cmp VWLDASMENDVEC + 1  ; 80
    beq pfbdasmcurocvecincchecklsbgt
    bmi pfbdasmcurocvecincdonedone
    bpl pfbdasmcurocvecincoverflow
pfbdasmcurocvecincchecklsbgt:
    lda VWLDASMCUROCVEC
    cmp VWLDASMENDVEC
    bmi pfbdasmcurocvecincdonedone
    nop

pfbdasmcurocvecincoverflow:
    lda #$ff
    sta DBLDASMDONEFLG
    nop

pfbdasmcurocvecincdonedone:    
    pla
    tay
    pla
    tax
    pla
    rts
    nop
    nop
    nop
    nop
;;;;;;;;;;END NEW INCREMENT CURRENT OPCODE VECTOR

;;;;;;; START "PROOF OF CONCEPT" DISASSEMBLER
    ;.org $1800
pfpocdasmentry:
    ;  Preserve the registers
    pha
    txa
    pha
    tya
    pha 
    
    ldy #$00
    lda (VWLDASMCUROCVEC),y  ; Load the OpCode at the "Current OpCode Vector"
    sta $0600                ; Store the OpCode in $0600
    tay                      ; Move the OpcCode to rY
    lda dfopcdmnemlut,y      ; Load the Mnemonic Offset from the lookup table
    sta $0601                ; Store the Mnemonic Offset in $0601
    lda dfopcdarglut,y       ; Load the Arg Count from the lookup table
    sta $0602                ; Store the Arg Count in $0602
    lda #$00                 ; Set the "Working Arg" to #$00
    sta $0603                ; Store the "Working Arg" to $0603
    lda #$00
    sta $0604                ; Out Buff Offset
        
    ;; We're going to put an output string in RAM, starting at $06010
    ;; First, post the current address
    lda VWLDASMCUROCVEC + 1
    jsr PFBYTETOASCII
    lda DWBTHRES ; 72
    jsr pfciohobufappendbytestart
    lda DWBTHRES + 1 ; 73
    jsr pfciohobufappendbytestart
    
    lda VWLDASMCUROCVEC + 0
    jsr PFBYTETOASCII
    lda DWBTHRES ; 72
    jsr pfciohobufappendbytestart
    lda DWBTHRES + 1 ; 73
    jsr pfciohobufappendbytestart
    
    lda #$3a ; ":"
    jsr pfciohobufappendbytestart
    lda #$20 ; " "
    jsr pfciohobufappendbytestart
    
    ;; Second, copy the Nmemonic
    lda $0601
    tay
    lda dfmnemreflut,y
    jsr pfciohobufappendbytestart
    iny
    lda dfmnemreflut,y
    jsr pfciohobufappendbytestart
    iny
    lda dfmnemreflut,y
    jsr pfciohobufappendbytestart
    ;;
    ;; We would put a decoration here if appropriate
    ;;
    ;; Add a space
    lda #$20
    jsr pfciohobufappendbytestart
    
    ;;
    ;; Convert the OpCode to ASCII Hex
    ldy #$00
    lda (VWLDASMCUROCVEC),y
    sta DBBTHSRC
    jsr PFBYTETOASCII
    lda DWBTHRES ; 72
    jsr pfciohobufappendbytestart
    lda DWBTHRES + 1 ; 73
    jsr pfciohobufappendbytestart
    ;;
    ;; Add a space
    lda #$20
    jsr pfciohobufappendbytestart

    ldy #$01 
pfpocdasmarglooptop:
    cpy $0602 ; If we're already at the "length" value, dump out.
    beq pfpocdasmdone
    
    ;; FIRST ARG
    lda (VWLDASMCUROCVEC),y
    sta DBBTHSRC
    jsr PFBYTETOASCII
    lda DWBTHRES ; 72
    jsr pfciohobufappendbytestart
    lda DWBTHRES + 1 ; 73
    jsr pfciohobufappendbytestart
    lda #$20
    jsr pfciohobufappendbytestart
    
    ;; SECOND ARG
    iny
    cpy $0602 ; If we're already at the "length" value, dump out.
    beq pfpocdasmdone
    lda (VWLDASMCUROCVEC),y
    sta DBBTHSRC
    jsr PFBYTETOASCII
    lda DWBTHRES ; 72
    jsr pfciohobufappendbytestart
    lda DWBTHRES + 1 ; 73
    jsr pfciohobufappendbytestart
    lda #$20
    jsr pfciohobufappendbytestart
    
    ;; THIRD ARG
    iny
    cpy $0602 ; If we're already at the "length" value, dump out.
    beq pfpocdasmdone
    lda (VWLDASMCUROCVEC),y
    sta DBBTHSRC
    jsr PFBYTETOASCII
    lda DWBTHRES ; 72
    jsr pfciohobufappendbytestart
    lda DWBTHRES + 1 ; 73
    jsr pfciohobufappendbytestart
    lda #$20
    jsr pfciohobufappendbytestart
    
pfpocdasmdone:
    lda #$0d
    jsr pfciohobufappendbytestart
    lda #$0a
    jsr pfciohobufappendbytestart
    lda #$00
    jsr pfciohobufappendbytestart
    lda #$ea
    jsr pfciohobufappendbytestart
    ; Restore the registers
    pla
    tay
    pla
    tax
    pla
    
    rts
    
;;;;;;; END "PROOF OF CONCEPT" DISASSEMBLER

pfbdasmclcdmsg:
    ;.asciiz "P: R65 DisASM"
    .asciiz "P: R65 CrapDASM"
    
    .byte $00,$00,$00,$00, $00,$00,$00,$00, $00,$00,$00,$00, $00,$00,$00,$00
    .asciiz "DEADBEEFdeadbeef"




; Lookup Tabels:  
;   Opcode to Mnemonic Lookup (dfopcdmnemlut)
;   Opcode to Arg Count Lookup
;   Mnemonic Reference (dfmnemreflut)

    .org $2000


;;;;; MNEMONIC BY OPCODE LOOKUP TABLE
; OpCodes are one byte each.
; OpCode is offset from start of table
; Value at offset is offset from start of dfmnemreflut containinf the Mnemonic
dfopcdmnemlut:
    .byte $30,$84,$f0,$f0,$f0,$84,$08,$f0,$d0,$84,$08,$f0,$f0,$84,$08,$f0
    .byte $10,$84,$f0,$f0,$f0,$84,$08,$f0,$48,$84,$f0,$f0,$f0,$84,$08,$f0
    .byte $6c,$04,$f0,$f0,$0c,$04,$a8,$f0,$d4,$04,$a8,$f0,$0c,$04,$a8,$f0
    .byte $f0,$04,$f0,$f0,$f0,$04,$a8,$f0,$4c,$04,$f0,$f0,$f0,$04,$a8,$f0
    .byte $b0,$44,$f0,$f0,$f0,$44,$7c,$f0,$c8,$44,$7c,$f0,$68,$44,$7c,$f0
    .byte $18,$44,$f0,$f0,$f0,$44,$7c,$f0,$50,$44,$f0,$f0,$f0,$44,$7c,$f0
    .byte $b4,$00,$f0,$f0,$f0,$00,$ac,$f0,$cc,$00,$ac,$f0,$68,$00,$ac,$f0
    .byte $1c,$00,$f0,$f0,$f0,$00,$ac,$f0,$54,$00,$f0,$f0,$f0,$00,$ac,$f0
    .byte $f0,$bc,$f0,$f0,$dc,$bc,$d8,$f0,$a0,$f0,$8c,$f0,$dc,$bc,$d8,$f0
    .byte $20,$bc,$f0,$f0,$dc,$bc,$d8,$f0,$9c,$bc,$c0,$f0,$f0,$bc,$f0,$f0
    .byte $78,$70,$74,$f0,$78,$70,$74,$f0,$98,$70,$88,$f0,$78,$70,$74,$f0
    .byte $24,$70,$f0,$f0,$78,$70,$74,$f0,$58,$f0,$c4,$f0,$78,$70,$74,$f0
    .byte $3c,$34,$f0,$f0,$3c,$34,$40,$f0,$a4,$34,$90,$f0,$f0,$34,$40,$f0
    .byte $28,$34,$f0,$f0,$f0,$34,$40,$f0,$5c,$34,$f0,$f0,$f0,$34,$40,$f0
    .byte $38,$b8,$f0,$f0,$38,$b8,$64,$f0,$94,$b8,$80,$f0,$f0,$b8,$64,$f0
    .byte $2c,$b8,$f0,$f0,$f0,$b8,$64,$f0,$60,$b8,$f0,$f0,$f0,$b8,$64,$f0

;;;;; ARGUMENT COUNT BY OPCODE LOOKUP TABLE
; OpCodes are one byte each.
; OpCode is offset from start of table
; Value at offset is number of additional bytes to read for this OpCode
dfopcdarglut:
    .byte $01,$02,$00,$00,$00,$02,$02,$00,$01,$02,$01,$00,$00,$03,$03,$00
    .byte $02,$02,$00,$00,$00,$02,$02,$00,$01,$03,$00,$00,$00,$03,$03,$00
    .byte $03,$02,$00,$00,$02,$03,$02,$00,$01,$02,$01,$00,$03,$03,$03,$00
    .byte $00,$02,$00,$00,$00,$02,$02,$00,$01,$03,$00,$00,$00,$03,$03,$00
    .byte $01,$02,$00,$00,$00,$02,$02,$00,$01,$02,$01,$00,$03,$04,$03,$00
    .byte $02,$02,$00,$00,$00,$02,$02,$00,$01,$03,$00,$00,$00,$03,$03,$00
    .byte $01,$02,$00,$00,$00,$02,$02,$00,$01,$02,$01,$00,$03,$03,$03,$00
    .byte $02,$02,$00,$00,$00,$02,$02,$00,$01,$03,$00,$00,$00,$03,$03,$00
    .byte $00,$02,$00,$00,$02,$02,$02,$00,$01,$00,$01,$00,$03,$03,$03,$00
    .byte $02,$02,$00,$00,$02,$02,$02,$00,$01,$03,$01,$00,$00,$03,$00,$00
    .byte $02,$02,$02,$00,$02,$02,$02,$00,$01,$02,$01,$00,$03,$03,$03,$00
    .byte $02,$02,$00,$00,$02,$02,$02,$00,$01,$00,$01,$00,$03,$03,$03,$00
    .byte $02,$02,$00,$00,$02,$03,$02,$00,$01,$02,$01,$00,$00,$03,$03,$00
    .byte $02,$02,$00,$00,$00,$02,$02,$00,$01,$03,$00,$00,$00,$03,$04,$00
    .byte $02,$02,$00,$00,$02,$02,$02,$00,$01,$02,$01,$00,$00,$03,$03,$00
    .byte $02,$02,$00,$00,$00,$02,$02,$00,$01,$03,$00,$00,$00,$03,$03,$00

;;;;; MNEMONIC TEXT LOOKUP TABLE
; Mnemonics are all 4 bytes long - 3 character and a NUL ($00) terminator
dfmnemreflut:
    .byte $41,$44,$43,$00,$41,$4e,$44,$00,$41,$53,$4c,$00,$42,$49,$54,$00
    .byte $42,$50,$4c,$00,$42,$4d,$49,$00,$42,$56,$43,$00,$42,$56,$53,$00
    .byte $42,$43,$43,$00,$42,$43,$53,$00,$42,$4e,$45,$00,$42,$45,$51,$00
    .byte $42,$52,$4b,$00,$43,$4d,$50,$00,$43,$50,$58,$00,$43,$50,$59,$00
    .byte $44,$45,$43,$00,$45,$4f,$52,$00,$43,$4c,$43,$00,$53,$45,$43,$00
    .byte $43,$4c,$49,$00,$53,$45,$49,$00,$43,$4c,$56,$00,$43,$4c,$44,$00
    .byte $53,$45,$44,$00,$49,$4e,$43,$00,$4a,$4d,$50,$00,$4a,$53,$52,$00
    .byte $4c,$44,$41,$00,$4c,$44,$58,$00,$4c,$44,$59,$00,$4c,$53,$52,$00
    .byte $4e,$4f,$50,$00,$4f,$52,$41,$00,$54,$41,$58,$00,$54,$58,$41,$00
    .byte $44,$45,$58,$00,$49,$4e,$58,$00,$54,$41,$59,$00,$54,$59,$41,$00
    .byte $44,$45,$59,$00,$49,$4e,$59,$00,$52,$4f,$4c,$00,$52,$4f,$52,$00
    .byte $52,$54,$49,$00,$52,$54,$53,$00,$53,$42,$43,$00,$53,$54,$41,$00
    .byte $54,$58,$53,$00,$54,$53,$58,$00,$50,$48,$41,$00,$50,$4c,$41,$00
    .byte $50,$48,$50,$00,$50,$4c,$50,$00,$53,$54,$58,$00,$53,$54,$59,$00
    .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
    .byte $3f,$3f,$3f,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00


...and that's all I have to say about that.

Thursday, December 9, 2021

Updates, Distractions, and Failures

 Updates, Distractions, and Failures

I dropped my phone over the last weekend and spidered the screen.  That was a disappointing failure.  New phone should be arriving today.  Apologies for the potato photos that follow.

PCB Update

I put in an order for 4 new boards weekend before last, and they showed up this past Tuesday, which was cool.  In that order were:

  • COREplus r0.2
  • SystemIO r0.2
  • ITX CORE Daughter Card (a.k.a. the CORE Mezzanine) r0.1
  • ATX Power Adapter/Switcher r0.1

New boards!

All the boards arrived, and appear to be manufactured as designed.  That's good.  Thanks, JLCPCB!

I assembled one of the COREplus r0.2 boards, and it works.  Power-on Reset works without bodges, and the blinkenlights work.  So, that's good.

COREplus r0.2 - BLINKENLIGHTS!

I did some continuity checks on the SystemIO r0.2, and it turns out I messed that up.  The silkscreen issue with the "future peripherals" headers has been resolved, which is great, but it looks like I messed up on the RS-232 fixes, so all 5 ports still have the reveresed TXD and RXD lines between the MAX232s and the respective DB9 connectors.  I DID fix the problem in the schematic, but, apparently, I got distracted and never updated the PCB in KiCAD.  That has been remedied, and so, in r0.3, there should be no bodges required (for that, at least).  A mistake I hope never to make again.

I assembled one of the ITX CORE Daughter Card r0.1 boards, and it appears to be working-ish... the CPU, RAM, and ROM are all appearing to do stuff.  ...that is, once I put the clock oscillator in the right way (after cooking 3 of them -- not my proudest moment).  Unfortunately, hooking up a Jenny-O with the 6551 daughter card is, so far, not yielding communication.  I'm investigating.

ITX CORE Daughter Card r0.1 - Can it be saved?

I have not yet assembled the ATX Power Adapter/Switcher r0.1.  Might get stuck in to that this week.  It is not my highest priority at the moment.

CoreROM update

I've been working on a disassembler for inclusion in the CoreROM.  The way it would work is you put a start address and an end address in some special spot in RAM, and it will pick out the opcodes, match them to the mnemonics, recognize how many arguments that opcode should have, see if there's any "decoration" (like ",Y" or ",X" or " A"), and display the mnemonic, the decoration (if any), the opcode and the arguments (if any).  This has been slow going.  Putting together the lookup tables to get the opcodes and argument counts manually was a total pain, and I think I messed it up.  I went back to the drawing board, and wrote a Python tool to build the lookup tables.  That seems to have worked a treat, but I think I'm having a problem with a subroutine call maybe nuking a register somewhere along the way.  Debugging continues.

RIBBBIT65 ITX update

As I was poking around on DigiKey and Mouser, I found IO connectors I think I'm going to use, which is good.  I'm looking at double-stacked DB9Fs for the general purpose RS-232s, a single DB9M for the console, and double-stacked DB25Fs for the 2 general purpose VIAs.  While I was on Mouser's site, I discovered that they sell WDC's product line -- like the whole thing, apparently.  Looks like they have the W65C02, W65C22, and W65C51 in PLCC.  I poked around a little more, and discovered that, even in THT sockets, they are quite a bit smaller than the DIP40s and DIP28s I've been using so far.  I can fit almost 3 PLCC44s in the space of one DIP40 (in terms of board real estate).  If I go that route for the WDC chips and the EEPROMs, and SMT for the MAX323s and RAM, I might be able to fit the CORE and SystemIO on one MiniITX board.  It will certainly be more expensive than using dual-wipe sockets on DIP chips as I have been so far, but in a Mini-ITX form factor, that might be excusable.  I'd probably have to do a mezzanine card for the "Pageable ROM" and maybe a 3.5" External Bay thingy (prolly 3D printed) for the Cartridge Slot as options, but that's still pretty cool.  I'd be curious to hear your thoughts.

So, as of early December, that's where we are.


Sunday, December 5, 2021

RIBBBIT65: Why Is?

RIBBBIT65: Why Is?

The RIBBBIT65_COREplus

First and foremost, the RIBBBIT65 is an autodidactic exercise, wherein I learn how computers work at the "machine language and bus signal" level.

You see, I was at just about the right age to be in the target demographic when home computers started taking off -- the late '70s, early '80s.  It was really neat.  A friend of mine who was very, very smart, and was fortunate enough to have positive and encouraging parents, got a computer... I think it was for Christmas... an Atari 400.  ...and I was *fascinated*.  He got really, really good with the programming... so much so that he'd started not just writing little machine language subroutines that he'd call from BASIC... no.  He got an Assembler/Editor cartridge and was writing whole programs in Assembly.  At this point I had no computer.  I would shoulder surf and he'd show me programs he'd written in BASIC, and I could kinda make sense of them.  I could *get* BASIC.  I could probably make a computer do things.  

Well, another Christmas, another computer.  I don't recall if it was the *next* Christmas, but it wasn't long after the Atari 400 hundred showed up, that his parents had gotten him an Atari 800 (With a floppy drive!) as an upgrade, since he'd outgrown the 400.  I mean, fine... anyone could outgrow 16K or RAM... but 48K?  I'd like to see you try.  Well, his 400 found its way to the basement of their house and stayed there for a while.  

At this time, I was more or less a fixture at their house (I was more ubiquitous than the paint on the walls), and we would often play in their basement (because... outside?  what's that?!).  On the way down and on the way up, I would see that Atari 400 sitting there... unused.  Lonely.  Finally, I got up the nerve (and scraped together a little cash) and asked my friend's dad if I could buy the old 400...with its cassette drive.  $30 later, it was mine.  

Soon, I was writing BASIC like a banshee.... I guess.  I don't know much about banshees.  Anyway, I was printing, "Hello world" on the screen and flashing colors and doing all sorts of basic stuff.  It was neat.  ...but there was something about sprites and machine language that made them.... beyond me... somehow.  Maybe it was the fact that Atari BASIC supported them, kinda, but I didn't really get a good idea of the how of it.  I don't know if it was a cognitive thing or a psychological thing... but my young thinkymeat was having none of it.

Time and a half went by, and I'd upgraded my rig to an Atari 800XL with a floppy drive, and I was doing some cool stuff with that, but I never really got into Assembly.  Eventually, I made the leap into PCs.  That was 1991, and I've been getting farther and farther from the bare metal ever since.

In the intervening years, I've actually settled into a career in IT.  I've become a Linux nerd.  I've picked up several languages, but in the back of my mind, there was a little bugaboo; a tiny voice in the dark, telling me I didn't really get it.  ...not really.  It was that sad little 400 in the basement.

In 2016, not long after starting a job with a 3-hour round-trip commute by rail, I decided I would undertake a project to "get" machine language.  I decided I would write a CPU emulator.  Strictly speaking, it ended up being more of a "machine language interpreter"... but, it worked.  I wrote a monitor program (in bare Z80 machine language... not Assembly.... the actual opcodes) that was a little under 2K.  Why yes, the train was a terrible soul-crushing thing.

I got a couple "retro computer" type kits, and they were neat, but there was always something lurking in the background.... telling me I didn't really get it.  ...not really.  Most of these machines, like the RC2014, are kinda limited in scope, and while others have done cool expansions to them, I was hitting a roadblock.  The "working" part of the system was a sort of barrier.  For fear of breaking what worked, I didn't dare muck about.

Then, in 2020, I caught wind of Ben Eater's excellent series of videos about building a 6502-based computer from the ground, up.  Like Sir Robin at the Bridge of Death, after seeing Galahad's triumph, I thought, "This is something I could do."  I ordered Ben's 6502 kit, and got cracking.  I was having some trouble keeping all the wiring straight on the breadboards, and I was getting frustrated... I didn't know whether the problem was my wiring, the breadboards, or faulty parts.  From a number of sources, I'd become aware that there was a decent Open Source "Electronic Design Aid" -- KiCAD, and there were board houses out there that could do low-cost prototype manufacturing... so I put ham and cheese together, and went about re-implementing Ben Eater's design in KiCAD, and getting some boards made.  After finding and fixing the error I'd made on the board (there's always one, isn't there?), it was great.  I could actually do things.  I could write programs in Assembly, burn them to an EEPROM, and they'd actually work.

At this point, I'd arrived at the same sort of frustrating point I was at with the "retro computer" kits.  If I was going to move forward, I'd have to take the risk of wrecking it.  But, there was one significant difference.  I had made everything that worked, and I had spares.

I was finally free to think creatively and solve problems (which, I readily admit, had been solved countless times before, far more elegantly, by numberless people).  Like so many other projects which had engaged and held my interest, I had a basic set of essentially indestructible tools, a practically limitless supply of resources, and only the laws of physics to constrain me.  I could play.  I could try things out.  I could fail.  

So, I thought about the itches that needed scratching.

One thing that bothered me about the commercially-available "home computers" was that they were kind of closed black boxes.  Between FCC regulations, product safety regulations, building down to a cost, and various other pressures, machines like the Atari 8-bits, and the Commodores were kind of closed off and inaccessible to me.  Here's your feature set.  Like it.  The Apple ][ seemed more open, but was obscenely expensive, and, therefore, off-limits.  Many of the retro kits were even more constrained.

I wanted a lab computer.  Something I could pull apart and rejigger as I saw fit, to serve whatever purpose I had in the moment.  I wanted a machine that would afford me a lot of IO possibilities, because who knows what I might want to do with it?  Something like one of those old Radio Shack "hundred and one electronic projects" kits, but not lame.  I decided it should have a good, broad set of base peripherals - A console, some serial ports, a couple VIAs, I2C and SPI, storage, so that you could stand up a really usable computer... or pare it back if need be, to save space or power, or whatever. I also thought it should have some expand ability so an end user could put in whatever they want.

I wanted to go through the process of building up an operating system.  What kind of masochist would subject himself to such a thing?  This kind, apparently.  Device drivers, APIs and so on.  I wanted to build those things, so I could really understand what's going on under the hood.

People have asked me about graphics and sound and what games I want to be able to play on it.  For me, the goal is not to play games on the RIBBBIT65.  I have a Nintendo Switch Lite for that.  The RIBBBIT65 *is* the game.

So, today, the RIBBBIT65 is on its way.  I have a good, stable core machine, and an IO platform on which to build something useful.  I have a decent Monitor program, and I'm working on an IO handler to abstract the various underlying peripherals.  There are design aspects which folks have told me remind them of the BBC Micro, which I suppose is flattering, as that's a highly-regarded machine for its time.  

I have a plan to do a version of the RIBBBIT65 in a Mini-ITX form-factor to allow more "hands off" use of the machine, as well as unifying a "bench-top" version, where the guts are all accessible, but it mechanically fits together better than the boards I've done so far.

I'm thinking of doing a hand-held "pendant"-style console device for interacting with the R65 Monitor, with, say, a 24-key keyboard, and either a character LCD or 7-segment LEDs to show addresses and data bytes.  It would speak a stripped down dialect of the monitor command set (for example, "page dump" wouldn't really work on a 6-digit LED)

I'm not just building a computer, I'm finally building understanding.  The RIBBBIT65 is on the verge of being a mere byproduct... an artifact whose significance lies in the research and trial and error that bought me the understanding to build it in the first place.  This is far more satisfying than any work I've done for money in the last 20 years.  It's certainly not for everyone.  But it is for me.


RIBBBIT65: What Is It?

RIBBBIT65: What Is It?

There are a lot of ideas out there in the world about what a computer should be, and what a computer should be able to do.

Certainly a computer should be able to execute specified commands in a specified order, retrieve and store data, and be able to perform arithmetic and logical operations on that data.  It should be able to accept some input, and provide some output.  Its execution of instructions should be able to be altered either by data values or input received.

Beyond that, the intended application goes a long way toward dictating what the specifications and requirements are which will drive the design.

So, what is the RIBBBIT65, beyond being a computer?  What kind of computer is it?

The RIBBBIT65 is an 8-bit microcomputer, based around the Western Design Center's W65C02 microprocessor family.

It is intended primarily as general purpose computer with an eye on learning.

The computing ecosystem is radically different today than it was when the MOS 6502 was first introduced in 1975.  Today, our computers have so much spare horsepower, we can emulate whole computer systems in our web browsers.  Almost everybody who could read this post has a computer of some kind and access to the Internet.  Today, you really don't need "the actual hardware" to enjoy a completely reasonable emulation or simulation of using old hardware, if that's your interest.

I'm not going to lie, though.  There are some of us, for whom the simulation is insufficient.  Some of us want to poke pins with probes.  Some of us want to talk to the CPU on its own terms.  There are some times when the simulation and the emulation are not what is needed.  Sometimes you actually need the hardware.

There are people out there who have done amazing work, re-implementing Commodore, Sinclair, and Atari systems with blends of new and old hardware, and I applaud their efforts.  Reverse-engineering a VIC-II or an ANTIC can't be an easy task.  For me, though, with each ASIC and ULA there is a definition of borders and an imposition of constraints.  With every piece of "other people's software" between me and the CPU, the machine itself becomes more diffuse and meaningless.  

I wanted a chance to work down on the bare iron, and stand up a computer.  A system.  I wanted the feeling of discovery and triumph that came from wrangling a box of rattly parts and wires into a working machine with peripherals and a workable but simple interface.  Something that would allow me to demonstrate, tame, and use most of the core functionality from the dawn of the microcomputer age.  

I have mixed feelings about things like floppy disks and CRT monitors.  Aesthetically, I find them appealing.  I like the idea of them -- the close relationship between the abstract and the concrete... between ethereal electrical fluctuations and real, physical phenomena.  Functionally, I feel they were good for their time, but I have no practical use for them today.

I had struggled for a long time with the conceptual leap required for me to grok machine language.  Ben Eater's "Hello World From Scratch" video straightened most of that out for me.  I finally saw a path to the kind of machine that interested me.

What kind of machine is that?  It's the RIBBBIT65, of course.

The RIBBBIT65 is a general purpose computer.  It's not a games machine or an industrial controller -- not by design, anyway.  Initially, I just wanted to make a board that would give me a good base-line 6502-based system that I could experiment with, that only required that I knew the 6502 itself, the basic layout of the memory map (e.g. where RAM, ROM, and IO are).

RIBBBIT65_COREplus

The RIBBBIT65_COREplus board satisfies that need for me.  It's got all the basic functionality, and conforms to a fairly straightforward model - 32K ROM, 32K RAM.  You want to do more with it, you can hang stuff off the bus.

The RIBBBIT65 CoreROM is currently in development, but at this stage, it has a working monitor program, and a framework for an abstracted IO handler and interrupt handler.  The CoreROM is divided into 4 8K segments, with one (the lowest 8K segment) being set aside as ROM that can be paged-in and -out as needed.

The RIBBBIT65 ROMxpander is still in early stages of development, but the intent is to provide 3 32K user-installable ROMs (intended to changed infrequently) which are each broken up into 4 8K segments, which can be paged in for the lower 8K of the CoreROM.  One possible application would be one ROM chip would contain up to 4 programming languages or tools, while another might contain up to 4 productivity tools.  The ROMxpander is also planned to accept an 8K "ROM cartridge" with the ability to quickly and easily switch ROM-based programs.

RIBBBIT65 SystemIO

The RIBBBIT65 SystemIO board provides a set of peripherals and related functionality to let the RIBBBIT65 interact with the world.  It has a serial console, which nearly all modern "retro-computer" kits have, but it also has 4 additional general purpose RS232 ports.  It has 2 general purpose W65C22 Versatile Interface Adapters, and a third for driving an LCD character display.  There are plans for storage devices, SPI & I2C adapters, and an interrupt controller to allow multiple devices to send interrupts to the CPU (provided the software is setupt to handle them properly).  Space has also been set aside for a "character addressable video display adapter" on the SystemIO bus, which could allow something on the order of Sinclair ZX Spectrum graphics, full-screen editing, and so on.

The RIBBBIT65 UserIO board is, at this stage, mostly just conceptual, but it is intended to leverage the SystemIO board, and provide an additional 16 ports for user-defined peripherals, with interrupt handling for upto 7 of them.

Finally, the RIBBBIT65-ITX (in development) is intended to provide a subset of RIBBBIT65 functionality in a Mini-ITX form factor to permit use in a variety of applications and settings, in an enclosure of the user's choosing, and connecting to industry standard ATX power and front-panel connections.

A New Start -- And A Return

Hi.

I'm Paul, a 50-something nerd. I've been noodling with computers in one way or another since the early 1980s. With the proliferation of "retrocomputing chic" out there, I thought I'd dip my toe in the field.

This is RIBBBITN3RDing

This is a particularly great time to get into "primitive computing", as the availability of parts, resources, and services is, for the most part, fantastic. Sure, there are specific parts for old Atari and Commodore machines that are no longer being manufactured -- but some of them have been reverse-engineered and created in CPLDs or other programmable devices.

Companies like Adafruit, Jameco, DigiKey, Mouser, and the like make parts available to ordinary folks like you and me. There're great, low-cost tools out there, from solder stations to oscilloscopes and logic analyzers, to make getting into this hobby a lot more straightforward than it was 20 years ago. Even Amazon has a lot of tools and parts for electronics hobbyists.

As if the availability of tools and parts was not enough, the availability of great information relating to retrocomputing both through "old fashioned" forums and static web pages, and though platforms like YouTube and Facebook is almost too much.

Of course, there are plenty of people who already knew this, and have been involved in the hobby for years, or decades. Thankfully, most of them are welcoming to new people in my experience, and har happy to give advice and answer questions.

My current project in this realm is the "RIBBBIT65" -- a 6502-based computer I was inspired to begin designing and building after watching these videos by Ben Eater. The RIBBBIT65 grew out of my desire to have a stable "core" that I could build on to develop peripherals and software. The project is ongoing, and I plan to document the stages of development, design choices, and lessons learned on this blog. I also have a YouTube channel where I post demos of nerdy stuff I'm working on (including RIBBBT65 stuff). I've already been working on the RIBBBIT65 for about a year and a half, so if you're feeling a little late to the party, I'm sorry. I'll try to get you caught up. This is an ongoing journey. I hope you join me, and we can learn together.

Caravan (Part 1) - A New Plan For A New Place

My partner and I are looking for a new place to be.  Being the computing-dependent nerd that I am, I want to be able to have all the service...