cardiograph-computer/2023-09-07.md

154 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 2023-09-07 — Dev notes
From apple note "card 7 sept"
## Peripherals brainstorm
[XXIIVV — varvara](https://wiki.xxiivv.com/site/varvara.html)
- i like their standardized IO…
- what IO do i have/want…?
- bitmapped display
- keypad
- ? printer
- ? paper tape / card reader
- other standard choices are…
- GPIO
- ascii keyboard
- serial terminal
- audio
- how about re-imagining it as a game system?
- just because that would help to explain the lack of standard IO
- but also it would ruin the whole idea of it being a model computer lol
- ok so cardiograph shouldnt have Keyboard, etc, because like a microprocessor trainer wouldnt
- (but a mainframe would… hmm)
- but at any rate, it would be nice if the CPU _did_ support those possibilities
- todo: look at uxntal runes and see how they compare to mine
## Interrupts
### uxn/varvara design
https://github.com/DeltaF1/uxn-impl-guide/blob/main/devices.md
> The Varvara specification asserts that the Uxn CPU core is non-interruptible. That is, the CPU is left to run on its current task until it hits a BRK instruction, even if some event happens in the host system ( such as the mouse moving ) Once the CPU stops executing, the next event can be serviced.
> Each device specification outlines the conditions under which the device vector will be triggered. Execution begins at the device's "vector" address. If this address is equal to 0x0000, then no code is executed. By convention, the first 2 bytes of each device store the device's vector address as a short.
> The initial vector that gets run by the emulator at startup is hardcoded to be address 0x0100.
- my understanding: this is similar to what i have… these “vectors” are memory-mapped inputs that are constantly kept up to date, but only read when a BRK instruction is encountered. when that happens, whatever routine you have pre-registered as an event handler gets called.
- Q: is that right?
- Q: is this a standard design?
- Q: lets see some examples?
### Scamp CPU (+ CP/M, 6502...)
[jes/scamp-cpu: A homebrew 16-bit CPU with a homebrew Unix-like-ish operating system.](https://github.com/jes/scamp-cpu)
[Scamp CPU: A homebrew 16-bit CPU with a homebrew Unix-like-ish operating system | Hacker News](https://news.ycombinator.com/item?id=29408046)
> I think the most surprising thing to me is the lack of interrupts. If you read this, jstanley: did you struggle much with that decision? I think of interrupts as nearly universally available on 8-bit micros, much less 16, but I have also wondered before how important they really were for what those machines ended up being used for. The (S)NES polled their controllers' shift registers in a really inefficient way, but it turned out fine. On the other hand, though, the vertical blank interrupt was pretty critical to their software and, of course, it became extremely common for NES cartridges to add extra chips to raise interrupts on particular horizontal scanlines. But, aside from neat graphical tricks, maybe interrupts just weren't all that important?
> You don't need to implement a nested vectored interrupt controller. Even just a timer/counter with overflow interrupt would solve your current issues with lockup by allowing you to implement preemptive multitasking. Once you do that it would be easy-ish to extend to the serial controller.
> Basically, on interrupt flag = 1, 1. Disable further interrupts (no nesting). This makes things easier to implement. 2. Save register state. For speed a special set of shadow registers can be used, or you can put register state on the stack. 3. Jump to interrupt routine code start. 4. Let interrupt handler run, clear interrupt flag, then return.
> In the simplest case an input flag simply causes a CALL (push pc, jump to address). In that case the interrupt handler needs to know to save state. You can test flags between instructions to see if you need to inject the push/jump.
> CP/M is really incredibly simple. You have some "kernel" type stuff towards the top of memory, with routines for reading/writing files on disk, and interacting with the console and a paper tape "reader + punch". When you type a command, the named program is loaded from disk into memory starting at 0x100 and then execution starts at 0x100. To interact with hardware, the program calls the kernel's routines (analogous to system calls). And that's basically all there is to it.
> 6502 is a very simple CPU and you can learn all of its instructions in several hours. But as it uses 1- address instructions, the code gets pretty verbose. For example, to add 10 to a variable you will have to write:
>
> ```
> LDA var
> CLC
> ADC #10
> STA var
>```
> That's 4 lines and many keypresses for a single addition! You might want to invent slightly more high-level language that would compile into assembly, like this:
>
> ```
> var, var2 = variables (2)
> var t=10
> var2 << 5 # Assign 5 to var2
>```
> By the way, you can use Python and operator overloading so that the lines above written in Python will generate assembly code when executed. I have used << instead of = in assignment because Python doesn't allow to
overload it.
### Apple II
!! [Keyboard interaction on the Apple II is entirely CPU-dependent, memory-mapped, a... | Hacker News](https://news.ycombinator.com/item?id=20404825)
### C64
[How the C64 Keyboard Works | C64 OS](https://c64os.com/post/?p=45)
## Reflections
i still want to understand the uxn approach better, and see if theres prior art
...
it seems like not having interrupts is fine
you just gotta do polling, but thats ok (and what some 8-bit micros did anyway)
and this should really help with the goal of making the simplest CPU possible
another thing that will help is leaving DMA to some other chip… and having a pin that pauses the CPU (like 1802/6502) should make that easy
## CPU pinout brainstorm
which means I think the CPU pinout can just be:
- power
- ground
- address x8
- data x8
- “dma okay”
- pause
- reset
(for later thought: bank-switching requires a memory controller… and how do we want to interface with that?)
### 1802 note
1802 clear + wait: load, reset, pause, run
## To do
Todo: make index for dev notes
## Bank switching
### Game boy
[game boy - How does the Gameboy's memory bank switching work? - Retrocomputing Stack Exchange](https://retrocomputing.stackexchange.com/questions/11732/how-does-the-gameboys-memory-bank-switching-work)
### C64
[Bank Switching - C64-Wiki](https://www.c64-wiki.com/wiki/Bank_Switching)
## ISA
consider an ISA with multiple operands?
good article: https://en.wikipedia.org/wiki/Orthogonal_instruction_set
## Think about writing simulators for these platforms
- Web
- Meowbit
- Microbit
- C64
- Gameboy
- Gameboy Advance
- Nintendo DS