Skip to content

Pi VDU Driver

David Banks edited this page Aug 31, 2022 · 30 revisions

Contents

Overview

The Hognose release of PiTubeDirect allows the Raspberry Pi's HDMI framebuffer to provide a second display for the system with far superior graphics performance and capabilities than the BBC's main display.

A VDU interface is provided to the Pi framebuffer, so that programs running on a Co Processor can access the second display in the same way they would access the BBC hosts's main display, by sending standard Acorn VDU commands. This VDU interface is broadly equivalent to the VDU interface provided by Acorn in MOS 3.20 on the Master, and includes all of the Graphics Extension (GXR) features such as circles, elipses, flood filling and sprites.

Multiple screen modes are supported, including the standard BBC text/graphics modes (MODE 0..6), MODE 7 (teletext), all RISCOS screen modes (8..53) and some PiTubeDirect specific modes (64..69). Resolutions of upto 1280x1024 are possible with 8, 16 and 32 bits/pixel. The screen mode can be selected using VDU 22,N (or by using the BASIC MODE command). User defined screen modes can be created using VDU 23,22.

In 8 bits/pixel screen modes the framebuffer contains 8-bit logical colour values.

In 16 bits/pixel screen modes the framebuffer contains 16-bit physical RGB565 values.

In 32 bits/pixel screen modes the framebuffer contains 32-bit physical ARGB values.

In all cases, the VDU interface operates in terms of 8-bit logical colours, and the mapping between logic colours and physical colours is managed using VDU 19.

In the 8 bits/pixel modes VDU 19 manipulates the Pi GPU's hardware palette. This allows the colour of existing objects to be refined, in the same manner as the Beeb's own palette allows.

In the 16 bits/pixel and 32 bits/pixel modes, there is no hardware palette (because it would be excessively large). Instead, VDU 19 operates on a 256 entry software table that maintains the current mapping between logical and physical colours. Making changes to this table does not affect objects already drawn on the screen.

Multiple text fonts are supported, including the standard 8x8 BBC font, the full set of teletext fonts (SAA5050..SAA5057) and 32 additional fonts of various sizes (from 6x8 to 8x14). It's even possible to use the Acorn Atom's 6847 font. Font scaling and spacing are supported, and character rounding can be applied to any font.

The VDU interface is implemented natively on the Pi (in C), so drawing to the Pi framebuffer is faster than drawing to the BBC host's main display. Much much faster!

A small amount of Co-processor specific software is required to implemented an OSWRCH redirector, to make using the second display transparent. This redirectory is currenly provided for the 6502 and Native ARM Co Processors. In addition, from the Native ARM Co Processor it's possible to bypass the VDU interface and directly access the framebuffer memory.

User Guide

Enabling the Pi framebuffer

PiTubeDirect disables the Pi framebuffer by default.

To enable it, edit cmdline.txt set vdu=1:

copro=24 copro1_speed=3 copro3_speed=4 tube_delay=0 elk_mode=0 vdu=1

Connect a HDMI cable/monitor up to the Pi and power up the system.

You should see the following screen:

Using the framebuffer from the Native ARM Co Processor

There are two ways to access the Pi Framebuffer from the Native ARM Co Processor:

  1. By enabling a custom VDU driver, using the *PIVDU command
  2. By writing code that directly accesses the framebuffer memory

The *PIVDU command takes a single argument which works as follows:

  • *PIVDU 0 - disable all VDU output
  • *PIVDU 1 - send VDU output to the Host framebuffer only
  • *PIVDU 2 - send VDU output to the Pi framebuffer only
  • *PIVDU 3 - send VDU output to both the Host and Pi framebuffer

The PIVDU command affects the operation of the following system calls:

  • OS_WriteC
  • OS_WriteS
  • OS_Write0
  • OS_NewLine
  • OS_Plot
  • OS_WriteN
  • OS_Byte R0=&09 - Set the flash mark time
  • OS_Byte R0=&0A - Set the flash space time
  • OS_Byte R0=&13 - Wait for VSYNC
  • OS_Byte R0=&86 - Read the text cursor position
  • OS_Byte R0=&87 - Read the character under the text cursor
  • OS_ReadLine
  • OS_ScreenMode
  • OS_ReadPoint
  • OS_ReadModeVariable
  • OS_ReadVduVariables
  • OS_SetColour
  • OS_SetECFOrigin

