XXIIVV

Varvara is a clean-slate computing stack based on the Uxn CPU.

The Varvara computer system was designed with a focus on portability, built on top of the 8-bit Uxn stack-machine. It is an ideal platform for running small audio/visual applications. To see a list of compatible software, see roms.

Devices are external systems connected to the Uxn CPU, such as the screen, the mouse, the keyboard, etc. There is a maximum of 16 devices, each device has 16 bytes of I/O memory.

Standard Devices

devicei/oNotes
0x000x08
00systemvector*red*The system device vector is currently unused.
wstgreen*
rstblue*
debug
halt
10consolevector*writeThe console device's vector is triggered once for each character received through stdin, and stored in the read port.
readerror
20screenvector*x*The screen device's vector is triggered 60 times per second, it is typically used to update pixels on the screen.
width*y*
height*addr*
autopixel
sprite
30
40
50
60
audiovector*adsr*The audio device vector is currently unused.
position*length*
outputaddr*
volume
pitch
80controllervector*nilThe controller device's vector is triggered each time a key is pressed or released.
button
key
90mousevector*nilThe mouse device's vector is triggered each time the mouse moved, or a button was pressed or released.
x*
y*
state
wheel
a0filevector*name*The file's vector is currently unused. The reading/writing of a file will set the success short to the length of that data.
success*length*
offset-high*addr(r)*
offset-low*addr(w)*
b0datetimeyear*nilThe datetime's vector is currently unused.
month
day
hour
minute
second

System Device

This device is holding 3 shorts to be used for application customization. For a device that does not use a screen, these bytes may be used for speech controls, or other system globals, for simplicity we call them the Red*, Green* and Blue* shorts.

The 0xe port is used to keep the debug mode flag, when active, the debug and diagnostic tools should be active. Writing to the 0xf port will send the program counter to 0x0000 and stop the evaluation.

%BREAKPOINT { #0101 #0e DEO2 } ( macro to set a break-point )

Console Device

The console device is the standard I/O device, it allows for communication between programs on the host computer, or even between instances of Uxn.

#41 .Console/write DEO ( to send the letter "A" )

To send data from one Uxn to another, when using a Unix host, use the following pattern:

uxnemu orca.rom | uxnemu piano.rom

For example, a program sending the line of text "hello", will trigger the console's vector 6 times; one for each character and a line ending character.

Screen Device

The screen device is made of two layers, each displaying 2-bits graphics in up to 4 colors. Drawing to the screen is done by writing values to the screen's x*, y* and pixel/sprite ports of the screen device.

M L Y X            D C B A            
| | | +---- Flipx  | | | +---- Blend   
| | +------ Flipy  | | +------ Blend   
| +-------- Layer  | +-------- Blend  
+---------- Mode   +---------- Blend  
Effects(MLYX)Blending(DBCA)
0bg 1b 4fg 1b 8bg 2b cfg 2b 0 4 8 c
1flipx 5flipx 9flipx dflipx 1 5 9d
2flipy 6flipy aflipy eflipy 2 6 a e
3flipxy 7flipxy bflipxy fflipxy 3 7 bf

To draw a single pixel at 20,30 with the second color on the foreground layer:

@paint-pixel
	#0020 .Screen/x DEO2 ( set x* position )
	#0030 .Screen/x DEO2 ( set y* position )
	#42 .Screen/pixel DEO2 ( draw 4-fg 2-color2 )
RTN

The screen can also draw 8x8 sprites by writing an addr* which points to the sprite data in memory. The sprite byte defines the layer to draw on, the type of data to draw, and the colors to use.

@paint-sprite
	#0020 .Screen/x DEO2 ( set x* position )
	#0030 .Screen/y DEO2 ( set y* position )
	;sprite .Screen/addr DEO2 ( set addr* position )
	#03 .Screen/sprite DEO ( draw 0-bg 3-color3 )
RTN

@sprite
	0f38 675f dfbf bfbf

Sprites are 8x8 tiles, stored in memory as sequences of 8 bytes for a 1-bit sprite, and 16 bytes for a 2-bits sprite. For example, the color byte #01 will paint a 1bpp sprite on the background with the first system color, and #42 will paint a 2-bits sprite on the foreground with the second system color.

The screen's auto byte automates the incrementation of the position and/or the sprite address whenever a drawing command is sent, so the program does not need to manually move to the next sprite, or the next tile. A pixel drawing will increment the positions by 1, and a sprite drawing, by 8. A 1bpp sprite drawing will increment the address by 8, and a 2bpp drawing, by 16.

* A Y X            
| | | +---- Auto X
| | +------ Auto Y  
| +-------- Auto Addr
+---------- Unused

Audio Device

When pitch is written to any of the audio devices, it starts playing an audio sample from Uxn's memory, pointed to by addr* and length*. It loops the sample (unless told not to) until it reaches the end of the ADSR envelope defined by adsr*.

Several fields contain more than one component:

ADSR*PitchVolume
SubfieldAttackDecaySustainReleaseLoopNoteLeftRight
Size (bits)44441744

Each of the ADSR components is measured in 15ths of a second, so writing #ffff to adsr* will play a note that lasts for exactly four seconds, with each section of the envelope lasting one second. If adsr* is #0000 then no envelope will be applied: this is most useful for longer samples that are set to play once by setting the most significant bit of pitch to 1.

The envelope varies the amplitude as follows: starting at 0%, rising to 100% over the Attack section, falling to 50% over the Decay section, remaining at 50% throughout the Sustain section and finally falling to 0% over the Release section. The envelope is linearly interpolated throughout each section.

The two volume components set how loudly the next sample will play. #ff sets maximum volume for both speakers.

When pitch is written, any sample that is currently playing will be replaced with the sample defined by all the values set in the device. While the sample is playing, the output byte can be read to find the loudness of the envelope at that moment.

Audio Sample Format

All samples used by the audio devices are mono and unsigned 8-bit (also known as u8), so the space taken up by samples is minimized. The sample rate of the samples depends on length*:

length*Sample typeSample rate
> 256Middle-C pitched sample44,100 Hz
2–256Single wavelengthVariable

Long samples are assumed to be already pitched to Middle C and will loop (unless No Loop is 1) until the end of the envelope. To play the sample at the same rate as it was recorded, write the Middle C MIDI note number, #3c, to pitch. To play at double or half speed, for example, write an octave higher or lower to pitch.

The minimum sample size that can be pitched at 44.1 kHz to Middle C with reasonable accuracy is 337 bytes long, which represents two cycles of the 261 Hz wave. The single wavelength mode in Uxn allows much smaller samples to be used, even down to only two bytes for a square wave. In this mode the length of the entire sample is taken to be one cycle of the Middle C note, so the pitch is not heard to vary even if length* were to change between sample plays.

Controller Device

This button byte works similarly to a NES controller, where there the state of each one of the 8 buttons is stored as a bit in a single byte. The keys byte contains the ascii character that is currently pressed.

0x01A Ctrl0x10Up
0x02B Alt0x20Down
0x04Select Shift0x40Left
0x08Start Escape0x80Right