Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 76 additions & 4 deletions docs/user_peripherals/12_vga.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,65 @@ You can also include images in this folder and reference them in the markdown. E
512 kb in size, and the combined size of all images must be less than 1 MB.
-->

# VGA adapter for TinyQV
# 4 color flexible resolution VGA adapter for TinyQV

Author: ReJ aka Renaldas Zioma

Peripheral index: 12

## What it does

TODO: Explain what your peripheral does and how it works
Flexible VGA framebuffer that allows multiple resolutions, up to 4 colors per scanline, 64 unique colors per frame and provides 1024x768 60Hz video signal (64 MHz pixel clock) suitable for a [TinyVGA PMOD](https://github.com/mole99/tiny-vga).

By default it is configured to display **20 x 16 pixels** choosing colors from a 2 entrees palette. Each pixel is 1 bit where 0 selects background and 1 foreground color. In this configuration CPU is completely free to attend to other tasks.

### Racing the Beam

This peripheral is inspired by the 8-bit era designs when Video RAM (VRAM) was prohibitively expensive and there was not enough memory worth of the whole screen resolution - frankly the situation is similar with Tiny Tapeout and TinyQV peripherals where the amount of memory bits is very limited.

Instead of large framebuffers, **Racing the Beam** technique was utilised to synchronize CPU with video signal and allow CPU to modify pixels in VRAM immediately after they have been displayed, forming the image of high resolution line by line.

**Racing the Beam** means that CPU has to run in tandem with video signal:
- **interrupts** can be used for a coarse wait - for the start of the frame or scanline,
- **blocking reads** for precise syncronisation - for scanline or even in the middle of the scanline.

Racing the Beam requires high CPU utilisation to support high screen resolutions. In the case of game, CPU could be processing game-pad inputs and executing gameplay logic only during the vertical blanking. The vertical blanking happens between scanlines 768 and 804 - roughly just 5% of the whole frame.

Of course sacrifice up to 95% of CPU time is significant, but it might be worth for games or graphical demos. With this peripheral, it is up to you to decide!

### Technical capabilities

A very wide range of possible resolutions:
- from 16 x 10 4-color to 1024 x 768 2-color modes,
- vertical and horizontal counters define the size of the pixel,
- visible portion of the horizontal line can be set to 960 or 1024 clock cycles.

The resolution of the screen, as well as 2 or 4 color mode can be changed at any point of the frame providing extra flexibility.

Video RAM and color palette:
- **320 bit** of Video RAM worth of 320 or 160 pixels depending on the color mode,
- configurable stride in bits for each new row of visible pixels,
- up to 4 color palette, can be modified at any point of the frame.

**Coarse** and **precise** syncronisation primitives:
- interrupts,
- cycle accurate blocking of the CPU,
- register to read out the current scanline number of the video signal.

### Syncronisation primitives

Syncronisation between CPU and video signal can be used either to update

User interrupts can be triggered by:
- end of the frame,
- end of the visible portion of the scanline,
- end of the row of pixels

CPU can be blocked with cycle level precision until:
- end of the visible portion of the scanline and start of the horizontal blanking is reached - `WAIT_HBLANK`
- the first pixel of the Video RAM was visualized and can be safely be modified by CPU again - `WAIT_PIXEL0`

Read-only register to access the current scanline number - `SCANLINE`.

## Register map

Expand All @@ -45,8 +95,30 @@ TODO: Explain what your peripheral does and how it works

## How to test

TODO: Explain how to use your project
### Default 20 x 16 pixels

By default VGA peripheral is configured to display screen resolution of 20 x 16 pixels.
Write to `PIXELS` register to change the pixels. Each pixel is 1 bit and CPU is free to attend to other tasks.

### 4-color 160 x 192

By default VGA peripheral will count 1024 cycles per visible line, however 1024 is not divisible by intended resolution of 160 pixels. You can shorten the screen width to 960 clocks instead since 960 are nicely divisible by 320. This is achieved by setting the **5th bit** of `MODE` register.

4 colors mode is enabled by setting the **6th bit** of `MODE` register.

The whole 160 pixel row nicely fits into the 320-bit VRAM and every new row of pixels will start from the very beginning of VRAM, therefore `VRAM_STRIDE` will be 0 (-1 will have the same effect reseting VRAM address to 0 at every row).

Finally, calculated pixel horizontal and vertical counters dividing 960x768 the visible VGA resolution by the inteded frame resolution 160x192 and subtract 1. Write counter values in `PIXEL_SIZE` register.

register[MODE] = 0b0011_0000
register[VRAM_STRIDE] = 0
register[PIXEL_SIZE] = (960 // 320 - 1) | ((768 // 192 - 1) << 16)

To **Race the Beam** block CPU until the next horizontal blank reading from `WAIT_HBLANK` registe, then write into the `PIXELS` as fast you can!

y = register[WAIT_HBLANK]
register[PIXELS] = ...

## External hardware

Tiny VGA Pmod
[TinyVGA PMOD](https://github.com/mole99/tiny-vga)
61 changes: 57 additions & 4 deletions docs/user_peripherals/20_AY8913.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,27 @@ Peripheral index: 20

## What it does

This is a replica of 8-bit classic **[AY-3-8913](https://en.wikipedia.org/wiki/General_Instrument_AY-3-8910)** 3-voice programmable sound generator (PSG) chip from General Instruments. The AY-3-8913 is a smaller variant of AY-3-8910 or its analog YM2149.
This is a replica of 8-bit classic **[AY-3-8910/AY-3-8912/AY-3-8913](https://en.wikipedia.org/wiki/General_Instrument_AY-3-8910)** 3-voice programmable sound generator (PSG) integrated into a modern RISC-V as a peripheral.

The AY-3-891x family of programmable sound generators was introduced by General Instrument in 1978. Variants of the AY-3-891x were broadly used in:

- home computers: Amstrad CPC, Atari ST, Oric-1, Sharp X1, MSX, ZX Spectrum 128/+2/+3
- game consoles: Intellivision, Vectrex
- and many arcade machines

### Technical capabilities

- **3 square wave** tone generators
- A single **white noise** generator
- A single **envelope** generator able to produce 10 different shapes
- Chip is capable to produce a range of waves from a **30 Hz** to **125 kHz**, defined by **12-bit** registers.
- **16** different volume levels on a logarithmic scale

## Register map

The behavior of the AY-3-891x is defined by 14 registers. All registers are READ ONLY!
The behavior of the AY-3-891x is defined by 14 registers. The register map matches the original AY-3-891x and should be able to play the original tunes without modifications.

All registers are **read only** in this peripheral and start in **unknown** uninitialised state upon reset!

| Address | Access | Bits used | Function | Description |
|---------|--------|----------------|------------------|------------------------|
Expand All @@ -44,10 +58,49 @@ The behavior of the AY-3-891x is defined by 14 registers. All registers are READ
| 12 | R | ```xxxxxxxx``` | ---//--- | 8-bit coarse frequency |
| 13 | R | ```....xxxx``` | Envelope Shape | 4-bit shape control |

### Square wave tone generators

Square waves are produced by counting down the 12-bit counters. Counter counts up from 0. Once the corresponsding register value is reached, counter is reset and
the output bit of the channel is flipped producing square waves.

The audio chip is internally clocked at 2 MHz which was the most common timing used during the 8-bit era for AY-3-891x and the following formula can be used to calculate the tone period:

2 MHz / 16 * note frequency

### Noise generator

Noise is produced with 17-bit [Linear-feedback Shift Register (LFSR)](https://en.wikipedia.org/wiki/Linear-feedback_shift_register) that flips the output bit pseudo randomly.
The shift rate of the LFSR register is controller by the 5-bit counter.

### Envelope

The envelope shape is controlled with 4-bit register, but can take only 10 distinct patterns. The speed of the envelope is controlled with 16-bit counter. Only a single envelope is produced that can be shared by any combination of the channels.

### Volume
Each of the three AY-3-891x channels have dedicated DAC that converts 16 levels of volume to a logarithmic scale roughly 3 dB apart.

## IO pins

There is a single PWM output signal that is connected to all the output pins uo_out[7:0].
The input pins are not used.

## How to test

TODO: Explain how to use your project
All register state are in **unknown** uninitialised state upon reset. The very first thing you should do is to set them to zero!

In order to play a standard pitch A440 note you have to enable Channel A tone in the mixer:

register[7] = 0b00_001_000

Set volume loud:

register[8] = 0b0000_1111

Set A440 tone using the formulas:

register[0] = (2_000_000 // (16 * 440)) & 0xFF
register[1] = (2_000_000 // (16 * 440)) >> 8

## External hardware

Tiny Tapeout Audio PMOD
(Tiny Tapeout Audio PMOD)[https://store.tinytapeout.com/products/Audio-Pmod-p716541601]