Memotech-Bill / PicoBB

BBC BASIC for Raspberry Pi Pico
zlib License
32 stars 4 forks source link

PicoBB - Pico BBC BASIC

For the original BBCSDL please go to https://github.com/rtrussell/BBCSDL

This project is part of an attempt to implement BBC Basic on a Raspberry Pi Pico. It was originally a fork of R. Russell's repository, but now that is included as a sub-module.

For discussion see https://www.raspberrypi.org/forums/viewtopic.php?f=144&t=316761

It includes work by:

Apologies to anyone else I omitted.

There are currently four standard builds, see Releases for pre-built UF2 files:

Console version: bbcbasic_pkc in folder console/pico

Console version with WiFi: bbcbasic_pwc in folder console/pico_w

GUI version: bbcbasic_pkg in folder bin/pico

GUI version with WiFi: bbcbasic_pwg in folder bin/pico_w

Any of the four builds will run on either a Pico or a Pico W (and probably most other RP2040 boards) but clearly the networking will only actually work on a Pico W.

Many other custom builds are available by specifying options on the make command line.

The following limitations are noted:

  1. Memory is limited. Complex expressions or deeply nested routines may result in the CPU stack reaching HIMEM or any INSTALLed libraries or refresh buffers. Usually this will result in either "Expression evaluation too deep!" or "Recursion too deep!" error message. It may be possible to resolve this by lowering HIMEM. It may, however, be possible for the situation to go unnoticed in which case the Pico may crash and have to be reset.

  2. HIMEM-PAGE=128K with additional space reserved for CALL and INSTALL libraries and the CPU stack.

  3. Programs in tests and the root filesystem have been tested and appear to work. However, any remaining bugs are more likely to be related to the Pico port. As always this is open source with expressly no warranty provided.

  4. There is are known buffer overflows in the wrappers appearing in lfswrap.c which are triggered when a filename path grows to be greater than 256 characters. Please don't do that.

This project includes source from various locations with difference licenses. See the various LICENSE.txt files.

Build Instructions

Building has been tested on a Raspberry Pi running Rasperry Pi OS. Building in other environments may present difficulties.

To build this for the Pico, make sure you have the SDK installed and the tinyusb module installed. Building the GUI versions requires pico-extras as well as pico-sdk. Set the environment variables PICO_EXTRAS_PATH and PICO_SDK_PATH respectively to the locations where these are installed. Installing the SDK using the script pico_setup.sh will automatically install and configure everything required.

Download the source code using:

 git clone --recurse-submodules https://github.com/Memotech-Bill/PicoBB.git

Ensure that the environment variable PICO_SDK_PATH points to the path where the SDK is installed. Select the folder for the required build then type:

 make

Having completed the make, the following files should be in the folder:

where "_xxx" is replaced by the suffix appropriate to the build.

To install, plug a Pico or Pico W into the USB port while holding the boot button and then copy the required file onto the device using a command such as:

 cp -v bbcbasic_xxx.uf2 /media/pi/RPI-RP2

Repeat the process for filesystem.uf2

Usage Notes

For information BBC BASIC syntax and usage, see the BBC BASIC Manual. Note that the description of the IDE in sections 1 and 2 of the documentation is not applicable, this is not supported by the Pico version.

Connecting to the Console versions (from Raspberry Pi)

If using USB, connect as

  picocom /dev/ttyACM0

Or if using Raspberry Pi serial port, connect as

  picocom -b 115200 /dev/ttyS0

to use the interpreter. If using a serial connection tap the Enter key one or two times to initiate the connection. The onboard LED will flash while awaiting connection.

Note that you may use minicom as well, however, minicom will not display color correctly or resize the terminal window for the different MODE settings in BBC Basic.

If connected to the Pico via USB then the Pico can be restarted by changing the USB Baud rate to special values:

Connecting to the GUI versions

To use (once the Pico has been programmed), assuming a Pico on a VGA Demo board:

File system

Files are loaded from and saved to the Pico Flash memory. The standard BBC Basic commands may be used to navigate the folder structure.

If SD card support has been included then the contents of the SD card appear under the /sdcard folder. A SD or SDHC card may be used and it should be FAT formatted.

Thumb Assembler

There is a built-in assembler for the ARM v6M instruction set as supported by the Pico. By default the assembler uses "Unified" syntax. However including the following pseudo-op

syntax d

enables the following extensions to the allowed syntax:

The extensions may be disabled again by specifying:

syntax u

Sound

All sound implementations use the BBC BASIC SOUND and ENVELOPE commands. STEREO and VOICE are also implemented for high quality (SDL) sound.

For the console builds it will be necessary to attach low-pass filters to the sound output pins (pins 32 & 34, GPIOs 27 & 28) and then connect the output from these to an amplifier.

For the GUI builds, the VGA demo board includes the necessary post-processing, and an amplifier (or high impedance headphones) can be connected directly to the output sockets.

Serial Input and Output

Depending upon the build used, serial devices may appear as as single /dev/uart or the pair /dev/uart0 and /dev/uart1. A serial port may be opened using a command of the form:

port% = OPENUP("/dev/uart.baud=9600 parity=N data=8 stop=1 tx=0 rx=1 cts=2 rts=3")

Any of the pin numbers (tx, rx, cts, rts) may be omitted in which case that pin will not be connected. This enables transmit only, or receive only connections, and connections without flow control. The pin numbers selected must be valid Pico pin numbers for the relevent UART and function.

If not specified, the following defaults are assumed: parity=N data=8 stop=1.

The baud rate must be specified.

If keyword=value format is used then the parameters may be given in any order. Alternately the keyword and equals sign may be omitted in which case the parameters must be in the order shown above.

Note: Contrary to the BBC Basic documentation commas must not be used between the parameters.

If the BBC Basic user interface is connected via USB, then either serial interface may be used. If the user interface is connected via a serial connection, then do not open that interface (/dev/uart0 for a bare Pico, /dev/uart1 for a Pico on VGA Demo board).

Pico SDK

Many of the functions from the Pico C SDK may be accessed using the BBC BASIC command SYS. This can also access many of the C routines in the interpreter or the C runtime library. For a list of the supported functions see the build/sympico.h file in the folder for the version being used.

Note that the ARM processor in the Pico requires that integer values are aligned on word (four byte) addresses. However, in general BBC BASIC does not in general align its variables. This is not a problem when passing values into the SDK, but if addresses are being passed in order to access or return data then these must be correctly aligned. Failing to do so will result in a "Hard Fault".

The following variables in BBC BASIC are correctly aligned:

Network

The WiFi network is accessed using a Pico specific version of the BBC BASIC "socklib" library. See the BBC BASIC manual for details. This library is included in the filesystem images for the network builds.

The first time the library is used you will be prompted for the WiFi details (SSID, password and two letter country code). These will then be stored in the file "wifi.cfg" for subsequent use. To change the access point used, delete this file.

The filesystem images also include three example programs:

It is generally not practical to directly use the LWIP network routines provided by the Pico C SDK as these rely heavily on callbacks into user supplied C (or assembler) routines. Therefore some higher level routines have been written in C to provide the functions needed to implement "socklib". If required, these routines may be accessed directly using SYS. They are documented in the file "include/network.h".

File Transfer

In order to transfer files files to and from the Pico console versions of BBC BASIC, the XModem, YModem and ZModem protocols have been implemented. These are accessed by six new star commands:

*xupload <filename> - Receive an uploaded file using XModem protocol. The name of the file must be specified, as it is not sent by the upload program. Note that the length of the file will be padded out to the next multiple of 128 bytes.

*yupload [<filename>|<dirname/>] - Receive an uploaded file using YModem protocol. The filename is optional, but if given will override the name sent by the upload program. If a directory name (ending in '/') is given, the uploaded file will be placed in that directory. The exact file length will be preserved.

*zupload [<filename>|<dirname/>] - As for *yupload but using ZModem protocol.

*xdownload <filename> - Download a file using XModem protocol. It will be necessary to specify a filename at the receiving end. Note that the length of the file will be padded out to the next multiple of 128 bytes.

*ydownload <filename> - Download a file using YModem protocol. The exact file length is transferred and the name of the file is supplied to the download program.

*zdownload <filename> - As for *ydownload but using ZModem protocol.

Enter one of the above commands on the Pico, then on the terminal perform whatever action is required to start the upload or receive the download. For picocom that is <ctrl+A><ctrl+S> to send a file or <ctrl+A><ctrl+R> to receive a file. picocom uses ZModem by default.

