Initial commit

This commit is contained in:
slederer 2024-09-10 23:57:08 +02:00
commit 65ee0cd1f4
80 changed files with 27856 additions and 0 deletions

48
doc/irqctrl.md Normal file
View file

@ -0,0 +1,48 @@
# Interrupt Controller
The interrupt controller uses a single register at address: $980
## Reading the status register
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|t |t |t |t |t |t |t |t |t |t|t |t |t |t |t |t |
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|t |t |t |t |t |t |t |t |- |- |- |- |- |- |p1 |p0 |
|Bitfields|Description|
|---------|-----------|
| _t_ | unsigned 24 bit counter of timer ticks since reset
| _p1_ | IRQ 1 (timer tick) interrupt pending if 1
| _p0_ | IRQ 0 (UART) interrupt pending if 1
## Writing the status register
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |- |- |- |- |- |- |- |i |- |- |- |- |- |- |- |
|Bitfields|Description|
|---------|-----------|
| _i_ | 1 = interrupts enabled, 0 = interrupts disabled
## Notes
Interrupt processing is disabled on reset and needs to be enabled by writing a value with
bit 7 set to the status register (i.e. 127).
An interrupt is only signaled once to the CPU whenever one of the IRQ signals becomes active.
Reading the status register will reflect all pending interrupts since enabling interrupt processing.
Interrupt processing needs to be re-enabled after an interrupt occurs by setting bit 7 in the status register again. This will also clear all pending interrupts.

37
doc/mem.md Normal file
View file

@ -0,0 +1,37 @@
# Memory Layout
The Tridora system uses the following memory layout:
|Address (hex) |Address (decimal)|Description|
|-------|-----------|------------------------|
|$00000000| 0 | ROM |
|$00000800| 2048 | I/O area|
|$00001000| 4096 | RAM (SRAM)|
|$00010000| 65536 | RAM (DRAM)|
## Accessing Words and Bytes
Memory is word-oriented, so there is no access to individual bytes. Memory transfers always use 32 bits.
Word addresses in RAM and ROM use an increment of 4, so the first memory word is at address 0, the second is at address 4 etc.
This way, you can express a pointer to a specific byte within a word.
The lower two bits of the address are ignored when accessing RAM or ROM. So if you use 1 as a memory address, you still get the memory word at address 0.
The lower two bits of the address can be viewed as a byte address (0-3) within the word.
The _BSEL_ and _BPLC_ instructions are designed to assist with accessing bytes within a word.
Because memory is always accessed in words, the CPU is neither big-endian nor little-endian. However, the _BSEL_ and _BPLC_
instructions are big-endian when accessing bytes within a word, so the system can be considered big-endian.
## Accessing the I/O Area
The I/O area organizes memory slightly different. Here, pointing out individual bytes is not very useful, so the I/O controllers use register addresses with increments of one. In practice, there is only the VGA framebuffer controller which uses multiple registers.
The individual I/O controllers each have a memory area of 128 bytes, so there is a maximum number of 16 I/O controllers.
Currently, only I/O slots 0-3 are being used.
|I/O slot| Address | Controller |
|--------|---------|------------|
| 0 | $800 | UART |
| 1 | $880 | VGA |
| 2 | $900 | SPI-SD |
| 3 | $980 | IRQC |

67
doc/spisd.md Normal file
View file

