Sentinel65X-Handbook/Audio & Video.md

165 lines
10 KiB
Markdown
Raw Normal View History

2024-03-22 06:24:02 +01:00
---
gitea: none
include_toc: true
---
2024-03-22 06:18:23 +01:00
# Audio & Video
2024-03-23 01:46:28 +01:00
2024-03-24 01:44:00 +01:00
The VERA FPGA core, implemented on an iCE40 FPGA, is used to generate all audio and video signals produced by Sentinel 65X. This core, developed for the Commander X16 project by Frank van den Hoef, is licensed under the MIT license. It has been modified by Brian Swetland for Sentinel 65X, including porting it to be built using the Yosys open-source FPGA toolchain.
2024-03-23 01:46:28 +01:00
2024-03-24 01:44:00 +01:00
## Video
The VERA video generator outputs a fixed 640x480, 60Hz digital RGB signal, with a total of 4,096 possible colours, using a 12-bit R4G4B4 colour space.
The video generation is done using two independent tile/bitmap layers, and a third layer composed of 128 sprites. VERA supports a single palette of 256 colours, freely chosen from the 4,096 possible colours available.
## Audio
The VERA FPGA core produces audio output in i2S format, which is fed to the A/V port for conversion into an analog or digital format suitable for the target display device.
Audio is generated using a 16-voice stereo programmable sound generator, with each voice able to generate sounds independently, with the waveform for each chosen freely from among Pulse, Sawtooth, Triangle, and Noise.
VERA also generates sampled 48KHz 16-bit stereo audio from a 4KB on-chip memory buffer.
## Interrupts
The VERA implementation in Sentinel 65X has a dedicated vectored interrupt line to the CPU, which can be triggered by any or all of four conditions: Sprite collision, line number, PCM buffer status, or VSYNC.
2024-03-23 01:46:28 +01:00
## The Sentinel 65X A/V Port
2024-03-23 03:45:19 +01:00
2024-03-24 01:44:00 +01:00
Audio and video output in Sentinel 65X is directed to a pin header, which is connected to a small daughterboard which actually generates the final audio and video output signals, using electronics and connectors appropriate to the target display.
2024-03-23 03:45:19 +01:00
### Pinout
The A/V port is a 24-pin female pin header, with a pin and row pitch of 2.54mm. The pinout of the port, as seen from above, is shown in the following table:
| Pin | Label | | Label | Pin |
| :---: | :-----: | --- | :----: | :---: |
| 1 | +3.3V | | +5V | 2 |
| 3 | HSYNC | | VSYNC | 4 |
| 5 | RGB_R0 | | RGB_R1 | 6 |
| 7 | RGB_R2 | | RGB_R3 | 8 |
| 9 | RGB_G0 | | RGB_G1 | 10 |
| 11 | RGB_G2 | | RGB_G3 | 12 |
| 13 | RGB_B0 | | RGB_B1 | 14 |
| 15 | RGB_B2 | | RGB_B3 | 16 |
| 17 | LRCK | | BCK | 18 |
| 19 | ADATA | | SYSCLK | 20 |
| 21 | SCL | | SDA | 22 |
| 23 | GND | | GND | 24 |
2024-03-24 01:44:00 +01:00
## VERA Memory
VERA implements 128KB of internal memory, which exists in its own independent address space, connected to the CPU's address space through address and data registers. This RAM's address space is numbered from `0x00000` to `0x1FFFF`, and is organized as in the following table:
| Address Range | Description |
| :-------------------: | :---------------: |
| `0x00000` - `0x1F9BF` | Video RAM |
| `0x1F9C0` - `0x1F9FF` | Sound Registers |
| `0x1FA00` - `0x1FBFF` | Colour Palette |
| `0x1FC00` - `0x1FFFF` | Sprite Attributes |
2024-03-24 01:50:14 +01:00
## Hardware Registers
VERA is configured and controlled using a series of 32 memory-mapped I/O registers, located in the address space from `0x00DF00` to `0x00DF1F`.
### ADDRx_L
2024-03-24 02:11:33 +01:00
The `ADDRx_L` register is actually two registers, the `ADDR0_L` and `ADDR1_L` registers. Which of the two is accessed at memory address `0x00DF00` depends on the contents of `ADDRSEL`, which is bit 0 of the `CTRL` register, located at `0x00DF05`.
2024-03-24 02:08:29 +01:00
The `ADDR0_L` and `ADDR1_L` registers control the low byte of the selected address in VERA memory for reading or writing with the `DATA0` and `DATA1` registers, located at `0x00DF03` and `0x00DF04` respectively.
### ADDRx_M
2024-03-24 02:11:33 +01:00
The `ADDRx_M` register is actually two registers, the `ADDR0_M` and `ADDR1_M` registers. Which of the two is accessed at memory address `0x00DF01` depends on the contents of `ADDRSEL`, which is bit 0 of the `CTRL` register, located at `0x00DF05`.
2024-03-24 02:08:29 +01:00
The `ADDR0ML` and `ADDR1_M` registers control the middle byte of the selected address in VERA memory for reading or writing with the `DATA0` and `DATA1` registers, located at `0x00DF03` and `0x00DF04` respectively.
### ADDRx_H
2024-03-24 02:11:33 +01:00
The `ADDRx_H` register is actually two registers, the `ADDR0_H` and `ADDR1_H` registers. Which of the two is accessed at memory address `0x00DF00` depends on the contents of `ADDRSEL`, which is bit 0 of the `CTRL` register, located at `0x00DF05`.
2024-03-24 02:08:29 +01:00
The `ADDR0_H` and `ADDR1_H` registers control the low byte of the selected address in VERA memory for reading or writing with the `DATA0` and `DATA1` registers, located at `0x00DF03` and `0x00DF04` respectively.
2024-03-24 02:23:08 +01:00
Bit 0 of the `ADDRx_H` is bit 16 of the address of the data port selected by `ADDRSEL`. Bits 1 and 2 of `ADDRx_H` are unused. Bit 3 is called `DECR0` or `DECR1`; when this bit is clear, the address of the selected data port will increment by the amount set with bits 4-7, called `INCR0` or `INCR1`, according to the table below. When `DECR0` or `DECR1` is set, then the address will _decrement_ by the same amount when the matching data register is read from or written to.
2024-03-24 02:11:33 +01:00
| `INCR` value | Address Increment |
| -------------: | ---------------: |
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 4 |
| 4 | 8 |
| 5 | 16 |
| 6 | 32 |
| 7 | 64 |
| 8 | 128 |
| 9 | 256 |
| 10 | 512 |
| 11 | 40 |
| 12 | 80 |
| 13 | 160 |
| 14 | 320 |
| 15 | 640 |
2024-03-24 02:23:08 +01:00
### DATA0
The `DATA0` register, located at `0x00DF03`, is the first of two data registers available from VERA. It reads or writes the address in VERA's internal memory set in `ADDR0_L`, `ADDR0_M`, and `ADDR0_H`.
2024-03-24 02:27:27 +01:00
If the value in `INCR0` is nonzero, then after reading or writing from or to `DATA0`, the address stored in `ADDR0_L`, `ADDR0_M`, and `ADDR0_H` will be incremented by the number of addresses in the [table above](#addrx_h). If `DECR0` is set, then the address will _decrement_ by that amount instead.
2024-03-24 02:23:08 +01:00
### DATA1
`DATA1`, located at `0x00DF04`, is identical in function to `DATA0`, but uses the address and increment settings stored in `ADDR1_H` instead of `ADDR0_H`.
### CTRL
The `CTRL` register, located at `0x00DF05`, contains three significant bits: bit 0, called `ADDRSEL`, determines which `DATAx` register the `ADDRx` registers refer to. Bit 1, called `DCSEL`, controls which set of registers are accessed at addresses `0x00DF09` through `0x00DF0C`. Bit 7, called `RESET`, will reset VERA to the initial power-on state when a `1` value is written to it.
2024-03-24 02:36:46 +01:00
### IEN
The `IEN` register, located at `0x00DF06`, has six bits which relate to the generation of VERA interrupts:
- Bit 0, called `IEN_VSYNC`, enables the VSYNC interrupt when set.
- Bit 1, called `IEN_LINE`, enables the raster-line interrupt when set.
- Bit 2, called `IEN_SPRCOL`, enables the sprite collision interrupt when set.
- Bit 3, called `IEN_AFLOW`, enables the interrupt triggered when the PCM sample buffer is less than 1/4 full.
- Bit 6 contains the high-order bit of the 9-bit value of the `SCANLINE` register, located at `0x00DF08`. Both this bit and the `SCANLINE` register are read-only.
- Bit 7 contains the high-order bit of the 9-bit value of the `IRQLINE` register, located at `0x00DF08`. Both this bit and the `IRQLINE` register are write-only.
2024-03-24 03:34:34 +01:00
### ISR
The `ISR` register, located at `0x00DF07`, contains flag bits which identify the source of the active VERA interrupt:
- Bit 0, called `ISR_VSYNC`, identifies a VSYNC interrupt condition when set.
- Bit 1, called `ISR_LINE`, identifies a raster line interrupt condition when set.
- Bit 2, called `ISR_SPRCOL`, identifies a sprite collision interrupt condition when set.
- Bit 3, called `ISR_AFLOW`, identifies a PCM sample buffer low interrupt condition when set.
- Bits 4-7 store the sprite collision data.
Writing a `1` value to bits 0, 1, or 2 will clear the interrupt state of the relevant interrupt source. Bit 3 can only be cleared by filling the PCM sample buffer to at least 1/4 of its capacity.
### IRQLINE_L / SCANLINE_L
The low order 8 bits of the current scanline and the scanline which is set to trigger the scanline interrupt share the address `0x00DF08` -- `IRQLINE_L` is write-only, and `SCANLINE_L` is read-only, so there is no conflict.
### DC_VIDEO / DC_HSTART
The `DC_Video` and `DC_HSTART` registers share the address `0x00DF09`; which one is accessed at that address is determined by the `DCSEL` flag bit in the [CTRL](#ctrl) register -- a `0` value in `DCSEL` will enable the `DC_VIDEO` register, and a `1` value the `DC_HSTART` register.
`DC_VIDEO` stores three flag bits:
- Bit 4 enables tile/bitmap layer 0 when set to `1`.
- Bit 5 enables tile/bitmap layer 1 when set to `1`.
- Bit 6 enables sprites when set to `1`.
`DC_HSTART` controls the first active column of the screen, relative to the 640x480 display area. The value is the top 8 bits of a 10-bit number, the low order 2 bits of which are implied to be 0 -- that is, the value is an 8 bit number which will be multiplied by 4.
### DC_HSCALE / DC_HSTOP
The `DC_HSCALE` and `DC_HSTOP` registers share the address `0x00DF0A`; which one is accessed at that address is determined by the `DCSEL` flag bit in the [CTRL](#ctrl) register -- a `0` value in `DCSEL` will enable the `DC_HSCALE` register, and a `1` value the `DC_HSTOP` register.
`DC_HSCALE` sets a fractional scaling factor of the active part of the screen; a value of 128 will output one pixel for each input pixel, and a value of 64 will output two pixels for each input pixel.
`DC_HSTOP` controls the first active column of the screen, relative to the 640x480 display area. The value is the top 8 bits of a 10-bit number, the low order 2 bits of which are implied to be 0 -- that is, the value is an 8 bit number which will be multiplied by 4.