Skip to content

UART Commands

UART Register Map

The UART will be implemented first, though future options include MIDI or a Memory-Mapped IO solution. UART was chosen for a good compromise between simplicity in attaching the card to various systems, speed, and large command space.

To keep things simple, commands are always 2-bytes. The first byte is the command; and the second is the data. This does mean certain interactions, such as loading samples, are less efficient. As these interactions are not as time-critical, it seems worth it for the simplicity.

Though this may change, at present, an acknowledgement byte is sent back after every byte is sent. For command-data stanzas, $01 means the command was read, and $02 means the data was read.

Bank Select

Hex Command Bits
$FF Select Command Bank 7:0

This selects command banks for different functions. and provides a means for expansion as well as efficient use of register writes to save on bytes.

Banks:

  • $00 = Performance (Default)
  • $01 = Meta Control
  • $02 = Wave Frames Load
  • $03 = Sample Load
  • $FF = Reset

Performance

The performance bank is the default bank and where most musical interactions will occur. Each command includes the channel number as the lowest 3-bits. This was done to help reduce the amount of commands required for interactions that generally needed to be fast or are time-critical. One speed trade-off that was done was to avoid packed commands. Each command does a single thing rather than having a command have multiple functions which would require bitmasking and keeping track of more state on the computer side.

The one exception is the Channel Mode register.

Number Hex Command Bits
00 $00-07 Note Ctrl 7:6: Note Modes
01 $08-0F Channel Mode 7:6: Modes
02 $10-17 Start Frame Number 7:0
03 $18-1F Frame Range 7:0
04 $20-27 Sample Number 7:0
05 $28-2F Note MIDI Number 6:0
06 $30-37 Semitone 7:0, Signed
07 $38-3F Volume 6:0 (7:0 for distortion)
08 $40-47 Glide 7:0
09 $48-4F Pitch Slide 7:0, Signed
0A $50-57 Env Speed Divisor 7:0
0B $58-5F Env Vol Attack 7:0
0C $60-67 Env Vol Decay 7:0
0D $68-6F Env Vol Sustain 7:0
0E $70-77 Env Vol Release 7:0
0F $78-7F Vol LFO Types 7:5
10 $80-87 Vol LFO Frame 7:0
11 $88-8F Vol LFO Speed 7:0
12 $90-97 Vol LFO Amplitude 7:0
13 $98-9F Pitch LFO Types 7:5
14 $A0-A7 Pitch LFO Frame 7:0
15 $A8-AF Pitch LFO Speed 7:0
16 $B0-B7 Pitch LFO Amplitude 7:0
17 $B8-BF Frame Mod LFO Types 7:5
18 $C0-C7 Frame LFO Frame 7:0
19 $C8-CF Frame LFO Speed 7:0
1A $D0-D7 Frame LFO Amplitude 7:0
1B $D8-DF Reserved 7:0
1C $E0-E7 Reserved 7:0
1D $E8-Ef Reserved 7:0
1E $F0-F7 Reserved 7:0
XX $F8-FE Unavailable
XX $FF Select Command Bank 7:0

Channel Control Note Modes

7:6: * $0 = Off * $1 = Rel * $2 = Legato * $3 = On

Channel Modes

7:6:

  • $0 = Cyclic Wavetable
  • $1 = Modern LFSR Noise
  • $2 = GameBoy Style LFSR Noise
  • $3 = rand() Noise
  • $4 = Bitshift Noise
  • $E = Sample, One-Shot
  • $F = Sample, Looped

Volume

Actual volume can only go to 127 as the waves are 8-bit but sinusoidal meaning each half of the wave is only up to 127 in amplitude. However, increasing the volume beyond 127 can create distortion somewhat akin to wave-folding.

LFO Types

  • 0 = Off
  • 1 = Sine
  • 2 = Tri
  • 3 = Saw
  • 4 = Square
  • 5 = Random
  • 6 = Cross-Mod, Aligned Frame
  • 7 = Cross-Mod, Free Frame

Meta Control

This is a proposed mode to make it simpler to manipulate multiple channels at once. Still very much in the idea phase, but one idea is to be able to assign a channel leader and then followers which could share attributes.

Common example would be if wanting to use detune or chorus effects which would require 2 channels and updating the pitch of both. Instead, one could setup a leader/follower for pitch and only have to send a single note update on the primary to effectively update both channels.

Frame Manipulation Bank

Hex Command Bits
$00 Frame Command 7:0
$01 Frame Number 7:0
$02 Sample Position 5:0
$03 Sample 7:0

Enabling the stride means the frame position will auto-increment after each frame command. This allows for populating the frames without having to set the position each time. Note that this does mean it will jump to the next frame after writing the current frame.

This means you can load all frames by setting the frame number to 0 and writing all 256 frames.

Frame Commands

  • $0 = Read Next Sample, Stride 1

The byte returned after the message was sent will be the byte requested.

Sample Manipulation Bank

Hex Command Bits
$00 Sample Number 7:0
$01 Stride 7: Stride Enable
$02 Sample Position 7:0
$03 Sample 7:0

Enabling the stride means the sample position will auto-increment after each Sample command. This allows for populating the sample without having to set the position each time.