@ -0,0 +1,67 @@
# SPI SD-Card Controller
The SPI-SD-Card controller uses a single register at address $880.
## Reading the register
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |cd |cc |cb |tr |te |ra |ro |d |d |d |d |d |d |d |d |
|Bitfields|Description|
|---------|-----------|
| _cd_ | card detect |
| _cc_ | card changed |
| _cb_ | card busy |
| _tr_ | transmitter ready |
| _te_ | transmitter fifo empty |
| _ra_ | received byte available |
| _ro_ | receiver overrun |
| _d_ | received byte data |
Reading the register does not advance to the next byte in the read fifo. This is done by using the DR bit on a register write (see below).
## Writing the register
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |CW |CF |Cx |Cc |Cd |DR |DW |D |D |D |D |D |D |D |D |
|Bitfields|Description|
|---------|-----------|
| _CW_ | control write |
| _CF_ | enable receive filter |
| _Cx_ | enable transceiver |
| _Cc_ | force spi clock on |
| _Cd_ | write clock divider |
| _DR_ | read acknowledge |
| _DW_ | data write |
| _D_ | byte data |
* CF, Cx and Cc flags are used together with CW
* Cd together with d sets the clock divider
* DW together with d writes a data byte
* if the receive filter is set, all received bytes are ignored until a byte is received that is not $FF
* receiving a byte that is not $FF disables the receive filter
* Cc is used to enable the clock without sending/receiving anything - used for card initialization
Example transaction:
1. read register, loop until _te_ is set
1. write command bytes to register (_DW_ | data)
1. write _Cx_|_CF_ to register
1. read register, loop until _ra_ is set
1. process data byte
1. write _DR_ to register
1. repeat last three steps until complete response has been read
1. wait a bit/send a few more $FF bytes
1. disable transceiver, write _CW_ to register (Cx = 0)

1300
doc/tridoracpu.md Normal file

File diff suppressed because it is too large Load diff

83
doc/vga.md Normal file
View file

@ -0,0 +1,83 @@
# VGA Controller
Registers
|Name|Address|Description|
|----|-------|-----------|
|_FB_RA_ | $900 | Read Address |
|_FB_WA_ | $901 | Write Address |
| _FB_IO_ | $902 | I/O Register |
| _FB_PS_ | $903 | Palette Select |
| _FB_PD_ | $904 | Palette Data |
| _FB_CTL_ | $905 | Control Register |
## Pixel Data
Pixel data is organized in 32-bit-words. With four bits per pixel, one word
contains eight pixels.
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|p0 | p0 | p0 | p0 | p1 | p1 | p1 | p1 | p2 | p2 | p2 | p2 | p3 | p3 | p3 | p3 |
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|p4 | p4 | p4 | p4 | p5 | p5 | p5 | p5 | p6 | 62 | p6 | p6 | p7 | p7 | p7 | p7 |
|Bitfields|Description|
|---------|-----------|
| _p0_ | 4 bits color value (leftmost pixel) |
| _p1_ | 4 bits color value |
| _p2_ | 4 bits color value |
| _p3_ | 4 bits color value |
| _p4_ | 4 bits color value |
| _p5_ | 4 bits color value |
| _p6_ | 4 bits color value |
| _p7_ | 4 bits color value (rightmost pixel) |
Video memory uses a linear layout, with words using an address increment of one.
The first word (horizontal pixel coordinates 0-3) is at address 0, the second (coordinates 4-7) at address 1 etc.
The first line starts at address 0, the second at address 80 etc.
To access video memory, the corresponding video memory address must be written to a latch register, then pixel data can be read or written by the I/O register. Reading and writing uses separate latch registers (the "Read Adress" and "Write Address" registers. To read the same word and write it back, both addresses need to be set.
Both registers have an auto-increment function. After reading the I/O register, the FB_RA register is ingremented by one. After writing to the I/O register, the FB_WA register is incremented by one.
## Palette Data
The VGA controller uses a 16 color palette. The palette can be changed with the FB_PS and FB_PD registers. Writing to the FB_PS register selects a palette slot. Valid values are 0-15. After a palette slot is selected, color data can be read from and written to the FB_PD register. Color data is organized as follows:
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |- |- |- |r |r |r |r |g |g |g |g |b |b |b |b |
| _Bitfields_| Description |
|------------|--------------|
| _r_ | 4 bits red intensity |
| _g_ | 4 bits green intensity |
| _b_ | 4 bits blue intensity |
The FB_PS and PB_FD registers cannot be read.
## Control Register
The control register contains status information. It can only be read.
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|m |m |m |m |- |- |- |- |- |- |- |- |- |- |- |- |
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|_Value_|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |vb |
| _Bitfields_| Description |
|------------|--------------|
| _m_ | 4 bits mode indicator |
| _vb_ | vertical blank |
The _m_ field indicates the current graphics mode. At the time of writing, it is
always 1 which denotes a 640x400x4 mode.
The _vb_ bit is 1 when the video signal generator is in its vertical blank phase.