John West wrote:
I was in a similar position. The 6502 is too constraining, the 65816 is both too constraining and a dead end design, microcontrollers of any reasonable capability seem to require reading 500 pages of documentation and linking opaque binaries just to get them to the point of booting. Old-fashioned hobbyist microprocessors don't seem to exist any more.
I looked long and hard... And yes, basically this. There are some still in DIP format, but limiting in other ways. the ESP32 range of microcontrollers come close - they still have some closed libraries but this can be worked round if you need to.
Quote:
I wanted a system like the Commodore 64 that I grew up with, that I had full control over and could understand every part, only bigger and better. I ended up getting an FPGA development board and have had a lot of fun making the system of my dreams. If you want to try that route, I can help with Xilinx FPGAs and VHDL. There's nothing wrong with other FPGAs or Verilog - I just don't know enough about them.
Even that route is getting harder. Most FPGA development boards either have only the tiny internal RAM or a massive external SDRAM. I only found one that had a decent amount of SRAM and was still available. And that's going to need an adapter board so I can plug in the keyboard, monitor, and so on.
I looked at the Tang Nano 9K - mostly as it already had RISC-V cores for it, and HDMI (DVI) video output as well as more than enough RAM. I just couldn't get all the bits to bolt together in a sensible way, even though they had a GUI based tool to help build it. I did a few simple projects, counters, latches, etc. with it but other things got in the way, so temporarily left it. For now.
Quote:
If there is a microprocessor out there with the old 6502 simplicity but slightly more modern capabilities, I'd love to hear about it. (edit after reading posts made after I started typing: I had assumed the 68000 was long gone. I'm glad it isn't. Going to have to have another look at it)
For me... It's ARM. At least 32-bit ARM. Even so, getting a development platform going is the hard part. There is an ARM in a DIP package, but it's has limited SRAM - my case could be solved by using SPI RAM but that felt a bit weird. I have plenty of old Pi v1s about and they're cheap enough (Pi 1, Zero, etc. on ebay) and with on-board graphics was relatively easy.
ARM code vs. 6502... Remember the ARM designers had already built several 6502 projects, (Acorn System 1/2/3, Atom, BBC Micro, ...) even visiting Bill Mensch at one point. Acorn did make a 65816 system too - released just before the IIgs, but targetted at a different audience...
On programming: Mostly 3 letter mnemonics which are similar to the 6502 but changed to cope with e.g. more registers.
LDA #42 becomes:
LDR r0,#42LoaD Register r0 with the immediate value 42.
TYA, etc. is MOV (again because there are 16 registers, not just A,X,Y and S. (The ARM stack pointer and PC are 2 of those 16 registers)
Indexed addressing: LDA (zp),y might be LDR r0, [r1] but there are variants where you can auto-increment or add one register to another, so one register the base (like (zp)) and the other the index (like ,y)
I did feel it was tricky at first, but soon got the hang of it. There were a few "lightbulb" moments too when realising that register to register moves go via the ALU and the barrel shifter - So the ALU can be used to add/subtract and the shifter to multiply. The 'core' of my bytecode interpreter is just 2 ARM instructions compared to 9 '816 instructions.
Code:
ldrb r0,[regPC],#1
ldr pc,[ptrJ, r0, lsl #2]
The first, LoaD Register from the byte at [regPC] then increment regPC by 1. (regPC is an alias for one of the other registers). The word formed in r0 has the top 24-bits set to zero - unlike the '816 which loads a 16-bit value into A then if you want the byte you need to mask it out.
The second LoaD Register pc with the address created by shifting r0 to the left by 2 places, then adding this into the contents of ptrJ. (an alias for one of the other registers) This takes the byte loaded into r0, multiplies it by 4 to form a 32-bit word index into the jump table which has its base address held in register ptrJ.
There are similar condition flags too, but setting them isn't automatic - you use the CMP instruction or tag an opcode with a flag to say "set the codes".
Compare '816 with RISC-V and ARM here:
https://unicorn.drogon.net/nextOpcode.txtOnce I got the hang of tricks like that a whole load of optimisations opened up - You don't need to do it like that, and I didn't on day 1, but as I learned more I found I could condense things more.
I'll leave it at that, lest I dilute the 6502 content any more..
-Gordon