To directly access the framebuffer, the address of the framebuffer needs to be obtained by calling SYS OS_ReadVduVariables (&31), and reading the SCREENSTART (&94) variable. This returns the 32-bit base address of the screen.

Here is an ARM BASIC example that reads the screen size (variables &0B and &0C), the screen base address (variable &94) and the screen size (&95):

>LIST
10 DIM inblock% 32, outblock% 32
20 inblock%!0=&0B 
30 inblock%!4=&0C
40 inblock%!8=&94
50 inblock%!12=&96
60 inblock%!16=-1
70 SYS &31,inblock%,outblock%
80 I%=0
90 REPEAT
100 PRINT ~I%!inblock%;"=";~I%!outblock%
110 I%=I%+4
120 UNTIL I%!inblock%=-1
>RUN
         B=27F
         C=1FF
        94=1F95B000
        96=50000

The resolution of the screen is 640x512 pixels, the current base address is &1F95B000, and the size is &50000 bytes (320KB).

From ARM BASIC, it's also possible to read VDU variables directly using the VDU function:

>PRINT ~VDU &0B
       27F
>PRINT ~VDU &0C
       1FF
>PRINT ~VDU &94
  1F95B000
>PRINT ~VDU &96
     50000

Using the framebuffer from one of the 6502 Co Processors

The framebuffer is also available to any of the 6502 Co Processors: (Co Pros 0..3, 16-17, 24)

On the 6502 Co Processor, the only way to access the framebuffer is via the VDU interface. It's not possible to directly access the framebuffer memory, as it's typically too large to fit into the limited 6502 address space.

The VDU interface can be accessed through the following parasite-side registers:

  • &FEF8 - send a character to the VDU FIFO (write only)
  • &FEF1 - return the X location of the edit cursor in characters (read only)
  • &FEF2 - return the Y location of the edit cursor in characters (read only)
  • &FEF3 - return the character at the edit cursor (read only)

Note, for various reasons, these registers must be accessed using absolute addressing. So ?&FEF8=65 from BASIC will have no effect. But LDA #65:STA &FEF8 from assembler will work, and will write a single "A" character to the framebuffer.

To make using the framebuffer easier a small 6502 VDU driver is provided. This driver provides:

  • a host side OSWRCH redirector (which writes to the Pi VDU FIFO at host address &FEF2/4)
  • a parasite side OSWRCH redirector (which writes to the Pi VDU FIFO at parasite address &FEF8)
  • a parasite side OSWORD0 implemention that implements cursor editing on the Pi display

To start the 6502 VDU driver:

CALL &300

You can now use the Pi display as if it were the main display on the BBC.

For example, you should be able to run the SPHERE benchmark by doing

>OLD
>RUN

The source for the 6502 VDU driver is here: https://github.com/hoglet67/PiTubeDirect/blob/hognose-dev/tools/frame_buffer/osword.asm

It occupies addresses &300-&3FF, which are rarely used by software on the 6502 Co Processor.

The VDU interface can also be accessed from the host, as shown be the below example:

oswrch:
    PHA
    LDA #&03
    STA &FEE2
    PLA
    STA &FEE4
    RTS

The host register at &FEE2 controls the function of the register at &FEE4. Setting &FEE2 to the value 3 makes the VDU FIFO visible at &FEE4. Any 6502 addressing mode can be used to access the host-side registers.

Reference Guide

Graphics drawing from BBC BASIC

In BBC BASIC II and Basic IV, several graphics related statements are available:

  • CLG - same as VDU 16
  • CLS - same as VDU 12
  • COLOUR c - same as VDU 17,c
  • DRAW x,y - same as VDU 25,5,x;y;
  • GCOL m,c - same as VDU 18,m,c
  • MODE m - same as VDU 22,m
  • MOVE x,y - same as VDU 25,4,x;y;
  • PLOT k,x,y - same as VDU 25,k,x;y;
  • TAB(x,y) - same as VDU 31,x,y

In addition, there are three grapics related functions that can be used in expressions:

  • POINT(x,y) uses OSWORD &09 to read a pixel value
  • POS uses OSBYTE &86 to read the text cursor x location
  • VPOS uses OSBYTE &86 to read the text cursor y location

In ARM BASIC, several more commands are available:

  • BY - a modifier that can be used in MOVE, DRAW, POINT and FILL
  • CIRCLE [FILL] centre_x,centre_y,radius - draw/fill a circle
  • ELLIPSE [FILL] centre_x,centre_y,semi-major,semi-minor[,rotation] - draw/fill a circle
  • FILL [BY] x,y - flood fill a region
  • LINE x1,y1,x2,y2 - draw a line - same as VDU 25,4,x1;y1;25,5,x2;y2;
  • OFF - turn off the text cursor - same as VDU 23,1,0|
  • ON - turn on the text cursor - same as VDU 23,1,1|
  • ORIGIN x,y - set the graphics origin - same as VDU 29,x;y;
  • POINT x,y - plot a single point - same as VDU 25,69,x;y;
  • RECTANGLE [FILL] x, y, width[,height]
  • TINT

and some additional functions:

  • MODE returns the current screen mode
  • VDU n returns the current value of a VDU or MODE variable

For more information on the ARM BASIC graphics command, see the original Archimedes BBC Basic Guide

VDU codes

The VDU interface provides access to all of the framebuffer features.

For a complete list of Acorn VDU codes, see: http://beebwiki.mdfs.net/VDU

The following VDU codes are currently supported:

  • 0 - Does nothing
  • 4 - Write text at text cursor
  • 5 - Write text at graphics cursor
  • 7 - Make a short beep (do nothing)
  • 8 - Backspace cursor one character
  • 9 - Forward space cursor one character
  • 10 - Move cursor down one line
  • 11 - Move cursor up one line
  • 12 - Clear text area
  • 13 - Move cursor to start of current line
  • 16 - Clear graphics area
  • 17 - Define text colour
  • 18 - Define graphics colour
  • 19 - Define logical colour
  • 20 - Reset logical colours to defaults
  • 22 - Select screen mode
  • 23,1 - Enable/Disable cursor
  • 23,2-5 - Define ECF pattern
  • 23,9 - Set flash mark (on) time
  • 23,10 - Set flash space (off) time
  • 23,11 - Set default ECF Patterns
  • 23,12-15 - Define simple ECF pattern
  • 23,17 - Set subsidary colour effects
    • 23,17,0 - Set tint for text foreground colour
    • 23,17,1 - Set tint for text background colour
    • 23,17,2 - Set tint for graphics foreground colour
    • 23,17,3 - Set tint for graphics background colour
    • 23,17,4 - Select colour patterns
    • 23,17,5 - Swap text colours
    • 23,17,6 - Set ECF origin
  • 23,19 - Select font and set font metrics
    • 23,19,0,font_number,0,0,0,0,0,0
    • 23,19,0,font_number,h_scale,v_scale,h_spacing,v_spacing,rounding,0
    • 23,19,1,h_scale,v_scale,0,0,0,0,0
    • 23,19,2,h_spacing,v_spacing,0,0,0,0,0
    • 23,19,3,rounding
    • 23,19,"FONTNAME" (max of 8 characters, with 0 terminator if less than 8)
    • 23,19,128,font_number,0,0,0,0,0,0 (print the name of the font)
  • 23,22 - Select user defined screen mode
    • 23,22,xpixels;ypixels;xchars,ychars,colours,flags
  • 23,27 - Sprite operations
    • 23,27,0,N,0,0,0,0,0,0 - select sprite to be plotted
    • 23,27,1,N,0,0,0,0,0,0 - define sprite
  • 23,32..255 - Define character
  • 24 - Define graphics window
  • 25 - PLOT mode,x,y (see plot codes below)
  • 26 - Restore default windows
  • 27 - Treat next character as a normal (non-control) character, execept for:
    • 27,136 - Move edit cursor left
    • 27,137 - Move edit cursor right
    • 27,138 - Move edit cursor down
    • 27,139 - Move edit cursor up
  • 28 - Define text window
  • 29 - Define graphics origin
  • 30 - Home text cursor to top left
  • 31 - Move text cursor to x,y
  • 32-126 - Plot character at the currently active cursor
  • 127 - Delete character to left of cursor
  • 128-255 - Plot character at the currently active cursor

The following VDU codes are not yet implemented and are ignored:

  • 1 - Send next character to printer only (do nothing)
  • 2 - Enable printer
  • 3 - Disable printer
  • 6 - Enable VDU drivers
  • 14 - Page mode on
  • 15 - Page mode off
  • 21 - Disable VDU drivers or delete current line
  • 23 - All other flavours of VDU 23 other than the ones listed above

Plot codes

The Acorn VDU interface provides access to a wide range of drawing primtives through VDU 25.

For a complete list of the VDU 25 plot codes, see: http://beebwiki.mdfs.net/VDU_25

The following plot codes are supported by the PiTubeDirect VDU driver:

  • 0-7 - Plot solid line (both endpoints included)
  • 8-15 - Plot solid line (final endpoint omitted)
  • 16-23 - Plot dotted line (both endpoints included)
  • 24-31 - Plot dotted line (final endpoint omitted)
  • 32-39 - Plot solid line (initial endpoint omitted)
  • 40-47 - Plot solid line (final endpoint omitted)
  • 48-55 - Plot dotted line (initial endpoint omitted)
  • 56-63 - Plot dotted line (final endpoint omitted)
  • 64-71 - Plot point
  • 72-79 - Horizontal line fill (left and right) to non-background
  • 80-87 - Fill a triangle
  • 88-95 - Horizontal line fill (right only) to background
  • 96-103 - Fill a rectangle
  • 104-111 - Horizontal line fill (left and right) to foreground
  • 112-119 - Fill a parallelogram
  • 120-127 - Horizontal line fill (right only) to non-foreground
  • 128-135 - Flood fill to non-background
  • 136-143 - Flood fill to foreground
  • 144-151 - Draw a circle outline
  • 152-159 - Fill a circle
  • 160-167 - Plot a circular arc
  • 168-175 - Plot a filled chord segment
  • 176-183 - Plot a filled sector
  • 184-191 - Move/Copy rectangle
  • 192-199 - Plot ellipse outline
  • 200-207 - Plot solid ellipse
  • 232-239 - Draw Sprite

Screen Modes

The following screen modes are supported:

  • Screen modes 0..6 as per the original BBC micro
  • Screen mode 7: 480x500 @ 8bpp (40x25 Teletext) which has been extensively tested using the latest test suites
  • Screen modes 8..53 as per RISC OS, see this list of RISCOS Screen Modes
  • Screen mode 64: 640x512 @ 8bpp
  • Screen mode 65: 1280x1024 @ 8bpp
  • Screen mode 66: 640x512 @ 16bpp
  • Screen mode 67: 1280x1024 @ 16bpp
  • Screen mode 68: 640x512 @ 24bpp
  • Screen mode 69: 1280x1024 @ 24bpp
  • Screen mode 70: 720x500 @ 8bpp (60x25 Teletext)
  • Screen mode 71: 960x500 @ 8bpp (80x25 Teletext)
  • Further custom screen modes can be defined using VDU 23,22

Fonts

  • Standard MODE 0..6 BBC 8x8 font
  • Full set of MODE 7 teletext fonts
    • SAA5050 (UK)
    • SAA5051 (German)
    • SAA5052 (Swedish)
    • SAA5053 (Italian)
    • SAA5054 (Belgian)
    • SAA5055 (US
    • SAA5056 (Hebrew)
    • SAA5057 (Cyrillic)
  • Additional 31 fonts:
    • 8X10 (8x10)
    • 8X11SNSF (8x11)
    • 8X14 (8x14)
    • 8X8 (8x10)
    • 8X8ITAL (8x10)
    • 9X16 (8x14)
    • BIGSERIF (8x14)
    • BLCKSNSF (8x10)
    • BLOCK (8x14)
    • BOLD (8x14)
    • BROADWAY (8x14)
    • COMPUTER (8x14)
    • COURIER (8x14)
    • FUTURE (8x14)
    • GREEK (8x14)
    • HOLLOW (8x14)
    • ITALICS (8x14)
    • LCD (8x14)
    • MEDIEVAL (8x14)
    • NORWAY (8x14)
    • SANSERIF (8x14)
    • SCRIPT (8x14)
    • SLANT (8x14)
    • SMALL (6x 8)
    • STANDARD (8x14)
    • STRETCH (8x14)
    • SUB (8x14)
    • SUPER (8x14)
    • THIN (8x14)
    • THIN8X8 (8x 8)
    • THNSERIF (8x14)
  • Acorn Atom 6847 font
  • Advanced font capabilities:
    • font selection by name or number using VDU 23,19
    • font scaling and spacing useing VDU 23,17
    • font scaling allows a font to be scaled by an integer amount (which can be different in X and Y)
    • font spacing allows additional padding between characters
    • character rounding can be applied to any font
    • multiple fonts can be used on the screen at the same time

Screen shots of each font can be seen on a separate page: Pi VDU Fonts.

MODE variables

The following MODE variables can be read from the Native ARM Co Processor using OS_ReadModeVariables:

  • &00 (M_MODEFLAGS) Assorted flags
  • &01 (M_SCRRCOL) Number of text columns -1
  • &02 (M_SCRBROW) Number of text rows -1
  • &03 (M_NCOLOUR) Maximum logical colour
  • &04 (M_XEIGFACTOR) Conversion factor between OS units and pixels
  • &05 (M_YEIGFACTOR) Conversion factor between OS units and pixels
  • &06 (M_LINELENGTH) Number of bytes per pixel row
  • &07 (M_SCREENSIZE) Number of bytes for entire screen display
  • &08 (M_YSHIFTSIZE) Deprecated. Do not use
  • &09 (M_LOG2BPP) Log base 2 of bits per pixel
  • &0A (M_LOG2BPC) Log base 2 of bytes per character
  • &0B (M_XWINDLIMIT) Number of x pixels on screen -1
  • &0C (M_YWINDLIMIT) Number of y pixels on screen -1

For more information see: https://www.riscosopen.org/wiki/documentation/show/Mode%20Variable%20Numbers

VDU Variables

The following VDU variables can be read from the Native ARM Co Processor using OS_ReadVDUVariables:

  • &81 (V_GWBROW) Graphics Window – Bottom Row (ic)
  • &82 (V_GWRCOL) Graphics Window – Righthand Column (ic)
  • &83 (V_GWTROW) Graphics Window – Top Row (ic)
  • &84 (V_TWLCOL) Text Window – Lefthand Column
  • &85 (V_TWBROW) Text Window – Bottom Row
  • &86 (V_TWRCOL) Text Window – Righthand Column
  • &87 (V_TWTROW) Text Window – Top Row
  • &88 (V_ORGX) X coord of graphics Origin (ec)
  • &89 (V_ORGY) Y coord of graphics Origin (ec)
  • &8A (V_GCSX) Graphics Cursor X coord (ec)
  • &8B (V_GCSY) Graphics Cursor Y coord (ec)
  • &8C (V_OLDERCSX) Oldest gr. Cursor X coord (ic)
  • &8D (V_OLDERCSY) Oldest gr. Cursor Y coord (ic)
  • &8E (V_OLDCSX) Previous gr. Cursor X coord (ic)
  • &8F (V_OLDCSY) Previous gr. Cursor Y coord (ic)
  • &90 (V_GCSIX) Graphics Cursor X coord (ic)
  • &91 (V_GCSIY) Graphics Cursor Y coord (ic)
  • &92 (V_NEWPTX) New point X coord (ic)
  • &93 (V_NEWPTY) New point Y coord (ic)
  • &94 (V_SCREENSTART) As used by VDU drivers
  • &95 (V_DISPLAYSTART) As used by display hardware
  • &96 (V_TOTALSCREENSIZE) Memory allocated to screen
  • &97 (V_GPLFMD) GCOL action for foreground col
  • &98 (V_GPLBMD) GCOL action for background col
  • &99 (V_GFCOL) Graphics foreground col
  • &9A (V_GBCOL) Graphics background col
  • &9B (V_TFORECOL) Text foreground col
  • &9C (V_TBACKCOL) Text background col
  • &9D (V_GFTINT) Graphics foreground tint
  • &9E (V_GBTINT) Graphics background tint
  • &9F (V_TFTINT) Text foreground tint
  • &A0 (V_TBTINT) Text background tint
  • &A1 (V_MAXMODE) Highest built-in numbered mode known to kernel
  • &A2 (V_GCHARSIZEX) X size of VDU5 chars (pixels)
  • &A3 (V_GCHARSIZEY) Y size of VDU5 chars (pixels)
  • &A4 (V_GCHARSPACEX) X spacing of VDU5 chars (pixels)
  • &A5 (V_GCHARSPACEY) Y spacing of VDU5 chars (pixels)
  • &A7 (V_TCHARSIZEX) X size of VDU4 chars (pixels)
  • &A8 (V_TCHARSIZEY) Y size of VDU4 chars (pixels)
  • &A9 (V_TCHARSPACEX) X spacing of VDU4 chars (pixels)
  • &AA (V_TCHARSPACEY) Y spacing of VDU4 chars (pixels)
  • &AE (V_LEFT) border size1
  • &AF (V_BOTTOM) border size1
  • &B0 (V_RIGHT) border size1
  • &B1 (V_TOP) border size1
  • &100 (V_WINDOWWIDTH) Width of text window in chars
  • &101 (V_WINDOWHEIGHT) Height of text window in chars

The following VDU variables are not implemented:

  • &A6 (V_HLINEADDR) Address of horizontal line-draw routine
  • &AB (V_GCOLORAEORADDR) Addr of colour blocks for current GCOLs
  • &AC (V_VIDCCLOCKSPEED) VIDC clock speed in kHz3
  • &C0 (V_CURRENT) GraphicsV driver number2

For more information see: https://www.riscosopen.org/wiki/documentation/show/VDU%20Variables

Known issues

  • Disabling the VDU drivers is not implemented:

    • VDU 6 - Enable VDU driver
    • VDU 21 - Disable VDU driver
  • Page mode is not implemented:

    • VDU 14 - Enable page mode
    • VDU 15 - Disable page mode
  • VDU 23,7 (Scroll rectangle) is not yet implemented

  • VDU 23,8 (Clear block) is not yet implemented

  • VDU 23,16 (Cursor direction control) is not implemented

  • Chararacter size and spacing is implemented in a non-standard way:

    • it uses VDU 23,19 rather than VDU 23,17,7
  • Plot codes 208-215 (font plotting) are not implemented

  • Plot codes 184-191 (copy/move/swap block) is incomplete, only the block copy (185/189) is implemented and cliping is incomplete

  • Draw arc is buggy:

    • it doesn't currently handle screen modes with non-square pixels
    • it sometimes omits the final points
  • Fill arc/segment is buggy:

    • it sometimes misses bits of a very thin shapes
  • The following graphics related SWIs are not yet implemented:

    • OS_ChangedBox
    • OS_CheckModeValid
    • OS_ClaimScreenMemory
    • OS_Confirm
    • OS_Mouse
    • OS_Pointer
    • OS_PrettyPrint
    • OS_PrintChar
    • OS_ReadPalette
    • OS_RemoveCursors
    • OS_RestoreCursors
    • OS_SpriteOp
  • The 6502 VDU driver doesn't currently support the POS, VPOS and POINT functions. The values returned will be for the host display, not the Pi display.

  • Possible issues on the Pi 4 with using VSYNC interrupt (I need to confirm this)

  • Rapid VDU 19 palette changes seem to corrupt the palette and eventually crash the Pi

Clone this wiki locally