Close
0%
0%

JJ65C02

Working on my own version of a 65C02-based SBC. Everything is open source and permissively licensed.

Similar projects worth following
My take on a 65C02 based SBC.

Source and Schematics can be found at: https://github.com/jimjag/JJ65c02

Intro

I came across the various Ben Eaters 6502 Computer videos and addition to being impressed with his style, skill and knowledge, I also became intrigued. Back as an undergrad at JHU, one of my courses was in microprocessor architecture, and a project was a 6502 breadboard setup. I can't recall the full specifics; I am pretty sure that other than RAM and ROM (maybe 8k of each), there were no other 6502-family chips used in the project. Just some logic gates, switches and LEDs. Still, I had a blast with the project and took my time to plan every detail, both from a hardware placement standpoint to software design. When all was done, I was extremely proud of what I did and was also shocked when the Prof was just as impressed. He kept my wirewrap (no pushboards back then) and code as a prototype example for display in the course.

My first computer was, as with many, an Apple ][, which was also 6502 based, and I spent many, many, many hours coding on that, in both assembly and Basic. The skills I learned doing assembly language programming are still valuable to this day.

So when I saw Ben's videos, I was hooked. I decided to work on my own version... Here you go. All code and examples are available under permissive Open Source licenses, so please don't hesitate to use, and re-use, what you need.

Project Guidelines:

I'll be focusing on the 65C02 and its companion chips (eg: the 6522). Also, as much as possible, I'll make things as generic as possible so even if your design differs from mine, there will still be a lot that you can use, re-use or hack. I'll use more contemporary chips and solutions where it makes the design significantly more elegant, but won't let that over-shadow the actual retro nature of the project. 

  • Faster "EEPROM"

    Jim Jagielski18 hours ago 0 comments

    Like many, as I've starting ramping up the clock speed on my 6502-based SBC, it's the limited speed of the EEPROM (the AT28C256) which is the main limiting factor. A great replacement is to switch over to the DS1230Y Nonvolatile SRAM chip, which is pin compatible with the AT28C256 but much, much faster.

    Using the TL866II+ programmer, you can upload your "ROM" image quite easily as well:

    minipro -p "DS1230Y(RW)" -w ./minios.rom

  • PCBs delivered!

    Jim Jagielski11/24/2023 at 12:38 0 comments

    My order of PCBs from PCBWay just got delivered. They look fantastic and I'm quite happy with the quality and the speed of the shipment. Can't wait to start populating them.

  • Update Demo: Pi Pico I/O Support chip

    Jim Jagielski11/20/2023 at 16:16 0 comments

    Lots of work done over the last week or so on the I/O support chip for the JJ65C02 project. As a reminder, this Pi Pico is used for PS/2 keyboard input handling as well as VGA output and terminal emulation.

    Most of the work was on the ANSI/VT100 emulation side, adding in a blinking cursor, support for a large subset of Escape Sequences and more robust and reliable performance. I've also added in some extensions to the official Escape Sequences which allow me to draw graphics while in "terminal mode". These will be added to my port of EhBasic.

    All code and resources are available under permissive Open Source licenses on GitHub.

  • Raspberry Pi Pico Video and PS/2 Keyboard

    Jim Jagielski11/13/2023 at 18:01 0 comments

    I've pretty much completed the core library code for the VGA out and PS/2 Keyboard input handling on the Pi Pico, to be used as an A/V support chip on my JJ65C02 system and figured it was time for an update and even a video.

    The Pico outputs basic VGA at 640x480 with 16 colors. The entire frame is bit-mapped which allows for exacting graphics. The 16-color (4-bit) color palette is based on standard RGB with an extra Intensity bit, all of which are translated to the 0-0.7V VGA levels via a standard resistor ladder (I found that 470ohms for the RGB signals and 1kohms for the Intensity signal seems to work best).

    The VGA library supports Hunter-Adams graphics library with some additions, such as multiple fonts, scrolling, and a simple "text mode". The overall goal is to support a useful subset of Xterm/VT100 escape codes in addition to graphics primitives.

    I also use the Pico for PS/2 keyboard input handling, and the conversion of the scancodes to ASCII values (upper case, lower case, and control codes).

    Now that the basics are in place, I'll be ordering PCBs (from PCBWAY, of course) and interfacing the Pico with the 6502 board itself. Keyboard input will be transferred from the Pico to a VIA chip (with IRQ handling) and ASCII will be sent to the Pico via a different VIA port with a simple DATA_READY signal pin. With the single GPIO pin left over on the Pico, I've connected that to a simple audio amp circuit, so that I can eventually add audio waveform creation to the Pico as well.

    I'm avoiding the temptation to add a LOT of functionality to the Pico; it is, after all, a support chip, not the core of the system.

    You can see some of the basics running in the below video demo.

  • Schematics - working draft

    Jim Jagielski11/07/2023 at 19:57 0 comments

    Short update. Worked on the schematic (Kicad7) and wanted to share the current version:

  • Quick Update

    Jim Jagielski11/03/2023 at 12:47 0 comments

    Just a very quick update since my last post.

    It occured to me that I could simply use standard IRQ handling for the VIA input from the Pico (for PS2) instead of the CA/CB handshaking. This means that by dropping the handshake and moving to Interrupt handling, I now have one open pin to keep track of the 65C02 clock. Eventually, I may even decide to use the Pico to drive the clock, rather than just sense it. This again would reduce the overall chip count by one, and maybe add some flexibility. Plus, it wouldn't be a design change that makes what I do be incompatible with the standard BE6502 architecture (which is a goal for my project: I want whatever I do not be so specific to my design that nothing is re-usable by anyone else).

  • Raspberry Pi Pico for the win

    Jim Jagielski10/31/2023 at 12:58 0 comments

    After a lot of work and research, I decided to go with a RP2040-based option for my "specialized chip" and based on the availability of examples, as well as the price-point and the number of available GPIO pins, the Raspberry Pi Pico was the obvious winner.

    My current design uses every GPIO pin, because I plan on using the Pico to also do PS2 keyboard functions, and get rid of the ATMEGA chip completely. Also, but using both PORTA and PORTB on a single 65C22 (VIA) chip, I can reduce chip count again.

    The GPIO pinouts are as follows:

    • 6 GPIO pins for VGA output (HSYNC, VSYNC and RBGI)
    • 8 GPIO pins for communication to the Pico for VGA (directly connected using an I/O address)
    • 1 GPIO pin for RD between 65C02 and the Pico (tells Pico to read data on the above 8 pins)
    • 2 GPIO pins for PS2 Data and Clock
    • 7 GPIO pins for PS2 ASCII data to VIA
    • 2 GPIO pins for VIA handshake

    It would be great if there was another pin available for the 65C02 clock signal, but I'm fresh out.

    As far as the code is concerned, I'm working on the core VGA and PS2 functionality, and using PIO programming extensively. I found a great basis for the VGA library from a course taught by V. Hunter Adams  from Cornell. Using his work as a guide, I was able to also figure out how to use PIO for the PS2 timing and scancode stuff.

    Current versions of the code can be found at https://github.com/jimjag/JJ65c02/tree/main/Software/pico-code . I'll save a more indepth look at the code for another entry.

  • RP2040 choices

    Jim Jagielski10/24/2023 at 18:32 0 comments

    The Raspberry Pi Pico or the Arduino RP2040

    For VGA output, I was looking at either using a RP2040-based solution or a FPGA (likely the TinyFPGA BX). After giving it some more thought, and doing as much research as I could, I think I've settled on going w/ a RP2040 implementation. The reasons are:

    1. Price: Even the Arduino is less expensive that the TinyFPGA
    2. RAM: The RP2040 includes more RAM than the TinyFPGA
    3. Documentation: There are a lot more tutorials and projects already using the RP2040

    This leads me to the next major decision: which RP2040 option to use?

    Since I'm already including a different Arduino chip on my board, it would be nice to not have Yet Another Development Environment, and use the Arduino RP2040 Connect. Unfortunately, programming PIO on the Arduino is kinda wonky, requiring you to "compile" the PIO code using picoasm and then pull that resulting file into the Arduino IDE project. Workable, yes, but not ideal. Also, almost all PIO code assumes the Pico, and its pin layout. Do I really want to worry about that?

    I also like the Arduino because it's a smaller, more standard form factor, which means it is easier to find chip sockets for it. But unfortunately, it is the more expensive option, by far, and includes functionality that I really don't need.

    The Pico however is super cheap, and has a ton of already existing code and tutorials I could leverage. Its DIP size is weird, but that's just being picky. And from what I hear, the later versions of the Arduino IDE support the Pico natively (as a board). So maybe the answer is easier than I'm making it seem.

  • Address decoding

    Jim Jagielski10/19/2023 at 15:41 0 comments

    As with most people, I started off with very simple address decoding, little more than "if A15 is 1, select ROM; if 0, select RAM". Breaking out space for I/O makes it a little more difficult, but depending on what address space you pick, even that can be easy (and by easy I mean "not requiring a lot of logic gates").

    The problem is that this results in, at least in my opinion, a wasteful memory map. 32k of ROM seems way too much, and 32K RAM seems way too little. Carving out I/O space from ROM helps, but even then a simple implementation results in 16k or so just for I/O, which is extremely inefficient.

    So I try to create a memory map that maximizes RAM, and minimizes ROM and especially I/O. My first real option was below:

    MEMORY
    {  ZP:   start = $0,    size = $100,  type = rw, define = yes;
      RAM:  start = $0200, size = $7e00, type = rw, define = yes, file = "%O.bin";
      IO:   start = $8000, size = $1000, type = rw, define = yes, fill = yes, fillval = $ea, file = %O;
      ROM:  start = $9000, size = $7000, type = ro, define = yes, fill = yes, fillval = $ea, file = %O;
    }
    
    SEGMENTS {
      ZEROPAGE:  load = ZP,  type = zp,  define = yes;
      SYSRAM:    load = RAM, type = rw,  define = yes, optional = yes, start = $0200;
      PROG:      load = RAM, type = rw,  define = yes, optional = yes, start = $0300;
      DATA:      load = ROM, type = rw,  define = yes, optional = yes, run = RAM;
      BSS:       load = RAM, type = bss, define = yes, optional = yes;
      HEAP:      load = RAM, type = bss, define = yes, optional = yes;
      CODE:      load = ROM, type = ro,  define = yes,  start = $a000;
      RODATA:    load = ROM, type = ro,  define = yes, optional = yes;
      RODATA_PA: load = ROM, type = ro,  define = yes, optional = yes, align=$0100;
      ISR:       load = ROM, type = ro,  start = $ffc0;
      VECTORS:   load = ROM, type = ro,  start = $fffa;
    }

    There are some problems with the above, namely that ROM is still a bit too big and you really can't access the higher addresses of RAM. The other problem is that the logic required to implement the above introduces some gate delays, even using faster AC chips, that limit overall system clock speed. It's obvious that improvements need to be made.

    To handle both the complexity and the latency issues related to address decoding, I've moved to using a simple PLD, namely the Atmel ATF22V10C. I don't consider this "cheating" really, because I could easily use discrete chips if I wanted to, as long as I'm fine with clock speeds no faster than 4Mhz. But I like this solution for another reason: I can use CUPL to very easily design the logic.

    Normally, you would describe the logic using standard boolean logic, but CUPL provides a much more clear and concise way. For example:

    FIELD_ADDR = [A15..A00];
    /* Address Decode Logic */
    ROM       = ADDR:[B000..FFFF];  /* 20k */
    
    IS_ROM = ROM;

     CUPL is smart enough to generate the underlying logic.

    This makes it easy as well to carve out space for RAM bank switching as well, with some signal pins determining if we are in the banked address space as well as which bank we'll be using. The current PLD file for WinCUPL is as follows:

    Name     JJ65C02 ;
    PartNo   00 ;
    Date     10/6/2023 ;
    Revision 01 ;
    Designer Engineer ;
    Company  jimjag ;
    Assembly None ;
    Location  ;
    Device   p22v10 ;
    
    
    /* Pin Map
           --------
    PHI   |1     24| Vcc
    A15   |2     23| /RAM_CS
    A14   |3     22| /ROM_CS
    A13   |4     21| /IO_CS
    A12   |5     20| BA13
    BK0   |6     19| BA14
    BK1   |7     18| --
    --    |8     17| --
    --    |9     16| --
    --    |10    15| --
    --    |11    14| --
    Gnd   |12    13| --
           --------
    */
    
    /* Inputs:  From CPU*/
    
    Pin 1  =  PHI;   /* 65C02 CLK */
    Pin 2  =  A15;   /* Address lines from CPU */
    Pin 3  =  A14;
    Pin 4  =  A13;
    Pin 5  =  A12;
    Pin 6  =  BK0;   /* Bit 0 of the VIA 3-bit Bank number */
    Pin 7  =  BK1;   /* Bit 1 of the VIA 3-bit Bank number */
    
    /* Outputs:  Chip Selects */
    Pin 23 = RAM_CS;  /* to RAM /CS pin */
    Pin 22 = ROM_CS;  /* to ROM /CS */
    Pin 21 = IO_CS;   /* to IO (VIA and ACIA) /CS pin */
    Pin 20 = BA13;    /* To RAM chip, A13 */
    Pin 19 = BA14;    /* To RAM ship, A14 */
    
    
    FIELD ADDR = [A15..A00];
    
    /* Address Decode Logic */
    
    RAM       = ADDR:[0000..9FFF];  /* 32k */
    BANK = ADDR:[...
    Read more »

  • Thoughts on Phase 2

    Jim Jagielski10/13/2023 at 14:33 0 comments

    I was quite happy with how Phase 1 of my JJ65C02 project ended up. I had a pretty solid miniOS coded up. I had ported EHBasic to not only my system but also to the (more robust) ca65 development system, and removed hard-coded addresses allowing it to be ported, and run, on any 6502-based platform. I also had full RS-232 capability and a working and solid YMODEM implementation that I could use to download pre-built binaries to RAM. I even had some rudimentary sound capability. All in all, I had taken this stage of the design where I wanted it to go. And so I was able to spend a LOT of time using the platform and running BASIC programs on it as well as native 6502 apps.

    But as I did, I started getting the itch to start improving the hardware again, so much so that now I'm starting Phase 2 of the design in earnest. This promises to be a pretty significant change.

    First of all, I plan on removing support for the LCD screen and the directional buttons. They take up a lot of real estate on the board and they simply aren't worth keeping around anymore. This means, of course, that I need a new primary user interface. Now I could continue to simply use the serial interface but I've come around and decided that the logical next step really is adding in PS2 keyboard capability and some level of VGA output.

    My goal has always been to be faithful to the true retro nature of the project and so I've avoiding moving much capability to "modern", high-performance chips. But on the other hand, even old-school 6502 computers would used, when needed, specialized chips for video or I/O, and so it really doesn't feel like cheating all that much, if I handle the design carefully and in the spirit of retro. For the PS2 interface, since the design already includes a ATMEGA328, I'll leverage that. But the choice for VGA output isn't so clear.

    I see 3 main possibilities:

    • FPGA
    • Raspberry Pi PICO
    • Arduino Nano RP2040 Connect

    Each has their own pluses and minuses, but I'll leave a more full discussion of all that for its own separate post.

    The on-board speaker is also being dropped. Again, its a non-insignificant real estate hog on the PCB and I already have an audio jack output. I'll also be dropping the 9V input and move to a USB power port for native 5V coming in. And finally, I'll be likely moving from discrete logic chips to the ATF22V10C for the address decoding (and other signaling functions).

    In addition to these "improvement" changes, I'm also going to add in support for RAM banking (8k banks) to support more complex programming requirements. This necessitates a change in the memory map (which is one of the reasons behind the move to the ATF22V10C) which I'm still mulling over. I'd like to have more than 32K RAM dedicated, but it makes the address and chip/bank selection logic quite nasty.

    Off we go.

View all 12 project logs

Enjoy this project?

Share

Discussions

Peabody1929 wrote 11/03/2023 at 23:48 point

I'm looking forward to seeing a schematic update with the RP2040 included in the design.

  Are you sure? yes | no

Jim Jagielski wrote 11/14/2023 at 18:12 point

The schematic can be found at https://github.com/jimjag/JJ65c02/blob/main/Schematics/JJ65c02/JJ65c02-pico-version.pdf :-)

  Are you sure? yes | no

hubidrei wrote 10/21/2023 at 15:52 point

Why not let the RP2040 do all the RAM, ROM, IO. Like the NEO6502? 

The hard part is the programming of the RP2040.

  Are you sure? yes | no

Jim Jagielski wrote 10/23/2023 at 14:05 point

The main reason is that I want to use it _just_ for the things that don't have viable "retro" alternatives. With Video and Sound, the old-school chips simply aren't available anymore, but that's not the case with RAM or ROM.

I want to avoid the trap that projects like the Commander X16 and others fell into: in those projects, it seems like the 6502 is an after thought. You aren't programming the 6502; instead you are using the 6502 to program/run the Vera chip (for example).

The draw of real retro computing, IMO, is that it forces you to be creative and innovative, by seeing the limitations as a challenge to work through, not as something to work _around_.

  Are you sure? yes | no

Dan Maloney wrote 10/12/2023 at 17:13 point

Thanks for bringing this project over to Hackaday.io! Looking forward to more details

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates