Pound Shop BASIC

Quinapalus Home :: Things Technical :: Pound Shop BASIC

Pound Shop BASIC is a BASIC interpreter that runs on an LPC811 microcontroller. At the time of writing (June 2015) this device is available from Farnell for exactly one pound.

Hardware

The LPC811 comes in a 16-pin TSSOP package. Here is the complete circuit:

Pound Shop BASIC circuit

You may wish to add a decoupling capacitor across the supply pins. Unfortunately this adds to the cost.

Here is a list of the pins on the device and their functions.

Pin namePin numberFunction
PIO 0_016UART RXD input
PIO 0_19 SIN
PIO 0_26 SWDIO
PIO 0_35 SWCLK
PIO 0_44 UART TXD output
PIO 0_53 nRESET
PIO 0_615flag 0
PIO 0_714flag 1
PIO 0_811flag 2
PIO 0_910flag 3 (IE)
PIO 0_108 sense A
PIO 0_117 sense B
PIO 0_122 ISP entry
PIO 0_131 SOUT
VSS13Ground
VDD12Power supply

Power at between 1.8V and 3.3V should be supplied between VDD and VSS. The device also needs to be connected to an ordinary serial terminal (115200 baud, 8N1, no flow control) via the UART RXD and UART TXD pins. The RXD pin is 5V tolerant, so almost any USB-to-serial adaptor can be pressed into service. For convenience, the TXD and RXD pins are the same as those used when programming the device using its in-system programming (ISP) facility. Alternatively it can be programmed using the SWD interface if you have a suitable programmer. Pin P0_12, which controls entry to the in-system programming mode of the device on reset, should be pulled high for normal operation. The use of the flag, sense and SIN and SOUT pins is discussed below.

Software

In a triumph of nostalgia over efficiency, the software comprises two parts. The first, which occupies about 2200 bytes, is an emulator for the National Semiconductor SC/MP microprocessor. This device was popular in the late 1970s and early 1980s and is the first processor I ever programmed. The second part, occupying exactly 4 kbyte, is a slightly modified version of the NIBL BASIC interpreter. The code thus easily fits in the 8 kbyte of flash memory offered by the LPC811.

The program should also run in the LPC812 (although this is untested), which would make a full 4 kbyte page of RAM available to the interpreter and which (with some small modifications to the emulator) would allow the execution of BASIC programs stored in flash. Unfortunately the LPC812 costs two pence more than the LPC811.

The source code is available here. The emulator is open source, licensed under version 2 of the GNU GPL. Use at your own risk: it has not been exhaustively tested and the accuracy of SC/MP emulation, in particular for the incompletely-documented decimal add instructions, is by no means guaranteed. ‘Page wrapping‘ in pointer arithmetic is not implemented, and the delay instruction takes a fixed time. Interrupts are not implemented.

The code can be assembled using the GNU ARM (cross-) assembler. Here is a binary file with the seventh vector table entry correctly adjusted to cause the LPC811 to run the code automatically on reset.

The SC/MP emulator

The emulator is written entirely in ARM Cortex-M0 assembler. The benefit of using assembler rather than, for example, C, is not just reduced code size and increased speed: it also makes it possible to avoid the need for a stack. This saves on RAM use, and in particular it means that the full 2 kbyte of RAM in the microcontroller is available to the BASIC interpreter. The emulation is carried out entirely in registers in the processor; in fact, only eleven of the available fifteen registers are used. Emulation speed could probably be improved very slightly by using more of the registers, perhaps for holding useful constants. This would go some way to mitigating the fact that much of the flexibility in the use of immediate operands has been removed in the ARMv6-M architecture: for example, logical operations cannot take immediate operands.

With the CPU core clocked at 30 MHz the emulator executes approximately a million SC/MP instructions per second, about an order of magnitude faster than the original hardware.

NIBL BASIC

Ronald Dekker has a fascinating account of NIBL BASIC here, including a link to a summary of the language. Among its interesting features is the STAT pseudo-variable, which represents the status register of the processor. Writing values to STAT causes their three least-significant bits to appear on the flag outputs of the processor: this version of NIBL is modified to allow an extra bit to be output (which previously was the "interrupt enable" bit in the status register). Reading STAT allows the two "sense" inputs to be read. As a result it is possible to write simple programs in BASIC to control hardware, and this was the original market at which NIBL (‘National Industrial BASIC Language’) was aimed.

There are definite similarities between NIBL BASIC and the subsequent Acorn Atom BASIC (which in turn inspired BBC BASIC), such as the byte indirection and string operators and the use of the hash symbol to introduce hexadecimal constants. I would be interested in any evidence that this is not an accident; perhaps they have a common ancestor.

The SC/MP also features serial input and output pins called SIN and SOUT. These are not used in NIBL BASIC, but the emulator does support the SIO instruction and so it is possible to write a SC/MP assembler program that uses the pins and call it from BASIC.

Example program