For YModem or ZModem uploads it is not strictly necessary to first enter the star command on the Pico, starting of an upload will be automatically detected. However, doing so will avoid a long delay before a YModem upload starts.

Note: The Modem protocols are old, and not particularly well specified. There may well be differences in how different programs implement them. The Pico implementation as been tested using picocom with sx, sb or sz (depending upon protocol) for upload, and rx, rb or rz for download.

TODO: Add support for uploads and downloads on serial ports other than the console connection.

Alternately, some builds may allow file transfer via the network or an SD card.

System Identification

As per BBC BASIC standard, the low byte of the system variable @platform% will have the value 6 for any of the Pico implementations.

If running on a standard Pico, the other three bytes will be zero. If running on a Pico W, the second byte (bits 8-15) will have one of the following values:

The same information can be obtained using SYS to call the C function is_pico_w.

Note: The standard builds will return either 2 or 4 on a Pico W.

The Pico build also supplies a new (read only) system variable @picocfg&() which provides more details of the specific configuration:

This may be extended in the future if more capabilities are added.

Console Version with VGA Graphics

By request an option has been added in which the BBC BASIC console is over the USB or UART serial connection, but which is able to display text and graphics on a separate VGA display.

This capability is not included in any of the standard builds. To enable this feature use one of the following make commands

In console/pico:

make BOARD=vgaboard_sd CYW43=NONE STDIO=USB SERIAL_DEV=0 GRAPH=Y SOUND=I2S

or:

make BOARD=vgaboard_sd CYW43=NONE STDIO=USB SERIAL_DEV=0 GRAPH=Y SOUND=PWM

In console/pico_w:

make BOARD=vgaboard_sd_w STDIO=USB SERIAL_DEV=0 GRAPH=Y SOUND=I2S

or:

make BOARD=vgaboard_sd_w STDIO=USB SERIAL_DEV=0 GRAPH=Y SOUND=PWM

To use the feature use the *output command to specify the display device

Note that since BBC BASIC uses VDU commands to draw any graphics, the VGA display must be selected as an output device before any graphics can be drawn. The serial console will ignore the graphics VDU commands.

GUI version

Video Modes

The implementation currently supports 16 video modes:

Mode Colours Text Graphics Letterbox
0 2 80 x 32 640 x 256 Y
1 4 40 x 32 320 x 256 Y
2 16 20 x 32 160 x 256 Y
3 2 80 x 25 640 x 225
4 2 40 x 32 320 x 256 Y
5 4 20 x 32 160 x 256 Y
6 2 40 x 25 320 x 225
7 8 40 x 25 Teletext
8 2 80 x 30 640 x 480
9 4 40 x 30 320 x 480
10 16 20 x 30 160 x 480
11 2 80 x 25 640 x 450
12 2 40 x 30 320 x 480
13 4 20 x 30 160 x 480
14 2 40 x 25 320 x 450
15 16 40 x 30 320 x 240

Modes 0-7 reproduce those from the BBC Micro. Modes 0-2, 4 & 5 only have 256 rows of pixels which are displayed in the centre of the monitor so may appear squashed.

Modes 3 & 6 can also display graphics.

Except for Mode 7, colours 8-15 are high intensity rather than flashing.

The generally most useful modes are mode 8, which is a monochrome display with the highest resolution, and mode 15, which is a 16 colour mode with square pixels. The default mode on startup is mode 8.

Screen Refresh

By default the commands "*refresh [off|on]" do nothing. However one of two different implementations may be enabled.

"refresh buffer" enables double buffering of the display. In this mode turning refresh off hides any screen changes until a "refresh" or "*refresh on" command. For low resolution modes 4-7 or 12-14 both buffers fit within the statically allocated video storage. However for the higher resolution modes a second buffer is allocated above HIMEM and above any INSTALLed libraries. It will probably be necessary to lower HIMEM to make sufficient room for this second buffer.

"*refresh queue" enables an alternate mode in which, while refreshing is turned off, all VDU requests are stored in a queue and then processed as quickly as possible when refreshing is enabled. The VDU queue is stored above HIMEM and any INSTALLed libraries. However the size of the queue is typically smaller than a second frame buffer. The size of the queue may be specified by a decimal number following "queue".

"*refresh none" disables "refresh [off|on]".

User defined characters

Command VDU 23,... may be used to define user character shapes. The following points should be noted:

Serial Input and Output

The default GUI builds on the VGA demo board have no free external connections. With non default builds, either disabling the SD card or modifying the board (removing links or cutting tracks) it is possibe to to enable one serial connection.

There are two ways of using this:

The serial port may be opened for input or output as:

port% = OPENUP ("/dev/serial.")

It defaults to the standard 115200 baud, no parity, 8 data bits, 1 stop bit. Other formats may be specified by using a statement of the form:

port% = OPENUP("/dev/serial.baud=9600 parity=N data=8 stop=1")

If any of the parameters are omitted then the default values will be used.

If keyword=value format is used then the parameters may be given in any order. Alternately the keyword and equals sign may be omitted in which case the parameters must be in the order shown above.

Note: Contrary to the BBC Basic documentation commas must not be used between the parameters.

Missing features & Qwerks

The Pico implementation is missing features compared to the BBCSDL implementation on full operating systems. The limitations include:

Custom Builds

The make command used alone produces the standard builds. Custom builds may be produced by adding parameters to make command.

make supports the following options;

Note: the Makefile runs Python scripts to automaticly generate C files "sympico.h" and "pico_stub.c" needed to implement the SYS interface to the Pico SDK functions before running CMake. Therefore directly running CMake to build the software is not straightforward.

The options supported by the CMake script are similar to those for make:

Note: In a non-default build, if bit 2 of the STACK_CHECK option is not set then m0FaultDispatch is optionally linked. The license for this library is free for hobby and other non-commercial products. If you wish to create a commercial version of the program contained here, please add -DFREE to the CMakeLists.txt file.

Standard builds

The configurations for the standard builds are:

Pico Console:

BOARD=pico_w
CYW43=GPIO
STDIO=USB+UART
LFS=Y
FAT=N
SOUND=SDL
SERIAL_DEV=1
MIN_STACK=Y
SUFFIX=_pkc

Pico W Console:

BOARD=pico_w
CYW43=BACKGROUND
STDIO=USB+UART
LFS=Y
FAT=N
SOUND=SDL
SERIAL_DEV=1
MIN_STACK=Y
SUFFIX=_pwc

Pico GUI:

BOARD=vgaboard_sd_w
CYW43=GPIO
STDIO=PICO
LFS=Y
FAT=Y
SOUND=PWM
SERIAL_DEV=0
PRINTER=N
MIN_STACK=Y
SUFFIX=_pkg

Pico W GUI

BOARD=vgaboard_sd_w
CYW43=BACKGROUND
STDIO=PICO
LFS=Y
FAT=Y
SOUND=PWM
SERIAL_DEV=0
PRINTER=N
MIN_STACK=Y
SUFFIX=_pwg

Board definition

The GUI version has been designed to run on a Pico attached to a VGA demonstration board as per chapter 3 of Hardware design with RP2040 or the commercial version Pimoroni Pico VGA Demo Base.

The Pico SDK provides a single board definition file (vgaboard.h) for this configuration. However this does not completely describe all the hardware configurations. Therefore this repository includes three custom board definition files (in the boards/ folder):

vgaboard_sd

As supplied from Pimoroni, with no soldering, the Pico on the VGA board may be used with:

However there is no UART serial connection. This configuration is described by the vgaboard_sd configuration file.

vgaboard_serial

If a 3x2 header is soldered to the VGA board at the location labelled "SD Jumpers", then three of the pins may be used to connect to one of the Pico UARTs. However with a serial device is connected here the SD card can no longer be used. This configuration is described by the vgaboard_serial configuration file.

If the header is solderd in, but no serial device is attached then the configuration is still described by the vgaboard_sd configuration file.

vgaboard_cut

If, in adddition to attaching the 3x2 header, the tracks on the under-side of the board, joining the pads GP20 to SD01 and GP21 to SD02 are cut, then it is possible to use both the UART and the SD card, but the SD card can only be used in 1-bit or SPI modes. This configuration is described by the vgaboard_cut configuration file.

If jumpers are used to reconnect GP20 to SD01 and GP21 to SD02, then 4-bit SD mode may be used and this configuration is described by the original vgaboard_sd configuration file.

Pico W support

In addition to the above three board definitions there is also vgaboard_sd_w, vgaboard_serial_w, and vgaboard_cut_w for use if a Pico W is used on the VGA board instead of a standard Pico.