Sentinel65X-Handbook/Audio & Video.md

428 lines
24 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 06:24:35 +01:00
The VERA FPGA core, implemented on an [iCE40 UltraPlus 5K FPGA](https://www.latticesemi.com/en/Products/FPGAandCPLD/iCE40UltraPlus), is used to generate all audio and video signals produced by Sentinel 65X. This core, developed for the [Commander X16](https://github.com/commanderx16) project by [Frank van den Hoef](https://github.com/fvdhoef/vera-module/tree/rev4), is licensed under the MIT license. It has been modified by [Brian Swetland](https://github.com/swetland/vera-module) for Sentinel 65X, including porting it to be built using the [Yosys open-source FPGA toolchain](https://github.com/YosysHQ/yosys).
2024-03-23 01:46:28 +01:00
2024-03-25 04:43:55 +01:00
Note: This page contains documentation specific to the VERA as it is used in Sentinel 65X, and cannot be taken as applicable to any other project.
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.
2024-03-24 06:23:37 +01:00
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. An approximation of this colour gamut of 4,096 colours can be seen below:
2024-03-24 01:44:00 +01:00
2024-03-24 06:22:43 +01:00
![12-bit RGB image of a parrot](images/RGB_12bits_palette_sample_image.png) ![12-bit colour palette](images/RGB_12bits_palette_color_test_chart.png)
2024-03-24 06:21:51 +01:00
2024-03-24 08:35:36 +01:00
Each of the tile/bitmap layers is fully indepentent for content, mode, scrolling, etc. Both layers support two special modes useful for text displays, in 16 and 256 colours.
There are enough sprites supported to act as a third bitmap layer, should the programmer wish to make use of sprites in that manner.
2024-03-24 01:44:00 +01:00
## Audio
2024-03-24 08:35:36 +01:00
The VERA FPGA core produces audio output in [I²S](https://en.wikipedia.org/wiki/I²S) format, which is fed to the A/V port for conversion into an analog or digital format suitable for the target display device.
2024-03-24 01:44:00 +01:00
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
2024-03-24 08:35:36 +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
2024-03-24 20:58:14 +01:00
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.
2024-03-24 05:37:53 +01:00
`DC_HSCALE` sets a fractional horizontal 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.
2024-03-24 03:34:34 +01:00
2024-03-24 05:37:53 +01:00
`DC_HSTOP` controls the last 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_VSCALE / DC_VSTART
The `DC_VSCALE` and `DC_VSTART` registers share the address `0x00DF0B`; 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_VSCALE` register, and a `1` value the `DC_VSTART` register.
`DC_VSCALE` sets a fractional vertical 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_VSTART` controls the first active row of the screen, relative to the 640x480 display area. The value is the top 8 bits of a 9-bit number, the low order bit of which is implied to be 0 -- that is, the value is an 8 bit number which will be multiplied by 2.
### DC_BORDER / DC_VSTOP
The `DC_BORDER` and `DC_VSTOP` registers share the address `0x00DF0B`; 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_BORDER` register, and a `1` value the `DC_VSTOP` register.
`DC_BORDER` stores the 8-bit pallette index of the colour used to fill the "inactive" region of the screen, as determined by the `DC_HSTART`, `DC_HSTOP`, `DC_VSTART`, and `DC_VSTOP` registers.
`DC_VSTOP` controls the last active row of the screen, relative to the 640x480 display area. The value is the top 8 bits of a 9-bit number, the low order bit of which is implied to be 0 -- that is, the value is an 8 bit number which will be multiplied by 2.
### L0_CONFIG
The `L0_CONFIG` register, located at `0x00DF0D`, controls the configuration of tile/bitmap layer 0.
Bits 0-1 store the colour depth of the layer; that is, the number of bits used per pixel in the tile or bitmap data used to render the layer:
| Value | Depth |
| :---: | :---: |
| 0 | 1 bpp |
| 1 | 2 bpp |
| 2 | 4 bpp |
| 3 | 8 bpp |
Bit 2 sets the layer to use tiles mode when set to `0`; a value of `1` will set the layer to use bitmap mode.
2024-03-25 04:43:55 +01:00
Bit 3, called `T256C`, is used with tiles modes to enable or disable 256-colour 1bpp mode. Other tile mode colour depths ignore this flag bit.
2024-03-24 05:37:53 +01:00
Bits 4-5 encode the tile map width, while bits 6-7 encode the tile map height, according to the values in the following table:
| Value | Map Width / Height |
| :---: | :----------------: |
2024-03-24 07:29:05 +01:00
| 0 | 32 tiles |
2024-03-24 05:37:53 +01:00
| 1 | 64 tiles |
| 2 | 128 tiles |
| 3 | 256 tiles |
### L0_MAPBASE
The `L0_MAPBASE` register, located at `0x00DF0DE`, encodes the high 8 bits of the 17-bit address in VERA memory where the map data for layer 0 can be found; since the bottom 9 bits are implicitly `0`, this means the map data must always begin on a 512-byte alignment boundary.
2024-03-24 05:57:12 +01:00
### L0_TILEBASE
The `L0_TILEBASE` register, located at `0x00DF0F`, encodes the following data:
- Bit 0 controls the pixel width of tiles in layer 0; a `0` value means that a tile is 8 pixels wide, while a `1` value means that tile is 16 pixels wide.
- Bit 1 controls the pixel height of tiles in layer 0; a `0` value means that a tile is 8 pixels tall, while a `1` value means that tile is 16 pixels tall.
- Bits 2-7 hold the top six bits of the 17-bit address in VERA memory where the tile data can be found; as bits 0-10 are implicitly `0`, this means that tile data is always aligned on a 2,048-byte boundary.
### L0_HSCROLL_L / L0_HSCROLL_H
The `L0_HSCROLL_L` and `L0_HSCROLL_H` registers, located at addresses `0x00DF10` and `0x00DF11`, encode the low order byte and high order 4 bits, respectively, of the layer 0 horizontal scroll value; this value ranges from 0 to 4,095, and is defined in terms of pixels.
### L0_VSCROLL_L / L0_VSCROLL_H
The `L0_VSCROLL_L` and `L0_VSCROLL_H` registers, located at addresses `0x00DF12` and `0x00DF13`, encode the low order byte and high order 4 bits, respectively, of the layer 0 vertical scroll value; this value ranges from 0 to 4,095, and is defined in terms of pixels.
### Layer 1 Registers
2024-03-24 06:16:44 +01:00
The layer 1 control registers function exactly the same as their equivalents for layer 0:
- `L1_CONFIG` is located at `0x00DF14`
- `L1_MAPBASE` is located at `0x00DF15`
- `L1_TILEBASE` is located at `0x00DF16`
- `L1_HSCROLL_L` is located at `0x00DF17`
- `L1_HSCROLL_H` is located at `0x00DF18`
- `L1_VSCROLL_L` is located at `0x00DF19`
- `L1_VSCROLL_H` is located at `0x00DF1A`
### AUDIO_CTRL
The `AUDIO_CTRL` register at `0x00DF1B` controls several aspects of the PCM audio subsystem:
- Bits 0-3 control the volume of the PCM sample playback.
- Bit 4 controls whether the PCM audio will be monaural (`0` value) or stereo (`1` value).
- Bit 5 controls whether PCM audio sample data is 8-bit (`0` value) or 16-bit (`1` value).
- Bit 6 is a read-only flag bit which indicates that the PCM sample buffer is empty when it is set to `1`.
- Bit 7 encodes two values; when read, this bit will be a `1` when the PCM sample buffer is full. In that case, writes to the buffer are silently ignored. When a `1` value is _written_ to this bit, the PCM sample buffer will be cleared.
### AUDIO_RATE
The `AUDIO_RATE` register at `0x00D1C` controls the sample rate of the PCM audio playback:
| Value | Description |
| :---: | :---------: |
| 128 | 48828.125Hz |
| 64 | 24414Hz |
| 32 | 12207Hz |
| 0 | No playback |
An intentional mismatch between the actual recorded sample rate and the sample rate of the playback can be used to speed up or slow down the PCM sample.
### AUDIO_DATA
The `AUDIO_DATA` register at `0x00DF1D` is a write-only register which accepts byte writes to the PCM audio buffer.
### SPI_DATA
The `SPI_DATA` register at `0x00DF1E` is used to read and write data from the selected SPI device a byte at a time.
### SPI_CTRL
The `SPI_CTRL` register at `0x00DF1F` is used to control the SPI subsystem:
- Bit 0 is used to assert the SPI select line with a `1` value, and deassert it with a `0` value.
- Bit 1 controls the clock rate of the SPI data clock; when set to `0` this will be approximately 12.5MHz, while when set to `1` the clock will run at approximately 390KHz, which can be useful with slow SPI devices or when an SD card requires a slower clock during initialization.
- Bit 2 controls the "auto-transmit" function, which begins reading a new byte from SPI (sending the value `0xFF`) automatically when the `SPI_DATA` register is read. This can be used to simplify and speed up SPI reads.
- Bit 7 will read as a `1` value as long as a byte is being transferred over SPI.
2024-03-24 05:57:12 +01:00
2024-03-24 06:31:25 +01:00
## Colour Palette
VERA supports a single, shared palette of 256 colours, each of which is freely chosen from among the 4,096 possible colours the hardware can generate.
The palette is stored in VERA memory beginning at VERA address `0x1FA00`, and consists of 256 entries with the following format:
| Byte | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
2024-03-24 06:32:40 +01:00
| 0 | G3 | G2 | G1 | G0 | B3 | B2 | B1 | B0 |
2024-03-24 06:32:56 +01:00
| 1 | | | | | R3 | R2 | R1 | R0 |
2024-03-24 06:31:25 +01:00
2024-03-24 06:35:45 +01:00
Note that the high order four bits in the second byte of each palette entry is unused.
2024-03-24 07:29:05 +01:00
## Sprite Entries
2024-03-24 08:43:06 +01:00
Sprites are controlled using 128 eight-byte control entries, beginning at VERA address `0x1FC00`. Each of these entries contains the following structure:
2024-03-24 07:29:05 +01:00
<table>
<tr>
<th>Offset</th>
<th>Bit&nbsp;7</th>
<th>Bit&nbsp;6</th>
<th>Bit&nbsp;5</th>
<th>Bit&nbsp;4</th>
<th>Bit&nbsp;3</th>
<th>Bit&nbsp;2</th>
<th>Bit&nbsp;1</th>
<th>Bit&nbsp;0</th>
</tr>
<tr>
<td>0</td>
<td align="center" colspan="8">Bitmap (Address bits 5-12)</td>
</tr>
<tr>
<td>1</td>
<td>Mode</td>
<td align="center" colspan="3">-</td>
<td align="center" colspan="4">Bitmap (Address bits 13-16)</td>
</tr>
<tr>
<td>2</td>
<td align="center" colspan="8">X Position (Low 8 bits)</td>
</tr>
<tr>
<td>3</td>
<td align="center" colspan="6">-</td>
<td align="center" colspan="2">X Position (High 2 bits)</td>
</tr>
<tr>
<td>4</td>
<td align="center" colspan="8">Y Position (Low 8 bits)</td>
</tr>
<tr>
<td>5</td>
<td align="center" colspan="6">-</td>
<td align="center" colspan="2">Y Position (High 2 bits)</td>
</tr>
<tr>
<td>6</td>
<td align="center" colspan="4">Collision Mask</td>
<td align="center" colspan="2">Layer Position</td>
<td align="center">Vertical Flip</td>
<td align="center">Horizontal Flip</td>
</tr>
<tr>
<td>7</td>
<td align="center" colspan="2">Sprite Height</td>
<td align="center" colspan="2">Sprite Width</td>
<td align="center" colspan="4">Palette Offset</td>
</tr>
</table>
2024-03-24 07:36:22 +01:00
The bitmap address of a sprite is the top 12 bits of a 17-bit VERA memory address; the low order 5 bits are always `0`, which means that sprite data is always aligned to a 32-byte boundary.
The X and Y positions are 10-bit numbers representing the offset from the screen origin of the sprite's origin.
2024-03-24 20:58:14 +01:00
The four-bit collision mask is used in detecting collisions between sprites in hardware. When two sprites' defined areas on screen overlap, their collision masks are used as operands in a binary AND operation; if the result is nonzero, then the collision will trigger a sprite collision interrupt if that interrupt source is enabled. Thus, a sprite with a collision mask of `0b0101` can trigger interrupts by colliding with sprites whose interrupt masks have bit 0, bit 2, or both set, regardless of the status of the other two bits. This makes sprite collision more efficient, by allowing groups of sprites which can and cannot detect collision with rach other to be defined, saving time resolving needless collisions.
2024-03-24 07:36:22 +01:00
The layer position value determines the drawing order of the sprite relative to the two tile/bitmap layers:
2024-03-24 20:58:14 +01:00
| Value | Description |
| :---: | :-----------------------------: |
| 0 | Disabled |
2024-03-24 07:36:56 +01:00
| 1 | Between background and layer 0 |
2024-03-24 20:58:14 +01:00
| 2 | Between layer 0 and 1 |
| 3 | Above layer 1 |
2024-03-24 07:36:22 +01:00
2024-03-24 08:35:36 +01:00
The horizontal and vertical flip bits, as you would expect, flip the sprite's bitmap along the horizontal and vertical axes, respectively.
2024-03-24 21:03:01 +01:00
The palette offset is used to translate colour values from the sprite bitmap data, where those values are between 1 and 15. Such values are modified by adding the product of 16 and the palette offset. This can be used to enable more colourful sprites when the sprite is set to 4bpp mode, with proper organization of the VERA palette.
2024-03-24 08:35:36 +01:00
2024-03-24 20:58:14 +01:00
## Sprite Multiplexing
While it should rarely be necessary, the presence of the raster line interrupt does allow for the re-use of sprites during the rendering of a single frame; the maximum number of effective sprites possible on screen in a single frame has not been experimentally demonstrated.
2024-03-24 21:21:06 +01:00
## Tile Data
The individual tile bitmaps are 8x8, 8x16, 16x8, or 16x16 pixel bitmaps, which can be in a 1, 2, 4, or 8bpp format, with each pixel stored as a colour palette index.
## Map Data
Tilemaps are stored as sequences of two-byte structures. The interpretation of those bytes depends on the settings of the layer.
2024-03-24 21:23:02 +01:00
### 1-Bit Tile Mode
2024-03-24 21:21:06 +01:00
In 1bpp tile mode, with the `T256C` flag cleared, the first byte of the map data is an index into the tile data, and the second byte is split into two nybbles, the low-order nybble holding the foreground colour, and the high-order nybble holding the background colour for that tile.
2024-03-25 04:43:55 +01:00
In 1bpp tile mode, with the `T256C` flag set, instead the second byte is the foreground colour of the tile, with the background colour being transparent.
2024-03-24 21:21:06 +01:00
2024-03-24 21:23:02 +01:00
### 2-, 4-, and 8-Bit Tile Modes
2024-03-24 21:21:06 +01:00
In other bit depths, tile mode interprets the first byte of the map data is the low-order eight bits of the tile index. The second byte is interpreted as follows:
- The low two bits of the second byte are the high-order bits of the tile index.
- Bits 2 and 4 control horizontal and vertical flipping of the bimap used for that position in the map.
- Bits 4-7 contain a 4-bit palette offset.
Palette offsets modify the colour indices in the tile data as follows:
- Color 0 (transparent) and 16-255 are used as-is
- Colours 1-15 are modified by adding the product of the palette offset and 16 -- that is, if the palette offset is 2, then colours 1-15 will have 32 added to the palette index.
2024-03-24 05:37:53 +01:00
## 16-Bit Reads/Writes
With appropriate configuration of registers, it is possible to perform sequential 16-bit reads and writes to VERA address space:
- Set `ADDR0` to the lowest address to read or write in VERA memory, and clear `DECR0`.
- Set `ADDR1` to a value exactly one address higher than `ADDR0`, and clear `DECR1`.
- Set both `INCR0` and `INCR1` to a value of `0` or `2`.
- Set the CPU register to be used to read from or write to VERA memory to be 16 bits wide.
- Read or write to `DATA0` using a 16-bit load or store instruction. This will implicitly read `DATA1`.
- If `INCR0` and `INCR1` are both set to `0`, then the address will not increment at all; if they are set to `2`, then the address of both `DATA0` and `DATA1` will be incremented by `2` addresses.
Such 16-bit reads and writes are almost twice as cycle-efficient as reading or writing in 8-bit increments, as the extra byte takes only a single extra CPU cycle.
2024-03-24 06:35:45 +01:00
The SDK will provide a C function pair `vera_memcpy_read()` and `vera_memcpy_write()` handle bulk data transfers; it will use this mode of reading and writing without futher intervention by the programmer.