Here is an example interaction with the system demonstrating a program that calculates e (the base of natural logarithms) to arbitrary precision. The number of decimal digits in the result is set by N in the first line of the program.

>LIST

100N=20:X=TOP:Y=TOP+N
110FORI=0TON-1:@(X+I)=0:@(Y+I)=0:NEXTI
120@Y=1:D=1:DO
130U=0:FORI=N-1TO0STEP-1:U=U+@(X+I)+@(Y+I):@(X+I)=MOD(U,10):U=U/10:NEXTI
140PR@X,".";:FORI=1TON-1:PR@(X+I);:NEXTI:PR""
150U=0:V=0
160FORI=0TON-1:U=U*10+@(Y+I):@(Y+I)=U/D:U=MOD(U,D):V=V+@(Y+I):NEXTI
170IFU>D/2@(Y+N-1)=@(Y+N-1)+1
180D=D+1:UNTILV=0

>RUN

 1 . 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 2 . 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 2 . 5  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 2 . 6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  7 
 2 . 7  0  8  3  3  3  3  3  3  3  3  3  3  3  3  3  3  3  4 
 2 . 7  1  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  7 
 2 . 7  1  8  0  5  5  5  5  5  5  5  5  5  5  5  5  5  5  6 
 2 . 7  1  8  2  5  3  9  6  8  2  5  3  9  6  8  2  5  4  0 
 2 . 7  1  8  2  7  8  7  6  9  8  4  1  2  6  9  8  4  1  3 
 2 . 7  1  8  2  8  1  5  2  5  5  7  3  1  9  2  2  3  9  9 
 2 . 7  1  8  2  8  1  8  0  1  1  4  6  3  8  4  4  7  9  8 
 2 . 7  1  8  2  8  1  8  2  6  1  9  8  4  9  2  8  6  5  2 
 2 . 7  1  8  2  8  1  8  2  8  2  8  6  1  6  8  5  6  4  0 
 2 . 7  1  8  2  8  1  8  2  8  4  4  6  7  5  9  0  0  2  4 
 2 . 7  1  8  2  8  1  8  2  8  4  5  8  2  2  9  7  4  8  0 
 2 . 7  1  8  2  8  1  8  2  8  4  5  8  9  9  4  4  6  4  4 
 2 . 7  1  8  2  8  1  8  2  8  4  5  9  0  4  2  2  5  9  2 
 2 . 7  1  8  2  8  1  8  2  8  4  5  9  0  4  5  0  7  0  7 
 2 . 7  1  8  2  8  1  8  2  8  4  5  9  0  4  5  2  2  6  9 
 2 . 7  1  8  2  8  1  8  2  8  4  5  9  0  4  5  2  3  5  1 
 2 . 7  1  8  2  8  1  8  2  8  4  5  9  0  4  5  2  3  5  5 

>

The program executes in about 20 seconds and the final result has an error of about one digit in the last place. The maximum possible value of N when using the 2 kbyte of RAM in the LPC811 is 717; the program calculates e to 717 digits in just over two and a half hours. The result is

2.71828182845904523536028747135266249775724709369995
  95749669676277240766303535475945713821785251664274
  27466391932003059921817413596629043572900334295260
  59563073813232862794349076323382988075319525101901
  15738341879307021540891499348841675092447614606680
  82264800168477411853742345442437107539077744992069
  55170276183860626133138458300075204493382656029760
  67371132007093287091274437470472306969772093101416
  92836819025515108657463772111252389784425056953696
  77078544996996794686445490598793163688923009879312
  77361782154249992295763514822082698951936680331825
  28869398496465105820939239829488793320362509443117
  30123819706841614039701983767932068328237646480429
  53118023287825098194558153017567173613320698112509
  9618188159304167

The last digit should be 9.

Acknowledgement

Pound Shop BASIC is a reimplementation on the ARM Cortex-M0 core of Karen Orton’s PICL, which runs on a PIC16F877 microcontroller with an external RAM chip. Several of the ideas here, including the use of pseudo-instructions to replace the NIBL communications routines and the extension to four flag bits, are stolen from that project.


This page most recently updated Sat 16 Sep 16:09:16 BST 2017
Word Matcher

Options...
Type a pattern, e.g.
h???o
into the box and click ‘Go!’ to see a list of matching words. More...


Qxw screen
Qxw is a free (GPL) crossword construction program. Answer treatments, circular and hex grids, jumbled entries, more besides. Release 20140331 for both Linux and Windows. More...

Practical Signal Processing front cover
My book, ‘Practical Signal Processing’, is published by Cambridge University Press. You can order it directly from them, or via amazon.co.uk or amazon.com. Paperback edition now also available. Browse before you buy at Google Books. Wydanie polskie.

If you find this site useful or diverting, please consider a donation to NASS (a UK registered charity), to KickAS (in the US), or to a similar body in your own country.

Copyright ©2004–17.
All trademarks used are hereby acknowledged.