PicoMite User Manual
PicoMite User Manual
User Manual
Revision 0
(13 June 2025)
Support
The compiled object code (the .uf2 file) for the PicoMite firmware is free software: you can use or redistribute
it as you please. The source code is on GitHub ( https://github.com/UKTailwind/PicoMiteAllVersions ) and
can be freely used subject to some conditions (see the header in the source files).
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
This Manual
Copyright 2025 Geoff Graham and Peter Mather
The author of this manual is Geoff Graham with input by Peter Mather, Harm de Leeuw, Mick Ames and many
others on The Back Shed forum. It is distributed under a Creative Commons Attribution-NonCommercial-
ShareAlike 3.0 Australia license (CC BY-NC-SA 3.0)
Introduction............................................................................................................................. 4
Firmware Versions and Files .................................................................................................. 5
Serial Console ........................................................................................................................ 7
First Steps .............................................................................................................................. 9
Hardware Details .................................................................................................................. 11
Using MMBasic..................................................................................................................... 15
Full Screen Editor ................................................................................................................. 19
Variables and Expressions ................................................................................................... 21
Subroutines and Functions ................................................................................................... 26
Video Output ........................................................................................................................ 29
Keyboard/Mouse/Gamepad.................................................................................................. 31
Program and Data Storage................................................................................................... 34
Sound Output ....................................................................................................................... 41
Using the I/O pins ................................................................................................................. 45
Special Device Support ........................................................................................................ 49
Display Panels ...................................................................................................................... 55
Graphics Functions............................................................................................................... 64
WiFi and Internet Functions.................................................................................................. 71
Long Strings ......................................................................................................................... 81
MMBasic Characteristics ...................................................................................................... 82
Predefined Read Only Variables .......................................................................................... 84
Options ................................................................................................................................. 89
Commands ......................................................................................................................... 100
Functions ............................................................................................................................ 169
Obsolete Commands and Functions .................................................................................. 187
Appendix A – Serial Communications ................................................................................ 188
Appendix B – I2C Communications .................................................................................... 190
Appendix C – 1-Wire Communications ............................................................................... 193
Appendix D – SPI Communications.................................................................................... 194
Appendix E – Regex Syntax ............................................................................................... 196
Appendix F – The PIO Programming Package................................................................... 198
Appendix G – Sprites.......................................................................................................... 207
Appendix H – Special Keyboard Keys ................................................................................ 209
Appendix I – Programming in BASIC - A Tutorial ............................................................. 211
Embedded Controller
Versions of the firmware without a video output are primarily intended for use as an embedded controller. This
is where the Raspberry Pi Pico or Pico 2 is used as the brains inside some device. For example, a burglar
alarm, a heating controller, weather station, etc. Quite often they have an attached touch sensitive LCD panel
for the user to control the device and observe the output.
There is also a version of the firmware that supports the wireless interface on the Raspberry Pi Pico W (and
2 W) and using this you can create an embedded controller which has a miniature web server running on the
Pico and can access the Internet to get the time, send emails, etc.
To enter programs, set options and generally manage the Raspberry Pi Pico as an embedded controller you
use the serial console to connect to a desktop or laptop computer. Unlike the self contained computer
described above, this is the only way to communicate with the BASIC interpreter so it is important that you
can connect to it. For a description of the serial console see the heading Serial Console below.
Processor Support
The PicoMite firmware supports the original RP2040 processors used in the Raspberry Pi Pico and the newer
RP2350 used in the Raspberry Pi Pico 2. The firmware is also designed to work with modules produced by
other vendors that use the same chips.
The RP2350 comes in four sub versions designated the RP2350A, RP2350B, RP2354A and the RP2354B. The
RP2354A and the RP2354B are not currently supported (although they may be in the future).
The RP2350B is the same as the RP2350A except that it has 18 additional I/O pins (pins GP30 to GP47) which
are automatically made available in MMBasic. Both of these chips are supported by the same PicoMite
firmware and work the same. So, within this manual, all references to the RP2350 apply equally to both the A
and B varients and the same firmware can be used.
Throughout this manual any references to the Raspberry Pi Pico also includes the Raspberry Pi Pico 2 unless it
specifically excluded. If there are differences then the part number of the processor (RP2040 or RP2350) will
be used to make the difference obvious.
File Names
There are a twelve firmware files contained in the firmware distribution zip file.
A typical filename for a firmware image looks like this:
PicoMiteRP2350VGAUSBV6.00.02.uf2
Where (in this example):
RP2350 is the processor that the firmware is compiled for.
VGAUSB is the feature set supported (VGA and USB).
V6.00.01 is the version number. This will be incremented in future releases.
.uf2 is the extension indicating a loadable Raspberry Pi Pico firmware image.
PicoMiteRP2040 RP2040
PicoMiteRP2350 RP2350
PicoMiteRP2040USB RP2040
PicoMiteRP2350USB RP2350
PicoMiteRP2040VGA RP2040
PicoMiteRP2350VGA RP2350
PicoMiteRP2040VGAUSB RP2040
PicoMiteRP2350VGAUSB RP2350
PicoMiteHDMI RP2350
PicoMiteHDMIUSB RP2350
WebMiteRP2040 RP2040
WebMiteRP2350 RP2350A
Terminal Emulator
You also need a terminal emulator running on your desktop or laptop computer. This is a program that acts like
an old fashioned computer terminal where it will display text received from a remote computer and any key
presses will be sent to the remote computer over the serial link. The terminal emulator that you use should
support VT100 emulation as this is required by the editor built into the PicoMite firmware.
For Windows users it is recommended that you use Tera Term
as this has a good VT100 emulator and is known to work with
the XModem protocol which you can use to transfer programs
to and from the PicoMite. Tera Term can be downloaded from:
http://tera-term.en.lo4d.com .
The screen shot on the right shows the setup for Tera Term. Note
that the "Port:" setting will vary depending on which USB port
your Raspberry Pi Pico was plugged into.
The PicoMite firmware will ignore the baud rate setting so it can
be set to any speed (other than 1200 baud which puts the Pico
into firmware upgrade mode).
If you are using Tera Term do not set a delay between
characters and if you are using Putty set the backspace key to
generate the backspace character.
The Console
Once you have identified the virtual serial port and
have connected your terminal emulator to it, you
should be able to press return on your keyboard and
see the MMBasic prompt, which is the greater than
symbol (eg, “>”).
This is the console and you use it to issue
commands to configure MMBasic, load the BASIC
program, edit and run it. MMBasic also uses the
console to display any error messages.
Apple Macintosh
The Apple Macintosh (OS X) is somewhat easier as it has the device driver and terminal emulator built in.
First start the application ‘Terminal’ and at the prompt list the connected serial devices by typing in:
ls /dev/tty.*.
The USB to serial converter will be listed as something like /dev/tty.usbmodem12345. While still at the
Terminal prompt you can run the terminal emulator at 115200 baud by using the command:
screen /dev/tty.usbmodem12345 115200
By default the function keys will not be correctly defined for use in the PicoMite's built in program editor so
you will have to use the control sequences as defined in the chapter Full Screen Editor of this manual. To
avoid this you can configure the terminal emulator to generate these codes when the appropriate function keys
are pressed.
Documentation for the screen command is here: https://www.systutorials.com/docs/linux/man/1-screen/
Linux
For Linux see these posts:
https://www.thebackshed.com/forum/ViewTopic.php?TID=14157&PID=175474#175474#175466
and
https://www.thebackshed.com/forum/ViewTopic.php?FID=16&TID=16312&LastEntry=Y#213664#213594
Android
For Android devices see this post:
https://www.thebackshed.com/forum/ViewTopic.php?FID=16&TID=17476&LastEntry=Y#230521#230517
Saved Variables:
16K (100%) Free
RAM:
0K ( 0%) 0 Variables
0K ( 0%) General
228K (100%) Free 112K (100%) Free
What is the current time? Note that the internal clock is reset to midnight on power up.
> PRINT TIME$
00:04:01
Count to 20:
> FOR a = 1 to 20 : PRINT a; : NEXT a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
A Simple Program
To enter a program, you can use the EDIT command which is described later in this manual. However, for the
moment, all that you need to know is that anything that you type will be inserted at the cursor, the arrow keys
will move the cursor and backspace will delete the character before the cursor.
To get a quick feel for how MMBasic works, try this sequence:
At the command prompt type EDIT followed by the ENTER key.
The editor should start up and you can enter this line: PRINT "Hello World"
Press the F1 key in your terminal emulator (or CTRL-Q which will do the same thing). This tells the
editor to save your program and exit to the command prompt.
At the command prompt type RUN followed by the ENTER key.
You should see the message: Hello World
Congratulations. You have just written and run your first program in BASIC.
If you type EDIT again you will be back in the editor where you can change or add to your program.
For versions with VGA video output six pins (GP16 to GP21) are reserved for that function. Similarly HDMI
versions have eight pins (GP12 to GP19) that are reserved for that function. Refer to the chapter titled Video
Output for more information.
The version of the firmware with USB keyboard/mouse support also reserves pin 11 (GP8) for the serial
console Tx and pin 12 (GP9) for Rx. Refer to the chapter Keyboard/Mouse/Ganepad for more information.
The notation is as follows:
GP0 to GP28 Can be used for digital input or output.
COM1, COM2 Can be used for asynchronous serial I/O (UART0 and UART1 pins on the Pico datasheet).
I2C, I2C2 Can be used for I2C communications (I2C0 and I2C1 pins on the Pico datasheet).
SPI, SPI2 Can be used for SPI I/O (see Appendix D). (SPI0 and SPI1 pins on the Pico datasheet).
PWMnx Can be used for PWM output (see the PWM and SERVO commands).
GND Common ground.
VBUS 5V supply directly from the USB port.
VSYS 5V supply used by the SMPS to provide 3.3V. This can be used as a 5V output or input.
3V3EN Enable 3.3V regulator (low = off, high = enabled).
RUN Reset pin, low will hold the device in reset.
ADCn These pins can be used to measure voltage (analog input).
ADC VREF Reference voltage for voltage measurement.
AGND Analog ground.
Within the MMBasic program I/O pins can be referred by using the physical pin number (i.e. 1 to 40) or the GP
number (i.e. GP0 to GP28). For example, the following refer to the same pin and operate identically:
SETPIN 32, DOUT
and
SETPIN GP27, DOUT
In the PicoMite firmware on-chip functions such as the SPI and I2C interfaces are not allocated to fixed pins,
unlike (for example) the Micromite. The PicoMite firmware makes extensive use of the SETPIN command, not
only to configure I/O pins but also to configure the pins used for interfaces such as serial, SPI, I2C, etc.
PSRAM
The RP2350 supports PSRAM and some commercial offerings have added 8MB of PSRAM to boards with the
80-pin RP2350B (eg, Pimoroni PGA2350).
The PSRAM is accessed via a Quad SPI bus so it is comparatively slow although it is buffered via a cache
which mitigates that issue. If PSRAM is present and configured MMBasic will add it to the general purpose
RAM pool so programs will have an enormous amount of general RAM to work with, even though it may be a
little slower.
To access any PSRAM an additional pin is needed for the chip select function and this is selected using the
OPTION PSRAM PIN command. Valid pins for the PSRAM chip select are GP0, GP8, GP19 and GP47.
Power Supply
The Raspberry Pi Pico has a flexible power
VBUS VSYS 3V3EN 3V3
system.
The input voltage from either the USB or VBUS
inputs is connected through a Schottky diode to the 100K
buck-boost SMPS (Switch Mode Power Supply)
which has an output of 3.3V. The SMPS will
accommodate input voltages from 1.8V to 5.5V BUCK-BOOST RP2040
USB
allowing the device to run from a wide range of SMPS & Flash
Input
power sources including batteries.
External circuitry can be powered by VBUS
(normally 5V) or by the 3V3 (3.3V) output which
can source up to 300mA.
For embedded controller applications generally an external power source (other than USB) is required and this
can be connected to VSYS via a Schottky diode. This will allow the Raspberry Pi Pico to be powered by
whichever supply is producing the highest voltage (USB or VSYS). The diodes will prevent feedback into the
lower voltage supply.
Clock Speed
By default the clock speed for the RP2040 used in the Raspberry Pi Pico is 200MHz and for the RP2350 used
in the Raspberry Pi Pico 2 is 150MHz. These are the recommended maximums.
Using the OPTION CPUSPEED command, most RP2040 CPUs can be overclocked up to 420MHz or 396MHz
for the RP2350 (PicoMite and WebMite only). They can also run slower to a minimum of 48MHz. This option
is saved and will be reapplied on power up. When changing the clock speed the PicoMite firmware will be
reset then rebooted so the USB connection will be disconnected.
Versions with Video @ 640x400 resolution have the clock set to 252MHz however this can be changed using
OPTION RESOLUTION to 252MHz, 315MHz or 378MHz.
At other video resolutions the clock speed is fixed at 283.2MHz, 324MHz, 360MHz ,372MHz or 375MHz
depending on the video resolution selected and this cannot be changed.
Nearly all tested Raspberry Pi Picos have worked correctly at 380MHz or more, so overclocking can be useful.
If the processor fails to restart at its new clock speed you can reset it by loading Clear_flash.uf2 to reset the
Pico to its factory fresh state.
Power Consumption
The power consumption is dependent on the clock speed, however at the default clock speed (200MHz for the
RP2040 and 150MHz for the RP2350), the typical power consumption is 25mA. This does not include any
current sourced or sunk by the I/O pins or the 3V3 pin:
The power consumption for the WebMite version for the Raspberry Pi Pico W is the same at 20mA with the
WiFi disabled but, when the WiFi is enabled, the power consumption will rise to 40 to 70mA.
Program Structure
A BASIC program starts at the first line and continues until it runs off the end of the program or hits an END
command - at which point MMBasic will display the command prompt (>) on the console and wait for
something to be entered.
A program consists of a number of statements or commands, each of which will cause the BASIC interpreter to
do something (the words statement and command generally mean the same and are used interchangeably).
Normally each statement is on its own line but you can have multiple statements in the one line separated by
the colon character (:). For example.
A = 24.6 : PRINT A
Appendix I (Programming in BASIC - A Tutorial) at the rear of this manual provides a comprehensive tutorial
on the language which will take you through the fundamentals in an easy to read format with lots of examples.
Shortcut Keys
The function keys on the keyboard used for the console can be used at the command prompt to automatically
enter common commands. These function keys will insert the text followed by the Enter key so that the
command is immediately executed:
F2 RUN
F3 LIST
F4 EDIT
F5 Sends ESC sequence to clear the VT100 screen. Also clears the console.
F10 AUTOSAVE
F11 XMODEM RECEIVE
F12 XMODEM SEND
Function keys F1, and F5 to F9 can be programmed with custom text. See the OPTION FNKey command.
Saved Variables
Often there is a need to save data that can be recovered when power is restored. For example, program options,
calibration settings, etc. This can be done with the VAR SAVE command which will save the variables listed
on its command line in non-volatile flash memory. The space reserved for saved variables is 16KB.
These variables can be restored with the VAR RESTORE command which will add all the saved variables to
the variable table of the running program. Normally this command is placed near the start of a program so that
the variables are ready for use by the program.
This facility is intended for saving calibration data, user selected options and other items which change
infrequently. It should not be used for high-speed saves as you may wear out the flash memory. The flash used
for the Raspberry Pi Pico has a high endurance but this can be exceeded by a program that repeatedly saves
variables. If you do want to save data often you should add a real time clock chip. The RTC commands can
then be used to store and retrieve data from the RTC's battery backed memory. See the RTC command for
more details.
Saved variables are cleared when a new program is loaded.
Watchdog Timer
One of the uses for the Raspberry Pi Pico is as an embedded controller. It can be programmed in MMBasic and
when the program is debugged and ready for "prime time" the OPTION AUTORUN configuration setting can
be turned on. The module will then automatically run its program when power is applied and act as a custom
circuit performing some special task. The user need not know anything about what is running inside it.
However, there is the possibility that a fault in the program could cause MMBasic to generate an error and
return to the command prompt. This would be of little use in an embedded situation as the device would not
have anything connected to the console. Another possibility is that the BASIC program could get itself stuck in
an endless loop for some reason. In both cases the visible effect would be the same… the program would stop
running until the power was cycled.
To guard against this the watchdog timer can be used. This is a timer that counts down to zero and when it
reaches zero the processors will be automatically restarted (the same as when power was first applied), this will
occur even if MMBasic was sitting at the command prompt. Following the restart the automatic variable
MM.WATCHDOG will be set to true to indicate that the restart was caused by a watchdog timeout.
The WATCHDOG command should be placed in strategic locations in the program to keep resetting the timer
and therefore preventing it from counting down to zero. Then, if a fault occurs, the timer will not be reset, it
will count down to zero and the program will be restarted (assuming the AUTORUN option is set).
PIN Security
Sometimes it is important to keep the data and program in an embedded controller confidential. In the
PicoMite firmware this can be done by using the OPTION PIN command. This command will set a pin number
(which is stored in flash) and whenever the PicoMite firmware returns to the command prompt (for whatever
reason) the user at the console will be prompted to enter the PIN number. Without the correct PIN the user
cannot get to the command prompt and their only option is to enter the correct PIN or reboot the PicoMite
firmware. When it is rebooted the user will still need the correct PIN to access the command prompt.
Because an intruder cannot reach the command prompt they cannot list or copy a program, they cannot change
the program or change any aspect of MMBasic or the PicoMite firmware. Once set the PIN can only be
removed by providing the correct PIN as set in the first place. If the number is lost the only method of recovery
is to reload the PicoMite firmware (which will erase the program and all options).
There are other time consuming ways of accessing the data (such as using a programmer to examine the flash
memory) so this should not be regarded as the ultimate security but it does act as a significant deterrent.
The Library
Using the LIBRARY feature it is possible to create BASIC functions, subroutines and embedded fonts and add
them to MMBasic to make them permanent and part of the language. For example, you might have written a
series of subroutines and functions that perform sophisticated bit manipulation; these could be stored as a
Program Initialisation
The library can also include code that is not contained within a subroutine or function. This code (if it exists)
will be run automatically before a program starts running (ie, via the RUN command). This feature can be used
to initialise constants or setup MMBasic in some way. For example, if you wanted to set some constants you
could include the following lines in the library code:
CONST TRUE = 1
CONST FALSE = 0
For all intents and purposes, the identifiers TRUE and FALSE have been added to the language and will be
available to any program that is run.
MM.STARTUP
There may be a need to execute some code on initial power up, perhaps to initialise some hardware, set some
options or print a custom start-up banner. This can be accomplished by creating a subroutine with the name
MM.STARTUP. When the PicoMite firmware is first powered up or reset it will search for this subroutine and,
if found, it will be run once.
For example, if the Raspberry Pi Pico has a real time clock attached, the program could contain the following
code:
SUB MM.STARTUP
RTC GETTIME
END SUB
MM.PROMPT
If a subroutine with this name exists it will be automatically executed by MMBasic instead of displaying the
command prompt. This can be used to display a custom prompt, set colours, define variables, etc all of which
will be active at the command prompt.
Note that MMBasic will clear all variables and I/O pin settings when a program is run so anything set in this
subroutine will only be valid for commands typed at the command prompt (i.e. in immediate mode).
As an example the following will display a custom prompt:
SUB MM.PROMPT
PRINT TIME$ "> ";
END SUB
Note that while constants can be defined, they will not be visible because a constant defined inside a subroutine
is local to a subroutine. However, DIM will create variables that are global that that should be used instead.
MM.END
If a subroutine named MM.END exists in the program it will be executed whenever the program ends with an
actual or implied END command. It is not executed if the program ends with a Ctrl-C.
The optional parameter ‘noend’ to the END command can be used to block execution of the MM.END
subroutine if needed (see the END command for more information),
Using a Mouse
Versions of the PicoMite firmware that support VGA/HDMI (in both the RP2040 and RP2350 versions) also
supports the use of a PS2 or USB mouse in the editor. For the details of connecting a mouse see the heading
Keyboard/Mouse/Gamepad later in this manual.
If you start the editor with a mouse plugged in and are in video MODE 1 with colour coding enabled you will
see a character highlighted with red on a white background. This highlight can be moved using the mouse. Left
clicking on the mouse will move the edit cursor to that position (ie, the same as using the cursor keys). Right
clicking the mouse is the same as pressing F4 on the keyboard and clicking the scroll wheel is the same as F5.
This means that in the editor’s normal mode you can position the mouse cursor and by right clicking the editor
will enter mark mode (cut-and-copy) with the cursor starting where the mouse cursor was. Then moving the
mouse and then left clicking will highlight the characters from the mark position to the new mouse position.
Right clicking (same as F4) will cut the highlighted region to the clipboard while clicking the scroll wheel
(same as F5) will copy the highlighted text to the clipboard without deleting it from the text. Both will return
the editor to normal mode.
In normal mode the contents of the clipboard can be inserted into the text by moving the mouse to the new
position and clicking the scroll wheel (same as F5).
Variables
Variables can start with an alphabetic character or underscore and can contain any alphabetic or numeric
character, the period (.) and the underscore (_). They may be up to 31 characters long.
A variable name or a label must not be the same as a command, function or one of the following keywords:
THEN, ELSE, GOTO, GOSUB, TO, STEP, FOR, WHILE, UNTIL, LOAD, MOD, NOT, AND, OR, XOR,
AS.
Eg, step = 5 is illegal as STEP is a keyword.
MMBasic supports three types of variables:
1. Double Precision Floating Point.
These can store a number with a decimal point and fraction (eg, 45.386) however they will lose accuracy
when more than 14 digits of precision are used. Floating point variables are specified by adding the
suffix '!' to a variable's name (eg, i!, nbr!, etc). They are also the default when a variable is created
without a suffix (eg, i, nbr, etc).
2. 64-bit Signed Integer.
These can store positive or negative numbers with up to 19 decimal digits without losing accuracy but
they cannot store fractions (i.e. the part following the decimal point). These are specified by adding the
suffix '%' to a variable's name. For example, i%, nbr%, etc.
3. A String.
A string will store a sequence of characters (eg, "Tom"). Each character in the string is stored as an eight
bit number and can therefore have a decimal value of 0 to 255. String variable names are terminated with
a '$' symbol (eg, name$, s$, etc). Strings can be up to 255 characters long.
Note that it is illegal to use the same variable name with different types. Eg, using nbr! and nbr% in the
same program would cause an error.
Most programs use floating point variables for arithmetic as these can deal with the numbers used in typical
situations and are more intuitive than integers when dealing with division and fractions. So, if you are not
bothered with the details, always use floating point.
Constants
Numeric constants may begin with a numeric digit (0-9) for a decimal constant, &H for a hexadecimal
constant, &O for an octal constant or &B for a binary constant. For example &B1000 is the same as the
decimal constant 8. Constants that start with &H, &O or &B are always treated as 64-bit unsigned integer
constants.
Decimal constants may be preceded with a minus (-) or plus (+) and may be terminated with 'E' followed by an
exponent number to denote exponential notation. For example 1.6E+4 is the same as 16000.
When a constant number is used it will be assumed that it is an integer if a decimal point or exponent is not
used. For example, 1234 will be interpreted as an integer while 1234.0 will be interpreted as a floating point
number.
String constants must be surrounded by double quote marks ("). Eg, "Hello World".
OPTION DEFAULT
A variable can be used without a suffix (i.e. !, % or $) and in that case MMBasic will use the default type of
floating point. For example, the following will create a floating point variable:
Nbr = 1234
However. the default can be changed with the OPTION DEFAULT command. For example, OPTION
DEFAULT INTEGER will specify that all variables without a specific type will be integer. So, the following
will create an integer variable:
OPTION DEFAULT INTEGER
Nbr = 1234
OPTION EXPLICIT
By default MMBasic will automatically create a variable when it is first referenced. So, Nbr = 1234 will
create the variable and set it to the number 1234 at the same time. This is convenient for short and quick
programs but it can lead to subtle and difficult to find bugs in large programs. For example, in the third line of
this fragment the variable Nbr has been misspelt as Nbrs. As a consequence the variable Nbrs would be
created with a value of zero and the value of Total would be wrong.
Nbr = 1234
Incr = 2
Total = Nbrs + Incr
The OPTION EXPLICIT command tells MMBasic to not automatically create variables. Instead they must be
explicitly defined using the DIM, LOCAL or STATIC commands (see below) before they are used. The use of
this command is recommended to support good programming practice. If it is used it should be placed at the
start of the program before any variables are used.
STATIC
Inside a subroutine or function it is sometimes useful to create a variable which is only visible within the
subroutine or function (like a LOCAL variable) but retains its value between calls to the subroutine or function.
You can do this by using the STATIC command. STATIC can only be used inside a subroutine or function and
uses the same syntax as LOCAL and DIM. The difference is that its value will be retained between calls to the
subroutine or function (i.e. it will not be initialised on the second and subsequent calls).
For example, if you had the following subroutine and repeatedly called it, the first call would print 5, the
second 6, the third 7 and so on.
SUB Foo
STATIC var = 5
PRINT var
var = var + 1
END SUB
Note that the initialisation of the static variable to 5 (as in the above example) will only take effect on the first
call to the subroutine. On subsequent calls the initialisation will be ignored as the variable had already been
created on the first call.
As with DIM and LOCAL the variables created with STATIC can be float, integers or strings and arrays of
these with or without initialisation. The length of the variable name created by STATIC and the length of the
subroutine or function name added together cannot exceed 31 characters.
CONST
Often it is useful to define an identifier that represents a value without the risk of the value being accidently
changed - which can happen if variables were used for this purpose (this practice encourages another class of
difficult to find bugs).
Using the CONST command you can create an identifier that acts like a variable but is set to a value that cannot
be changed. For example:
CONST InputVoltagePin = 31
CONST MaxValue = 2.4
The identifiers can then be used in a program where they make more sense to the casual reader than simple
numbers. For example:
IF PIN(InputVoltagePin) > MaxValue THEN SoundAlarm
A number of constants can be created on the one line:
CONST InputVoltagePin = 31, MaxValue = 2.4, MinValue = 1.5
The value used to initialise the constant is evaluated when the constant is created and can be an expression
including user defined functions.
The type of the constant is derived from the value assigned to it; so for example, MaxValue above will be a
floating point constant because 2.4 is a floating point number. The type of a constant can also be explicitly set
by using a type suffix (i.e. !, % or $) but it must agree with its assigned value.
Arithmetic operators:
^ Exponentiation (eg, b^n means bn)
* / \ MOD Multiplication, division, integer division and modulus (remainder)
+ - Addition and subtraction
Shift operators:
x << y x >> y These operate in a special way. << means that the value returned
will be the value of x shifted by y bits to the left while >> means the
same only right shifted. They are integer functions and any bits
shifted off are discarded and any bits introduced are set to zero.
Logical operators:
NOT INV invert the logical value on the right (eg, NOT(a=b) is a<>b)
or bitwise inversion of the value on the right (eg, a = INV b)
<> < > <= =< Inequality, less than, greater than, less than or equal to, less than or
>= => equal to (alternative version), greater than or equal to, greater than or
equal to (alternative version)
= equality
AND OR XOR Conjunction, disjunction, exclusive or
For Microsoft compatibility the operators AND, OR and XOR are integer bitwise operators. For example,
PRINT (3 AND 6) will output the number 2. Because these operators can act as both logical operators (for
example, IF a=5 AND b=8 THEN …) and as bitwise operators (eg, y% = x% AND &B1010) the interpreter
will be confused if they are mixed in the same expression. So, always evaluate logical and bitwise expressions
in separate expressions.
The other logical operations result in the integer 0 (zero) for false and 1 for true. For example the statement
PRINT 4 >= 5 will print the number zero on the output and the expression A = 3 > 2 will store +1 in A.
String operators:
+ Join two strings
<> < > <= =< Inequality, less than, greater than, less than or equal to, less than or
>= => equal to (alternative version), greater than or equal to, greater than or
equal to (alternative version) in order of ascii value.
= Equality
String comparisons respect case. For example "A" is greater than "a".
Subroutines
A subroutine acts like a command and it can have arguments (sometimes called a parameter list). In the
definition of the subroutine they look like this:
SUB MYSUB arg1, arg2$, arg3
<statements>
<statements>
END SUB
And when you call the subroutine you can assign values to the arguments. For example:
MYSUB 23, "Cat", 55
Inside the subroutine arg1 will have the value 23, arg2$ the value of "Cat", and so on. The arguments act
like ordinary variables but they exist only within the subroutine and will vanish when the subroutine ends. You
can have variables with the same name in the main program and they will be hidden by the arguments defined
for the subroutine.
When calling a subroutine you can supply less than the required number of values and in that case the missing
values will be assumed to be either zero or an empty string. You can also leave out a value in the middle of the
list and the same will happen. For example:
MYSUB 23, , 55
Will result in arg2$ being set to the empty string "".
Rather than using the type suffix (eg, the $ in arg2$) you can use the suffix AS <type> in the definition of the
subroutine argument and then the argument will be known as the specified type, even when the suffix is not
used. For example:
SUB MYSUB arg1, arg2 AS STRING, arg3
IF arg2 = "Cat" THEN …
END SUB
Inside a subroutine you can define a variable using LOCAL (which has the same syntax as DIM). This variable
will only exist within the subroutine and will vanish when the subroutine exits.
Functions
Functions are similar to subroutines with the main difference being that the function is used to return a value in
an expression. The rules for the argument list in a function are similar to subroutines. The only difference is
that brackets are required around the argument list when you are calling a function, even if there are no
arguments (brackets are optional when calling a subroutine).
To return a value from the function you assign a value to the function's name within the function. If the
function's name is terminated with a $, a % or a ! the function will return that type, otherwise it will return
whatever the OPTION DEFAULT is set to. You can also specify the type of the function by adding AS <type>
to the end of the function definition.
For example:
FUNCTION Fahrenheit(C) AS FLOAT
Fahrenheit = C * 1.8 + 32
END FUNCTION
Passing Arrays
Single elements of an array can be passed to a subroutine or function and they will be treated the same as a
normal variable. For example, this is a valid way of calling the Swap subroutine (discussed above):
Swap dat(i), dat(i + 1)
This type of construct is often used in sorting arrays.
You can also pass one or more complete arrays to a subroutine or function by specifying the array with empty
brackets instead of the normal dimensions. For example, a(). In the subroutine or function definition the
associated parameter must also be specified with empty brackets. The type (i.e., float, integer or string) of the
argument supplied and the parameter in the definition must be the same.
In the subroutine or function the array will inherit the dimensions of the array passed and these must be
respected when indexing into the array. If required the dimensions of the array could be passed as additional
arguments to the subroutine or function or it could find these via the BOUND() function. The array is passed
by reference which means that any changes made to the array within the subroutine or function will also apply
to the supplied array.
For example, when the following is run the words "Hello World" will be printed out:
DIM MyStr$(5, 5)
MyStr$(4, 4) = "Hello" : MyStr$(4, 5) = "World"
Concat MyStr$()
PRINT MyStr$(0, 0)
SUB Concat arg$()
arg$(0,0) = arg$(4, 4) + " " + arg$(4, 5)
END SUB
Early Exit
There can be only one END SUB or END FUNCTION for each definition of a subroutine or function. To exit
early from a subroutine (i.e., before the END SUB command has been reached) you can use the EXIT SUB
command. This has the same effect as if the program reached the END SUB statement. Similarly you can use
EXIT FUNCTION to exit early from a function.
Recursion
Recursion is where a subroutine or function calls itself. You can do recursion in MMBasic but there are a
number of issues (these are a direct consequence of the limitations of microcontrollers and the BASIC
language):
There is a fixed limit to the depth of recursion. In the PicoMite firmware this is 50 levels.
If you have many arguments to the subroutine or function and many LOCAL variables (especially strings)
you could easily run out of memory before reaching the 50 level limit.
Any FOR…NEXT loops and DO…LOOPs will be corrupted if the subroutine or function is recursively
called from within these loops.
VGA Video
For versions of the firmware that support a VGA video output the following diagram illustrates how to attach
such a monitor. The VGA output is automatically enabled at startup – there are no options that need to be set.
270Ω
390Ω
VGA Monitor
820Ω DE15 15-pin D-sub
Raspberry
Pi Pico 270Ω
VGA CONNECTOR
RED FRONT VIEW
GP21
GREEN
GP20
½ GREEN
GP19
BLUE
GP18
GROUND
GND
VERT SYNC
GP17
HORIZ SYNC
GP16
The output is in the standard VGA format with a pixel rate of 25.175MHz and a frame rate of 60Hz.
There are two or three modes which can be selected using the MODE command:
MODE 1 Monochrome with a resolution of 640 x 480 (default at startup)
MODE 2 16 colours with a resolution of 320 x 240
MODE 3 16 colours with a resolution of 640 x 480 (RP2350 only)
In MODE 2 and 3 the output is 16 colours in the 4-bit RGB121 format (i.e. 1 bit for red, 2 bits for green, and 1
bit for blue). In MODE 2 the pixels are duplicated along both the x and y axis giving a 320 x 240 resolution
while the monitor still sees a 640 x 480 signal.
The output from MMBasic is written as a bitmap to a framebuffer. The firmware then uses the second CPU in
the processor to feed this framebuffer data, a pixel line at a time, via DMA to one of the RP2040’s
programmable I/O controllers (PIO0) to generate the display. As this runs independently of the main processor
there is little or no impact on MMBasic caused by generating the VGA output.
HDMI Video
For versions of the firmware that support HDMI video the following table lists the connections to the standard
HDMI Type A socket. The HDMI output is automatically enabled at startup – there are no options that need to
be set.
HDMI Pin 1: Pin 21 (GP16) via a 220Ω resistor HDMI Pin 13: No Connection
HDMI Pin 2: Ground HDMI Pin 14: No Connection
HDMI Pin 3: Pin 22 (GP17) via a 220Ω resistor HDMI Pin 15: No Connection
HDMI Pin 4: Pin 24 (GP18) via a 220Ω resistor HDMI Pin 16: No Connection
HDMI Pin 5: Ground HDMI Pin 17: Ground
HDMI Pin 6: Pin 25 (GP19 via a 220Ω resistor HDMI Pin 18: +5V via Schottky barrier diode
HDMI Pin 7: Pin 16 (GP12) via a 220Ω resistor HDMI Pin 19: No Connection
HDMI Pin 8: Ground
HDMI Pin 9: Pin 17 (GP13) via a 220Ω resistor
HDMI Pin 10: Pin 19 (GP14) via a 220Ω resistor HDMI
HDMI Pin 11: Ground Front
HDMI Pin 12: Pin 20 (GP15) via a 220Ω resistor View
The construction pack for this design can be downloaded from: https://geoffg.net/picomitevga.html (at the
bottom of the page).
GND
The recommended MOSFET is a TN0702N3-G or ZVNL110A however the commonly available 2N7000 has
been tested and works well.
After it is connected the keyboard must be enabled with the OPTION KEYBOARD command.
The I/O pins on the RP2350 series of microcontrollers can withstand 5V (while powered up) so the keyboard
can be directly connected as illustrated with the 5V supplied by the VSYS pin on the Raspberry Pi Pico 2.
The keyboard is enabled with the OPTION KEYBOARD command.
PS2 Mouse
The I/O pins used for a PS2 mouse must be configured using the commands OPTION MOUSE (at the
command prompt) or MOUSE OPEN (within a program).
A PS2 mouse is powered via 5V so on a Raspberry Pi Pico (RP2040) a level shifter will be required for the
mouse clock and data pins - this can be the same as the above circuit for a PS2 keyboard. On a Raspberry Pi
Pico 2 (RP2350) a level shifter is not required so the mouse can be directly connected.
USB Hub
The firmware will also support a USB hub via this interface so it is possible to have multiple keyboards or a
keyboard plus a mouse plus a gamepad, etc. A maximum of 4 devices may be connected via a hub. These are
reference by a channel index number (1 to 4). Use MM.INFO(USB n) to return the device code for any device
connected to channel n. By default a keyboard will be allocated to channel 1. A mouse will be allocated to
channel 2. The first gamepad will be allocated to channel 3 and a second gamepad to channel 4.
If you use a USB hub it is better to use an unpowered hub (ie, one that is powered by the Raspberry Pi Pico).
This is because the USB protocol stack cannot reset the hub and it may be confused if the power on the Pico is
cycled without doing the same for the hub. The hub can also be confused if devices are swapped while the hub
is powered. If this happens you should cycle the power on the Pico followed by the hub then add the USB
devices one by one.
Note that a hub is not required. If you only want to connect one device (for example a keyboard) you can just
plug the device (using an adapter cable) directly into the Pico’s USB connector.
USB Keyboard
When a USB keyboard is connected it will be immediately recognised (no configuration required) and
MMBasic will allocate it to channel 1 by default– there is nothing extra required.
USB Mouse
When a USB mouse is connected it will be immediately recognised (no configuration required) and MMBasic
will allocate it to channel 2 by default– there is nothing extra required.
USB Gamepad
One or more PS3 or PS4 controllers or gamepad such as a Super Nintendo
SNES Controller with a USB interface can be connected via USB (illustrated on
the right).
By default the first gamepad will be allocated to channel 3 and a second
gamepad channel 4. Within a program the data from the gamepad can be read
using the DEVICE(GAMEPAD) function.
Using a Mouse
The mouse is especially useful in the MMBasic program editor where it can replicate much of the functionality
found in GUI editors such as Notepad in Windows (see the heading Full Screen Editor above in this manual).
This includes positioning the insert point and copy and paste using the clipboard.
A mouse can also be used in a program where its position can be queried by using the DEVICE() function. As
an example, the following program will report any mouse movement.
Note that the mouse is always allocated to channel 2
‘ continuous loop to print on the console any movement
Do
mx=DEVICE(MOUSE 2, x)
my=DEVICE(MOUSE 2, y)
If mx <> tx Or my <> ty Then Print mx, my
tx = mx : ty = my
Loop
Flash Slots
There are three of these which can be used to save completely different programs or previous versions of the
program you are working on (in case you need to revert to an earlier version). In addition, MMBasic will allow
a BASIC program to load and run another program saved to a numbered flash location while retaining all the
variables and settings of the original program – this is called chaining and allows for a much larger program to
be run than the amount of program memory would normally allow.
To manage these numbered locations in flash you can use the following commands (note that in the following n
is a number from 1 to 3):
FLASH SAVE n Save the program in the program memory to the flash location n.
FLASH LOAD n Load a program from flash location n into the program memory.
FLASH RUN n Run a program from flash location n, clears all variables but does not erase
or change the program held in the main program memory.
FLASH LIST Display a list of all flash locations including the first line of the program.
FLASH LIST n [,ALL] Lists the program held in location n. Use FLASH LIST n,ALL to list
without page breaks
FLASH ERASE n Erase flash location n.
FLASH ERASE ALL Erase all flash locations.
FLASH CHAIN n Run the program in flash location n, leaving all variables intact. This allows
for very large programs, that can be split into two or three parts, to be run.
It does not erase or change the program held in the main program memory.
FLASH OVERWRITE n Erase flash location n and then save the program in the program memory to
that location.
FLASH DISK LOAD f$ [,O] Loads a flash slot with a binary file created using LIBRARY DISK SAVE.
Overwrites the slot if the optional “O” is specified.
In addition, the command OPTION AUTORUN can be used to specify a flash program location to be set
running when power is applied or the CPU restarted. This option can also be used without specifying a flash
location and in that case MMBasic will automatically run the program in program memory.
Notes:
It is recommended that you include a comment describing the program as the first line of the program. This
will then be displayed by the FLASH LIST command and will help identify the program.
All BASIC programs saved to flash may be erased if you upgrade (or downgrade) the PicoMite firmware.
So make sure that you backup these first.
The LIBRARY command uses Slot 3 for saving library data therefore only 2 slots will be available if the
library feature is used.
Flash Filesystem
This is an area of the Raspberry Pi Pico’s flash memory which is automatically created by the firmware and
will look like a normal disk drive to MMBasic. It is called drive A: and data and programs can be read/written
using the normal BASIC file commands (SAVE, RUN, OPEN, etc). In addition, sub directories can be created
and deleted and long filenames used.
For example, to run a program:
RUN "A:/MyProgram.bas"
Open a text file for random access:
OPEN "A:/data/database.dat" FOR RANDOM as #4
SD Cards
An SD card socket can be connected to the Raspberry Pi Pico and accessed as drive B:. Like the Flash
Filesystem the normal BASIC file commands can be used to save/load programs as well as opening data files
for read/write.
Cards up to 32 GB formatted in FAT16 or FAT32 are supported and the files created can also be read/written
on personal computers running Windows, Linux or the Mac operating system. The PicoMite firmware uses the
SPI protocol to talk to the card and this is not influenced by the card type, so all types (Class 4, 10, UHS-1 etc)
are supported. For a description of SPI see: http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
The SPI protocol needs to be specifically configured before it can be used. This can be done in one of two
ways - by using the “system” SPI port or by directly specifying the I/O pins to use:
System SPI Port
This is a port that will be used for system use (SD card, LCD display and the touch controller on an LCD
panel). There are a number of ports and pins that can be used (see the chapter PicoMite Hardware) but this
example uses SPI on pins GP18, GP19 and GP16 for Clock, MOSI and MISO respectively.
OPTION SYSTEM SPI GP18, GP19, GP16
Then MMBasic must be told that there is an SD card attached and what pin is used for the Chip Select (CS)
signal:
OPTION SDCARD GP22
Dedicated I/O Pins
Alternatively, where no other devices share the SPI bus with the SD card it can be set up with:
OPTION SDCARD CS_pin, CLK_pin, MOSI_pin, MISO_pin
In this case the pins can be assigned completely flexibly and do not need to be capable of SPI operation but SD
card performance will be better if valid SPI pins are chosen.
These commands must be entered at the command prompt (not in a program) and will cause the PicoMite
firmware to restart. This has the side effect of disconnecting the USB console interface which will need to be
reconnected.
When the Raspberry Pi Pico is restarted MMBasic will automatically initialise the SD Card interface. This SPI
port will then not be available to BASIC programs (ie, it is reserved). To verify the configuration, you can use
the command OPTION LIST to list all options that have been set including the configuration of the SD Card.
The basic circuit diagram for connecting the SD Card connector using these pin allocations is illustrated below.
PicoMite
GP22
GP19
GP18
GP16
Note that you can use many different configurations using various pin allocations – this is just an example
based on the configuration commands listed above.
XModem Transfer
In addition to the standard method of XModem transfer which copies to or from the program memory the
PicoMite firmware can also copy to and from a file on the Flash Filesystem or SD Card. The syntax is:
XMODEM SEND filename$
or
XMODEM RECEIVE filename$
Where ‘filename$’ is the file to save or send. ‘filename$’ can be a string expression, variable or constant. If it
is a constant the string must be quoted (eg,, XMODEM SEND "prbas.bas"). In the case of receiving a file, any
file with the same name will be overwritten.
DO
abort: PRINT
PRINT "Number of records in the file =" LOF(#1)/RecLen
INPUT "Command (r = read, w = write, a = append, q = quit): ", cmd$
IF cmd$ = "q" THEN CLOSE #1 : END
IF cmd$ = "a" THEN
SEEK #1, LOF(#1) + 1
ELSE
INPUT "Record Number: ", nbr
IF nbr < 1 or nbr > LOF(#1)/RecLen THEN PRINT "Invalid record" : GOTO abort
SEEK #1, RecLen * (nbr - 1) + 1
ENDIF
IF cmd$ = "r" THEN
PRINT "The record = " INPUT$(RecLen, #1)
ELSE
LINE INPUT "Enter the data to be written: ", dat$
PRINT #1,dat$ + SPACE$(RecLen - LEN(dat$));
ENDIF
LOOP
Random access can also be used on a normal text file. For example, this will print out a file backwards:
OPEN "file.txt" FOR RANDOM AS #1
FOR i = LOF(#1) TO 1 STEP -1
SEEK #1, i
PRINT INPUT$(1, #1);
NEXT i
CLOSE #1
Filter Circuits
Most low cost amplified speakers (for a personal computer) will not respond to the carrier frequency so they
will act as a low pass filter in themselves. Therefore, if you want to keep it simple, you can directly connect the
PWM output to an amplified speaker’s input and a reasonable sound output should be achieved.
However, the high level of the 44KHz carrier may cause problems for the amplifier (eg, overheating or
distortion) so the following filter is recommended. This removes most of the carrier and delivers about 2V
peak to peak (0.6V RMS) with reasonable fidelity up to 8KHz (more than enough for most amplified speakers):
Below is a superior circuit producing quality audio with an insignificant amount of the carrier remaining. This
is suitable for a more sophisticated HiFi amplifier/speaker configuration. The output is good for 10Hz to
15KHz at about 3V peak to peak (1V RMS) at 1KHz.
Stereo
4.7mH Output
PWM-A Pin Left
220Ω Right
2.7nF Common
PicoMite
Outputs 4.7mH
220Ω
PWM-B Pin
2.7nF
Both circuits are designed to feed an amplifier (not directly drive a headphone or speaker) and rely on capacitor
coupling into the following amplifier (most have this).
MCP48n2 DAC
The audio output can also be generated through a connected MCP48n2 DAC (eg, MCP4822) in which case it is
configured using the command:
OPTION AUDIO SPI CS-PIN, CLK-PIN, MOSI-PIN
The DAC does not need a complex low pass filter and a 120Ω resistor connected to the DAC output with the
other end of the resistor connected to GND via a 100nF capacitor will be adequate. When a MCP4822 is used
the LDAC pin on the DAC should be connected to GND.
I2S DAC
The audio output can also be generated though an I2S DAC such as the PCM5102A. The DAC must support
creating its own master clock as this is not created by the firmware. The I2S DAC is available on the Pico2
(RP2350A/B) and uses PIO2 to generate the output so this will not be available when the I2S DAC is enabled.
The I2S DAC is also available on the RP2040 and uses
PIO 0. In the case of the RP2040 VGA versions this is
shared with the VGA PIO.
It is configured with the command:
OPTION AUDIO I2S BCLK-PIN, DIN-PIN
The I2S word clock (LRCK) will then be on the next pin to
the BCLK. So, for example if BCLK is set to GP0 then
LRCK will be on GP1. Both these pins and the DIN pin
must be unused when the command is issued. Typically, the
DAC module will also require a GND and power pin to be
connected (typically 5V)
The I2S DAC will produce CD quality audio from FLAC files and output from MP3 files limited only by the
inherent MP3 compression. FLAC files up to 96000Hz and 24-bit have been tested.
Using PLAY
It is important to realise that the PLAY command will generate the audio in the background. This allows a
program (for example) to play the sound of a bell while continuing with its control function. Without the
background facility the whole BASIC program would freeze while the sound was played.
However, generating the audio in the background has some subtle inferences which can trip up newcomers.
For example, take the following program:
PLAY TONE 500, 500, 2000
END
You may expect the 500Hz tone to sound for 2 seconds but in practice it will not make any sound at all. This is
because MMBasic will execute the PLAY TONE command (which will start generating the sound in the
background) and then it will immediately execute the END command which will terminate the program and the
background sound. This will happen so fast that nothing is heard.
Similarly the following program will not work either:
PLAY TONE 500, 500, 2000
PLAY TONE 300, 300, 5000
This is because the first command will set a 500Hz the tone playing but then the second PLAY command will
immediately replace that with a 300Hz tone and following that the program will run off the end terminating the
program (and the background audio), resulting in nothing being heard.
If you want MMBasic to wait while the PLAY command is doing its thing you should use suitable PAUSE
commands. For example:
PLAY TONE 500, 500
PAUSE 2000
PLAY TONE 300, 300
PAUSE 5000
PLAY STOP
This applies to all versions of the PLAY command including PLAY WAV.
Utility Commands
There are a number of commands that can be used to manage the sound output:
PLAY PAUSE Temporarily halt (pause) the currently playing file or tone.
PLAY RESUME Resume playing a file or tone that was previously paused.
PLAY NEXT Play the next WAV, MP3 or FLAC file in a directory
PLAY PREVIOUS Play the previous WAV, MP3, or FLAC file in a directory
PLAY STOP Terminate the playing of the file or tone. The sound output will also be
automatically stopped when the program ends.
Digital Inputs
A digital input is the simplest type of input configuration. If the input voltage is higher than 2.5V the logic
level will be true (numeric value of 1) and anything below 0.65V will be false (numeric value of 0). The inputs
use a Schmitt trigger input so anything in between these levels will retain the previous logic level.
Note that the maximum voltage on the RP2040 (ie, the Raspberry Pi Pico) I/O pins is 3.3V. Level shifting will
be required if a device uses 5V levels for signalling. The Raspberry Pi Pico 2 using the RP2350 can tolerate 5V
(while powered) so, in this case, level shifting is not required for signals up to 5V.
In your BASIC program you would set the input as a digital input and use the PIN() function to get its level.
For example:
SETPIN GP4, DIN
IF PIN(GP4) = 1 THEN PRINT "High"
The SETPIN command configures pin GP4 as a digital input and the PIN() function will return the value of that
pin (the number 1 if the pin is high). The IF command will then execute the command after the THEN
statement if the input was high. If the input pin was low the program would just continue with the next line in
the program.
The SETPIN command also recognises a couple of options that will connect an internal resistor from the input
to either the supply or ground. This is called a "pullup" or "pulldown" resistor and is handy when connecting to
a switch as it saves having to install an external resistor to place a voltage across the contacts. Due to a
hardware issue with the RP2350 processor it is recommended that an external resistor of 8,2K or less be used if
a pulldown is required on that processor.
Analog Inputs
Pins marked as ADC can be configured to measure the voltage on the pin. The input range is from zero to 3.3V
and the PIN() function will return the voltage. For example:
> SETPIN 31, AIN
> PRINT PIN(31)
2.345
>
You will need a voltage divider if you want to measure voltages greater than 3.3V. For small voltages you may
need an amplifier to bring the input voltage into a reasonable range for measurement.
The measurement uses 3.3V power supply to the CPU as its reference and it is assumed that this is exactly
3.3V. This value can be changed with the OPTION VCC command. In order to get the best possible reading,
the analogue input is sampled 10 times. The values are then sorted and the top 2 and bottom 2 discarded and the
remaining 6 averaged.
If you want the direct reading from the ADC you can use the raw mode by using the ARAW option to the
SETPIN command:
SETPIN pinno,ARAW
In this case a value between 0 and 4095 will be returned based on a single sample.
The ADC commands provide an alternate method of recording analog inputs and are intended for high speed
recording of many readings into an array.
Counting Inputs
Any four pins can be used as counting inputs to measure frequency, period or just count pulses on the input.
The pins used for this function can be configured using the OPTION COUNT command but, if not changed,
will default to GP6, GP7, GP8 and GP9.
Digital Outputs
All I/O pins can be configured as a digital output using the DOUT parameter to the SETPIN command. For
example:
SETPIN GP15, DOUT
This means that when an output pin is set to logic low it will pull its output to zero and when set high it will
pull its output to 3.3V. In MMBasic this is done with the PIN command. For example PIN(GP15) = 0
will set pin GP15 to low while PIN(GP15) = 1 will set it high.
Interrupts
Interrupts are a handy way of dealing with an event that can occur at an unpredictable time. An example is
when the user presses a button. In your program you could insert code after each statement to check to see if
the button has been pressed but an interrupt makes for a cleaner and more readable program.
When an interrupt occurs MMBasic will execute a defined subroutine and when finished return to the main
program. The main program is completely unaware of the interrupt and will carry on as normal.
Any I/O pin that can be used as a digital input can be configured to generate an interrupt using the SETPIN
command with up to ten interrupts active at any one time. Interrupts can be set up to occur on a rising or falling
digital input signal (or both) and will cause an immediate branch to the specified user defined subroutine. The
target can be the same or different for each interrupt. Return from an interrupt is via the END SUB or EXIT
SUB commands. Note that no parameters can be passed to the subroutine however within the interrupt calls to
other subroutines and functions are allowed.
If two or more interrupts occur at the same time they will be processed in order of the interrupts as defined
below. During the processing of an interrupt all other interrupts are disabled until the interrupt subroutine
returns. During an interrupt (and at all times) the value of the interrupt pin can be accessed using the PIN()
function.
Interrupts can occur at any time but they are disabled during INPUT statements. Also interrupts are not
recognised during some long hardware related operations (eg, the TEMPR() function, LCD drawing
commands, and SD access commands) although they will be recognised if they are still present when the
operation has finished. When using interrupts the main program is completely unaffected by the interrupt
activity unless a variable used by the main program is changed during the interrupt.
Because interrupts run in the background they can cause difficult to diagnose bugs. Keep in mind the following
factors when using interrupts:
Interrupts are only checked by MMBasic at the completion of each command, and they are not latched by
the hardware. This means that an interrupt that lasts for a short time can be missed, especially when the
program is executing commands that take some time to execute. Most commands will execute in under
15µs however some commands such as the TEMPR() function can take up to 200ms so it is possible for
an interrupt to occur and vanish within this window and thus not be recognised.
When inside an interrupt all other interrupts are blocked so your interrupts should be short and exit as
soon as possible. For example, never use PAUSE inside an interrupt. If you have some lengthy
processing to do you should simply set a flag and immediately exit the interrupt, then your main program
loop can detect the flag and do whatever is required.
The subroutine that the interrupt calls (and any other subroutines or functions called by it) should always
be exclusive to the interrupt. If you must call a subroutine that is also used by an interrupt you must
disable the interrupt first (you can reinstate it after you have finished with the subroutine).
Remember to disable an interrupt when you have finished needing it – background interrupts can cause
strange and non-intuitive bugs.
In addition to interrupts generated by the change in state of an I/O pin, an interrupt can also be generated by
other sections of MMBasic including timers and communications ports and the above notes also apply to them.
The list of all these interrupts (in high to low priority ranking) is:
1. PID control loops
2. ON KEY individual
3. ON KEY general
4. ON PS2
5. PIO RX FIFO
6. PIO TX FIFO
7. PIO RX DMA completion
8. PIO TX DMA completion
Measuring Temperature
The TEMPR() function will get the temperature from a DS18B20
3.3V
temperature sensor. This device can be purchased on eBay for about
US$5 in a variety of packages including a waterproof probe version. 4.7K
LCD Display
The LCD command will display text on a standard LCD module with the
minimum of programming effort.
This command will work with LCD modules that use the KS0066,
HD44780 or SPLC780 controller chip and have 1, 2 or 4 lines. Typical
displays include the LCD16X2 (futurlec.com), the Z7001
(altronics.com.au) and the QP5512 (jaycar.com.au). eBay is another
good source where prices can range from $10 to $50.
To setup the display you use the DEVICE LCD INIT command:
LCD INIT d4, d5, d6, d7, rs, en
d4, d5, d6 and d7 are the numbers of the I/O pins that connect to inputs D4, D5, D6 and D7 on the LCD module
(inputs D0 to D3 and R/W on the module should be connected to ground). 'rs' is the pin connected to the
register select input on the module (sometimes called CMD or DAT). 'en' is the pin connected to the enable or
chip select input on the module.
Any I/O pins on the Raspberry Pi Pico can be used and you do not have to set them up beforehand (the LCD
command automatically does that for you). The following shows a typical set up.
+5V
10K
2 3
Vdd CO NTRAS T
RS 4
RS
EN 6
EN
LCD Module
PicoMite D7 D6 D5 D4 D3 D2 D1 D0 GND R/W
14 13 12 11 10 9 8 7 1 5
D7
D6
D5
D4
Note that this example also uses the TEMPR() function to get the temperature (described above).
Keypad Interface
A keypad is a low tech but effective method of entering numeric data. The PicoMite firmware supports either a
4x3 keypad or a 4x4 keypad and the monitoring and decoding of key presses is done in the background. When
a key press is detected an interrupt will be issued where the program can deal with it.
Examples of a 4x3 keypad and a 4x4 keypad are the Altronics S5381 and S5383 (go to www.altronics.com ).
To enable the keypad feature you use the command:
KEYPAD var, int, r1, r2, r3, r4, c1, c2, c3, c4
Where ‘var’ is a variable that will be updated with the key code and ‘int’ is the name of the interrupt subroutine
to call when a new key press has been detected. ‘r1’, ‘r2’, ‘r3’ and ‘r4’ are the pin numbers used for the four
row connections to the keypad (see the diagram below) and ‘c1’, ‘c2’, ‘c3’ and ‘c4’ are the column
connections. ‘c4’ is only used with 4x4 keypads and should be omitted if you are using a 4x3 keypad.
Any I/O pins on the Raspberry Pi Pico can be used and you do not have to set them up beforehand, the
KEYPAD command will automatically do that for you.
R1
1 2 3 20
R2
4 5 6 21
R3
7 8 9 22
R4
10 0 11 23
PicoMite
C1
C2
C3
C4
The detection and decoding of key presses is done in the background and the program will continue after this
command without interruption. When a key press is detected the value of the variable var will be set to the
number representing the key (this is the number inside the circles in the diagram above). Then the interrupt
will be called.
For example:
Keypad KeyCode, KP_Int,GP2,GP3,GP4,GP5,GP6,GP7,GP8 ' 4x3 keybd
DO
< body of the program >
LOOP
WS2812 Support
The PicoMite firmware has built in support for the WS2812 multicolour LED chip. This chip needs a very
specific timing to work properly and with the DEVICE WS2812 command it is easy to control these devices
with minimal effort.
The PicoMite firmware includes support for many LCD display panels using an SPI, I2C or parallel interface.
These commands must be entered at the command prompt (not in a program) and will cause the PicoMite
firmware to restart. This has the side effect of disconnecting the USB console interface which will need to be
reconnected.
Note that the maximum voltage on all the Raspberry Pi Pico’s I/O pins is 3.3V. Level shifting will be required
for displays that use 5V levels for signalling. The Raspberry Pi Pico 2 can tolerate 5V (while powered) so, in
this case, level shifting is not required.
System SPI Bus
The system SPI bus is a dedicated SPI channel which is used by many LCD panels, all touch controllers and
also to communicate with a SD Card. If any of these are attached the I/O pins used for the system SPI bus must
be defined first.
This is done using this command:
OPTION SYSTEM SPI CLK-pin, MOSI-pin, MISO-pin
This must be entered at the command prompt and will cause the firmware to restart and disconnect the USB
console interface, which will need to be reconnected. This option will be reapplied on startup and the pins will
be reserved and not be available for other uses.
A typical example is:
OPTION SYSTEM SPI GP18, GP19, GP16
Note that the speed of drawing to SPI based displays and accessing SD cards is not affected by the CPU speed.
The following table lists the connections required to support the SD Card connector:
8-bit parallel Raspberry Pi Pico
Description
Display
SD_CS SD Card Chip Select Recommended Pin 29/GP22
SD_DIN SD Card Data In (MOSI) Recommended Pin 15/GP11
SD_CLK SD Card SPI Clock Recommended Pin 14/GP10
SD_DO SD Card Data Out (MISO) Recommended Pin 16/GP12
Where a connection is listed as "Recommended" this is only a suggestion and other pins can be used depending on
the hardware configuration. Regardless, the specific pin should be specified in the appropriate OPTION
command (see below).
Generally 7 inch and larger displays have a separate pin on the connector (marked 5V) for powering the backlight
from a 5V supply. If this pin is not provided the backlight power will be drawn from the 3.3V pin. Note that the
power drawn by the backlight can be considerable. For example, a 7 inch display will typically draw 330 mA
from the 5V pin.
If the Pico’s 3,3V output is used for powering a panel plus its backlight, it may easily require more current than
the Pico can supply. Symptoms of a marginal supply could include TOUCH calibration failures or SD access
failures. In this case an external 3.3V supply should be used.
The current drawn by the backlight can also cause a voltage drop on the LCD display panel’s ground pin which
can in turn shift the logic levels as seen by the display controller resulting in corrupted colours or text. An easy
way of diagnosing this effect is to reduce the CPU speed to (say) 48MHz. If this fixes the problem it is a strong
indication that this is the cause. Soldering power and ground wires direct to the LCD display panel’s PCB is one
workaround.
Care must be taken with display panels that share the SPI port between a number of devices (SD Card, touch, etc).
In this case all the Chip Select signals must configured in MMBasic or disabled by a permanent connection to
3.3V. If this is not done the pin will float causing the wrong controller to respond to commands on the SPI bus.
In the PicoMite firmware either SPI channel can used to communicate with the touch controller and the SD Card
interface as defined by the OPTION SYSTEM SPI setting. If this is set, that SPI channel will be unavailable to
BASIC programs (which can use the other SPI channel).
Touch Support
Many LCD panels are supplied with a resistive touch sensitive panel and associated controller chip. MMBasic
fully supports this interface and this allows many of the physical knobs and switches used in a project to be
implemented as on-screen controls activated by touch.
In all cases the LCD display panel itself should be configured and tested first, then the touch feature can be
configured. The touch controller uses the SPI protocol for communications and for LCD panels using the SPI
protocol this has normally been previously done using the OPTION SYSTEM SPI command.
For display panels using I2C or a parallel interface the OPTION SYSTEM SPI command must be separately
used to define the system SPI bus for use by the touch controller. This command was discussed near the start
of this chapter and defined in detail in the Options chapter of this manual.
For example, using the recommended pins for an 8-bit parallel display (described above) you would use:
OPTION SYSTEM SPI GP10, GP11, GP12
To use the touch facility MMBasic must be told that the touch controller is available on the system SPI bus by
using the OPTION TOUCH command. This tells MMBasic what pins are used for the Chip Select and Interrupt
signals.
As an example, for a typical ILI9341 display, this sets Chip Select to the GP12 pin and Interrupt to GP11:
OPTION TOUCH GP12, GP11
This must be entered at the command prompt and will cause the firmware to restart and disconnect the USB
console interface, which will need to be reconnected.
When the PicoMite firmware is restarted MMBasic will automatically initialise the touch controller. To verify the
configuration, you can use the command OPTION LIST to list all options that have been set including the
configuration of the display panel and touch.
Care must be taken when the SPI port is shared between a number of devices (SD Card, touch, etc). In this case
all the Chip Select signals must configured in MMBasic or alternatively disabled.
Touch Functions
To detect if and where the screen is touched you can use the following functions in a BASIC program:
TOUCH(X)
Returns the X coordinate of the currently touched location or -1 if the screen is not being touched.
TOUCH(Y)
Returns the Y coordinate of the currently touched location or -1 if the screen is not being touched.
Touch Interrupts
An interrupt can be set on the IRQ pin number that was specified when the touch facility was configured. To
detect touch down the interrupt should be configured as INTL (i.e., high to low). The interrupt can be
cancelled with the command SETPIN pin, OFF.
The following program illustrates how the touch interrupt can be used. Whenever the screen is touched it will
print on the console the coordinates of that touch. It assumes that the command OPTION TOUCH 7, 15 was
used to initially configure the touch function:
SETPIN 15, INTL, MyInt ' assumes that OPTION TOUCH 7, 15 was used
DO : LOOP
SUB MyInt ' subroutine called on a touch interrupt
PRINT TOUCH(X) TOUCH(Y)
END SUB
GP11
GP16
GP19
GP12
GP18
GP16
GP18
+5V
GP16
GP18
GP19
GP19
GP22
GP15
GP14
GP13
Ground
+5V
To match the above connections the following configuration commands should be entered, one by one at the
command prompt:
OPTION SYSTEM SPI GP18, GP19, GP16
OPTION LCDPANEL ILI9341, L, GP15, GP14, GP13
OPTION TOUCH GP12, GP11
OPTION SDCARD GP22
These commands will be remembered and automatically applied on power up. Note that after each command is
entered the firmware will restart, and the USB connection will be lost and must be reconnected.
Next the touch screen should be calibrated with:
GUI CALIBRATE
You can then test the various components.
The following will draw multiple colourful overlapping circles on the LCD screen which will confirm that the
LCD is connected correctly:
GUI TEST LCDPANEL
The following will test the touch interface. When you touch the LCD screen a dot should appear on the screen
at the exact point of the touch.
GUI TEST TOUCH
If this is not accurate you may have to run the GUI CALIBRATE command a second time taking greater care.
Finally, the following will list the files on the SD Card, if it executes without error you can be assured that the
SD Card interface is good.
FILES
If you run into trouble getting the display to work it is worth disconnecting everything and clear the options
with the command OPTION RESET so that you can start with a clean slate. Then reconnect it one stage at a
time and configure and test each new stage as you progress. As you do this remember that any device
connected to the SPI bus must be configured in MMBasic or its chip select line must be held logic high. This is
because the voltage on an unconnected chip select line will float, possibly causing the wrong device to respond
to signals intended for another device.
Also note that the ILI9341 controller is very sensitive to static discharge so, if the panel will not respond, it
could easily be damaged and it would be worth testing with another panel.
Supported Hardware
LCD Panels
The resolution and number of colours supported by an LCD panel is determined by the panel itself and the
driver – see the chapter Display Panels for the details.
VGA Video
There are a number of modes which can be selected using the MODE command:
OPTION RESOLUTION 640x480
MODE 1 640x480 monochrome with RGB121 tiles, optional layer buffer
MODE 2 320x240 4-bit colour, optional layer buffer (RP2350 only) second optional layer buffer
MODE 3 640x480 4-bit colour, optional layer buffer (RP2350 only)
OPTION RESOLUTION 720x400
MODE 1 720x400 monochrome with RGB121 tiles, optional layer buffer
MODE 2 360x200 4-bit colour, optional layer buffer (RP2350 only) second optional layer buffer
MODE 3 720x400 4-bit colour, optional layer buffer (RP2350 only)
OPTION RESOLUTION 800x600 (RP2350 only)
MODE 1 800x600 monochrome with RGB121 tiles, optional layer buffer
MODE 2 400x300 4-bit colour, two optional layers
MODE 3 800x600 4-bit colour, optional layer buffer
OPTION RESOLUTION 848x480 (RP2350 only)
MODE 1 848x480 monochrome with RGB121 tiles, optional layer buffer
MODE 2 424x240 4-bit colour, two optional layers
MODE 3 848x480 4-bit colour, optional layer buffer
HDMI Video (RP2350 only)
Each HDMI resolution can operate in a number of modes which are set using the MODE command:
OPTION RESOLUTION 640x480
MODE 1 640x480x2-colours with RGB555, optional layer buffer
MODE 2 320x240x16colours and colour mapping to RGB555 palette, two optional layers
MODE 3 640x480x16 colours and colour mapping to RGB555 palette, optional layer buffer
MODE 4 320x240x32768 colours, optional layer buffer
MODE 5 320x240x256 colours and colour mapping to RGB555 palette, optional layer buffer
OPTION RESOLUTION 720x400
MODE 1 720x400 monochrome with with RGB555 tiles, optional layer buffer
MODE 2 360x200 4-bit colour and colour mapping to RGB555 palette, two optional layers
MODE 3 720x400 4-bit colour and colour mapping to RGB555 palette, optional layer buffer
MODE 4 360x200x32768 colours, optional layer buffer
MODE 5 360x200x256 colours and colour mapping to RGB555 palette, optional layer buffer
OPTION RESOLUTION 800x600 (RP2350 only)
MODE 1 800x600 monochrome with RGB332 tiles, optional layer buffer
MODE 2 400x300 4-bit colour and colour mapping to RGB332 palette, optional layer buffer
MODE 3 800x600 4-bit colour and colour mapping to RGB332 palette, optional layer buffer
MODE 5 400x300x256 colours, optional layer buffer
Colours
Colour is specified as a true colour 24 bit number where the top eight bits represent the intensity of the red
colour, the middle eight bits the green intensity and the bottom eight bits the blue. The easiest way to generate
this number is with the RGB() function which has the form:
RGB(red, green, blue)
The RGB() function also supports a shortcut where you can specify common colours by naming them. For
example, RGB(red) or RGB(cyan). The colours that can be named using the shortcut form are white, black,
blue, green, cyan, red, magenta, yellow, brown, white, orange, pink, gold, salmon, beige, lightgrey and grey (or
USA spelling gray/lightgray).
MMBasic will automatically translate all colours to the format required by the individual display controller.
For example, in the case of the ILI9341 LCD controller, is 64K colours in the 565 format.
The default for commands that require a colour parameter can be set with the COLOUR command (can also be
spelt COLOR). This is handy if your program uses a consistent colour scheme, you can then set the defaults
and use the short version of the drawing commands throughout your program.
The COLOUR command takes the format: COLOUR foreground-colour, background-colour
Fonts
There are eight built in fonts. These are:
Embedded Fonts
If required, additional fonts can be embedded in a BASIC program. These fonts work exactly same as the built
in font (i.e. selected using the FONT command or specified in the TEXT command).
The format of an embedded font is:
DefineFont #Nbr
hex [[ hex[…]
hex [[ hex[…]
END DefineFont
It must start with the keyword "DefineFont" followed by the font number (which may be preceded by an
optional # character). Any font number in the range of 2 to 5 and 8 to 16 can be specified and if it is the same
as a built in font it will replace that font.
The body of the font is a sequence of 8-digit hex words with each word separated by one or more spaces or a
new line. The font definition is terminated by an "End DefineFont " keyword. These can be placed anywhere
in a program and MMBasic will skip over it. This format is the same as that used by the Micromite.
Additional fonts and information can be found in the Embedded Fonts folder in the PicoMite firmware
download. These fonts cover a wide range of character sets including a symbol font (Dingbats) which is handy
for creating on screen icons, etc.
Screen Coordinates
All coordinates and measurements on the screen are done in terms of pixels with the X coordinate being the
horizontal position and Y the vertical position. The top left corner of the screen has the coordinates X = 0 and
Y = 0 and the values increase as you move down and to the right of the screen.
There are four read only variables which provide useful information about the display currently connected:
MM. HRES
Returns the width of the display (the X axis) in pixels.
MM.VRES
Returns the height of the display (the Y axis) in pixels.
MM.INFO(FONTHEIGHT)
Returns the height of the current default font (in pixels). All characters in a font have the same height.
MM.INFO(FONTWIDTH)
Returns the width of a character in the current font (in pixels). All characters have the same width.
Drawing Commands
There are ten basic drawing commands that you can use within MMBasic programs to draw graphics. Most of
these have optional parameters. You can completely leave these off the end of a command or you can use two
commas in sequence to indicate a missing parameter. For example, the fifth parameter of the LINE command
is optional so you can use this format:
LINE 0, 0, 100, 100, , rgb(red)
Optional parameters are indicated below by italics, for example: font.
In the following commands C is the drawing colour and defaults to the current foreground colour. FILL is the
fill colour which defaults to -1 which indicates that no fill is to be used.
Rotated Text
As described above the alignment of the text in the TEXT command can be specified by using one or two
characters in a string expression for the third parameter of the command. In this string you can also specify a
third character to indicate the rotation of the text.
This character can be one of:
N for normal orientation
V for vertical text with each character under the previous running from top to bottom.
I the text will be inverted (i.e. upside down)
U the text will be rotated counter clockwise by 90º
D the text will be rotated clockwise by 90º
Transparent Text
The VGA or HDMI video output or LCD displays using the SSD1963, ST7796S, ILI9341, ST7789_320, or
ILI9488 with MISO connected are capable of transparent text.
In this case the TEXT command will allow the use of -1 for the background colour. This means that the text is
drawn over the background with the background image showing through the gaps in the letters.
Load Image
The LOAD IMAGE and LOAD JPG commands can be used to load an image from the Flash Filesystem or SD
Card and display it on the LCD display. This can be used to draw a logo or add an ornate background to the
graphics drawn on the display.
Advanced Graphics
NOT AVAILABLE IN
VGA/HDMI AND WEBMITE
RP2040 VERSIONS
The PicoMite firmware
includes a suite of advanced
graphics functions to make it
easy for a programmer to create
touch sensitive control elements
on an LCD panel. These
include on screen switches,
buttons, indicator lights,
keyboard, etc.
DO
TEXT MM.HRes/2, MM.VRes/4, TIME$, "CM", 1, 4, RGB(CYAN), DBlue
TEXT MM.HRes/2, MM.VRes*3/4, DATE$, "CM"
IF TOUCH(X) <> -1 THEN END
LOOP
This program starts by defining a constant with a value corresponding to a dark blue colour and then sets the
defaults for the colours and the font. It then draws a box with red walls and a dark blue interior.
Following this the program enters a continuous loop where it performs three functions:
1. Displays the current time inside the previously drawn box. The string is drawn centred both horizontally
and vertically in the middle of the box. Note that the TEXT command overrides both the default font and
colours to set its own parameters.
2. Draws the date centred in the lower half of the screen. In this case the TEXT command uses the default
font and colours previously set.
3. Checks for a touch on the screen. This is indicated when the TOUCH(X) function returns something
other than -1. In that case the program will terminate.
The screen display should look like this (the font used in this illustration is different):
This chapter provides an overview of the WiFi and Internet features implemented in the WebMite version for
the Raspberry Pi Pico W and the Raspberry Pi Pico 2 W.
These functions are complex and, as a result, a few points should be noted:
Implementing the Internet protocols uses a lot of the resources of the processor (particularly RAM) so
the WebMite firmware should only be used where WiFi and Internet connectivity are important and
some performance impact can be tolerated compared to the standard Raspberry Pi Pico.
This manual describes how the WebMite interfaces with the WiFi and Internet protocols and provides
some simple examples but it does not describe HTML, TCP and the many other protocols and
conventions involved. They can be confusing for the newcomer who will need to consult some of the
many primers available on the web.
While processing complex Internet protocols the WebMite firmware can get confused and hang or throw
an error and return to the command prompt. To allow for this, programs should use the WATCHDOG
feature to recover from such situations. It is also recommended that from time to time (eg, once a week)
the program should force a reboot using CPU RESTART to ensure that the protocol stacks are reset.
File Transfer
Files can be transferred to and from the WebMite via XModem or TFTP. XModem is supported by Tera Term
and will operate over Telnet the same as it does over a direct serial connection. However TFTP is much faster
and more reliable than XModem so it is the recommended method of transferring files to and from the
WebMite.
A TFTP server on the WebMite is automatically enabled when you are connected to a WiFi network so nothing
is needed there. You do need a TFTP client for your PC and many different implementations are available for
Windows, Mac OS and Linux. Note that many tutorials on TFTP discuss setting up a TFTP server - this is not
needed, you only need a client.
For Windows a TFTP client is included in the operating system but it needs to be enabled via the Control Panel.
To do this select:
Control Panel -> Programs and Features -> Turn Windows features on or off
Then scroll down the list and tick TFTP Client.
To send a file from your PC to the WebMite run the following in a Command or Power Shell window on your
Windows PC (‘IP-Addr’ is the IP address of the WebMite):
TFTP -i IP-Addr PUT filename
And to copy a file from the WebMite to your PC:
TFTP -i IP-Addr GET filename
To list the functions of the TFTP client use the following:
TFTP -h
An alternative and simple graphical Windows TFTP client is: http://www.3iii.dk/linux/dd-wrt/tftp2.exe
Sending an Image
You can insert an image in your web page using the following html code <img src="pix.jpg"/>. When
the remote browser reads this it will send the following request GET /pix.jpg HTTP. You can then send the
requested image using the code shown in bold:
s$ = LGetStr$(buff%(), p% + 4, t% - p% - 5)
IF s$ = "/" THEN
WEB TRANSMIT PAGE a%,"index.html"
ELSE IF s$ = "/page2.html" THEN
WEB TRANSMIT PAGE a%,"page2.html"
ELSE IF s$ = "/pix.jpg" THEN
WEB TRANSMIT FILE a%,"pix.jpg","image/jpeg"
ENDIF
Note that pix.jpg must be a jpeg image residing in the default directory of the internal flash filesystem or SD
card. The WebMite is not a fast server so small and simple images are preferred.
The "image/jpeg" parameter is known as a MIME type and there are many different types, other common
image types are image/bmp, image/png, and image/gif.
Note that the above HTML code contains two BASIC variables (offb$ and onb$) which will be substituted by
the WEB TRANSMIT PAGE command. These variables control how the button is displayed. If they are set to
an empty string the button will display as unchecked or, if it is set to the string "checked='checked'", the
button will display as checked. These variables should be initialised when the program starts running.
When the user clicks on the first button the browser will send a request containing: GET /?RB=OFF HTML
and when the second is clicked the request will be: GET /?RB=ON HTML
In the ELSE IF chain in the TCP interrupt subroutine we can act on these requests:
ELSE IF s$ = "/?RB=OFF"
' <insert code here to turn off the device>
offb$ = "checked='checked'" : onb$ = ""
WEB TRANSMIT PAGE a%, "index.html"
ELSE IF s$ = "/?RB=ON"
' <insert code here to turn on the device>
offb$ = "" : onb$ = "checked='checked'"
WEB TRANSMIT PAGE a%, "index.html"
Essentially all that this code does is turn off or on the device as requested, sets the variables onb$ and offb$ to
reflect the new state of the buttons and then resends the whole web page back to the browser.
Using UDP
User Datagram Protocol (UDP) is a fast and lightweight protocol used to send messages between devices. It
can be unreliable because it doesn't guarantee that data packets will be delivered or arrive in order, however it is
often used for time sensitive applications that prioritize speed over reliability.
Setting up a UDP server is similar to setting up a TCP server. Firstly UDP is enabled with the following option
entered at the command prompt (this will also cause a restart):
OPTION UDP SERVER PORT port_nbr
In your program you need to start the server running with the following command:
WEB UDP INTERRUPT InterruptSub
Where 'InterruptSub' is the name of your subroutine that will be called whenever a message is received by the
UDP server. When this happens the IP address of the sending device will be held in the read only variable
MM.ADDRESS$ and the received message in MM.MESSAGE$.
You can send a UDP message using:
WEB UDP send ip_address$, port_nbr, message$
The following demonstration uses two WebMites configured with OPTION WIFI on the same network.
Before starting both WebMites must be configured with OPTION UDP SERVER PORT 77.
‘ interrupt subroutine
Sub myint
Print "Received " + mm.message$ + " from " + mm.address
pause 100
WEB UDP send mm.address$, 77, " WebMite #1 message"
End Sub
Then run the program, which will initially sit in a loop doing nothing.
On the second WebMite enter the following program substituting the IP address with the one from the first
WebMite. Then run the program:
WEB UDP interrupt myint
WEB UDP send "192.168.1.127", 77, "Starting UDP echo"
Do
'<do some processing here>'
Loop
‘ interrupt subroutine
Sub myint
Print "Received " + mm.message$ + " from " + mm.address$
pause 100
WEB UDP send mm.address$, 77, "WebMite #2 message"
End Sub
The result will be a very fast ping pong of UDP messages between the two WebMites.
Sending EMails
When you have a remote device like the WebMite it is useful for it to be able to send emails to raise the alarm
over faults, report on its status and so on. The WebMite can do this using the SMTP protocol to connect to a
server which will then relay the email to its destination.
The following example uses the free SMTP relay service offered by SMTP2GO which allows for 1000 emails
per month (plenty for the WebMite).
To get started you need to create a free login at SMTP2GO ( https://www.smtp2go.com/ ), register a Verified
Sender and create an associated username and password. Both then need to be converted to Base64 encoded
strings (the following website will do this for you: https://www.base64encode.org ). Note that SMTP2GO
does not accept registration requests from people with a generic free email address (eg, [email protected]).
The Base64 encoded username should be used to replace the nnnnnnnnnn string in the first line of the
following program while the Base64 encoded password should be used to replace the xxxxxxxxxxxx in the
second line. The other four lines at the start of the program should also be replaced with your data:
CONST cr = Chr$(13)+Chr$(10)
DIM buff%(4096/8), body$
Note that the mailfrom$ email address used in the above program MUST be the same as that used when you
registered the Verified Sender with SMTP2GO. If they are not the same SMTP2GO will reject the email (this
is an anti spam precaution).
These days using an SMTP relay service is complicated by variations in the SMTP protocol used by each
vendor and the various protections in place to reduce the amount of spam. This example is specific to the
SMTP protocol as used by SMTP2GO however other services can also be used but the program must be
modified to accommodate their own version of the SMTP protocol.
Base 64 Encoding
Base64 is system for converting binary data to a text string that only uses ASCII characters (ie, there are no
control characters). It’s designed to make it easy to send binary data over the internet using protocols which do
not accept binary data and many protocols require its use.
The following function will convert an MMBasic string containing binary data into a Base 64 encoded string.
End Function
A typical use is in the above program for sending emails. Rather than use an external service to convert the
username and password to Base64 you can do this in the program using this function. For example:
MQTT Client
MQTT is a protocol that allows clients like the WebMite to post or retrieve messages on a server (also called a
MQTT broker). This is rather like a bulletin board or web based forum where people post messages which
others can later read at their leisure – the main difference is that MQTT is designed for machine to machine
communications.
A typical example could be a battery powered WebMite which is monitoring the water level in a dam. Twice a
day it would power up, make the measurement, post the result on a MQTT broker and power down again. A
client program (perhaps on a PC) could later read these messages, display the results and graph them.
There are many free brokers available, use Google to search for "free MQTT broker".
Ping
The WebMite will respond to a ping message so you can check if it is alive and accessible. If it is connected to
the public Internet a free service like https://uptimerobot.com/ can be used to alert you if it has stopped running.
Streaming audio
The WEB OPEN TCP STREAM and WEB TCP CLIENT STREAM commands can together with the PLAY
STREAM command very simply implement a basic internet radio capability. This is demonstrated in the code
below which receives the UK program ClassicFM. NB: a VS1053 audio codec is required for this program.
Option escape
Option default none
' create the request for the radio site (ClassicFM)
Dim a$="ice-the.musicradio.com"
Dim q$="GET "
Inc q$,"/ClassicFMMP3"
Inc q$," HTTP/1.1\r\n"
Inc q$,"Host: "
Inc q$,a$
Inc q$,"\r\nConnection: close\r\n\r\n"
' Configure the VS1053 and tell it to play from the circular buffer
Play stream buff%(), r%, w%
' Send the request to start the stream using the circular buffer specified
WEB TCP CLIENT STREAM q$, buff%(), r%, w%
Constants
Numeric constants may begin with a numeric digit (0-9) for a decimal constant, &H for a hexadecimal
constant, &O for an octal constant or &B for a binary constant. For example &B1000 is the same as the
decimal constant 8. Constants that start with &H, &O or &B are always treated as 64-bit integer constants.
Decimal constants may be preceded with a minus (-) or plus (+) and may be terminated with 'E' followed by an
exponent number to denote exponential notation. For example 1.6E+4 is the same as 16000. If the decimal
constant contains a decimal point or an exponent, it will be treated as a floating point constant; otherwise it will
be treated as a 64-bit integer constant.
String constants are surrounded by double quote marks ("). Eg, "Hello World".
Implementation Characteristics
Maximum program - see table. Note that MMBasic tokenises the program when it is stored in flash so the final
size in flash might vary from the plain text size.
Maximum length of a command line is 255 characters.
Maximum length of a variable name or a label is 31 characters.
Maximum number of dimensions - see table.
Maximum number of arguments to commands that accept a variable number of arguments is 50.
Maximum number of nested FOR…NEXT loops is 20.
Maximum number of nested DO…LOOP commands is 20.
Maximum number of nested GOSUBs is 50.
Maximum number of nested multiline IF…ELSE…ENDIF commands is 20.
Maximum number of user defined labels, subroutines and functions (combined) – see table.
Maximum number of interrupt pins that can be configured: 10
Numbers are stored and manipulated as double precision floating point numbers or 64-bit signed integers. The
range of floating point numbers is 1.797693134862316e+308 to 2.225073858507201e-308.
The range of 64-bit integers (whole numbers) that can be manipulated is ± 9223372036854775807.
Maximum string length is 255 characters.
Maximum line number is 65000.
Maximum number of background pulses launched by the PULSE command is 5.
Maximum number of global variables and constants - see table.
Maximum number of local variables - see table
The maximum number of files that can be listed by the FILES command is 1000.
The maximum length of a filename/path is 63 characters.
Compatibility
MMBasic implements a large subset of Microsoft’s GW-BASIC. There are numerous differences due to
physical and practical considerations but most standard BASIC commands and functions are essentially the
same. An online manual for GW-BASIC is available at http://www.antonis.de/qbebooks/gwbasman/index.html
and this provides a more detailed description of the commands and functions.
MMBasic also implements a number of modern programming structures documented in the ANSI Standard for
Full BASIC (X3.113-1987) or ISO/IEC 10279:1991. These include SUB/END SUB, the DO WHILE …
LOOP, the SELECT…CASE statements and structured IF . THEN … ELSE … ENDIF statements.
MM.VER Returns the version number of the firmware as a floating point number in the
form aa.bbcc where aa is the major version number, bb is the minor version
number and cc is the revision number. For example version 6.03.00 would
return 6.03 and version 6.03.01 will return 6.0301.
MM.CMDLINE$ This constant variable containing any command line arguments passed to the
current program is automatically created when an MMBasic program runs;
see RUN and * commands for details.
• Programs run from the Editor or using OPTION AUTORUN will set
MM.CMDLINE$ to the empty string.
• If not required this constant variable may be removed from memory
using ERASE MM.CMDLINE$
MM.DEVICE$ A string representing the device or platform that MMBasic is running on.
MM.ERRNO If a statement caused an error which was ignored these variables will be set
MM.ERRMSG$ accordingly. MM.ERRNO is a number where non zero means that there was
an error and MM.ERRMSG$ is a string representing the error message that
would have normally been displayed on the console. They are reset to zero
and an empty string by RUN, ON ERROR IGNORE or ON ERROR SKIP.
MM.HRES Integers representing the current horizontal and vertical resolution of the
VGA/HDMI video output or the LCD display panel (if configured) in pixels.
MM.VRES
MM.HEIGHT Returns the number of characters across the physical display with the current
font or the number of characters down the display with the current font
MM.WIDTH
MM.HPOS Returns the current horizontal and vertical position (in pixels) following the
last graphics or print command.
MM.VPOS
MM.INFO(ADC) Returns the number of the buffer currently ready to read when using ADC
RUN (1 or 2). Returns 0 if nothing ready.
MM.INFO(BOOT) Tells you the reason for the last restart of the Pico
Returns:
Restart - the device has been restarted with CPU RESTART or an
OPTION command
S/W Watchdog - the device has been restarted by a software watchdog
timeout
H/W Watchdog - the device has been restarted by a hardware watchdog
timeout
Firmware update - the device has been restarted following a firmware
update
Power On - the device has been powered up
Reset Switch - the device has been restarted using the reset switch
Unknown code &Hn - unknown reason - please report the code and version
RP2040/2350
MM.INFO(BOOT COUNT) Returns the number of times the Pico has been restarted since the flash drive
was last formatted
.
MM.INFO$(CPUSPEED) Returns the CPU speed as a string.
MM.INFO$(LCDPANEL) Returns the name of the configured LCD panel or a blank string.
MM.INFO(LCD320) Returns true if the display is capable of 320x240 operation using the
OPTION LCD320 command
MM.INFO$(SDCARD) Returns the status of the SD Card. Valid returns are:
DISABLED, NOT PRESENT, READY, and UNUSED
MM.INFO$(CURRENT) Returns the name of the current program when loaded from a file or NONE
if called after a NEW, AUTOSAVE, XMODEM or EDIT Command.
MM.INFO$(PATH) Returns the path of the current program or NONE if called after a NEW or
EDIT Command.
MM.INFO(DISK SIZE) Returns the capacity of the Flash Filesystem or SD Card, whichever is the
active drive, in bytes
MM.INFO(EXISTS FILE Returns 1 if the file specified exists, returns -1 if fname$ is a directory,
fname$) otherwise returns 0.
MM.INFO(EXISTS DIR Returns a Boolean indicating whether the directory specified exits.
dirname$)
MM.INFO(FREE SPACE) Returns the free space on the Flash Filesystem or SD Card whichever is the
active drive.
MM.INFO(FILESIZE file$) Returns the size of file$ in bytes or -1 if not found, -2 if a directory.
MM.INFO(FONT ADDRESS Returns the address of the memory location with the address of FONT n .
n)
MM.INFO(FLASH) Reports which flash slot the program was loaded from if applicable.
MM.INFO(FLASH ADDRESS Returns the address of the flash slot n.
n)
MM.INFO(HEAP) Returns the amount of MMbasic Heap memory free. MMBasic heap is used
for strings, arrays and various other temporary and permanent buffers (eg,
audio)
MM.INFO(HPOS) The current horizontal and vertical position (in pixels) following the last
MM.INFO(VPOS) graphics or print command.
MM.INFO$(MODBUFF Returns the address in memory of the buffer used for storing MOD files
ADDRESS)
MM.INFO$(OPTION option) Returns the current value of a range of options that affect how a program
will run. “option” can be one of AUTORUN, AUDIO, BASE, BREAK,
CONSOLE, DEFAULT, EXPLICIT, KEYBOARD, ANGLE, HEIGHT,
WIDTH, FLASH SIZE
MM.INFO$(PIN pinno) Returns the status of I/O pin 'pinno'. Valid returns are:
OFF, DIN, DOUT, AIN, etc
MM.INFO(PINNO GPnn) Returns the physical pin number for a given GP number. GPnn can be an
unquoted string (GP01), a string literal(“GP01”) or a string variable. Ie,
A$=”GP01”: MM.INFO(PINNO A$) .
MM.INFO(PS2) Reports the last raw message received on the PS2 interface if enabled.
MM.INFO(PWM DUTY C%, Returns the current duty cycle in clock counts of PWM channel C%,N%
n%) Where N%=0 for A and 1 for B
MM.INFO$(SOUND) Returns the current activity on the audio output (OFF, PAUSED, TONE,
WAV, FLAC, SOUND)
MM.INFO(SPI SPEED Returns the actual speed of the SYSTEM SPI or an error if not set
MM.INFO(STACK) Returns the C stack pointer. Complex or recursive Basic code may result in
the error "Stack overflow, expression too complex at depth %" This will
occur when the stack is below &H 2003f800. Monitoring the stack will
allow the programmer to identify simplifications to the Basic code to avoid
the error.
MM.INFO(SYSTICK) Returns the current value of the system 24-bit systick timer which runs at the
CPU clock speed
MM.INFO(TRACK) Returns the name of the FLAC, MP3, WAV or MIDI file currently playing
on the audio output.
MM.INFO$(TOUCH) Returns the status of the Touch controller. Valid returns are:
“Disabled”, “Not calibrated”, and “Ready”.
MM.INFO(USB n) Return the device code for any device connected to channel ‘n’ which is a
number from 1 to 4. The returned device code can be:
0=not in use, 1=keyboard, 2=mouse, 128=ps4, 129=ps3, 130=SNES/Generic
By default a connected keyboard will be allocated to channel 1, a mouse the
channel 2, and gamepads to channel 3 and then channel 4. If 2 or more
keyboards or mice are connected or 3 or more gamepads then the additional
devices will be allocated to the highest available channel.
MM.INFO$(LINE) Returns the current line number as a string. LIBRARY returned if in the
Library and UNKNOWN if not in a program. Assists in diagnostics while
unit testing.
MM.INFO(UPTIME) Returns the time in seconds since booted as a floating point number.
WEBMITE ONLY
MM.INFO(TCPIP STATUS) Returns the TCPIP status of the connection
MM.INFO(WIFI STATUS) Returns the WIFI status of the connection.
Valid returns are:
0 WiFi is down
1 Connected to WiFi
2 Connected to WiFi, but no IP address (TCPIP STATUS only)
3 Connected to WiFi with an IP address (TCPIP STATUS only)
-1 Connection failed
-2 No matching SSID found (could be out of range, or down)
-3 Authentication failure
MM.MESSAGE$ WEBMITE ONLY
Returns the contents of the last UDP datagram received or last MQTT packet
received
MM.ONEWIRE Following a 1-Wire reset function this integer variable will be set to indicate
the result of the operation: 0 = Device not found, 1 = Device found,
2=Device timeout.
MM.I2C Following an I2C write or read command this integer variable will be set to
indicate the result of the operation as follows:
0 = The command completed without error.
1 = Received a NACK response
2 = Command timed out
MM.PS2 Returns the last code received on the PS2 interface if enabled.
Permanent?
OPTION ANGLE RADIANS | This command switches trig functions between degrees and radians.
DEGREES Acts on SIN, COS, TAN, ATN, ATAN2, MATH ATAN3, ACOS, ASIN
OPTION AUTOREFRESH Black and white displays can only be updated a full screen at a time. By
OFF | ON using OPTION AUTOREFRESH OFF/ON you can control whether a
write command immediately updates the display or not. If
AUTOREFRESH is OFF the REFRESH command can be used to
trigger the write. This applies to the following displays: N5110,
SSD1306I2C, SSD1306I2C32, SSD1306SPI and ST7920
OPTION AUTORUN ON
[,NORESET]
Instructs MMBasic to automatically run a program on power up or
restart.
OPTION BASE 0 | 1 Set the lowest value for array subscripts to either 0 or 1.
This must be used before any arrays are declared and is reset to the
default of 0 on power up.
OPTION BAUDRATE nn Set the baudrate of the serial console (if it is configured).
OPTION BREAK nn Set the value of the break key to the ASCII value 'nn'. This key is used to
interrupt a running program.
The value of the break key is set to CTRL-C key at power upand when a
program is run but it can be changed to any keyboard key using this
command in a program (for example, OPTION BREAK 4 will set the break
key to the CTRL-D key). Setting this option to zero will disable the break
function entirely.
OPTION COLOURCODE ON
Turn on or off colour coding for the editor's output. Keywords will be in
cyan, comments in yellow, etc. The default is OFF.
or
OPTION COLOURCODE The keyword COLORCODE (USA spelling) can also be used.
OFF This will work on VGA/HDMI video and the serial console using a
terminal emulator with VT100 emulation (eg, Tera Term). This
command must be run at the command prompt (not in a program).
OPTION CONSOLE output Specifies where print statements will output. Valid settings are BOTH (i.e.
SCREEN and SERIAL), SERIAL, SCREEN, NONE. This is a temporary
option that is reset when a program exits.
OPTION CONTINUATION
LINES ON/OFF
Enables or disables the use of continuation lines in the editor and with the
LIST command. Line continuation is indicated by a space followed by an
underscore character at the end of a line. When enabled the editor will
automatically split lines as it reads them from file and add the continuation
characters required. When exiting the editor, the continuation characters
are removed before saving. While in the editor the user can create long
lines by adding their own continuation characters. This makes using a
small screen as a console much easier.
OPTION DEFAULT FLOAT | Used to set the default type for a variable which is not explicitly defined.
INTEGER | STRING | NONE If OPTION DEFAULT NONE is used then all variables must have their
type explicitly defined or the error “Variable type not specified” will
occur.
When a program is run the default is set to FLOAT for compatibility with
Microsoft BASIC and previous versions of MMBasic.
OPTION DEFAULT Set the default foreground and background colours for both the
COLOURS foreground
[,background]
monochrome and colour modes. The colour must be one of the following:
white, yellow, lilac, brown, fuchsia, rust, magenta, red, cyan, green,
cerulean, midgreen, cobalt, myrtle, blue and black. A numeric value
cannot be used. The default is white, black.
If background is omitted it defaults to black.
Set the characteristics of the display terminal used for the console. Both
OPTION DISPLAY lines
[,chars]
the LIST and EDIT commands need to know this information to
correctly format the text for display.
'lines' is the number of lines on the display and 'chars' is the width of the
display in characters. The default is 24 lines x 80 chars and when
changed this option will be remembered even when the power is
removed. Maximum values are 100 lines and 240chars.
This will send an ESC sequence to set the VT100 terminal to the
matching size. TerraTerm, Putty and MMCC respond to this sequence
and set the terminal width (if the option is enabled in the terminal setup).
This option is not available if an LCD display is being used as the
console.
OPTION ESCAPE Enables the ability to insert escape sequences into string constants. See
the section Special Characters in Strings.
OPTION EXPLICIT Placing this command at the start of a program will require that every
variable be explicitly declared using the DIM, LOCAL or STATIC
commands before it can be used in the program.
This option is disabled by default when a program is run. If it is used it
must be specified before any variables are used.
OPTION FAST AUDIO When using the PLAY SOUND command, changes to sounds, volumes,
ON|OFF or frequencies can cause audible clicks in the output. The firmware
attempts to mitigate this by ramping the volume down on the channel’s
previous output before changing the output and ramping it back up
again. This significantly improves the audio output but at the expense of
OPTION HEARTBEAT
ON/OFF [HEARTBEATpin]
Enables or disables the output of the heartbeat LED.
In the case of the Pico-W the heartbeat is on a pin controlled by the
CWY43 chip.
NOT WEBMITE VERSION
By default, for RP2350A chips the heartbeat is enabled on GP25.
If it is disabled the program can control the LED via GP25.
For RP2350B chips the heartbeat is not enabled.
If the heartbeat is disabled then the command can be used both to
enable it and optionally specify the pin to use (default GP25)
OPTION KEYBOARD nn
[,capslock] [,numlock]
Configure a keyboard. This can be used for console input and any
characters typed will be available via any commands that read from the
[,repeatstart] [,repeatrate] console (serial over USB).
or ‘nn is a two character code defining the keyboard layout. The choices are
OPTION KEYBOARD US for the standard keyboard layout in the USA, Australia and New
DISABLE Zealand and UK for the United Kingdom, GR for Germany, FR for
France, BR for Brazil and ES for Spain.
OPTION LCDPANEL Configures a virtual LCD panel without a physically connected panel.
VIRTUAL_C VIRTUAL _C = Colour, 4bit, 320 x 240
or VIRTUAL _M = Monochrome, 640 x 480
OPTION LCDPANEL Using this feature a program can draw graphical images on this virtual
VIRTUAL_M panel and then save them as a BMP file. Useful for creating a graphic
image for export without an attached display
OPTION LCDPANEL options Configures the PicoMite firmware to work with an attached LCD panel.
or See the chapter LCD Displays for the details.
OPTION LCDPANEL DISABLE This command must be run at the command prompt (not in a program).
OPTION LCDPANEL Configures the LCD display panel for use as the console output. The LCD
CONSOLE [font [, fc [, bc [, must support transparent text (i.e. the SSD1963_x, ILI9341 or
blight]]] [,NOSCROLL] ST7789_320 controllers).
or 'font' is the default font, 'fc' is the default foreground colour, 'bc' is the
OPTION LCDPANEL default background colour. These parameters are optional and default to
NOCONSOLE font 1, white, black and 100%. These settings are applied at power up.
The optional NOSCROLL command changes the firmware such that
when outputting to the last line of the display rather than the display
scrolling it is cleared and output continues at the top of the display. This
allows displays that don’t support reading to be used as a console device
and:
Note that for displays other than the SSD1963 scrolling for any console
output is very slow so it is recommended to use the NOSCROLL option
for these displays. This setting is saved in flash and will be automatically
applied on startup. To disable it use the OPTION LCDPANEL
NOCONSOLE command.
This command must be run at the command prompt.
OPTION LEGACY ON This will turn on or off compatibility mode with the graphic commands
or used in the original Colour Maximite. The commands COLOUR, LINE,
CIRCLE and PIXEL use the legacy syntax and all drawing commands
OPTION LEGACY OFF
will accept colours in the range of 0 to 7. Notes:
Keywords such as RED, BLUE, etc are not implemented so they
should be defined as constants if needed.
Refer to the Colour Maximite MMBasic Language Manual for the
syntax of the legacy commands. This can be downloaded from
https://geoffg.net/OriginalColourMaximite.html .
OPTION LIST This will list the settings of any options that have been changed from their
default setting and are the permanent type. OPTION LIST also shows the
version number and which firmware is loaded.
This command must be run at the command prompt (not in a program).
OPTION MILLISECONDS This enables or disables a millisecond output in the TIME$ function.
ON|OFF Ie, HH:MM:SS.mmm
The milliseconds counter is set to zero whenever the time is updated
using the TIME command, WEB NTP command or RTC GETTIME
command. Default is OFF.
OPTION MODBUFF
ENABLE/DISABLE [sizeinK]
Creates or removes an area of flash memory used for loading and
playing .MOD files. If enabled then a mod buffer is created with a size
of 128Kbytes. This can be overridden with “sizeinK”.
Note that this option reserves part of the Flash Filesystem (ie, it shrinks
the Flash Filesystem). The default is disabled.
Note: This option is not required on an RP2350 with PSRAM enabled.
In this case the MOD file will be loaded to space in the PSRAM.
OPTION MOUSE DISABLE Disables the automatic connection to a PS2 mouse and frees up the pins
for normal usage.
OPTION NOCHECK ON/OFF This command, when set ON, disables the standard checking for
interrupts and ctrl-C at the end of every command. Setting it to ON
allows time critical processing to take place without risk of interruption.
However, the command should be used carefully or the program may
only be stopped with a H/W reset.
OPTION PIN nbr Set 'nbr' as the PIN (Personal Identification Number) for access to the
console prompt. 'nbr' can be any non zero number of up to eight digits.
Whenever a running program tries to exit to the command prompt for
whatever reason MMBasic will request this number before the prompt is
presented. This is a security feature as without access to the command
prompt an intruder cannot list or change the program in memory or
modify the operation of MMBasic in any way. To disable this feature
enter zero for the PIN number (i.e. OPTION PIN 0).
A permanent lock can be applied by using 99999999 for the PIN
number. If a permanent lock is applied or the PIN number is lost the
only way to recover is to reload the PicoMite firmware.
This command must be run at the command prompt (not in a program).
OPTION SDCARD
COMBINED CS
If this is specified the touch chip select pin is also used for the SDcard.
In this case external circuitry is needed to implement the SD chip select
as follows.
Specify the I2C port and pins for use by system devices (LCD panel, and
OPTION SYSTEM I2C sdapin,
sclpin [,SLOW/FAST]
RTC).
The PicoMite firmware uses a specific I2C port for system devices,
leaving the other for the programmer. This command specifies which
pins are to be used, and hence which of the I2C ports is to be used.
The pins allocated to the SYSTEM I2C will not be available for other
MMBasic SETPIN settings but can be used for additional I2C devices
using the standard I2C command. Note: I2C(2) OPEN and I2C(2)
CLOSE are not available in this case.
By default the I2C port is opened at a speed of 400KHz and with a
100mSec timeout. The I2C frequency can be set using the optional third
parameter which can take the values FAST = 400KHz or SLOW =
100KHz.
This command must be run at the command prompt (not in a program).
WEBMITE ONLY
OPTION TCP SERVER PORT Launches a TCP server on port 'n' during every restart of the WebMite.
n Typically HTTP servers use port 80.
USE "OPTION TCP SERVER PORT 0" to disable
When the server is running it can respond to up to MM.INFO(MAX
CONNECTIONS)
WEBMITE ONLY
OPTION TELNET CONSOLE Configures the handling the console over Telnet.
OFF|ONLY|ON ON = Console output sent to USB and Telnet
ONLY= Console output sent to Telnet only
OFF = Console output sent to USB only
WEBMITE ONLY
OPTION TFTP OFF|ON Enables or disables the TFTP server. Default is on.
OPTION TOUCH FT6336 Enables touch support for FT6336 capacitive touch chip. Sensitivity is a
IRQpin, RESETpin [,BEEPpin] number between 0 and 255 - defaults to 50, lower is more sensitive.
[,sensitivity] SDA and SCK should be connected to valid I2C pins and set up with
OPTION SYSTEM I2C. See also the TOUCH function.
OPTION VCC voltage Specifies the voltage (Vcc) supplied to the Raspberry Pi Pico.
When using the ADC pins to measure voltage the PicoMite firmware
uses the voltage on the pin marked VREF as its reference. This voltage
can be accurately measured using a DMM and set using this command
for more accurate measurement.
The parameter is not saved and should be initialised either on the
command line or in a program. The default if not set is 3.3.
‘ (single quotation mark) Starts a comment and any text following it will be ignored. Comments can be
placed anywhere on a line.
*file The star/asterisk command is a shortcut for RUN that may only be used at the
MMBasic prompt. eg,
* RUN
*foo RUN "foo"
*"foo bar" RUN "foo bar"
*foo –wombat RUN "foo", "--wombat"
*foo "wom" RUN "foo", CHR$(34) + "wom" + CHR$(34)
*foo --wom="bat" RUN "foo","--wom=" + CHR$(34) + "bat" + CHR$(34)
String expressions are not supported/evaluated by this command; any
arguments provided are passed as a literal string to the RUN command.
/* Start and end of multiline comments. /* and */ must be the first non-space
characters at the start of a line and have a space or end-of-line after them (i.e.
*/
they are MMBasic commands). Multi-line comments cannot be used inside
subroutines and functions. Any characters after */ on a line are also treated as
a comment.
.PROGRAM name Commands for writing in-line PIO assembler programs. In all cases the
.END PROGRAM [list] parameters are unquoted string literals. Variables are not allowed.
.SIDE SET n
.LABEL label
.LINE n or NEXT
.WRAP n
.WRAP TARGET n
JMP params
WAIT params
IN params
OUT params
PUSH params
PULL params
MOV params
NOP params
IRQ SET params
IRQ WAIT params
IRQ CLEAR params
IRQ NOWAIT params
IRQ params
SET params
A: or B: Shortcut for DRIVE “A:” and DRIVE “B:” at the command prompt
ADC OPEN freq, n_channels This allocates up to 4 ADC channels for use and sets them to be converted at
[,interrupt] the specified frequency.
The range of pins are GP26, GP27, GP28, and GP29 for the RP2940 and
RP2350A. Plus GP55, GP56, GP57, GP58 on the RP2350B. If the number of
channels is one then it will always be GP26 used, if two then GP26 and GP27
are used, etc. Sampling of multiple channels is sequential (there is only one
ADC). The pins are locked to the function when ADC OPEN is active
The maximum total frequency is CPUspeed/96 (eg, 520KHz if all four
channels are to be sampled with the CPU set at 200MHz). Note that a
aggregate sampling frequency over 500Khz is overclocking the ADC.
The optional interrupt parameter specifies an interrupt to call when the
conversion completes. If not specified then conversion will be blocking
ADC FREQUENCY freq This changes the sampling frequency of the ADC conversion without having to
close and re-open
ADC CLOSE Releases the pins to normal usage
ADC START array1!() This starts conversion into the specified arrays. The arrays must be floating
[,array2!()] [,array3!()] point and the same size. The size of the arrays defines the number of
[,array4!()] [,C1min] [,C1max] conversions. Start can be called repeatedly once the ADC is OPEN
[,C2min] [,C2max] [,C3min]
‘Cxmin’ and ‘Cxmax’ will scale the readings. For example, C1min=200 and
[,C3max] [,C4min] [,C4max]
C1max=100 will create values ranging from 200 to 100 for equivalent voltages
of 0 - 3.3. If the scaling is not used the results are returned as a voltage
between 0 and OPTION VCC (defaults to 3.3V).
ADC RUN Runs the ADC continuously in double buffered mode. The ADC first fills
array1%(),array2%) array1% and then array2% and then back to array1% etc. If more than one
ADC channel is specified in the ADC OPEN command the data are
interleaved. The data is returned as packed 8-bit values (Use MEMORY
UNPACK to convert to a normal array). MM.INFO(ADC) will return the
number of the buffer currently available for reading (1 or 2).
ARRAY ADD in(), value This adds (or appends for strings) the value 'value' to every element of the
,out() matrix in() and puts the answer in out(). Works for arrays of any
dimensionality of strings and both integer and float (can convert between
integer and float). Setting num to 0 or “” is optimised and is a fast way of
copying an entire array. in() and out() can be the same array.
ARRAY INSERT This is the opposite of ARRAY SLICE, has a very similar syntax, and allows
targetarray(), [d1] [,d2] [,d3] you, for example, to substitute a single vector into an array of vectors with a
[,d4] [,d5] , sourcearray() single instruction or a one dimensional array of strings into a two dimensional
array of strings. The arrays can be numerical or strings and ‘sourcearray’ and
‘destinationarray’ must be the same (NB: can convert between integers and
floats for numerical arrays).
eg,
OPTION BASE 1
DIM targetarray(3,4,5)
DIM sourcearray(4)=(1,2,3,4)
ARRAY INSERT targetarray(), 2, , 3, sourcearray()
Will set elements 2,1,3 = 1 and 2,2,3 = 2 and 2,3,3 = 3 and 2,4,3 = 4
ARRAY SLICE sourcearray(), This command copies a specified set of values from a multi-dimensional array
[d1] [,d2] [,d3] [,d4] [,d5] into a single dimensional array. It is much faster than using a FOR loop. The
destinationarray() slice is specified by giving a value for all but one of the source array indices
and there should be as many indices in the command, including the blank one,
as there are dimensions in the source array. The arrays can be numerical or
strings and ‘sourcearray’ and ‘destinationarray’ must be the same (NB: can
convert between integers and floats for numerical arrays).
eg,
OPTION BASE 1
DIM a(3,4,5)
DIM b(4)
ARRAY SLICE a(), 2, , 3, b()
Will copy the elements 2,1,3 and 2,2,3 and 2,3,3 and 2,4,3 into array b()
ARC x, y, r1, [r2], a1, a2 [, c] Draws an arc of a circle with a given colour and width between two radials
(defined in degrees). Parameters for the ARC command are:
x: X coordinate of centre of arc
y: Y coordinate of centre of arc
r1: inner radius of arc
r2: outer radius of arc - can be omitted if 1 pixel wide
a1: start angle of arc in degrees
a2: end angle of arc in degrees
c: Colour of arc (if omitted it will default to the foreground colour)
Zero degrees is at the 12 o'clock position.
AUTOSAVE Enter automatic program entry mode. This command will take lines of text
or from the console serial input and save them to program memory.
AUTOSAVE CRUNCH This mode is terminated by entering Control-Z or F1 which will then cause the
received data to be transferred into program memory overwriting the previous
or
program. Use F2 to exit and immediately run the program.
AUTOSAVE APPEND
The CRUNCH option instructs MMBasic to remove all comments, blank lines
and unnecessary spaces from the program before saving. This can be used on
large programs to allow them to fit into limited memory. CRUNCH can be
abbreviated to the single letter C.
The APPEND option will leave the existing program intact and append the new
data from the serial input to the end of it.
At any time this command can be aborted by Control-C which will leave
program memory untouched.
This is one way of transferring a BASIC program into the Raspberry Pi Pico.
The program to be transferred can be pasted into a terminal emulator and this
command will capture the text stream and store it into program memory. It can
also be used for entering a small program directly at the console input.
BIT(var%, bitno) = value Sets a specific bit (0-63) in an integer variable. ‘value’ can be 0 or 1.
See also the BIT function
BITBANG Replaced by the command DEVICE. For compatibility BITBANG can still be
used in programs and will be automatically converted to DEVICE
BLIT BLIT is a simple memory operation copying to and from a display or memory
to a display or memory.
Notes:
32 buffers are available ranging from #1 to #32.
When specifying the buffer number the # symbol is optional.
All other arguments are in pixels.
BLIT READ [#]b, x, y, w, h BLIT READ will copy a portion of the display to the memory buffer '#b'. The
source coordinate is 'x' and 'y' and the width of the display area to copy is 'w'
and the height is 'h'. When this command is used the memory buffer is
automatically created and sufficient memory allocated. This buffer can be
freed and the memory recovered with the BLIT CLOSE command.
BLIT WRITE [#]b, x, y BLIT WRITE will copy the memory buffer '#b' to the display. The destination
[,mode] coordinate is 'x' and 'y'.
The optional 'mode' parameter defaults to 0 and specifies how the stored image
data is changed as it is written out. It is the bitwise AND of the following
values:
&B001 = mirrored left to right
&B010 = mirrored top to bottom
&B100 = don't copy transparent pixels
BLIT LOAD[BMP] [#]b, BLIT LOAD will load a blit buffer from a 24-bit bmp image file. x,y define the
fname$ [,x] [,y] [,w] [,h] start position in the image to start loading and w,h specify the width and height
of the area to be loaded. This command will work on most display panels (not
just panels using the ILI9341 controller).
eg,
BLIT LOAD #1,"image1", 50,50,100,100
will load an area of 100 pixels square with the top left had corner at 50,50 from
the image image1.bmp
BLIT CLOSE [#]b BLIT CLOSE will close the memory buffer '#b' to allow it to be used for
another BLIT READ operation and recover the memory used.
NOT VGA OR HDMI VERSIONS
BLIT MERGE colour, x, y, w, Copies an area of the framebuffer defined by the ‘x’ and ‘y’ pixel coordinates
h of the top left and with a width of ‘w’ and height ‘h’ to the LCD display. As
part of the copy it will overlay the LCD display with pixels from the layer
buffer that aren’t set to the ‘colour’ specified. The colour is specified as a
number between 0 and 15 representing:
Black, Blue, Myrtle, Cobalt, Midgreen, Cerulean, green, cyan, red, magenta,
rust, fuschia, brown, lilac, yellow and white
Requires both a framebuffer and a layer buffer to have been created to operate.
Will automatically wait for frame blanking before starting the copy on
ILI9341, ST7789_320 and ILI9488 displays
BLIT COMPRESSED Acts the same as BLIT MEMORY but assumes the data is compressed and
address%, x, y [,col] ignores the top bit in the width and height
BLIT x1, y1, x2, y2, w, h Copy one section of the display screen to another part of the display.
The source coordinate is 'x1' and 'y1'. The destination coordinate is 'x2' and
'y2'. The width of the screen area to copy is 'w' and the height is 'h'.
All arguments are in pixels.
If the output is to an LCD panel it must be either the SSD19863, ILI9341_8,
ILI9341, ILI9488 (if MISO connected), or ST7789_320 controllers.
BOX x, y, w, h [, lw] [,c] Draws a box on the display with the top left hand corner at 'x' and 'y' with a
[,fill] width of 'w' pixels and a height of 'h' pixels.
'lw' is the width of the sides of the box and can be zero. It defaults to 1.
'c' specifies the colour and defaults to the default foreground colour if not
specified. 'fill' is the fill colour. It can be omitted or set to -1 in which case the
box will not be filled.
All parameters can be expressed as arrays and the software will plot the
number of boxes as determined by the dimensions of the smallest array. 'x' and
'y', must both be arrays or be single variables /constants otherwise an error will
be generated. 'w', 'h' , 'lw', 'c', and fill can be either arrays or single
variables/constants.
See the chapter Graphics Commands and Functions for a definition of the
colours and graphics coordinates
CALL usersubname$ This is an efficient way of programmatically calling user defined subroutines
[,usersubparameters,..] (see also the CALL() function). In many cases it can allow you to get rid of
complex SELECT and IF THEN ELSEIF ENDIF clauses and is processed in a
much more efficient way.
The “usersubname$” can be any string or variable or function that resolves to
the name of a normal user subroutine (not an in-built command). The
“usersubparameters” are the same parameters that would be used to call the
subroutine directly. A typical use could be writing any sort of emulator where
one of a large number of subroutines should be called depending on some
variable. It also allows a way of passing a subroutine name to another
subroutine or function as a variable.
CAMERA OPEN XLKpin, This initialises the camera, It outputs a 12MHz clock on XLK (PWM) and
PLKpin, HSpin, VSCpin, checks that it is correctly receiving signals on PLK, VS, and HS. The camera is
RETpin, D0pin set to a resolution of 160x120 (QQVGA) which is the maximum achievable
within the limits of the available memory.
Enable OPTION SYSTEM I2C in the PicoMite firmware and wire SCL and
SDA to the relevant pins (may be labelled SIOC and SIOD on the camera
module). These connections must have a pullup to 3.3V - 2K7 recommended)
Other pins are wired as per the OPEN command. (NB: VS may be labelled
VSYNC, HS may be labelled HREF, PLK may be labelled PCLK, RET may
be labelled RESET and XLK may be XCLK on your module)
D0pin defines the start of a range of 8 contiguous pins (eg,GP0 - GP7).
CAMERA CAPTURE [scale, This captures a picture from the camera (RGB565) and displays it on an LCD
[x , y]] screen. An SPI LCD must be connected and enabled in order for the command
to work. (ILI9341 and ST7789_320 recommended).
Scale defaults to 1 and x,y each to 0
By default a 160x120 image is output on the LCD with the top left at 0,0 on the
LCD. Setting scale to 2 will fill a 320x240 display with the image. Setting the
x and y parameters will offset the top left of the image on the LCD.
Update rate in a continuous loop is 7FPS onto the display at 1:1 scale and 5FPS
scaled to 320x240.
Assuming the display has MISO wired it is then possible to save the image to
disk using the SAVE IMAGE command.
CAMERA CLOSE Closes the camera subsystem and frees up all the pins allocated in the OPEN
command.
CAMERA CHANGE The camera firmware is also able to detect motion in the camera's field of view
image%(),change! [,scale [,x using the command. It does this by operating the camera in YUV mode rather
,y]] than RGB. This has the advantage that the intensity information and colour
information are separated and just one byte is needed for a 256-level greyscale
image which is ideal fer detecting movement.
image% is an array of size 160x120 bytes (DIM image%(160,120/8-1)
On calling the command it holds a packed 8-bit greyscale image.
CAMERA TEST tnum Enables or disables a test signal from the camera. tnum=2 generates colourbars
and tnum=0 sets back to the visual input.
CAMERA REGISTER reg%, Sets the register "reg%" in the camera to the value "data%". When used the
data% command will report to the console the previous value and automatically
confirms that the new value has been set as requested. The colour rendition of
the camera as initialised is reasonable but could probably be improved further
by tuning the various camera registers.
CAT S$, N$ Concatenates the strings by appending N$ to S$. This functionally the same as
S$ = S$ + N$ but operates somewhat faster.
CHAIN fname$ [cmdline$] Allows a program to run another program with the variable space preserved –
the command is recommended to be used in top level program and not from
within a subroutine. If the optional ‘cmdline$ parameter is specified this is
passed to the chained program in MM.CMDLINE$
CHDIR dir$ Change the current working directory on the default drive to ‘dir$’
The special entry “.” represents the parent of the current directory and “.”
represents the current directory. "/" is the root directory.
CIRCLE x, y, r [,lw] [, a] [, Draw a circle centred at 'x' and 'y' with a radius of 'r' on the display output. ‘lw’
c] [, fill] is optional and is the line width (defaults to 1).
'c' is the optional colour and defaults to the current foreground colour if not
specified. The optional 'a' is a floating point number which will define the
aspect ratio. If the aspect is not specified the default is 1.0 which gives a
standard circle. 'fill' is the fill colour and can be omitted or set to -1 in which
case the box will not be filled.
All parameters can be expressed as arrays and the software will plot the
number of circles as determined by the dimensions of the smallest array. 'x',
'y' and 'r' must all be arrays or all be single variables/constants otherwise an
error will be generated. 'lw', 'a', 'c', and fill can be either arrays or single
variables/constants.
See the chapter Graphics Commands and Functions for a definition of the
colours and graphics coordinates.
CLEAR Delete all variables and recover the memory used by them.
See ERASE for deleting specific array variables.
CLOSE [#]fnbr [,[#]fnbr] … Close the file(s) previously opened with the file number ‘#fnbr’. The # is
optional. Also see the OPEN command.
CLS [colour] Clears the LCD panel's screen. Optionally 'colour' can be specified which will
be used for the background colour when clearing the screen.
COLOUR fore [, back] Sets the default colour for commands (PRINT, etc) that display on the on the
or attached LCD panel. 'fore' is the foreground colour, 'back' is the background
COLOR fore [, back] colour. The background is optional and if not specified will default to black.
COLOUR MAP inarray%(), This command generates RGB888 colours in outarray% from colour codes (0-
outarray%() [,colourmap%()] 15) in inarray%. If the optional colourmap% parameter is used this must be 16
elements long). In this case the values in inarray% are mapped to the colours
for that index value in colourmap%
CONFIGURE cfg Configures a board as per the “cfg” specified equivalent of OPTION RESET).
CONFIGURE LIST Lists all the various configurations available for the firmware version.
CONST id = expression Create a constant identifier which cannot be changed once created.
[, id = expression] … etc 'id' is the identifier which follows the same rules as for variables. The
identifier can have a type suffix (!, %, or $) but it is not required. If it is
specified it must match the type of 'expression'. 'expression' is the value of the
identifier and it can be a normal expression (including user defined functions)
which will be evaluated when the constant is created.
A constant defined outside a sub or function is global and can be seen
throughout the program. A constant defined inside a sub or function is local to
that routine and will hide a global constant with the same name.
CONTINUE Resume running a program that has been stopped by an END statement, an
error, or CTRL-C. The program will restart with the next statement following
the previous stopping point.
Note that it is not always possible to resume the program correctly – this
particularly applies to complex programs with graphics, nested loops and/or
nested subroutines and functions.
CONTINUE DO Skip to the end of a DO/LOOP or a FOR/NEXT loop. The loop condition will
or then be tested and if still valid the loop will continue with the next iteration.
CONTINUE FOR
COPY fname1$ TO fname2$ Copy a file from ‘fname1$’ to ‘fname2$’. Both are strings.
A directory path can be used in both 'fname$' and 'fname$'. If the paths differ
the file specified in 'fname$' will be copied to the path specified in 'fname2$'
with the file name as specified. The filenames can include the drive
specification in the case that you are copying to and or from the non-active
drive (see the DRIVE command)
COPY fname$ TO dirname$ Wildcard copy. The bulk copy is triggered if fname$ contains a '*' or a '?'
character. dirname$ must be a valid directory name and should NOT end in a
slash character
CPU SLEEP n Will cause the processors to sleep for ‘n’ seconds. Note that the CPU does not
have a true low power sleep so the power saving is limited.
CSUB name [type [, type] Defines the binary code for an embedded machine code program module
…] written in C or ARM assembler. The module will appear in MMBasic as the
hex [[ hex[…] command 'name' and can be used in the same manner as a built-in command.
hex [[ hex[…] Multiple embedded routines can be used in a program with each defining a
different module with a different 'name'.
END CSUB
The first 'hex' word is a 32 bit word which is the offset in bytes from the start
of the CSUB to the entry point of the embedded routine (usually the function
main()). The following hex words are the compiled binary code for the
module. These are automatically programmed into MMBasic when the
program is saved. Each 'hex' must be exactly eight hex digits representing the
bits in a 32-bit word and be separated by one or more spaces or new lines. The
command must be terminated by a matching END CSUB. Any errors in the
data format will be reported when the program is run.
During execution MMBasic will skip over any CSUB commands so they can
be placed anywhere in the program.
The type of each parameter can be specified in the definition. For example:
CSUB MySub integer, integer, string
This specifies that there will be three parameters, the first two being integers
and the third a string.
Note:
Up to ten arguments can be specified ('arg1', 'arg2', etc).
If a variable or array is specified as an argument the C routine will
receive a pointer to the memory allocated to the variable or array and the
C routine can change this memory to return a value to the caller. In the
case of arrays, they should be passed with empty brackets eg, arg(). In
the CSUB the argument will be supplied as a pointer to the first element
of the array.
Constants and expressions will be passed to the embedded C routine as
pointers to a temporary memory space holding the value.
DEVICE BITSTREAM pinno, This command is used to generate an extremely accurate bit sequence on the
n_transitions, array%() pin specified. The pin must have previously been set up as an output and set to
the required starting level.
Notes:
The array contains the length of each level in the bitstream in
microseconds. The maximum period allowed is 65.5 mSec
The first transition will occur immediately on executing the command.
The last period in the array is ignored other than defining the time before
control returns to the program or command line.
The pin is left in the starting state if the number of transitions is even and
the opposite state if the number of transitions is odd.
DEVICE CAMERA See CAMERA command
DEVICE SERIALTX pinno, Outputs 'ostring$' as a serial data stream on 'pinno'. 'baudrate' can be between
baudrate, ostring$ 110 and 230400 (230400 may need CPU to be overclocked).
Note that the program will halt and interrupts ignored during transmission.
DEVICE SERIALRX pinno, Inputs serial data on ‘pinno’. ‘baudrate’ can be between 110 and 230400
baudrate, istring$, (230400 may need CPU to be overclocked). ‘status%’ returns:
timeout_in_ms, status% [,nbr] -1 = timeout (Note: use LEN(istring$) to see number of chars received)
[,terminators$] 2 = number of characters requested satisfied
3 = terminating character satisfied
‘nbr’ specifies the number of characters to be received before the command
returns. ‘terminators$’ specifies one or more signle characters that can be used
to terminate reception.
The program will halt and interrupts ignored while this command is executing.
DIM [type] decl [,decl].. Declares one or more variables (i.e. makes the variable name and its
where 'decl' is: characteristics known to the interpreter).
var [length] [type] [init] When OPTION EXPLICIT is used (as recommended) the DIM, LOCAL or
STATIC commands are the only way that a variable can be created. If this
'var' is a variable name with
option is not used then using the DIM command is optional and if not used the
optional dimensions
variable will be created automatically when first referenced.
'length' is used to set the
The type of the variable (i.e. string, float or integer) can be specified in one of
maximum size of the string to
three ways:
'n' as in LENGTH n
By using a type suffix (i.e. !, % or $ for float, integer or string). For example:
'type' is one of FLOAT or
INTEGER or STRING (the DIM nbr%, amount!, name$
type can be prefixed by the By using one of the keywords FLOAT, INTEGER or STRING immediately
keyword AS - as in AS after the command DIM and before the variable(s) are listed. The specified
FLOAT) type then applies to all variables listed (i.e. it does not have to be repeated).
'init' is the value to initialise For example:
the variable and consists of: DIM STRING first_name, last_name, city
= <expression> By using the Microsoft convention of using the keyword "AS" and the type
For a simple variable one keyword (i.e. FLOAT, INTEGER or STRING) after each variable. If you use
expression is used, for an array this method the type must be specified for each variable and can be changed
a list of comma separated from variable to variable.
expressions surrounded by For example:
brackets is used. DIM amount AS FLOAT, name AS STRING
Floating point or integer variables will be set to zero when created and strings
will be set to an empty string (i.e. ""). You can initialise the value of the
Examples: variable by using an equals symbol (=) and an expression following the
DIM nbr(50) variable definition. For example:
DIM STRING city = "Perth", house = "Brick"
DIM INTEGER nbr(50)
The initialising value can be an expression (including other variables) and will
DIM name AS STRING
be evaluated when the DIM command is executed. See the chapter Defining
DIM a, b$, nbr(100), strn$(20) and Using Variables for more examples of the syntax.
DIM a(5,5,5), b(1000) As well as declaring simple variables the DIM command will also declare
DIM strn$(200) LENGTH 20 arrayed variables (i.e. an indexed variable with a number of dimensions).
DIM STRING strn(200) Following the variable's name the dimensions are specified by a list of numbers
LENGTH 20 separated by commas and enclosed in brackets. For example:
DIM a = 1234, b = 345 DIM array(10, 20)
DIM STRING strn = "text" Each number specifies the index range in each dimension. Normally the
indexing of each dimension starts at 0 but the OPTION BASE command can
DIM x%(3) = (11, 22, 33, 44)
be used to change this to 1.
The above example specifies a two dimensional array with 11 elements (0 to
10) in the first dimension and 21 (0 to 20) in the second dimension. The total
number of elements is 231 and because each floating point number requires 8
bytes a total of 1848 bytes of memory will be allocated.
Strings will default to allocating 255 bytes (i.e. characters) of memory for each
element and this can quickly use up memory when defining arrays of strings.
In that case the LENGTH keyword can be used to specify the amount of
memory to be allocated to each element and therefore the maximum length of
the string that can be stored. This allocation ('n') can be from 1 to 255
characters.
DO This structure will loop forever; the EXIT DO command can be used to
<statements> terminate the loop or control must be explicitly transferred outside of the loop
LOOP by commands like GOTO or EXIT SUB (if in a subroutine).
DO WHILE expression Loops while ‘expression’ is true (this is equivalent to the older WHILE-WEND
<statements> loop). If, at the start, the expression is false the statements in the loop will not
LOOP be executed, not even once.
DO Loops until the expression following UNTIL is true. Because the test is made
<statements> at the end of the loop the statements inside the loop will be executed at least
LOOP UNTIL expression once, even if the expression is true.
DO Loops until the expression following WHILE is false. Because the test is made
<statements> at the end of the loop the statements inside the loop will be executed at least
LOOP WHILE expression once, even if the expression is false.
DRIVE drive$ Sets the active disk drive as ‘drive$’. ‘drive$’ can be “A:” or “B:” where A is
the flash drive and B is the SD Card if configured
END [noend] End the running program and return to the command prompt. If a subroutine
or named MM.END exists in the program it will be executed whenever the
program ends with an actual or implied END command. It is not executed if
END cmd$
the program ends with the break character (ie, Ctrl-C).
The optional parameter ‘noend’ can be used to block execution of the
MM.END subroutine eg, “END noend”
if 'cmd$' is specified then it will be executed as though at the command prompt
after the program finishes. Note: if "END cmd$" is used but a subroutine
MM.END exists it will be executed and cmd$ ignored.
END CSUB Marks the end of a C subroutine. See the CSUB command.
Each CSUB must have one and only one matching END CSUB statement.
END FUNCTION Marks the end of a user defined function. See the FUNCTION command.
Each function must have one and only one matching END FUNCTION
statement. Use EXIT FUNCTION if you need to return from a function from
within its body.
END SUB Marks the end of a user defined subroutine. See the SUB command.
Each sub must have one and only one matching END SUB statement. Use
EXIT SUB if you need to return from a subroutine from within its body.
ERASE variable [,variable].. Deletes global variables and frees up the memory allocated to them. This will
work with arrayed variables and normal (non array) variables. Arrays can be
specified using empty brackets (eg, dat()) or just by specifying the variable's
name (eg, dat).
Use CLEAR to delete all variables at the same time (including arrays).
EXECUTE command$ This executes the Basic command "command$". Use should be limited to basic
commands that execute sequentially for example the GOTO statement will not
work properly
Things that are tested and work OK include GOSUB, Subroutine calls, other
simple statements (like PRINT and simple assignments)
Multiple statements separated by : are not allowed and will error
The command sets an internal watchdog before executing the requested
command and if control does not return to the command, like in a GOTO
statement, the timer will expire. In this case you will get the message
"Command timeout".
RUN is a special case and will cancel the timer allowing you to use the
command to chain programs if required.
FILES [fspec$] [,sort] Lists files in any directories on the default Flash Filesystem or SD Card.
'fspec$' (if specified) can contain a path and search wildcards in the
filename. Question marks (?) will match any character and an asterisk (*) will
match any number of characters. If omitted, all files will be listed.
For example:
* Find all entries
*.TXT Find all entries with an extension of TXT
E*.* Find all entries starting with E
X?X.* Find all three letter file names starting and ending with X
mydir/* Find all entries in directory mydir
NB: putting wildcards in the pathname will result in an error
'sort' specifies the sort order as follows:
size by ascending size
time by descending time/date
name by file name (default if not specified)
type by file extension
FLAG(n%)=value Sets a bit in a system flag register. N% can be between 0 and 63 (i.e. 64 flag
bits are available). Value can be 0 or 1.
See also the FLAGS command and FLAG function and MM.FLAGS
FLAGS=value% Sets all bits in the system flag register to the value specified.
See also the FLAG command and the FLAGS function and MM.FLAGS
FLASH Manages the storage of programs in the flash memory. Up to three programs
can be stored in the flash memory and retrieved as required. Note that these
saved programs will be erased with a firmware upgrade.
One of these flash memory locations can be automatically loaded and run when
power is applied using the OPTION AUTORUN n command. In the following
‘n’ is a number 1 to 3.
FLASH LIST Displays a list of all flash locations including the first line of the program.
FLASH SAVE n Save the current program to the flash location specified.
FLASH LOAD n Load a program from the specified flash location into program memory.
FLASH RUN n Runs the program in flash location n, clear all variables. Does not change the
program memory.
FLASH CHAIN n Runs the program in flash location n, leaving all variables intact (allows for a
program that is much bigger than the program memory). Does not change the
program memory. NB: if the chained program uses the READ command it
must call RESTORE before the first read.
FLASH OVERWRITE n Erase a flash program location and then save the current program to the flash
location specified.
FLASH DISK LOAD n, Loads the contents of file fname$ into flash slot n as a binary image. The file
fname$ [,O[VERWRITE]] can be created using LIBRARY DISK SAVE. Also, any file created externally
with data required by a program can be loaded and accessed using commands
like PEEK and MEMORY COPY using the address of the flash slot.
If the optional parameter OVERWRITE (or O) is specified the content of the
flash slot will be overwritten without an error being raised.
FLUSH [#]fnbr Causes any buffered writes to a file previously opened with the file number
‘#fnbr’ to be written to disk. The # is optional. Using this command ensures
that no data is lost if there is a power cut after a write command.
FONT [#]font-number, scaling This will set the default font for displaying text on an LCD panel or the video
output.
Fonts are specified as a number. For example, #2 (the # is optional). See the
chapter Graphics Commands and Functions for details of the available fonts.
'scaling' can range from 1 to 15 and will multiply the size of the pixels making
the displayed character correspondingly wider and higher. Eg, a scale of 2 will
double the height and width.
FOR counter = start TO finish Initiates a FOR-NEXT loop with the 'counter' initially set to 'start' and
[STEP increment] incrementing in 'increment' steps (default is 1) until 'counter' is greater than
'finish'.
The ‘increment’ can be an integer or a floating point number. Note that using a
floating point fractional number for 'increment' can accumulate rounding errors
in 'counter' which could cause the loop to terminate early or late.
'increment' can be negative in which case 'finish' should be less than 'start' and
the loop will count downwards.
See also the NEXT command.
FRAMEBUFFER LAYER Creates a framebuffer “L” with a RGB121 colour space and resolution to
match the configured SPI colour display
FRAMEBUFFER CLOSE Closes a framebuffer and releases the memory. The optional parameter
[which] "which" can be F or L. If omitted closes both.
FRAMEBUFFER COPY Does a highly optimised full screen copy of one framebuffer to another.
from, to [,b] "from" and "to" can be N, F, or L where N is the physical display.
You can only copy from N on displays that support BLIT and transparent text.
The firmware will automatically compress or expand the RGB resolution when
copying to and from unmatched framebuffers.
Of course copying from RGB565 to RGB121 loses information but for many
applications (eg, games) 16 colour levels is more than enough.
When copying to an LCD display the optional parameter “b” can be used
(FRAMEBUFFER COPY F/L, N, B). This instructs the firmware to action the
copy using the second CPU in the Raspberry Pi Pico and control returns
immediately to the Basic program
FRAMEBUFFER WAIT Pauses processing until the LCD display enters frame blanking. Implemented
for ILI9341, ST7789_320 and ILI9488 displays. Used to reduce artefacts when
writing to the screen
FRAMEBUFFER MERGE Copies the contents of the Layer buffer and Framebuffer onto the LCD display
[colour] [,mode] [,updaterate] omitting all pixels of a particular colour. Preconditions for the command
are that FRAMEBUFFER and LAYERBUFFER are both created
FRAMEBUFFER MERGE - writes the contents of the framebuffer to the
physical display overwriting any pixels in the framebuffer that are set in the
layerbuffer (not zero)
FRAMEBUFER MERGE col - writes the contents of the framebuffer to the
physical display overwriting any pixels in the framebuffer that are in the
layerbuffer not set to the transparent colour "col". The colour is specified as a
number between 0 and 15 representing:
0:BLACK,1:BLUE,2:MYRTLE,3:COBALT,4:MIDGREEN,5:CERULEAN,6:
GREEN,7:CYAN,8:RED,9:MAGENTA,10:RUST,11:FUCHSIA,12:BROWN,
13:LILAC,14:YELLOW,15:WHITE
FRAMEBUFFER MERGE col,B - as above except that the transfer to the
physical display takes place on the second CPU and control returns to Basic
immediately
FRAMEBUFFER MERGE col,R [,updaterate] - sets the second CPU to
continuously update the physical display with the merger of the two buffers.
Automatically sets FRAMEBUFFER WRITE F if not F or L already set. By
default the screen will update as fast as possible (At 200MHz an ILI9341 in
SPI mode updates about 13 times a second, in 8-bit parallel mode the ILI9341
achieves 27 FPS)
If "updaterate" is set then the screen will update to the rate specified in
milliseconds (unless that is less than the fastest achievable on the display)
NB: FRAMEBUFFER WRITE cannot be set to N while continuous merged
update is active.
Waits for the latest update on the second CPU to complete to allow drawing
without tearing
FRAMEBUFFER CREATE Creates a framebuffer “F” with a colour space and resolution to match the
current display mode
FRAMEBUFFER CREATE 2 RP2350 only: Creates a second framebuffer “2” with a colour space and
resolution to match the current display mode
FRAMEBUFFER LAYER Creates a layer buffer “L” with a colour space and resolution to match the
[colour] current display mode. The optional parameter colour is specified as a number
0-15 (modes 2 and 3), RGB888 colour (mode 4) or 0-255 (mode 5) and
specifies a colour which is ignored when the layer is applied to the display. In
display modes where automatic layer application is not supported a layer buffer
acts as another framebuffer.
FRAMEBUFFER LAYER RP2350 only: Creates a second layer buffer “T” with a colour space and
TOP [colour] resolution to match the current display mode. The optional parameter colour is
specified as a number 0-15 (modes 2 and 3), 0-255 (mode 5) and specifies a
colour which is ignored when the layer is applied to the display. In display
modes where automatic 2nd layer application is not supported acts as another
framebuffer.
FRAMEBUFFER CLOSE Closes a framebuffer and releases the memory. The optional parameter
[which] "which" can be F, 2, T or L. If omitted closes all.
FRAMEBUFFER COPY Does a highly optimised full screen copy of one framebuffer to another.
from, to [,b] "from" and "to" can be N, F, 2, T, or L where N is the physical display.
If the optional parameter ‘b’ is specified pauses processing until the Monitor
enters frame blanking.
FRAMEBUFFER WAIT Pauses processing until the next frame blanking starts
FUNCTION xxx (arg1 Defines a callable function. This is the same as adding a new function to
[,arg2, …]) [AS <type>} MMBasic while it is running your program.
<statements> 'xxx' is the function name and it must meet the specifications for naming a
<statements> variable. The type of the function can be specified by using a type suffix (i.e.
xxx = <return value> xxx$) or by specifying the type using AS <type> at the end of the functions
END FUNCTION definition. For example:
FUNCTION xxx (arg1, arg2) AS STRING
'arg1', 'arg2', etc are the arguments or parameters to the function (the brackets
are always required, even if there are no arguments). An array is specified by
GAMEPAD COLOUR Changes the colour of the display panel on a PS4 controller on USB channel
channel, colour ‘channel’. ‘colour’ is set as a standard RGB888 value e.g. RGB(RED)
GAMEPAD HAPTIC channel Causes the left and right vibration motors to operate on a PS4 controller on
left, right USB channel ‘channel’. ’left’ and ‘right’ must be a number between 0 (off)
and 255 (maximum).
GAMEPAD INTERRUPT Enables interrupts on the button presses on a USB game controller. The
ENABLE channel, int [,mask] optional parameter ‘mask’ defines which of the switches will trigger the
interrupt (defaults to all). ‘mask’ is a bitmap corresponding to the output of the
DEVICE(GAMEPAD channel,B) function.
GAMEPAD INTERRUPT Disables interrupts from the gamepad on the channel specified
DISABLE channel
GAMEPAD MONITOR Use GAMEPAD MONITOR before plugging in a gamepad and when plugged
in it will show the before and after report with each change of buttons
GAMEPAD CONFIGURE Use to configure a gamepad that isn’t supported by the firmware. Run the
vid,pid,i0,c0,i1,c1,i2,c2,i3,c3,i command before plugging in the gamepad. All 34 parameters are mandatory.
4,c4,i5,c5,i6,c6,i7,c7,i8,c8,i9,c In each case the i/c parameters define the index into the report and the bit
GOTO target Branches program execution to the target, which can be a line number or a
label.
GUI BITMAP x, y, bits [, Displays the bits in a bitmap on a VGA/HDMI monitor or LCD panel starting
width] [, height] [, scale] [, at 'x' and 'y' on an attached device.
c] [, bc] 'height' and 'width' are the dimensions of the bitmap as displayed on the device
and default to 8x8.
'scale' is optional and defaults to that set by the FONT command.
'c' is the drawing colour and 'bc' is the background colour. They are optional
and default to the current foreground and background colours.
The bitmap can be an integer or a string variable or constant and is drawn using
the first byte as the first bits of the top line (bit 7 first, then bit 6, etc) followed
by the next byte, etc. When the top line has been filled the next line of the
displayed bitmap will start with the next bit in the integer or string.
See the chapter Graphics Commands and Functions for a definition of the
colours and graphics coordinates.
HELP searchtext The help command looks for a file “help.txt” on the A: drive. This can be a
user written or community developed file and must be in a particular format.
For each help entry the first line must be a search string prefixed with a ~
character. This is used for the help functionality to find an entry and is not
displayed. The ‘searchtext’ can contain ? for single character substitution or *
for multiple character (or none) substitution.
Following, the search string the next line would typically give the syntax of a
particular command of function. Any subsequent lines would be further
explanation.
HUMID pin, tvar, hvar Returns the temperature and humidity using the DHT22 sensor. Alternative
[,DHT11] versions of the DHT22 are the AM2303 or the RHT03 (all are compatible).
'pin' is the I/O pin connected to the sensor. Any I/O pin may be used.
'tvar' is the variable that will hold the measured temperature and 'hvar' is the
same for humidity. Both must be present and both must be floating point
variables.
For example: HUMID 3, TEMP!, HUMIDITY!
Temperature is measured in ºC and the humidity is percent relative humidity.
Both will be measured with a resolution of 0.1. If an error occurs (sensor not
connected or corrupt signal) both values will be 1000.0.
Normally the DHT22 should powered by 3.3V to keep its output below 3.6V
for the Raspberry Pi Pico (the Pico 2 does not have this issue) and the signal
pin of should be pulled up by a 1K to 10K resistor (4.7K recommended) to
3.3V.
The optional DHT11 parameter modifies the timings to work with the DHT11.
Set to 1 for DHT11 and 0 or omit for DHT22.
I2C OPEN speed, timeout Enables the first I2C module in master mode. ‘speed’ is the clock speed (in
KHz) to use and must be one of 100, 400 or 1000.
‘timeout’ is a value in milliseconds after which the master send and receive
commands will be interrupted if they have not completed. The minimum value
is 100. A value of zero will disable the timeout (though this is not
recommended).
I2C WRITE addr, option, Send data to the I2C slave device. ‘addr’ is the slave’s I2C address.
sendlen, senddata [,sendata ..] ‘option’ can be 0 for normal operation or 1 to keep control of the bus after the
command (a stop condition will not be sent at the completion of the command)
‘sendlen’ is the number of bytes to send. ‘senddata’ is the data to be sent - this
can be specified in various ways (all values sent will be between 0 and 255).
Notes:
The data can be supplied as individual bytes on the command line.
Example: I2C WRITE &H6F, 0, 3, &H23, &H43, &H25
The data can be in a one dimensional array specified with empty brackets
(i.e. no dimensions). ‘sendlen’ bytes of the array will be sent starting with
the first element.
Example: I2C WRITE &H6F, 0, 3, ARRAY()
The data can be a string variable (not a constant).
Example: I2C WRITE &H6F, 0, 3, STRING$
I2C CHECK addr Will set the read only variable MM.I2C to 0 if a device responds at the address
‘addr’. MM.I2C will be set to 1 if there is no response.
I2C CLOSE Disables the master I2C module. This command will also send a stop if the bus
is still held.
I2C2 The same set of commands as for I2C (above) but applying to the second I2C
channel.
IF expr THEN stmt [: stmt] Evaluates the expression ‘expr' and performs the statement following the
or THEN keyword if it is true or skips to the next line if false. If there are more
statements on the line (separated by colons (:) they will also be executed if true
IF expr THEN stmt ELSE stmt
or skipped if false. The ELSE keyword is optional and if present the
statement(s) following it will be executed if 'expr' resolved to be false.
The ‘THEN statement’ construct can be also replaced with:
GOTO linenumber | label’.
This type of IF statement is all on one line.
IF expression THEN Multiline IF statement with optional ELSE and ELSEIF cases and ending with
<statements> ENDIF. Each component is on a separate line.
[ELSEIF expression THEN Evaluates 'expression' and performs the statement(s) following THEN if the
<statements>] expression is true or optionally the statement(s) following the ELSE statement
[ELSE if false. The ELSEIF statement (if present) is executed if the previous
<statements>] condition is false and it starts a new IF chain with further ELSE and/or ELSEIF
ENDIF statements as required. One ENDIF is used to terminate the multiline IF.
INC var [,increment] Increments the variable “var” by either 1 or, if specified, the value in
increment. “increment” can be negative which will decrement.
This is functionally the same as var = var + increment but is processed
much faster
INPUT ["prompt$";] var1 Will take a list of values separated by commas (,) entered at the console and
[,var2 [, var3 [, etc]]] will assign them to a sequential list of variables.
For example, if the command is: INPUT a, b, c
And the following is typed on the keyboard: 23, 87, 66
Then a = 23 and b = 87 and c = 66
The list of variables can be a mix of float, integer or string variables. The
values entered at the console must correspond to the type of variable.
If a single value is entered a comma is not required (however that value cannot
contain a comma).
INPUT #nbr, Same as above except that the input is read from a serial port or file previously
list of variables opened for INPUT as ‘nbr’. See the OPEN command.
INTERRUPT [myint] This command triggers a software interrupt. The interrupt is set up using
INTERRUPT ‘myint’ where ‘myint’ is the name of a subroutine that will be
executed when the interrupt is triggered.
Use INTERRUPT 0 to disable the interrupt
Use INTERRUPT without parameters to trigger the interrupt.
Note: the interrupt can also be triggered from within a CSUB
IR dev, key , int Decodes NEC or Sony infrared remote control signals.
or An IR Receiver Module is required to sense the IR light and demodulate the
IR CLOSE signal. It can be connected to any pin however this pin must be configured in
advanced using the command: SETPIN n, IR
The IR signal decode is done in the background and the program will continue
after this command without interruption. 'dev' and 'key' should be numeric
variables and their values will be updated whenever a new signal is received
('dev' is the device code transmitted by the remote and 'key' is the key pressed).
'int' is a user defined subroutine that will be called when a new key press is
received or when the existing key is held down for auto repeat. In the interrupt
subroutine the program can examine the variables 'dev' and 'key' and take
appropriate action.
The IR CLOSE command will terminate the IR decoder.
Note that for the NEC protocol the bits in 'dev' and 'key' are reversed. For
example, in 'key' bit 0 should be bit 7, bit 1 should be bit 6, etc. This does not
affect normal use but if you are looking for a specific numerical code provided
by a manufacturer you should reverse the bits. This describes how to do it:
http://www.thebackshed.com/forum/forum_posts.asp?TID=8367
See the chapter Special Hardware Devices for more details.
IR SEND pin, dev, key Generate a 12-bit Sony Remote Control protocol infrared signal.
'pin' is the I/O pin to use. This can be any I/O pin which will be automatically
configured as an output and should be connected to an infrared LED. Idle is
low with high levels indicating when the LED should be turned on.
'dev' is the device being controlled and is a number from 0 to 31, 'key' is the
simulated key press and is a number from 0 to 127.
The IR signal is modulated at about 38KHz and sending the signal takes about
25mS during which program execution is paused.
KEYPAD var, int, r1, r2, r3, Monitor and decode key presses on a 4x3 or 4x4 keypad.
r4, c1, c2, c3 [, c4] Monitoring of the keypad is done in the background and the program will
or continue after this command without interruption. 'var' should be a numeric
KEYPAD CLOSE variable and its value will be updated whenever a key press is detected.
'int' is a user defined subroutine that will be called when a new key press is
received. In the interrupt subroutine the program can examine the variable 'var'
and take appropriate action.
r1, r2, r3 and r4 are pin numbers used for the four row connections to the
keypad and c1, c2, c3 and c4 are the column connections. c4 is optional and is
KILL file$ [,all] Deletes the file specified by ‘file$’. Any extension must be specified.
Bulk erase is triggered if fname$ contains a '*' or a '?' character. If the optional
'all' parameter is used then you will be prompted for a single confirmation. If
'all' is not specified you will be prompted on each file.
LCD INIT d4, d5, d6, d7, rs, Display text on an LCD character display module. This command will work
en with most 1-line, 2-line or 4-line LCD modules that use the KS0066, HD44780
or or SPLC780 controller (however this is not guaranteed).
LCD line, pos, text$
The LCD INIT command is used to initialise the LCD module for use. 'd4' to
or
'd7' are the I/O pins that connect to inputs D4 to D7 on the LCD module (inputs
LCD CLEAR
D0 to D3 should be connected to ground). 'rs' is the pin connected to the
or
register select input on the module (sometimes called CMD). 'en' is the pin
LCD CLOSE connected to the enable or chip select input on the module. The R/W input on
the module should always be grounded. The above I/O pins are automatically
set to outputs by this command.
When the module has been initialised data can be written to it using the LCD
command. 'line' is the line on the display (1 to 4) and 'pos' is the character
location on the line (the first location is 1). 'text$' is a string containing the text
to write to the LCD display.
'pos' can also be C8, C16, C20 or C40 in which case the line will be cleared
and the text centred on a 8 or 16, 20 or 40 line display. For example:
LCD 1, C16, "Hello"
LCD CLEAR will erase all data displayed on the LCD and LCD CLOSE will
terminate the LCD function and return all I/O pins to the not configured state.
See the chapter Special Hardware Devices for more details.
LCD CMD d1 [, d2 [, etc]] These commands will send one or more bytes to an LCD display as either a
or command (LCD CMD) or as data (LCD DATA). Each byte is a number
between 0 and 255 and must be separated by commas. The LCD must have
LCD DATA d1 [, d2 [, etc]]
been previously initialised using the LCD INIT command (see above).
These commands can be used to drive a non standard LCD in "raw mode" or
they can be used to enable specialised features such as scrolling, cursors and
custom character sets. You will need to refer to the data sheet for your LCD to
find the necessary command and data values.
LET variable = expression Assigns the value of 'expression' to the variable. LET is automatically assumed
if a statement does not start with a command. For example:
Var = 56
LIBRARY SAVE The library is a special segment of program memory that can contain program
code such as subroutines, functions and CFunctions. These routines are not
or visible to the programmer but are available to the running program and act the
LIBRARY DELETE same as the built in commands and functions in MMBasic.
Any code in the library that is not contained within a subroutine or function
or will be executed immediately before a program is run. This can be used to
initialise constants, set options, etc. See the heading The Library in this manual
LIBRARY LIST for a full explanation.
LINE x1, y1, x2, y2 [, LW [, On an attached LCD display this command will draw a line starting at the
C]] coordinates ‘x1’ and ‘y1’ and ending at ‘x2’ and ‘y2’.
‘LW’ is the line’s width and is only valid for horizontal or vertical lines. It
defaults to 1 if not specified. ‘C’ is an integer representing the colour and
defaults to the current foreground colour.
All parameters can be expressed as arrays and the software will plot the
number of lines as determined by the dimensions of the smallest array. 'x1',
'y1', 'x2', and 'y2' must all be arrays or all be single variables /constants
otherwise an error will be generated. 'lw' and 'c' can be either arrays or single
variables/constants.
For horizontal and vertical lines that have a defined width and the x1 and y1
coordinate define the top-left pixel of the thick line. i.e. the line is to the right
of the specified position or below it on the screen. For diagonal lines width a
width > 1 the line is centered on the origin and destination pixels. If width is
given as a -ve value then lines in all directions are centered on the given
coordinates.
LINE AA x1, y1, x2, y2 [, Draws a line with anti-aliasing . The parameters are as per the LINE command
LW [, C]] above. However this version will use variable intensity values of the specified
colour to reduce the “staggered” quality of diagonal lines. In addition this
version can draw diagonal lines of any width. Note that it does not accept
arrays as parameters.
LINE GRAPH x(), y(), colour This command generates a line graph of the coordinate pairs specified in “x()”
and “y()”. The graph will have n-1 segments where there are n elements in the
x and y arrays.
LINE INPUT [prompt$,] Reads an entire line from the console input into ‘string-variable$’.
string-variable$ ‘prompt$’ is a string constant (not a variable or expression) and if specified it
will be printed first. A question mark is not printed unless it is part of
‘prompt$’. Unlike INPUT, this command will read a whole line, not stopping
for comma delimited data items.
LINE INPUT #nbr, Same as above except that the input is read from a serial communications port
string-variable$ or a file previously opened for INPUT as ‘nbr’. See the OPEN command.
LIST PINS Lists the current status of all pins on the processor
LIST SYSTEM I2C Lists a map of all I2C devices connected to the system I2C bus
LIST VARIABLES [s%()] Lists all global variables and contants and, if invoked in a subroutine, the variable
used by that subroutine and any subroutines that called it. If the optional parameter
s$() is used the variables will be listed to s%() treated as a longstring (see
LONGSTRING command).
LOAD file$ [,R] Loads a program called ‘file$’ from the Flash Filesystem or SD Card into program
memory.
If the optional suffix ,R is added the program will be immediately run without
prompting (in this case ‘file$’ must be a string constant). The RUN command
does the same thing and allows a string variable to be used.
If an extension is not specified “.BAS” will be added to the file name.
LOAD CONTEXT [KEEP] Restores the variable space to the previously saved state and optionally
preserves the stored variables to allow a second LOAD if required.
See also SAVE CONTEXT
LOAD IMAGE file$ [, x] [, y] Load a bitmapped image (BMP) from the Flash Filesystem or SD Card and
display it on the display.
''file$' is the name of the file and 'x' and 'y' are the screen coordinates for the
top left hand corner of the image. If the coordinates are not specified the image
will be drawn at the top left hand position on the screen.
If an extension is not specified “.BMP” will be added to the file name.
All types of the BMP format are supported including black and white and true
colour 24-bit images.
LOCAL variable [, variables] Defines a list of variable names as local to the subroutine or function. This
See DIM for the full syntax. command uses exactly the same syntax as DIM and will create variables that
will only be visible within the subroutine or function. They will be
automatically discarded when the subroutine or function exits.
LONGSTRING The LONGSTRING commands allow for the manipulation of strings longer
than the normal MMBasic limit of 255 characters.
Variables for holding long strings must be defined as single dimensioned
integer arrays with the number of elements set to the number of characters
required for the maximum string length divided by eight. The reason for
dividing by eight is that each integer in an MMBasic array occupies eight
bytes. Note that the long string routines do not check for overflow in the
length of the strings. If an attempt is made to create a string longer than a long
string variable's size the outcome will be undefined.
LONGSTRING AES128 Encrypts or decrypts the longstring in in%() putting the answer in out%()
ENCRYPT/DECRYPT For CBC and CTR modes the encryption will generate a random initialisation
CBC/ECB/CTR vector and prepend out%() with the IV. If an explicit IV is specified this will be
key$/key[!/%](), in%(), out%() used instead of the random vector and this will be prepended to out%()
[,iv$/iv[!/%]()]
For CBC and CTR decryption the firmware assumes that the first 16 bytes of
in%() are the initialisation vector.
In the case where you want to transmit a message without IV you can use
LONGSTRING RIGHT to remove the IV before sending the message. In this
case the recipient must know the IV as well as the key and create a complete
longstring before using DECRYPT. This can be done by using LONGSTRING
CONCAT to add the incoming message to a longstring containing the IV.
LONGSTRING APPEND Append a normal MMBasic string to a long string variable. ‘array%()’ is a long
array%(), string$ string variable while ‘string$’ is a normal MMBasic string expression.
LONGSTRING BASE64 This BASE64 encodes or decodes the longstring in in%() placing the answer in
ENCODE/DECODE in%(), out%(). The array used as the output must be big enough relative to the input
out%() and the direction. Encoding increases length by 4/3 and decoding decreases it
by 3/4
LONGSTRING CLEAR Will clear the long string variable ‘array%()’. i.e. it will be set to an empty
array%() string.
LONGSTRING CONCAT Concatenate one long string to another. ‘dest%()’ is the destination variable
dest%(), src%() and ‘src%()’ is the source variable. ‘src%()’ will the added to the end of
‘dest%()’ (the destination will not be overwritten).
LONGSTRING LCASE Will convert any uppercase characters in ‘array%()’ to lowercase. ‘array%()’
array%() must be long string variable.
LONGSTRING LEFT Will copy the left hand 'nbr' characters from ‘src%()’ to ‘dest%()’ overwriting
dest%(), src%(), nbr whatever was in ‘dest%()’. i.e. copy from the beginning of ‘src%()’. ‘src%()’
and ‘dest%()’ must be long string variables. 'nbr' must be an integer constant or
expression.
LONGSTRING LOAD Will copy 'nbr' characters from ‘string$’ to the long string variable ‘array%()’
array%(), nbr, string$ overwriting whatever was in ‘array%()’.
LONGSTRING MID dest%(), Will copy 'nbr' characters from ‘src%()’ to ‘dest%()’ starting at character
src%(), start, nbr position 'start' overwriting whatever was in ‘dest%()’. i.e. copy from the
middle of ‘src%()’. 'nbr' is optional and if omitted the characters from 'start' to
the end of the string will be copied ‘src%()’ and ‘dest%()’ must be long string
variables. 'start' and 'nbr' must be integer constants or expressions.
LONGSTRING PRINT [#n,] Prints the longstring stored in ‘src%()’ to the file or COM port opened as ‘#n’.
src%() [;] If ‘#n’ is not specified the output will be sent to the console. Add a semi-colon
to supress CR/LF.
LONGSTRING REPLACE Will substitute characters in the normal MMBasic string ‘string$’ into an
array%() , string$, start existing long string ‘array%()’ starting at position ‘start’ in the long string.
LONGSTRING RESIZE Sets the size of the longstring to ‘nbr’. This overrides the size set by other
addr%(), nbr longstring commands so should be used with caution. Typical use would be in
using a longstring as a byte array.
LONGSTRING RIGHT Will copy the right hand 'nbr' characters from ‘src%()’ to ‘dest%()’ overwriting
dest%(), src%(), nbr whatever was in ‘dest%()’. i.e. copy from the end of ‘src%()’. ‘src%()’ and
‘dest%()’ must be long string variables. 'nbr' must be an integer constant or
expression.
LONGSTRING SETBYTE Sets byte ‘nbr’ to the value “data”, ‘nbr’ respects OPTION BASE
addr%(), nbr, data
LONGSTRING TRIM Will trim ‘nbr’ characters from the left of a long string. ‘array%()’ must be a
array%(), nbr long string variables. 'nbr' must be an integer constant or expression.
LONGSTRING UCASE Will convert any lowercase characters in ‘array%()’ to uppercase. ‘array%()’
array%() must be long string variable.
MAP( n ) = rgb% This will assign the 24-bit colour 'rgb% to all pixels with the 4 or 8-bit colour
value of 'n'. The change is activated after the MAP SET command.
MAP GREYSCALE This will set the colour map to 16 or 32 levels of grey (depending on the
MODE). MAP GRAYSCALE is also valid.
MAP SET This will cause MMBasic to update the colour map (set using MAP(n)=rgb%)
during the next frame blanking interval.
MAP RESET This will reset the colour map to the default colours
MAP( n ) = rgb% This will assign the 24-bit colour 'rgb% to all pixels with the 4-bit colour value
of 'n'. The RGB value is converted to one of the available 16 VGA RGB121
colours as set by the resistor network. The change is activated after the MAP
SET command.
MAP MAXIMITE This will set the colour map to the colours implemented in the original Colour
Maximite.
MAP SET This will cause MMBasic to update the colour map (set using MAP(n)=rgb%)
during the next frame blanking interval.
MAP RESET This will reset the colour map to the default colours which in 4-bit mode are:
‘n’ Colour Value
15 WHITE RGB(255, 255, 255)
14 YELLOW RGB(255, 255, 0)
13 LILAC RGB(255, 128, 255)
12 BROWN RGB(255, 128, 0)
11 FUCHSIA RGB(255, 64, 255)
10 RUST RGB(255, 64, 0)
9 MAGENTA RGB(255, 0, 255)
8 RED RGB(255, 0, 0)
7 CYAN RGB(0, 255, 255)
6 GREEN RGB(0, 255, 0)
5 CERULEAN RGB(0, 128, 255)
4 MIDGREEN RGB(0, 128, 0)
3 COBALT RGB(0, 64, 255)
2 MYRTLE RGB(0, 64, 0)
1 BLUE RGB(0, 0, 255)
0 BLACK RGB(0, 0, 0)
MATH The math command performs many simple mathematical calculations that can
be programmed in BASIC but there are speed advantages to coding looping
structures in the firmware and there is the advantage that once debugged they
are there for everyone without re-inventing the wheel. Note: 2 dimensional
maths matrices are always specified DIM matrix(n_columns, n_rows) and of
course the dimensions respect OPTION BASE. Quaternions are stored as a 5
element array w, x, y, z, magnitude.
MATH SCALE in(), scale This scales the matrix in() by the scalar scale and puts the answer in out().
,out() Works for arrays of any dimensionality of both integer and float and can
convert between. Setting b to 1 is optimised and is the fastest way of copying
an entire array.
MATH INTERPOLATE in1(), This command implements the following equation on every array element:
in2(), ratio, out() out = (in2 - in1) * ratio + in1
Arrays can have any number of dimensions and must be distinct and have the
same number of total elements. The command works with both integer and
floating point arrays in any mixture
MATH WINDOW in(), This command takes the “in” array and scales it between “minout” and
minout, maxout, out() [,minin, “maxout” returning the answer in “out”. Optionally, it can also return the
maxin] minimum and maximum values found in the original data (“minin” and
“minout”).
Note: “minout” can be greater than “maxout” and in this case the data will be
both scaled and inverted.
e.g
DIM IN(2)=(1,2,3)
DIM OUT(2)
MATH WINDOW IN(),7,3,OUT(),LOW,HIGH
Will return OUT(0)=7, OUT(1)=5,OUT(2)=3,LOW=1,HIGH=3
This command can massively simplify scaling data for plotting etc.
MATH POWER inarray(), Raises each element in ‘inarray()’ to the ‘power’ defined and puts the output in
power, outarray() ‘outarray()’
MATH SHIFT inarray%(), This command does a bit shift on all elements of inarray%() and places the
nbr, outarray%() [,U] result in outarray%() (may be the same as inarray%()). nbr can be between -63
and 63. Positive numbers are a left shift (multiply by power of 2). Negative
number are a right shift. The optional parameter ,U will force an unsigned
shift.
Matrix arithmetic
MATH M_INVERSE array!(), This returns the inverse of array!() in inversearray!(). The array must be square
inversearray!() and you will get an error if the array cannot be inverted (determinant=0).
array!() and inversearray!() cannot be the same.
Multiply the arrays in1() and in2() and put the answer in out()c. All arrays must
MATH M_MULT in1(), in2(), be 2D but need not be square. If not square then the arrays must be
out() dimensioned in1(m,n) in2(p,m) ,out(p,n)
Vector arithmetic
MATH V_PRINT array() Quick mechanism to print a small array on a single line. ‘hex’ will print in hex.
[,hex]
Converts a vector inV() to unit scale and puts the answer in outV()
MATH V_NORMALISE (sqr(x*x + y*y +....)=1
inV(), outV() There is no limit on number of elements in the vector
Multiplies matrix() and vector inV() returning vector outV(). The vectors and
MATH V_MULT matrix(), the 2D matrix can be any size but must have the same cardinality.
inV(), outV()
Calculates the cross product of two three element vectors inV1() and inV2()
MATH V_CROSS inV1(), and puts the answer in outV()
inV2(), outV()
This command rotates the coordinate pairs in “xin()” and “yin()” around the
MATH V_ROTATE x, y, a, centre point defined by “x” and “y” by the angle “a” and puts the results in
xin(), yin(), xout(), yout() “xout()” and “yout()”. NB: the input and output arrays can be the same and the
rotation angle is, by default, in radians but this can be changed using the
OPTION ANGLE command.
Quaternion arithmetic
Invert the quaternion in inQ() and put the answer in outQ()
MATH Q_INVERT inQ(),
outQ()
Converts a vector specified by x , y, and z to a normalised quaternion vector
MATH Q_VECTOR x, y, z,
outVQ() with the original magnitude stored
outVQ()
Generates a normalised rotation quaternion outRQ() to rotate quaternion
MATH Q_CREATE theta, x, vectors around axis x,y,z by an angle of theta. Theta is specified in radians.
y, z, outRQ()
MATH FFT signalarray!(), Performs a fast fourier transform of the data in “signalarray!”. "signalarray"
FFTarray!() must be floating point and the size must be a power of 2 (eg, s(1023) assuming
OPTION BASE is zero)
"FFTarray" must be floating point and have dimension 2*N where N is the
same as the signal array (eg, f(1,1023) assuming OPTION BASE is zero)
The command will return the FFT as complex numbers with the real part in
f(0,n) and the imaginary part in f(1,n)
MATH FFT INVERSE Performs an inverse fast fourier transform of the data in “FFTarray!”.
FFTarray!(), signalarray!() "FFTarray" must be floating point and have dimension 2*N where N must be a
power of 2 (eg, f(1,1023) assuming OPTION BASE is zero) with the real part
in f(0,n) and the imaginary part in f(1,n).
"signalarray" must be floating point and the single dimension must be the same
as the FFT array.
The command will return the real part of the inverse transform in "signalarray".
MATH FFT MAGNITUDE Generates magnitudes for frequencies for the data in “signalarray!”
signalarray!(),magnitudearray! "signalarray" must be floating point and the size must be a power of 2 (eg,
() s(1023) assuming OPTION BASE is zero). "magnitudearray" must be floating
point and the size must be the same as the signal array
The command will return the magnitude of the signal at various frequencies
according to the formula:
frequency at array position N = N * sample_frequency / number_of_samples
MATH FFT PHASE Generates phases for frequencies for the data in “signalarray!”.
signalarray!(), phasearray!() "signalarray" must be floating point and the size must be a power of 2 (eg,
s(1023) assuming OPTION BASE is zero). "phasearray" must be floating
point and the size must be the same as the signal array
The command will return the phase angle of the signal at various frequencies
according to the formula above.
MATH PID INIT channel, This command sets up a PID controller that can work automatically in the
pid_params!(), callback background. Up to 8 PID controllers can run simultaneously (channels 1 to 8)
‘callback’ is a MMbasic subroutine which is called at the rate defined by the
sample time. See the MATH(PID …) function for details of what should be
included in the subroutine.
The pid_params!() array must be dimensioned for all the listed elements,
including the controller memory parameters (DIM pid_params!(13)) and be
initialised with the required settings.
PID configuration
Element 0 = Kp
Element 1 = Ki
Element 2 = Kd
Element 3 = tau ' Derivative low-pass filter time constant
Element 4 = limMin 'Output limits
Element 5 = limMax
Element 6 = limMinInt 'Integrator limits
Element 7 = limMaxInt
Element 8 = T 'Sample time (in seconds)
Controller "memory"
Element 9 = integrator
Element 10 = prevError
Element 11 = differentiator
Element 12 = prevMeasurement
Element 13 = out
MATH PID START channel Starts a previously initialised PID controller on the channel specified
MATH PID STOP channel Stops a previously initialised PID controller on the channel specified and
deletes the internal data structures
See
https://www.thebackshed.com/forum/ViewTopic.php?FID=16&TID=17263
For an example of setting up and running a PID controller
MATH AES128 This command encrypts or decrypts the data in 'in' and puts the answer in 'out'
ENCRYPT/DECRYPT using the AES128 encryption method specified
CBC/ECB/CTR key$/key(), The parameters can each be either a string, integer array, or float array with any
in$/in(), out$/out() [,iv$/iv()] mix possible
The key must be 16 elements long (16*8=128bits), in and out must be a
multiple of 16 elements long. In the case of out being specified as a string (e.g.
out$), the string variable must exist and should be set to empty (DIM out$="")
The maximum number of elements in 'in' and 'out' is limited by memory when
defined as arrays. Strings for encrypting are limited to 240bytes (EBR) and
224bytes (CTR and CBC).
Saved Variables:
16K (100%) Free
RAM:
0K ( 0%) 0 Variables
0K ( 0%) General
228K (100%) Free
Notes:
Memory usage is rounded to the nearest 1K byte.
General memory (RAM) is used by arrays, strings, serial I/O buffers, etc.
MEMORY SET address, byte, This command will set a region of memory to a value.
numberofbytes BYTE = One byte per memory address.
SHORT = Two bytes per memory address.
MEMORY SET BYTE WORD = Four bytes per memory address.
address, byte, numberofbytes
FLOAT = Eight bytes per memory address.
‘increment’ is optional and controls the increment of the ‘address’ pointer as
MEMORY SET SHORT the operation is executed. For example, if increment=3 then only every third
address, short, numberofshorts element of the target is set. The default is 1.
MEMORY PRINT #]fnbr , These commands save or read ‘nbr’ of data bytes from or to memory from or to
nbr, address%/array() an open disk file.
The memory to be saved can be specified as an integer array in which case the
MEMORY INPUT [#]fnbr , nbr of bytes to be saved or read is checked against the array size. Alternatively,
nbr, address%/array() a memory address can be used in which case no checking can take place and
user errors could result in a crash of the firmware..
MEMORY PACK Memory pack and unpack allow integer values from one array to be
source%()/sourceaddress%, compressed into another or uncompressed from one to the other.
dest%()/destaddress%, The two arrays are always normal integer arrays but the packed array can have
number, size 2, 4, 8, 16 or 64 values “packed into them. Thus a single integer array element
could store 2 off 32-bit words, 4 off 16 bit values, 8 bytes, 16 nibbles, or 64
MEMORY UNPACK booleans (bits).
source%()/sourceaddress%, “number specifies the number of values to be packed or unpacked and “size”
dest%()/destaddress%, specifies the number of bits (1,4,8,16,or 32)
number, size Alternatively, memory address(es) can be used in which case no checking can
take place and user errors could result in a crash of the firmware.
MKDIR dir$ Make, or create, the directory ‘dir$’ on the default Flash Filesystem or SD
Card.
MID$( str$, start, num) = str2$ The ‘num’ characters in 'str$', beginning at position 'start', are replaced by the
characters in 'str2$'.
MOUSE For all variants of the command. In the case of USB firmware ‘channel’ is the
USB port that the mouse is connected to (1-4). See MM.INFO(USB n) for
more information. For PS2 firmware ‘channel’ is fixed at the value 2
MOUSE INTERRUPT 'int' is a user defined subroutine that will be called when the left mouse button
ENABLE channel, int is pressed.
MOUSE SET channel, y- Sets the current position that will be returned by the mouse x, y and optionally
coord, y-coord [, wheel-count] wheel positions
Closes access to the mouse and restores the pins to normal use. The command
MOUSE CLOSE channel
will error if OPTION MOUSE has been set.
NEW Clears the program memory and all variables including saved variables.
NEXT [counter-variable] [, NEXT comes at the end of a FOR-NEXT loop; see FOR.
counter-variable], etc The ‘counter-variable’ specifies exactly which loop is being operated on. If no
‘counter-variable’ is specified the NEXT will default to the innermost loop. It
is also possible to specify multiple counter-variables as in:
NEXT x, y, z
ON ERROR ABORT This controls the action taken if an error occurs while running a program and
or applies to all errors discovered by MMBasic including syntax errors, wrong data,
missing hardware, etc.
ON ERROR IGNORE
ON ERROR ABORT will cause MMBasic to display an error message, abort the
or
program and return to the command prompt. This is the normal behaviour and is
ON ERROR SKIP [nn] the default when a program starts running.
or ON ERROR IGNORE will cause any error to be ignored.
ON ERROR CLEAR ON ERROR SKIP will ignore an error in a number of commands (specified by
the number 'nn') executed following this command. 'nn' is optional, the default if
not specified is one. After the number of commands has completed (with an
error or not) the behaviour of MMBasic will revert to ON ERROR ABORT.
If an error occurs and is ignored/skipped the read only variable MM.ERRNO
will be set to non zero and MM.ERRMSG$ will be set to the error message that
would normally be generated. These are reset to zero and an empty string by ON
ERROR CLEAR. They are also cleared when the program is run and when ON
ERROR IGNORE and ON ERROR SKIP are used.
ON ERROR IGNORE can make it very difficult to debug a program so it is
strongly recommended that only ON ERROR SKIP be used.
ON KEY target The first version of the command sets an interrupt which will call 'target' user
or defined subroutine whenever there is one or more characters waiting in the serial
console input buffer.
ON KEY ASCIIcode, target
Note that all characters waiting in the input buffer should be read in the interrupt
subroutine otherwise another interrupt will be automatically generated as soon as
the program returns from the interrupt.
The second version allows you to associate an interrupt routine with a specific
key press. This operates at a low level for the serial console and if activated the
key does not get put into the input buffer but merely triggers the interrupt. It uses
a separate interrupt from the simple ON KEY command so can be used at the
same time if required.
In both variants, to disable the interrupt use numeric zero for the target, i.e.:
ON KEY 0. or ON KEY ASCIIcode, 0
OPEN comspec$ AS GPS Will open a serial communications port for reading from a GPS receiver. See
[,timezone_offset] [,monitor] the GPS function for details. The sentences interpreted are GPRMC, GNRMC,
GPGGA and GNGGA.
The timezone_offset parameter is used to convert UTC as received from the
GPS to the local timezone. If omitted the timezone will default to UTC. The
timezone_offset can be a any number between -12 and 14 allowing the time to
be set correctly even for the Chatham Islands in New Zealand (UTC +12:45).
If the monitor parameter is set to 1 then all GPS input is directed to the
console. This can be stopped by closing the GPS channel.
PAUSE delay Halt execution of the running program for ‘delay’ ms. This can be a fraction.
For example, 0.2 is equal to 200 µs. The maximum delay is 2147483647 ms
(about 24 days).
Note that interrupts will be recognised and processed during a pause.
PIN( pin ) = value For a ‘pin’ configured as digital output this will set the output to low
(‘value’ is zero) or high (‘value’ non-zero). You can set an output high or low
before it is configured as an output and that setting will be the default output
when the SETPIN command takes effect.
See the function PIN() for reading from a pin and the command SETPIN for
configuring it. Refer to the chapter Using the I/O pins for a general description
of the PicoMite firmware's input/output capabilities.
PIO The processors chip in the Raspberry Pi Pico with the RP2040 processors
contains a programmable I/O system with two identical PIO devices (pio%=0
or pio%=1) acting like specialised CPU cores.
The Raspberry Pi Pico 2 with the RP2350 processors has three PIO devices.
See the Appendix F for a more detailed description of programming PIOs.
PIO assemble pio,linedata$ This command will assemble and load text based PIO assembler code
including labels for jumps.
Use: PIO assemble pio,".program anything" to initialise the assembler.
Use: PIO assemble pio,".side_set n [opt] [pindirs]" if using side set. This is
mandatory in order to correctly construct the op-codes if one or more side set
pins are used.
It does not load the pinctrl register as this is specific to the state-machine.
Also note the "opt" parameter changes the op-code on instructions that have a
side parameter.
Use: PIO assemble pio,".line n" to assemble starting from a line other than 1 -
this is optional.
Use: PIO assemble pio,".end program [list]" to terminate the assembly and
program the pio. The optional parameter LIST causes a hex dump of the op-
codes to the terminal.
Use: PIO assemble pio,"label:" to define a label. This must appear as a separate
command.
Use: PIO assemble “’.wrap target” to specify where the program will wrap to.
See PIO(.wrap target) for how to use this.
PIO WRITE pio, Writes the data elements to the pio and state machine specified. The write is
state_machine, count, data0 blocking so the state machine needs to be able to take the data supplied
[,data1..] NB: this command will probably need additional capability in future releases
PIO READ pio, Reads the data elements from the pio and state machine specified. The read is
state_machine, count, non-blocking so the state machine needs to be able to supply the data
data%[()] requested. When count is one then an integer can be used to receive the data,
otherwise and integer array should be specified.
NB: this command will probably need additional capability in future releases.
PIO CLEAR pio This stops the pio specified on all statemachines and clears the control registers
for the statemachines PINCTRL, EXECTRL, and SHIFTCTRL to defaults.
PIO PROGRAM pio,array%() Programs the entire pio program memory with the data in array%(). See
Appendix F.
PIO PROGRAM LINE pio, Programs just the specified line in a PIO program.
line, instruction
PIO SET BASE 0/16 PIO commands can only work with 32 GPIO ports. For the RP2350B this
command tells the system to use GP0-GP31 (0) or GP16-GP47 (16)
PIO Configure pio, sm, clock The parameters in this command are essentially the same as you would use in
[,startaddress] the PIO INIT command plus the helper functions PINCTRL, SHIFTCTRL and
[,sidesetbase] [,sidesetno] EXECCTRL but combined into a single command. This is required because
[,sidesetout] the Pico sdk does some very clever processing behind the scenes to handle the
[,setbase] [,setno] [,setout] RP2350B
[,outbase] [,outno] [,outout]
[,inbase] sidesetbase, sidebase outbase, inbase and jmppin are pin definitions. You can
[,jmppin] [,wraptarget] [,wrap] specify these as either a GPno or a pin number (e.g. GP3 or 5). In all cases
[,sideenable] [,sidepindir] specify the actual pin. So if PIO SET BASE is set to 16 for that PIO then
[,pushthreshold] values GP16 to GP47 are valid. If PIO SET BASE is not set or is set to 0 then
[,pullthreshold] [,autopush] pins GP0 to GP31 are valid. They all default to the base set except jmppin
[,autopull] [,inshiftdir] (defaults to -1) which needs to be explicitly set if you want to use a jmppin as
[,outshiftdir] this triggers setting the required status bit
[,joinrxfifo] [,jointxfifo]
[,joinrxfifoget] [,joinrxfifoput] clock is the desired PIO clock speed in Hz
sidesetno, setno and outno specify the number of pins that can be used for
those functions - default to 0
inshiftdir and outshiftdir default to 1 - shift out of output shift register to right
and shift input shift register to right (data enters from left).
All other parameters are booleans that can enable a specific function - 1 to
enable 0 to disable - all default to 0.
Simple example:
'PIO Configure pio, sm, clock, startaddress,
'sidesetbase, sidesetno, sidesetout,
'setbase, setno, setout, outbase, outno, outout, inbase,
'jmppin, wraptarget, wrap, sideenable, sidepindir,
'pushthreshold, pullthreshold, autopush, autopull, inshiftdir, outshiftdir,
'joinrxfifo, jointxfifo, joinrxfifoget, joinrxfifoput
PIO assemble 1
.program test
.line 0
.wrap target
Set pins,1
Set pins,0
.wrap
.end program
SetPin gp45,pio1
PIO set base 1,16
PIO configure 1,0,1000000,,,,,gp45,1,1,,,,,,Pio(.wrap target),Pio(.wrap)
PIO start 1,0
Do
Loop
PIXEL x, y [,c] Set a pixel on a video output or an attached LCD panel to a colour.
'x' is the horizontal coordinate and 'y' is the vertical coordinate of the pixel. 'c'
is a 24 bit number specifying the colour. 'c' is optional and if omitted the
current foreground colour will be used.
All parameters can be expressed as arrays and the software will plot the
number of pixels as determined by the dimensions of the smallest array. 'x' and
'y' must both be arrays or both be single variables /constants otherwise an error
will be generated. 'c' can be either an array or a single variable or constant.
See the chapter Graphics Commands and Functions for a definition of the
colours and graphics coordinates.
PLAY FLAC file$ [, interrupt] Will play a FLAC file on the sound output.
'file$' is the FLAC file to play (the extension of .flac will be appended if
missing). The sample rate can be up to 48kHz in stereo (96kHz if the Pico is
overclocked)
The FLAC file is played in the background. 'interrupt' is optional and is the
name of a subroutine which will be called when the file has finished playing.
If file$ is a directory the Pico will play all of the files in that directory in turn.
PLAY WAV file$ [, interrupt] Will play a WAV file on the sound output.
'file$' is the WAV file to play (the extension of .wav will be appended if
missing). The WAV file must be PCM encoded in mono or stereo with 8 or
16-bit sampling. The sample rate can be up to 48kHz in stereo (96kHz if the
Pico is overclocked).
The WAV file is played in the background. 'interrupt' is optional and is the
name of a subroutine which will be called when the file has finished playing.
PLAY MP3 file$ [, interrupt] Will play a MP3 file on the sound output (RP2350 ONLY).
'file$' is the MP3file to play (the extension of .mp3 will be appended if
missing). The sample rate can be up to 48kHz.
The MP3 file is played in the background. 'interrupt' is optional and is the
name of a subroutine which will be called when the file has finished playing.
If file$ is a directory the Pico will play all of the files in that directory in turn.
Plays a specific sample in the mod file on the channel specified. The volume is
PLAY MODSAMPLE optional and can be between 0 and 64. This command can only be used when
Samplenum, channel there is a mod file already playing and allows sound effects to be output whilst
[,volume] the background music is still playing.
Loads a 1024 element array comprising 4096 16-bit values between 0 and
PLAY LOAD SOUND 4095. This provides the data for any arbitrary waveform that can be played by
array%() the PLAY SOUND command. You can use the MEMORY PACK command to
create the arrays from a normal 40956 element integer array.
PLAY PAUSE PLAY PAUSE will temporarily halt the currently playing file or tone.
PLAY RESUME PLAY RESUME will resume playing a sound that was paused.
PLAY STOP PLAY STOP will terminate the playing of the file or tone. When the program
terminates for whatever reason the sound output will also be automatically
stopped.
PLAY VOLUME left, right Will adjust the volume of the audio output.
'left' and 'right' are the levels to use for the left and right channels and can be
between 0 and 100 with 100 being the maximum volume. There is a linear
relationship between the specified level and the output. The volume defaults to
maximum when a program is run.
PLAY NEXT Stops playback of the current audio file and starts the next one in the directory
PLAY PREVIOUS Stops playback of the current audio file and starts the previous one in the
directory
PLAY MP3 file$ [, interrupt] Will play a MP3 file on the sound output.
'file$' is the MP3 file to play (the extension of .mp3 will be appended if
missing). The sample rate should be 44100Hz stereo.
The MP3 file is played in the background. 'interrupt' is optional and is the
name of a subroutine which will be called when the file has finished playing.
If file$ is a directory the Pico will play all of the files in that directory in turn.
PLAY HALT This command works when a MP3 file is playing. It stops playback and
records the current file position to allow playback to be resumed from the same
point. This command is specifically designed to support for mp3 audio books
PLAY CONTINUE track$ Resumes playback of the MP3 track specified. "track$" will be the name of the
file that was playing when halted with all file attributes removed
eg,
PLAY MIDIFILE file$ [, Will play a MIDI file on the sound output.
interrupt] 'file$' is the MIDI file to play (the extension of .mid will be appended if
missing).
The MIDI file is played in the background. 'interrupt' is optional and is the
name of a subroutine which will be called when the file has finished playing.
If file$ is a directory the Pico will play all of the files in that directory in turn.
PLAY MIDI Initiates the real-time midi mode. In this mode midi instructions can be sent to
the VS1053 to select which instruments to play on which channels, turn notes
on, and turn them off in real timer
PLAY MIDI CMD cmd%, Sends a midi command when in real time midi mode. An example would be to
data1%, data2% allocate an instrument to a channel. Eg,
PLAY MIDI CMD &B11000001,4 ‘set channel 1 to instrument 4
Plays a MIDI test sequence, n=0 to 3, 0 = normal realtime, the others play note
PLAY MIDI TEST n and instrument samples
Turns on the note on the channel specified when in real time MIDI mode
PLAY NOTE ON channel%,
note%, velocity%
Turns off the note on the channel specified when in real time MIDI mode
PLAY NOTE OFF channel%,
note% [,velocity%]
Sends data to the VS1053 CODEC from the circular buffer “buffer%”. This
PLAY STREAM buffer%(), command initiates a background output stream where the VS1053 is sent
readpointer%, writepointer% anything in the buffer between the readpointer and the write pointer, updating
the readpointer as it goes. Can be used for arbitrary waveform output.
POKE BYTE addr%, byte Will set a byte or a word within the virtual memory space.
or POKE BYTE will set the byte (i.e. 8 bits) at the memory location 'addr%' to
POKE SHORT addr%, short% 'byte'. 'addr%' should be an integer.
or POKE SHORT will set the short integer (i.e. 16 bits) at the memory location
POKE WORD addr%, word% 'addr%' to 'word%'. 'addr%' and short%' should be integers.
or POKE WORD will set the word (i.e. 32 bits) at the memory location 'addr%' to
'word%'. 'addr%' and 'word%' should be integers.
POKE INTEGER addr%, int%
POKE INTEGER will set the MMBasic integer (i.e. 64 bits) at the memory
or
location 'addr%' to int%'. 'addr%' and int%' should be integers.
POKE FLOAT addr%, float!
POKE FLOAT will set the word (i.e. 32 bits) at the memory location 'addr%' to
or 'float!'. 'addr%' should be an integer and 'float!' a floating point number.
POKE VAR var, offset, byte POKE VAR will set a byte in the memory address of 'var'. 'offset' is the
or ±offset from the address of the variable. An array is specified as var().
POKE VARTBL, offset, byte POKE VARTBL will set a byte in MMBasic's variable table. 'offset' is the
±offset from the start of the variable table. Note that a comma is required after
the keyword VARTBL.
or
POKE DISPLAY command This command sends commands and associated data to the display controller
[,data1] [,data2] [,datan] for a connected display. This allows the programmer to change parameters of
how the display is configured. eg, POKE DISPLAY &H28 will turn off an
SSD1963 display and POKE DISPLAY &H29 will turn it back on again.
POLYGON n, xarray%(), Draws a filled or outline polygon with ‘n’ xy-coordinate pairs in ‘xarray%()’
yarray%() [, bordercolour] [, and ‘yarray%()’. If ‘fillcolour’ is omitted then just the polygon outline is
fillcolour] drawn. If ‘bordercolour’ is omitted then it will default to the current default
foreground colour.
POLYGON n(), xarray%(), If the last xy-coordinate pair is not the same as the first the firmware will
yarray%() [, bordercolour()] [, automatically create an additional xy-coordinate pair to complete the polygon.
fillcolour()] The size of the arrays should be at least as big as the number of x,y coordinate
pairs.
'n' can be an array and the colours can also optionally be arrays as follows:
POLYGON n(), xarray%(),
yarray%() [, bordercolour] [, POLYGON n(), xarray%(), yarray%() [, bordercolour()] [, fillcolour()]
fillcolour] POLYGON n(), xarray%(), yarray%() [, bordercolour] [, fillcolour]
The elements of ‘array n()’ define the number of xy-coordinate pairs in each of
the polygons. eg, DIM n(1)=(3,3) would define that 2 polygons are to be
drawn with three vertices each. The size of the n array determines the number
of polygons that will be drawn unless an element is found with the value zero
in which case the firmware only processes polygons up to that point. The x,y-
coordinate pairs for all the polygons are stored in ‘xarray%()’ and ‘yarray%()’.
The ‘xarray%()’ and ‘yarray%()’ parameters must have at least as many
elements as the total of the values in the n array.
Each polygon can be closed with the first and last elements the same. If the last
element is not the same as the first the firmware will automatically create an
additional x,y-coordinate pair to complete the polygon. If fill colour is omitted
then just the polygon outlines are drawn.
The colour parameters can be a single value in which case all polygons are
drawn in the same colour or they can be arrays with the same cardinality as ‘n’.
In this case each polygon drawn can have a different colour of both border
and/or fill.
For example, this will draw 3 triangles in yellow, green and red:
DIM c%(2)=(3,3,3)
DIM x%(8)=(100,50,150,100,50,150,100,50,150)
DIM y%(8)=(50,100,100,150,200,200,250,300,300)
DIM fc%(2)=(rgb(yellow),rgb(green),rgb(red))
POLYGON c%(),x%(),y%(),fc%(),fc%()
PORT(start, nbr [,start, nbr]…) Set a number of I/O pins simultaneously (i.e. with one command).
= value 'start' is an I/O pin number and the lowest bit in 'value' (bit 0) will be used to
set that pin. Bit 1 will be used to set the pin 'start' plus 1, bit 2 will set pin
'start'+2 and so on for 'nbr' number of bits. I/O pins used must be numbered
consecutively and any I/O pin that is invalid or not configured as an output will
cause an error. The start/nbr pair can be repeated if an additional group of
output pins needed to be added.
For example; PORT(15, 4, 23, 4) = &B10000011
Will set eight I/O pins. Pins 15 and 16 will be set high while 17, 18, 23, 24 and
25 will be set to a low and finally 26 will be set high.
This command can be used to conveniently communicate with parallel devices
like LCD displays. Any number of I/O pins (and therefore bits) can be used
from 1 to the number of I/O pins on the chip.
See the PORT function to simultaneously read from a number of pins.
PRINT #nbr, expression Same as above except that the output is directed to a serial communications
[[,; ]expression] … etc port or a file opened for OUTPUT or APPEND with a file number of ‘nbr’.
See the OPEN command.
PRINT #GPS, expression Outputs a NMEA string to an opened GPS device. The string must start with a
[[,; ]expression] … etc $ character and end with a * character. The checksum is automatically
calculated and appended to the string together with the CR/LF characters.
PRINT @(x [, y]) expression Works on terminal console on an attached computer or VGA/HDMI video or
or the display if OPTION LCDPANEL CONSOLE is enabled.
PRINT @(x, [y], m) Same as the standard PRINT command except that the cursor is positioned at
expression the coordinates x, y expressed in pixels. If y is omitted the cursor will be
positioned at “x” on the current line.
Example: PRINT @(150, 45) "Hello World"
The @ function can be used anywhere in a print command.
Example: PRINT @(150, 45) "Hello" @(150, 55) "World"
The @(x,y) function can be used to position the cursor anywhere on or off the
screen. For example, PRINT @(-10, 0) "Hello" will only show "llo" as the
first two characters could not be shown because they were off the screen.
The @(x,y) function will automatically suppress the automatic line wrap
normally performed when the cursor goes beyond the right screen margin.
If 'm' is specified the mode of the video operation will be as follows:
m = 0 Normal text (white letters, black background)
m = 1 The background will not be drawn (ie, transparent)
m = 2 The video will be inverted (black letters, white background)
m = 5 Current pixels will be inverted (transparent background)
PULSE pin, width Will generate a pulse on 'pin' with duration of 'width' ms. 'width' can be a
fraction. For example, 0.01 is equal to 10µs and this enables the generation of
very narrow pulses.
The generated pulse is of the opposite polarity to the state of the I/O pin when
the command is executed. For example, if the output is set high the PULSE
command will generate a negative going pulse.
Notes:
'pin' must be configured as an output.
For a pulse of less than 3 ms the accuracy is ± 1 µs.
For a pulse of 3 ms or more the accuracy is ± 0.5 ms.
PWM channel, frequency, There are 8 separate PWM frequencies available (channels 0 to 7) and up to 16
[dutyA] outputs with individually controlled duty cycle. You can output on either
[,dutyB][,phase][,defer] PWMnA or PWMnB or both for each channel - no restriction. Duty cycles are
specified as a percentage and you can use a negative value to invert the output
(-100.0 <= duty <=100.0).
To use just channel B use the syntax: ‘PWM channel, frequency, , dutyB’ -
note the double comma before the required duty cycle.
Minimum frequency = (cpuspeed + 1) / (2^24) Hz. Maximum speed is
OPTION CPUSPEED/4. At very fast speeds the duty cycles will be
increasingly limited.
Phase is a parameter that causes the waveforms to be centred such that a wave
form with a shorter duty cycle starts and ends equal times from a longer one.
Use 1 to enable this mode and 0 (or omit) to run as normal
The parameter ‘deferredstart’ when set to 1 configures the PWM channels as
but does not start the output running. They can the be started using the PWM
SYNC command. This can be used to avoid any undesirable startup artefacts
The PWM command is also capable of driving servos as follows:
PWM 1,50,(position_as_a_percentage * 0.05 + 5)
PWM SYNC s0
[,s1][,s2][,s3][,s4][,s5][,s6][,s7
] This initiates the PWM on channels where a deferred start was defined or just
syncs existing running channels. However, the power comes in the ability to
offset the channels one to another (defined as a percentage of the time period as
per the duty cycle - can be a float)
PWM channel, OFF You can use an offset of -1 to omit a channel from the synch
RAM LIST Displays a list of all ram locations including the first line of the program.
RAM LIST n [,all] List the program saved to slot n. Use ALL to list without page breaks.
RAM SAVE n Save the current program to the ram location specified.
RAM LOAD n Load a program from the specified ram location into program memory.
RAM RUN n Runs the program in ram location n, clear all variables. Does not change the
program memory.
RAM CHAIN n Runs the program in ram location n, leaving all variables intact (allows for a
program that is much bigger than the program memory). Does not change the
program memory. NB: if the chained program uses the READ command it
must call RESTORE before the first read.
RAM FILE LOAD n, Loads the MMBasic file fname$ into the ram slot specified.
fname$ [,O[VERWRITE]] If the optional parameter OVERWRITE (or O) is specified the content of the
flash slot will be overwritten without an error being raised.
RBOX x, y, w, h [, r] [,c] Draws a box with rounded corners on the video output or attached LCD panel
[,fill] starting at 'x' and 'y' which is 'w' pixels wide and 'h' pixels high.
'r' is the radius of the corners of the box. It defaults to 10.
'c' specifies the colour and defaults to the default foreground colour if not
specified. 'fill' is the fill colour. It can be omitted or set to -1 in which case the
box will not be filled.
All parameters can be expressed as arrays and the software will plot the
number of boxes as determined by the dimensions of the smallest array. 'x', 'y',
'w', and 'h' must all be arrays or all be single variables /constants otherwise an
error will be generated. 'r', 'c', and 'fill' can be either arrays or single
variables/constants.
See the chapter Graphics Commands and Functions for a definition of the
colours and graphics coordinates.
READ variable[, variable].. Reads values from DATA statements and assigns these values to the named
variables. Variable types in a READ statement must match the data types in
DATA statements as they are read.
Arrays can be used as variables (specified with empty brackets, eg, a()) and in
that case the size of the array is used to determine how many elements are to be
read. If the array is multidimensional then the leftmost dimension will be the
fastest moving.
See also DATA and RESTORE.
READ SAVE READ SAVE will save the virtual pointer used by the READ command to
or point to the next DATA to be read. READ RESTORE will restore the pointer
that was previously saved.
READ RESTORE
This enables subroutines to READ data and then restore the read pointer so as
not to disturb other parts of the program that may be reading the same data
statements. These commands can be nested.
REFRESH Initiates an update of the screen for e-ink black and white displays.
These can only be updated a full screen at a time and if OPTION
AUTOREFRESH is OFF this command can be used to trigger the write.
This command works with the following displays: N5110, SSD1306I2C,
SSD1306I2C32, SSD1306SPI, ST7920.
RESTORE [line] Resets the line and position counters for the READ statement.
If ‘line’ is specified the counters will be reset to the beginning of the specified
line. ‘line’ can be a line number or a label or a variable with these values.
If ‘line’ is not specified the counters will be reset to the start of the program.
RMDIR dir$ Remove, or delete, the directory ‘dir$’ on the default Flash Filesystem or SD
Card.
RTC GETTIME RTC GETTIME will get the current date/time from a PCF8563, DS1307 or
DS3231 real time clock and set the internal MMBasic clock accordingly. The
date/time can then be retrieved with the DATE$ and TIME$ functions.
RTC SETTIME year, month, RTC SETTIME will set the time in the clock chip. 'hour' must use 24 hour
day, hour, minute, second notation. ‘year’ can be two or four digits. The RTC SETTIME command will
also accept a single string argument in the format of dd/mm/yy hh:mm. This
means the date/time could be entered by the user using a GUI FORMATBOX
with the DATETIME2 format (see Advanced Graphics Functions.pdf).
RTC SETREG reg, value The RTC SETREG and GETREG commands can be used to set or read the
RTC GETREG reg, var contents of registers within the real time clock chip. 'reg' is the register's
number, 'value' is the number to store in the register and 'var' is a variable that
will receive the number read from the register. These commands are not
necessary for normal operation but they can be used to manipulate special
features of the chip (alarms, output signals, etc). They are also useful for
storing temporary information in the chip's battery backed RAM.
These chips are I2C devices and must be connected to the two I2C pins as
specified by OPTION SYSTEM I2C with appropriate pullup resistors.
Also see the command OPTION RTC AUTO ENABLE.
SAVE file$ Saves the program in the current working directory of the Flash Filesystem or
SD Card as ‘file$’. Example: SAVE “TEST.BAS”
If an extension is not specified “.BAS” will be added to the file name.
See also FLASH SAVE n for saving to a Flash Slot.
SAVE IMAGE file$ [,x, y, w, Save the current image on the video output or LCD panel as a BMP file. Any
h] LCD panel must be capable of being read, for example, a ILI9341 based panel
or or a VIRTUAL_M or VIRTUAL_C panel.
SAVE COMPRESSED 'file$' is the name of the file. If an extension is not specified “.BMP” will be
IMAGE file$ [,x, y, w, h] added to the file name. The image is saved as a true colour 24-bit image.
‘x’, ‘y’, ‘w’ and ‘h’ are optional and are the coordinates (‘x’ and ‘y’ are the top
left coordinate) and dimensions (width and height) of the area to be saved. If
not specified, the whole screen will be saved. Note that ‘width’, if used, must
be a multiple of 2.
SAVE COMPRESSED IMAGE will work the same except that RLE
compression will be used to reduce the file size..
SAVE PERSISTENT n% Saves the value n% in a special memory location that will survive a watchdog
reset or a physical reset but not a power cycle
See also MM.PERSISTENT or MM.INFO(PERSISTENT)
SEEK [#]fnbr, pos Will position the read/write pointer in a file that has been opened on the Flash
Filesystem or SD Card for RANDOM access to the 'pos' byte.
The first byte in a file is numbered one so SEEK #5,1 will position the
read/write pointer to the start of the file opened as #5.
SELECT CASE value Executes one of several groups of statements, depending on the value of an
CASE testexp [[, testexp] …] expression. 'value' is the expression to be tested. It can be a number or string
<statements> variable or a complex expression.
<statements> 'testexp' (or test-n) is the value that is to be compared against. It can be:
CASE test-n [[, test-n] …] A single expression (i.e. 34, "string" or PIN(4)*5) to which it may equal
<statements> A range of values in the form of two single expressions separated by the
<statements> keyword "TO" (i.e. 5 TO 9 or "aa" TO "cc")
CASE ELSE A comparison starting with the keyword "IS" (which is optional). For
<statements> example: IS > 5, IS <= 10.
<statements> When a number of test expressions (separated by commas) are used the CASE
statement will be true if any one of these tests evaluates to true.
END SELECT
If 'value' cannot be matched with a 'testexp' it will be automatically matched to
the CASE ELSE. If CASE ELSE is not present the program will not execute any
<statements> and continue with the code following the END SELECT. When a
match is made the <statements> following the CASE statement will be
executed until END SELECT or another CASE is encountered when the
program will then continue with the code following the END SELECT.
An unlimited number of CASE statements can be used but there must be only
one CASE ELSE and that should be the last before the END SELECT.
Example:
SELECT CASE nbr%
CASE 4, 9, 22, 33 TO 88
statements
CASE IS < 4, IS > 88, 5 TO 8
statements
CASE ELSE
statements
SETPIN pin, cfg [, option] Will configure an external I/O pin. Refer to the chapter Using the I/O pins for
a general description of the Pico's input/output capabilities.
'pin' is the I/O pin to configure, ‘cfg’ is the mode that the pin is to be set to and
'option' is an optional parameter. 'cfg' is a keyword and can be any one of the
following:
OFF Not configured or inactive
AIN Analog input (i.e. measure the voltage on the input).
ARAW Fast analog input returning a value between 0 and 4095.
DIN Digital input
If 'option' is omitted the input will be high impedance
If 'option' is the keyword "PULLUP" or “PULLDOWN” a
constant current of about 50µA will be used to pull the input pin
up or down to 3.3V. Due to a bug in the RP2350 chips it is
recommended that a pulldown be implemented using a 8.2K or
less resistor.
FIN Frequency input
'option' can be used to specify the gate time (the length of time
used to count the input cycles). It can be any number between
10 ms and 100000 ms. The PIN() function will always return the
frequency correctly scaled in Hz regardless of the gate time used.
If 'option' is omitted the gate time will be 1 second.
The pins can be GP6, GP7, GP8 or GP9 (can be changed with
OPTION COUNT).
PIN Period input
'option' can be used to specify the number of input cycles to
average the period measurement over. It can be any number
between 1 and 10000. The PIN() function will always return the
average period of one cycle correctly scaled in ms regardless of
the number of cycles used for the average. If 'option' is omitted
the period of just one cycle will be used.
The pins can be GP6, GP7, GP8 or GP9 (can be changed with
OPTION COUNT).
CIN Counting input
‘option’ can be used to specify which edge triggers the count
and if any pullup or pulldown is enabled
2 specifies a falling edge with pullup,
3 specifies that both a falling and rising edge will trigger a
count with no pullup applied,
5 specifies both edges but with a pullup applied.
If ‘option’ is omitted a rising edge will trigger the count.
Due to a bug in the RP2350 chips pulldown is not recommended.
The pins can be GP6, GP7, GP8 or GP9 (can be changed with
OPTION COUNT).
SETPIN pin, cfg, target [, Will configure ‘pin’ to generate an interrupt according to ‘cfg’. Any I/O pin
option] capable of digital input can be configured to generate an interrupt with a
maximum of ten interrupts configured at any one time.
'cfg' is a keyword and can be any one of the following:
OFF Not configured or inactive
INTH Interrupt on low to high input
INTL Interrupt on high to low input
INTB Interrupt on both (i.e. any change to the input)
‘target' is a user defined subroutine which will be called when the event
happens. Return from the interrupt is via the END SUB or EXIT SUB
commands. 'option' is the same as used in SETPIN pin DIN (above).
This mode also configures the pin as a digital input so the value of the pin can
always be retrieved using the function PIN().
Refer to the chapter Using the I/O pins for a general description.
SETPIN p1[, p2 [, p3]], device These commands are used for the pin allocation for special devices.
Pins must be chosen from the pin designation diagram and must be allocated
before the devices can be used. Note that the pins (eg, rx, tx, etc) can be
declared in any order and that the pins can be referred to by using their pin
number (eg, 1, 2) or GP number (eg, GP0, GP1).
Note that on the WebMite version:
SPI1 and SPI2 are not available on GP20 to GP28
COM1 and COM2 are not available on P20 to GP28
I2C is not available on pin 34 (GP28)
The following are not available; GP29, GP25, GP24 and GP23
SETPIN rx, tx, COM1 Allocate the pins to be used for serial port COM1.
Valid pins are RX: GP1, GP13 or GP17
TX: GP0, GP12, GP16 or GP28
SETPIN rx, tx, COM2 Allocate the pins to be used for serial port COM2.
Valid pins are RX: GP5, GP9 or GP21
TX: GP4, GP8 or GP20
SETPIN rx, tx, clk, SPI Allocate the pins to be used for SPI port SPI.
Valid pins are RX: GP0, GP4, GP16 or GP20
TX: GP3, GP7 or GP19
CLK: GP2, GP6 or GP18
SETPIN sda, scl, I2C Allocate the pins to be used for the I2C port I2C.
Valid pins are SDA: GP0, GP4, GP8, GP12, GP16, GP20 or GP28
SCL: GP1, GP5, GP9, GP13, GP17 or GP21
SETPIN sda, scl, I2C2 Allocate the pins to be used for the I2C port I2C2.
Valid pins are SDA: GP2, GP6, GP10, GP14, GP18, GP22 or GP26
SCL: GP3, GP7, GP11, GP15, GP19 or GP27
SETPIN pin, IR Allocate pins for InfraRed (IR) communications (can be any pin).
SETPIN pin, PIOn Reserve pin for use by a PIO0, PIO1 or PIO2 (RP2350 only) (see Appendix F
for PIO details).
RP2350 ONLY
SETPIN GP1, FFIN [,gate] Sets GP1 as a fast frequency input.
Inputs up to the CPU speed /2 can be recorded.
‘gate’ can be used to specify the gate time (the length of time used to count the
input cycles). It can be any number between 10 ms and 100000 ms. The PIN()
function will always return the frequency correctly scaled in Hz regardless of
the gate time used. If 'option' is omitted the gate time will be 1 second.
The function uses PWM channel 0 to do the counting so it is incompatible with
any other use of that PWM channel.
SETTICK period, target [, nbr] This will setup a periodic interrupt (or "tick").
Four tick timers are available ('nbr' is 1, 2, 3 or 4). 'nbr' is optional and if not
specified timer number 1 will be used.
The time between interrupts is ‘period’ milliseconds and ‘target' is the interrupt
subroutine which will be called when the timed event occurs.
The period can range from 1 to 2147483647 ms (about 24 days).
These interrupts can be disabled by setting ‘period’ to zero
(i.e. SETTICK 0, 0, 3 will disable tick timer number 3).
SETTICK PAUSE, target Pause or resume the specified timer. When paused the interrupt is delayed but
[, nbr] the current count is maintained.
or
SETTICK RESUME, target
[, nbr]
SORT array() [,indexarray()] This command takes an array of any type (integer, float or string) and sorts it
[,flags] [,startposition] into ascending order in place.
[,elementstosort] It has an optional parameter ‘indexarray%()’. If used this must be an integer
array of the same size as the array to be sorted. After the sort this array will
contain the original index position of each element in the array being sorted
SPI OPEN speed, mode, bits Communications via an SPI channel. See Appendix D for the details.
SPI READ nbr, array() 'nbr' is the number of data items to send or receive
SPI WRITE nbr, data1, data2, 'data1', 'data2', etc can be float or integer and in the case of WRITE can be a
data3, … etc constant or expression.
SPI WRITE nbr, string$ If 'string$' is used 'nbr' characters will be sent.
SPI WRITE nbr, array() 'array' must be a single dimension float or integer array and 'nbr' elements will
SPI CLOSE be sent or received.
SPI2 The same set of commands as for SPI (above) but applying to the second SPI
channel.
SPRITE HIDE [#]n Removes sprite n from the display and replaces the stored background. To
restore a screen to a previous state sprites should be hidden in the opposite
order to which they were written "LIFO"
SPRITE HIDE ALL Hides all the sprites allowing the background to be manipulated.
The following commands cannot be used when all sprites are hidden:
SPRITE SHOW (SAFE)
SPRITE HIDE (SAFE, ALL)
SPRITE SWAP
SPRITE MOVE
SPRITE SCROLLR
SPRITE SCROLL
SPRITE RESTORE Restores the sprites that were previously hidden with SPRITE HIDE ALL.
SPRITE HIDE SAFE [#]n Removes sprite n from the display and replaces the stored background.
Automatically hides all more recent sprites as well as the requested one and
then replaces them afterwards. This ensures that sprites that are covered by
other sprites can be removed without the user tracking the write order. Of
course this version is less performant than the simple version and should only
be used it there is a risk of the sprite being partially covered.
SPRITE INTERRUPT sub Specifies the name of the subroutine that will be called when a sprite collision
occurs. See Appendix H for how to use the function SPRITE to interrogate
details of what has collided.
SPRITE READ [#]b, x, y, w, h This will copy a portion of the display to the memory buffer '#b'. The source
coordinate is 'x' and 'y' and the width of the display area to copy is 'w' and the
height is 'h'. When this command is used the memory buffer is automatically
created and sufficient memory allocated. This buffer can be freed and the
memory recovered with the SPRITE CLOSE command.
SPRITE WRITE [#]b, x, y Will copy sprite '#b' to the display. The destination coordinate is 'x' and 'y'.
[,mode] The optional 'mode' parameter defaults to 4 and specifies how the stored image
data is changed as it is written out. It is the bitwise AND of the following
values:
&B001 = mirrored left to right
&B010 = mirrored top to bottom
&B100 = don't copy transparent pixels
SPRITE LOADARRAY [#]n, Creates the sprite 'n' with width 'w' and height 'h' by reading w*h RGB888
w, h, array%() values from 'array%()'. The RGB888 values must be stored in order of columns
across and then rows down starting at the top left.
This allows the programmer to create simple sprites in a program without
needing to load them from disk or read them from the display. The firmware
will generate an error if 'array%()' is not big enough to hold the number of
values required.
SPRITE LOADBMP [#]b, Will load a blit buffer from a 24-bit bmp image file. 'x' and 'y' define the start
fname$ [,x] [,y] [,w] [,h] position in the image to start loading and 'w' and 'h' specify the width and
height of the area to be loaded.
eg, BLIT LOAD #1,"image1", 50,50,100,100 will load an area of
100 pixels square with the top left had corner at 50, 50 from the image
image1.bmp
SPRITE LOADPNG [#]b, Loads SPRITE number ‘b’ from the png file ‘fname$’. If no extension is
fname$ [,transparent] specified .png will be automatically added to the filename. The file must be in
[,alphacut] RGBA8888 format which is the normal default. The optional parameter
'transparent' (defaults to 0) specifies one of the colour codes (0-15) which will
be allocated to pixels in the png file with an alpha value less than 'alphacut'
(defaults to 20). The variable transparency can then used with the command
SPRITE SET TRANSPARENT n or FRAMEBUFFER LAYER n to display
the sprite with the transparent region hidden.
SPRITE MOVE Actions a single atomic transaction that re-locates all sprites which have
previously had a location change set up using the SPRITE NEXT command.
Collisions are detected once all sprites are moved and reported in the same way
as from a scroll
SPRITE NEXT [#]n, x, y Sets the X and Y coordinate of the sprite to be used when the screen is next
scrolled or the SPRITE MOVE command is executed. Using SPRITE NEXT
rather than SPRITE SHOW allows multiple sprites to be moved as part of the
same atomic transaction.
SPRITE SCROLL x, y [,col] Scrolls the background and any sprites on the active framebuffer (L or N) 'x'
pixels to the right and 'y' pixels up. 'x' can be any number between -
MM.HRES-1 and MM.HRES-1, 'y' can be any number between -MM.VRES-1
and MM.VRES-1.
Sprites on any layer other than zero will remain fixed in position on the screen.
By default the scroll wraps the image round. If 'col' is specified the colour will
replace the area behind the scrolled image. If 'col' is set to -1 the scrolled area
will be left untouched.
SPRITE SET Sets the colour code (0-15) which will be used as transparent when sprites are
TRANSPARENT n displayed over a background (defaults to 0).
STATIC variable [, variables] Defines a list of variable names which are local to the subroutine or function.
See DIM for the full syntax. These variables will retain their value between calls to the subroutine or
function (unlike variables created using the LOCAL command).
This command uses exactly the same syntax as DIM. The only difference is
that the length of the variable name created by STATIC and the length of the
subroutine or function name added together cannot exceed 31 characters.
Static variables can be initialised to a value. This initialisation will take effect
only on the first call to the subroutine (not on subsequent calls).
SUB xxx (arg1 [,arg2, …]) Defines a callable subroutine. This is the same as adding a new command to
<statements> MMBasic while it is running your program.
<statements> 'xxx' is the subroutine name and it must meet the specifications for naming a
END SUB variable.
'arg1', 'arg2', etc are the arguments or parameters to the subroutine. An array is
specified by using empty brackets. i.e. arg3(). The type of the argument can
be specified by using a type suffix (i.e. arg1$) or by specifying the type using
AS <type> (i.e. arg1 AS STRING).
Arguments in the caller's list that are a variable and have the correct type will
be passed by reference to the subroutine. This means that any changes to the
corresponding argument in the subroutine will also be copied to the caller's
variable and therefore may be accessed after the subroutine has ended. The
argument can be prefixed with BYVAL which will prevent this mechanism and
cause only the value to be used. Alternatively, the prefix BYREF instructs
MMBasic that a reference is required and an error will be generated if that
cannot be done.
Arrays are passed by specifying the array name with empty brackets (eg, arg())
and are always passed by reference and must be the correct type.
Every definition must have one END SUB statement. When this is reached the
program will return to the next statement after the call to the subroutine. The
command EXIT SUB can be used for an early exit.
SYNC time% [,period] The SYNC command allows the user to implement very precisely timed
or repeated actions (1-2 microseconds accuracy).
SYNC To enable this the command is first called with the parameter time%. This sets
up a repeating clock for time% microseconds. The optional parameter ‘period’
modifies the time and can be “U” for microseconds, “M” for milliseconds or
“S” for seconds.
Once the clock is set up the program is synchronised to it using the SYNC
command without parameters. This waits for the clock period to expire. For
periods below 2 ms this is non-interruptible. Above 2 ms the program will
respond to Ctrl-C but not any MMBasic interrupts.
Typical use is to set the clock outside of a loop and then at the top of the loop
call the SYNC command without parameters. This means the contents of the
loop will be executed exactly once for each clock period set.
For example, the following would drive a servo with the required precise 50Hz
timing:
SYNC 20, M
DO
SYNC
PULSE GP0,n
LOOP
TEMPR START pin [, This command can be used to start a conversion running on a DS18B20
precision] [,timeout] temperature sensor connected to 'pin'. Normally the TEMPR() function alone
is sufficient to make a temperature measurement so usage of this command is
optional. For more detail see the section Measuring Temperature.
This command will start the measurement on the temperature sensor. The
program can then attend to other duties while the measurement is running and
later use the TEMPR() function to get the reading. If the TEMPR() function is
used before the conversion time has completed the function will wait for the
remaining conversion time before returning the value.
Any number of these conversions (on different pins) can be started and be
running simultaneously.
'precision' is the resolution of the measurement and is optional. It is a number
between 0 and 3 meaning:
0 = 0.5ºC resolution, 100 ms conversion time.
1 = 0.25ºC resolution, 200 ms conversion time (this is the default).
The optional timeout parameter overrides the conversion times above to allow
for slow devices.
TEXT x, y, string$ Displays a string on the video output or attached LCD panel starting at 'x' and
[,alignment$] [, font] [, scale] 'y'.
[, c] [, bc] ‘string$’ is the string to be displayed. Numeric data should be converted to a
string and formatted using the Str$() function.
' alignment$' is a string expression or string variable consisting of 0, 1 or 2
letters where the first letter is the horizontal alignment around 'x' and can be L,
C or R for LEFT, CENTER, RIGHT and the second letter is the vertical
alignment around 'y' and can be T, M or B for TOP, MIDDLE, BOTTOM.
The default alignment is left/top.
For example. “CM” will centre the text vertically and horizontally.
The 'alignment$' string can be a constant (eg, “CM”) or it can be a string
variable. For backwards compatibility with earlier versions of MMBasic the
string can also be unquoted (eg, CM).
A a third letter can be used in the alignment string to indicate the rotation of the
text. This can be 'N' for normal orientation, 'V' for vertical text with each
character under the previous running from top to bottom, 'I' the text will be
inverted (i.e. upside down), 'U' the text will be rotated counter clockwise by
90º and 'D' the text will be rotated clockwise by 90º
'font' and 'scale' are optional and default to that set by the FONT command.
'c' is the drawing colour and 'bc' is the background colour. They are optional
and default to the current foreground and background colours.
See the chapter Graphics Commands and Functions for a definition of the
colours and graphics coordinates.
Sets the height of the tiles. ‘n’ can be between 12 and 480 (RP2040) or
TILE HEIGHT n between 8 and 480 (RP2350)
TIME$ = "HH:MM:SS" Sets the time of the internal clock. MM and SS are optional and will default to
or zero if not specified. For example TIME$ = "14:30" will set the clock to 14:30
with zero seconds.
TIME$ = "HH:MM"
With OPTION RTC AUTO ENABLE the PicoMite firmware starts with the
or
TIME$ programmed in RTC. Without OPTION RTC AUTO ENABLE the
TIME$ = "HH" firmware starts with TIME$="00:00:00"
TRACE ON TRACE ON/OFF will turn on/off the trace facility. This facility will print the
or number of each line (counting from the beginning of the program) in square
brackets as the program is executed. This is useful in debugging programs.
TRACE OFF
TRACE LIST will list the last 'nn' lines executed in the format described
or
above. MMBasic is always logging the lines executed so this facility is always
TRACE LIST nn available (ie, it does not have to be turned on).
TRIANGLE X1, Y1, X2, Y2, Draws a triangle on the attached video output or LCD display panel with the
X3, Y3 [, C [, FILL]] corners at X1, Y1 and X2, Y2 and X3, Y3. 'C' is the colour of the triangle and
defaults to the current foreground colour. 'FILL' is the fill colour and defaults
to no fill (it can also be set to -1 for no fill).
All parameters can be expressed as arrays and the software will plot the
number of triangles as determined by the dimensions of the smallest array
unless X1 = Y1 = X2 = Y2 = X3 = Y3 = -1 in which case processing will stop
at that point 'x1', 'y1', 'x2', 'y2', 'x3',and 'y3' must all be arrays or all be single
variables /constants otherwise an error will be generated 'c' and 'fill' can be
either arrays or single variables/constants.
TRIANGLE SAVE [#]n, Saves a triangular area of the screen to buffer #n.
x1,y1,x2,y2,x3,y3
TRIANGLE RESTORE [#]n Restores a saved triangular region of the screen and deletes the saved buffer.
VAR SAVE var [, var]… VAR SAVE will save one or more variables to non-volatile flash memory
or where they can be restored later (normally after a power interruption).
VAR RESTORE 'var' can be any number of numeric or string variables and/or arrays. Arrays
are specified by using empty brackets. For example: var()
or
The VAR SAVE command can be used repeatedly. Variables that had been
VAR CLEAR
previously saved will be updated with their new value and any new variables
(not previously saved) will be added to the saved list for later restoration.
VAR RESTORE will retrieve the previously saved variables and insert them
(and their values) into the variable table.
VAR CLEAR will erase all saved variables.
This command is normally used to save calibration data, options, and other
data which does not change often but needs to be retained across a power
interruption. Normally the VAR RESTORE command is placed at the start of
the program so that previously saved variables are restored and immediately
available to the program when it starts. Notes:
The storage space available to this command is 16KB.
Using VAR RESTORE without a previous save will have no effect and
will not generate an error.
If, when using RESTORE, a variable with the same name already exists its
value will be overwritten.
Saved arrays must be declared (using DIM) before they can be restored.
Be aware that string arrays can rapidly use up all the memory allocated to
this command. The LENGTH qualifier can be used when a string array is
WATCHDOG timeout Starts the watchdog timer which will automatically restart the processors when
or it has timed out. This can be used to recover from some event that disabled the
running program (such as an endless loop or a programming or other error that
WATCHDOG OFF
halts a running program). This can be important in an unattended control
or situation.
WATCHDOG HW timeout The timeout can either be processed in the system timer interrupt
or (WATCHDOG command) or as a true CPU/hardware watchdog
WATCHDOG HW OFF (WATCHDOG HW command).
If the hardware watchdog is used the timer has a maximum of 8.3 seconds. No
such limitation exists for the software watchdog.
'timeout' is the time in milliseconds (ms) before a restart is forced. This
command should be placed in strategic locations in the running BASIC
program to constantly reset the watchdog timer (to ‘timeout’) and therefore
prevent it from counting down to zero.
If the timer count does reach zero (perhaps because the BASIC program has
stopped running) the PicoMite firmware will be automatically restarted and the
automatic variable MM.WATCHDOG will be set to true (i.e. 1) indicating that
an error occurred. On a normal startup MM.WATCHDOG will be set to false
(i.e. 0). Note that OPTION AUTORUN must be specified for the program to
restart.
WATCHDOG OFF can be used to disable the watchdog timer (this is the
default on a reset or power up). The timer is also turned off when the break
character (CTRL-C) is used on the console to interrupt a running program.
WII [CLASSIC] OPEN Opens a WII Classic controller and implements background polling of the
[,interrupt] device. The Wii Classic must be wired to the pins specified by OPTION
SYSTEM I2C which is a prerequisite.
Open attempts to talk to the Wii Classic and will return an error if not found. If
found the firmware will sample the Wii data in the background at a rate of
50Hz. If an optional user interrupt is specified this will be triggered if any of
the buttons changes (both on and off)
See the DEVICE function for how to read data from the Wii Classic.
WII [CLASSIC] CLOSE CLOSE will stop the background polling and disable any interrupt specified
WII NUNCHUCK OPEN Opens a WII Nunchuck controller and implements background polling of the
[,interrupt] device. The Wii Nunchuck must be wired to the pins specified by OPTION
SYSTEM I2C which is a prerequisite.
Open attempts to talk to the Wii Nunchuck and will return an error if not
found. If found the firmware will sample the Wii data in the background at a
rate of 50Hz. If an optional user interrupt is specified this will be triggered if
either of the buttons changes (both on and off)
See the DEVICE function for how to read data from the Wii Nunchuck.
WII NUNCHUCK CLOSE CLOSE will stop the background polling and disable any interrupt specified
WEBMITE ONLY
WEB The WEB commands are used to manage the Internet capability of the
WebMite.
WEB NTP [timeoffset [, Get the date/time from an NTP server and set the internal WebMite date/time
NTPserver$]] [,timeout]]] clock.
' timeoffset' is the local time zone, and if omitted the date/time will be set to
GMT. ' NTPserver$' is the timeserver to use and if omitted will default to an
international timeserver pool. 'timeout' is the optional time out in milliseconds
and defaults to 5000.
WEB OPEN TCP CLIENT Opens a TCP client connection to a WEB server.
address$, port 'address$' is a string and is the address of the server to connect to. It can be
either a URL (eg, "api.openweathermap.org") or an IP address (eg,
"192.168.1.111"). 'port' is the number of the port to use.
Used with WEB TCP CLIENT REQUEST to interrogate the server.
Note that one CLIENT connection is allowed.
WEB OPEN TCP STREAM Opens a TCP client connection to a WEB server like WEB OPEN TCP
address$, port CLIENT but connects the WEB TCP CLIENT STREAM receiver logic rather
than the logic for WEB TCP CLIENT REQUEST.
'address$' is a string and is the address of the server to connect to. It can be
either a URL (eg, "api.openweathermap.org") or an IP address (eg,
"192.168.1.111"). 'port' is the number of the port to use.
Note that one CLIENT connection is allowed.
WEB SCAN [array%()] Scans for all available wifi connections. If ‘array%()’ is specified the output
will be stored in a Longstring, otherwise output will be to the console. The
command can be used whether ot not an network connection is already active.
WEB TCP CLIENT STREAM Connects to a server previously opened with WEB OPEN TCP STREAM.
command$, buffer%(), 'command$' is a string and is the request to be sent to the server.
readpointer%, writepointer%
'buffer%()' is an integer array which will receive the ongoing responses and
acts as a circular buffer of bytes received.
The firmware maintains the parameter ‘writepointer%’ as the data from the
server arrives.
‘readpointer%’ should be maintained by the Basic program as it removes data
from the circular buffer.
If ‘writepointer%’ catches up with ‘readpointer%’ then ‘readpointer%’ will be
incremented to stay one byte ahead and incoming data will be lost.
This command is designed to be compatible with the PLAY STREAM
command to allow the implementation of streaming internet audio.
WEB CLOSE TCP CLIENT Closes the connection to the remote server opened with WEB OPEN TCP
CLIENT. This must be done before another open is attempted.
WEB TCP INTERRUPT Start the TCP server running. 'InterruptSub' is the subroutine to call when a
InterruptSub request is made of the TCP server (ie, an interrupt).
Note that the OPTION WIFI command must have been used first followed by
the OPTION TCP SERVER PORT command to enable the TCP server.
WEB TCP READ cb%, Read the data from a potential TCP connection' cb%'. ' buff%()' is an array to
buff%() receive any data from that connection as a longstring. The size of this buffer
will limit the amount of data received from the remote client. If there is
nothing received on that connection this will return an empty string (ie,
LLEN(buff%())=0).
If there is data that has been received then the BASIC program must respond
with one of the WEB TRANSMIT commands in order to respond and close the
connection.
WEB TCP SEND cb%, These two commands allow more flexibility in using the TCP server. Unlike
data%() WEB TRANSMIT PAGE or WEB TRANSMIT FILE, WEB TCP SEND does
WEB TCP CLOSE cb% not create any sort of header, nor does it close the TCP connection after
transmission. It just sends exactly what is in the LONGSTRING data%() and it
is up to the Basic programmer to close the connection when appropriate.
WEB TRANSMIT CODE Send a numerical response to the open TCP connection 'cb%' and then closes
cb%, nnn% the connection.
Typical use would be TRANSMIT CODE cb%, 404 to indicate page not
found.
WEB TRANSMIT FILE cb%, Constructs an HTTP 1.1 header with the ’content-type$’ as specified, sends it
filename$, content-type$ and then sends the contents of the file to the open TCP connection cb% and on
completion, closes the connection.
’content-type$’ is a MIME type expressed as a string. Eg, "image/jpeg"
WEB UDP INTERRUPT Sets up a BASIC interrupt routine that will be triggered whenever a UDP
intname datagram is received. The contents will be saved in MM.MESSAGE$. The IP
address of the sender will be stored in MM.ADDRESS$.
WEB UDP SEND addr$, port, Used to send a datagram to a remote receiver. In this case the IP address must
data$ be specified and can be either a numeric address (eg, "192.168.1.147") or a
normal text address (eg, "google.com"). The port number of the receiver must
also be specified and the message itself. The SEND command can be used as a
response to an incoming message or stand-alone.
WS2812 type, pin, nbr, This command will drive one or more WS2812 LED chips connected to 'pin'.
value%[()] Note that the pin must be set to a digital output before this command is used.
'type' is a single character specifying the type of chip being driven:
O = original WS2812
B = WS2812B
S = SK6812
W =SK6812W (RGBW)
‘nbr’ is the number of LEDs in the chain (1 to 256). The 'value%()' array
should be an integer array sized to have exactly the same number of elements
as the number of LEDs to be driven.
For the first three variants each element in the array should contain the colour
in the normal RGB888 format (i.e. 0 to &HFFFFFF).
For type W use a RGBW value (0-&HFFFFFFFF).
If only one LED is connected then a single integer should be used for ‘value%’
(ie, not an array).
XMODEM SEND Transfers a BASIC program to or from a remote computer using the XModem
or protocol. The transfer is done over the USB console connection.
XMODEM SEND file$ XMODEM SEND will send the current program held in the PicoMite's
program memory to the remote device.
or
XMODEM RECEIVE will accept a program sent by the remote device and
XMODEM RECEIVE
save it into the PicoMite's the program memory overwriting the program
or currently held there.
XMODEM RECEIVE file$ In both cases you can also specify 'file$' which will transfer the data to/from a
or file on the Flash Filesystem or SD Card. If the file already exists it will be
XMODEM CRUNCH overwritten when receiving a file.
Note that the data is buffered in RAM which limits the maximum transfer size.
This command also creates a backup of the program in flash memory which will
be automatically retrieved if the CPU is reset of the power is lost.
The CRUNCH option works like RECEIVE but will remove all comments,
blank lines and unnecessary spaces from the program before saving. This can
be used on large programs to allow them to fit into limited memory.
SEND, RECEIVE and CRUNCH can be abbreviated to S, R and C.
ABS( number ) Returns the absolute value of the argument 'number' (i.e. any negative sign is
removed and a positive number is returned).
ACOS( number ) Returns the inverse cosine of the argument 'number' in radians.
ASC( string$ ) Returns the ASCII code (i.e. byte value) for the first letter in ‘string$’.
ASIN( number ) Returns the inverse sine value of the argument 'number' in radians.
ATAN2( y, x ) Returns the arc tangent of the two numbers x and y as an angle expressed in
radians.
It is similar to calculating the arc tangent of y / x, except that the signs of
both arguments are used to determine the quadrant of the result.
BIN$( number [, chars]) Returns a string giving the binary (base 2) value for the 'number'.
'chars' is optional and specifies the number of characters in the string with zero
as the leading padding character(s).
BIT(var%, bitno) 'returns the value of a specific bit (0-63) in an integer variable (0 or 1).
See also the BIT command
BYTE(var$, byteno) Returns the integer value of a specific byte in a string (0-255). This is the
equivalent of ASC(MID$(var$,byteno,1)) but operates much faster.
See also the BYTE command
CHOICE(condition, This function allows you to do simple either/or selections more efficiently and
ExpressionIfTrue, faster than using IF THEN ELSE ENDIF clauses.
ExpressionIfFalse) The condition is anything that will resolve to nonzero (true) or zero (false).
The expressions are anything that you could normally assign to a variable or
use in a command and can be integers, floats or strings.
Examples:
PRINT CHOICE(1, "hello","bye") will print "Hello"
PRINT CHOICE (0, "hello","bye") will print "Bye"
a=1 : b=1 : PRINT CHOICE (a=b, 4, 5) will print 4
CHR$( number ) Returns a one-character string consisting of the character corresponding to the
ASCII code (i.e. byte value) indicated by argument 'number'.
CINT( number ) Round numbers with fractional portions up or down to the next whole number
or integer.
For example, 45.47 will round to 45
45.57 will round to 46
-34.45 will round to -34
-34.55 will round to -35
See also INT() and FIX().
CWD$ Returns the current working directory on the Flash Filesystem or SD Card.
Invalid for exFAT format.
The format is: A:/dir1/dir2.
DATE$ Returns the current date based on MMBasic’s internal clock as a string in the
form "DD-MM-YYYY". For example, "28-07-2012".
DATETIME$(n) Returns the date and time corresponding to the epoch number ‘n’ (number of
seconds that have elapsed since midnight GMT on January 1, 1970).
The format of the returned string is “dd-mm-yyyy hh:mm:ss”. Use the text
NOW to get the current datetime string, ie, DATETIME$(NOW)
DAY$(date$) Returns the day of the week for a given date as a string.
For example, “Monday”, “Tuesday” etc.
‘date$’ is a string and its format can be DD-MM-YY or DD-MM-YYYY or
YYYY-MM-DD. You can also use NOW to get the day for the current date,
eg, PRINT DAY$(NOW)
DISTANCE( trigger, echo ) Measure the distance to a target using the HC-SR04 ultrasonic distance sensor.
or Four pin sensors have separate trigger and echo connections. 'trigger' is the I/O
DISTANCE( trig-echo ) pin connected to the "trig" input of the sensor and 'echo' is the pin connected to
the "echo" output of the sensor.
Three pin sensors have a combined trigger and echo connection and in that case
you only need to specify one I/O pin to interface to the sensor.
Note that the HC-SR04 is a 5V device so level shifting will be required on Pico
(RP2040) processors but not on Pico 2 (RP2350) processors.
The I/O pins are automatically configured by this function and multiple sensors
can be used on different I/O pins.
The value returned is the distance in centimetres to the target or -1 if no target
was detected or -2 if there was an error (i.e. sensor not connected).
EOF( [#]fnbr ) Will return true if the file previously opened on the Flash Filesystem or SD
Card for INPUT with the file number ‘#fnbr’ is positioned at the end of the file.
The # is optional. Also see the OPEN, INPUT and LINE INPUT commands
and the INPUT$ function.
EPOCH(DATETIME$) Returns the epoch number (number of seconds that have elapsed since midnight
GMT on January 1, 1970) for the supplied DATETIME$ string.
The format for DATETIME$ is “dd-mm-yyyy hh:mm:ss”, “dd-mm-yy
hh:mm:ss”, or “yyyy-mm-dd hh:mm:ss”,. Use NOW to get the epoch number
for the current date and time, i.e. PRINT EPOCH(NOW)
EVAL( string$ ) Will evaluate 'string$' as if it is a BASIC expression and return the result.
'string$' can be a constant, a variable or a string expression. The expression can
use any operators, functions, variables, subroutines, etc that are known at the
time of execution. The returned value will be an integer, float or string
depending on the result of the evaluation.
For example: S$ = "COS(RAD(30)) * 100" : PRINT EVAL(S$)
Will display: 86.6025
EXP( number ) Returns the exponential value of 'number', i.e. e^x where x is 'number'.
FIX( number ) Truncate a number to a whole number by eliminating the decimal point and all
characters to the right of the decimal point.
For example 9.89 will return 9 and -2.11 will return -2.
The major difference between FIX() and INT() is that FIX() provides a true
integer function (i.e. does not return the next lower number for negative
numbers as INT() does). This behaviour is for Microsoft compatibility.
See also CINT() .
FLAG(n%) Returns the value (0 or 1) of the bit n% (0-63) in the system flag register.
See also MM.FLAGS and the FLAG and FLAGS commands
FORMAT$( nbr [, fmt$] ) Will return a string representing ‘nbr’ formatted according to the specifications
in the string ‘fmt$’.
The format specification starts with a % character and ends with a letter.
Anything outside of this construct is copied to the output as is.
The structure of a format specification is:
% [flags] [width] [.precision] type
Where ‘flags’ can be:
- Left justify the value within a given field width
0 Use 0 for the pad character instead of space
+ Forces the + sign to be shown for positive numbers
space Causes a positive value to display a space for the sign. Negative
values still show the – sign
‘width’ is the minimum number of characters to output, less than this the
number will be padded, more than this the width will be expanded.
‘precision’ specifies the number of fraction digits to generate with an e, or f
type or the maximum number of significant digits to generate with a g type and
defaults to 4 digits. If specified, the precision must be preceded by a dot (.).
GPS() The GPS functions are used to return data from a serial communications
channel opened as GPS.
The function GPS(VALID) should be checked before any of these functions are
used to ensure that the returned value is valid.
GPS(DATE) Returns the normal date string corrected for local time eg, “12-01-2020”.
GPS(DOP) Returns DOP (dilution of precision) value (if sentence GGA is enabled).
GPS(FIX) Returns non zero (true) if the GPS has a fix on sufficient satellites and is
producing valid data.
GPS(GEOID) Returns the geoid-ellipsoid separation (if sentence GGA is enabled).
GPS(LATITUDE) Returns the latitude in degrees as a floating point number, values are negative
for South of equator
GPS(LONGITUDE) Returns the longitude in degrees as a floating point number, values are
negative for West of the meridian.
GPS(TIME) Returns the normal time string corrected for local time eg, “12:09:33”.
GPS(TRACK) Returns the track over the ground (degrees true) as a floating point number.
HEX$( number [, chars]) Returns a string giving the hexadecimal (base 16) value for the 'number'.
'chars' is optional and specifies the number of characters in the string with zero
as the leading padding character(s).
INKEY$ Checks the console input buffer and, if there is one or more characters waiting
in the queue, will remove the first character and return it as a single character in
a string.
If the input buffer is empty this function will immediately return with an empty
string (i.e. "").
INPUT$(nbr, [#]fnbr) Will return a string composed of ‘nbr’ characters read from a file or serial
communications port opened as 'fnbr'. This function will return as many
characters as are in the file or receive buffer up to ‘nbr’. If there are no
characters available it will immediately return with an empty string.
#0 can be used which refers to the console's input buffer.
The # is optional. Also see the OPEN command.
INT( number ) Truncate an expression to the next whole number less than or equal to the
argument. For example 9.89 will return 9 and -2.11 will return -3.
This behaviour is for Microsoft compatibility, the FIX() function provides a
true integer function. See also CINT() .
JSON$(array%(), string$) Returns a string representing a specific item out of the JSON input stored in the
longstring array%(). Note that many JSON data sets are quite large and may be
too big to parse with the memory available.
Examples (taken from api.openweathermap.org):
JSON$(a%(), “name”)
JSON$(a%(), “coord.lat”)
JSON$(a%(), “weather[0].description”)
JSON$(a%(),”list[4].weather[0].description
KEYDOWN(n) Return the decimal ASCII value of the USB keyboard key that is currently held
down or zero if no key is down. The decimal values for the function and arrow
keys are listed in Appendix F.
This function will report multiple simultaneous key presses and the parameter
'n' is the number of the keypress to report. KEYDOWN(0) will return the
number of keys being pressed
For example, if "c", "g" and "p" are pressed simultaneously KEYDOWN(0)
will return 3, KEYDOWN(1) will return 99, KEYDOWN(2) will return 103,
etc. The keys do not need to be pressed simultaneously and will report in the
order pressed. Taking a finger off a key will promote the next key pressed to
#1.
The first key ('n' = 1) is entered in the keyboard buffer (accessible using
INKEY$) while keys 2 to 6 can only be accessed via this function. Using this
function will clear the console input buffer.
KEYDOWN(7) will give any modifier keys that are pressed. These keys do not
add to the count in keydown(0)
The return value is a bitmask as follows:
lalt = 1, lctrl = 2, lgui = 4, lshift = 8, ralt = 16, rctrl = 32, rgui = 64, rshift = 128
KEYDOWN(8) will give the current status of the lock keys. These keys do not
add to the count in keydown(0)
The return value is a bitmask as follows:
caps_lock = 1, num_lock = 2, scroll_lock = 4
Note that some keyboards will limit the number of active keys that they can
report on.
LCOMPARE(array1%(), Compare the contents of two long string variables ‘array1%()’ and ‘array2%()’.
array2%()) The returned is an integer and will be -1 if ‘array1%()’ is less than ‘array2%()’.
It will be zero if they are equal in length and content and +1 if ‘array1%()’ is
greater than ‘array2%()’. The comparison uses the ASCII character set and is
case sensitive.
LGETBYTE(array%(), n) Returns the numerical value of the 'n'th byte in the LONGSTRING held in
'array%()'. This function respects the setting of OPTION BASE in determining
which byte to return.
LGETSTR$(array%(), start, Returns part of a long string stored in ‘array%()’ as a normal MMBasic string.
length) The parameters start and length define the part of the string to be returned.
LOC( [#]fnbr ) For a file on the Flash Filesystem or SD Card opened as 'fnbr' this will return
the current position of the read/write pointer in the file. Note that the first byte
in a file is numbered 1.
For a serial communications port opened as 'fnbr' this function will return the
number of bytes received and waiting in the receive buffer to be read. #0 can
be used which refers to the console's input buffer.
The # is optional.
LOF( [#]fnbr ) For a file on the Flash Filesystem or SD Card opened as 'fnbr' this will return
the current length of the file in bytes.
For a serial communications port opened as 'fnbr' this function will return the
space (in characters) remaining in the transmit buffer. Note that when the
buffer is full MMBasic will pause when adding a new character and wait for
some space to become available so this function can be used to avoid this.
The # is optional.
NB: for VGA all colours set by the map command will be converted to the
nearest RGB121 colour as determined by the VGA resistor network. For HDMI
displays colours will be converted to the nearest RGB555 colour (640x480
resolution) or RGB332 colour (1024x768 or 1280x720 resolution)
MATH(CRCn data [,length] Calculates the CRC to n bits (8, 12, 16, 32) of “data”. “data” can be an integer
[,polynome] [,startmask] or floating point array or a string variable. “Length” is optional and if not
specified the size of the array or string length is used. The defaults for
[,endmask] [,reverseIn]
startmask, endmask reverseIn, and reversOut are all zero. reverseIn, and
[,reverseOut] reversOut are both Booleans and take the value 1 or 0. The defaults for
polynomes are CRC8=&H07, CRC12=&H80D, CRC16=&H1021,
crc32=&H04C11DB7
eg, for crc16_CCITT use MATH(CRC16 array(), n,, &HFFFF)
MATH(RAND) Returns a random number 0.0 <= n < 1.0 using the "Mersenne Twister
algorithm. If not seeded with MATH RANDOMIZE the first usage seeds with
the time in microseconds since boot
Simple Statistics
Returns the Pearson's chi-squared value of the two dimensional array a())
MATH(CHI a())
Returns the associated probability in % of the Pearson's chi-squared value of
MATH(CHI_p a()) the two dimensional array a())
MATH(CROSSING array() This returns the array index at which the values in the array pass the "level" in
[,level] [,direction] the direction specified. level defaults to 0. Direction defaults to 1 ( valid values
are -1 or 1)
MATH(CORREL a(), a()) Returns the Pearson’s correlation coefficient between arrays a() and b()
MATH(MAX a() [,index%]) Returns the maximum of all values in the a() array, a() can have any number of
dimensions. If the integer variable is specified then it will be updated with the
index of the maximum value in the array. This is only available on one-
dimensional arrays
MATH(MEAN a()) Returns the average of all values in the a() array, a() can have any number of
dimensions
MATH(MEDIAN a()) Returns the median of all values in the a() array, a() can have any number of
dimensions
Returns the sample standard deviation of all values in the a() array, a() can have
MATH(SD a()) any number of dimensions
Returns the sum of all values in the a() array, a() can have any number of
MATH(SUM a()) dimensions
Vector Arithmetic
Returns the magnitude of the vector v(). The vector can have any number of
MATH(MAGNITUDE v()) elements
MATH(DOTPRODUCT v1(), Returns the dot product of two vectors v1() and v2(). The vectors can have any
v2()) number of elements but must have the same cardinality
Matrix Arithmetic
Returns the determinant of the array. The array must be square.
MATH(M_DETERMINANT
array!())
MATH(PID channel, This function must be called in the PID callback subroutine for the ‘channel’
setpoint!, measurement)) specified and returns the output of the controller function.
The ‘setpoint’ value is the desired state that the controller is trying to achieve.
The ‘measurement’ is the current value of the real world.
https://www.thebackshed.com/forum/ViewTopic.php?FID=16&TID=17263
For an example of setting up and running a PID controller
MATH(BASE64 Returns the length of out$/out(). This base64 encodes or decodes the data in 'in'
ENCODE/DECODE in$/in(), and puts the result in 'out'. Where arrays are used as the output they must be big
out$/out()) enough relative to the input and the direction. Encryption increases length by
4/3 and decryption decreases it by 3/4.
MAX( arg1 [, arg2 [, …]] ) Returns the maximum or minimum number in the argument list.
or Note that the comparison is a floating point comparison (integer arguments are
MIN( arg1 [, arg2 [, …]] ) converted to floats) and a float is returned.
MID$( string$, start ) Returns a substring of ‘string$’ beginning at ‘start’ and continuing for ‘nbr’
or characters. The first character in the string is number 1.
MID$( string$, start, nbr ) If ‘nbr’ is omitted the returned string will extend to the end of ‘string$’
OCT$( number [, chars]) Returns a string giving the octal (base 8) representation of 'number'.
'chars' is optional and specifies the number of characters in the string with zero
as the leading padding character(s).
PEEK(BYTE addr%) Will return a byte or a word within the processor’s virtual memory space.
or BYTE will return the byte (8-bits) located at 'addr%'
PEEK(SHORT addr%) SHORT will return the short integer (16-bits) located at 'addr%'
or
PEEK(WORD addr%) WORD will return the word (32-bits) located at 'addr%'
or
PEEK(INTEGER addr%) INTEGER will return the integer (64-bits) located at 'addr%'
or
PEEK(FLOAT addr%) FLOAT will return the floating point number (32-bits) located at 'addr%'
or
PEEK(VARADDR var) VARADDR will return the address (32-bits) of the variable 'var' in memory.
or An array is specified as var().
PEEK(CFUNADDR cfun) CFUNADDR will return the address (32-bits) of the CFunction 'cfun' in
memory. This address can be passed to another CFunction which can then call
or
it to perform some common process.
PEEK(VAR var, ±offset)
VAR, will return a byte in the memory allocated to 'var'. An array is specified
or as var().
PEEK( VARTBL, ±offset) VARTBL, will return a byte in the memory allocated to the variable table
or maintained by MMBasic. Note that there is a comma after the keyword
PEEK( PROGMEM, ±offset) VARTBL.
PEEK(BP, n%) peek(bp n%) ' returns the byte at address n% and increments n% to point to the
next byte.
peek(sp n%) ' returns the short at address n% and increments n% to point to the
PEEK(SP,n%)
next short.
peek(wp n%) ' returns the word at address n% and increments n% to point to
PEEK(WP,n%) the next word.
PIN( pin ) Returns the value on the external I/O ‘pin’. Zero means digital low, 1 means
digital high and for analogue inputs it will return the measured voltage as a
floating point number.
Frequency inputs will return the frequency in Hz. A period input will return
the period in milliseconds while a count input will return the count since reset
(counting is done on the positive rising edge). The count input can be reset to
zero by resetting the pin to counting input (even if it is already so configured).
When a pin is configured as an output this function will return the value of the
output setting (ie, high or low). Also see the SETPIN and PIN() = commands.
Refer to the chapter Using the I/O pins for a general description of the
PicoMite's input/output capabilities.
PIN( BOOTSEL ) Returns the state of the boot select switch allowing it to be used as a user input
in a program.
PIN( TEMP ) Returns the temperature of the RP2040/RP2350 chip (see the data sheet for the
details).
PIO(DMA RX POINTER) Returns the current data item being written or read by the PIO.
PIO(DMA TX POINTER)
PIO (SHIFTCTRL helper function to calculate the value of shiftctrl for the INIT MACHINE
push_threshold command .
[,pull_threshold] [,autopush]
[,autopull] [,in_shiftdir]
[,out_shiftdir] [,fjoin_tx]
[,fjoin_rx])
PIO (PINCTRL helper function to calculate the value of pinctrl for the INIT MACHINE
no_side_set_pins command. Note: The pin parameters must be formatted as GPn.
[,no_set_pins] [,no_out_pins]
[,IN base]
[,side_set_base] [,set_base][,
out_base])
PIO (EXECCTRL jmp_pin helper function to calculate the value of execctrl for the INIT MACHINE
,wrap_target, wrap command
[,side_pindir] [,side_en])
PIO (FSTAT pio) returns the value of the FSTAT register for the pio specified
PIO (FLEVEL pio) returns the value of the FLEVEL register for the pio specified
PIO(FLEVEL pio)
PIO(FLEVEL pio ,sm, DIR) dir can be RX or TX. Returns the level of the specific fifo
PIO(NEXT LINE) Returns the next unused PIO instruction slot after a block of PIO instructions
terminated by END PROGRAM
PIXEL( x, y) Returns the colour of a pixel on the video output or LCD display. 'x' is the
horizontal coordinate and 'y' is the vertical coordinate of the pixel.
If an LCD display is used it must use one of the SSD1963, ILI9341, ILI9488,
or ST7789_320 controllers.
PORT(start, nbr [,start, Returns the value of a number of I/O pins in one operation.
nbr]…) 'start' is an I/O pin number and its value will be returned as bit 0. 'start'+1 will be
returned as bit 1, 'start'+2 will be returned as bit 2, and so on for 'nbr' number of
bits. I/O pins used must be numbered consecutively and any I/O pin that is
invalid or not configured as an input will cause an error. The start/nbr pair can be
repeated up to 25 times if additional groups of input pins need to be added.
This function will also return the output state of a pin configured as an output.
This can be used to conveniently communicate with parallel devices like
memory chips. Any number of I/O pins (and therefore bits) can be used from 1
to the number of I/O pins on the chip.
See the PORT command to simultaneously output to a number of pins.
PULSIN( pin, polarity ) Measures the width of an input pulse from 1µs to 1 second with 0.1µs
or resolution.
PULSIN( pin, polarity, t1 ) 'pin' is the I/O pin to use for the measurement, it must be previously configured
as a digital input. 'polarity' is the type of pulse to measure, if zero the function
or
will return the width of the next negative pulse, if non zero it will measure the
PULSIN( pin, polarity, t1, t2 ) next positive pulse.
't1' is the timeout applied while waiting for the pulse to arrive, 't2' is the timeout
used while measuring the pulse. Both are in microseconds (µs) and are
optional. If 't2' is omitted the value of 't1' will be used for both timeouts. If
both 't1' and 't2' are omitted then the timeouts will be set at 100000 (i.e.
100ms).
This function returns the width of the pulse in microseconds (µs) or -1 if a
timeout has occurred. The measurement is accurate to ±0.5% and ±0.5µs.
Note that this function will cause the running program to pause while the
measurement is made and interrupts will be ignored during this period.
RIGHT$( string$, number-of- Returns a substring of ‘string$’ with ‘number-of-chars’ from the right (end) of
chars ) the string.
RND( number ) Returns a pseudo-random number in the range of 0 to 0.999999. The 'number'
or value is ignored if supplied.
RND See also the RANDOMIZE command (RP2040 only).
SGN( number ) Returns the sign of the argument 'number', +1 for positive numbers, 0 for 0, and
-1 for negative numbers.
SPRITE(C, [#]n ) Returns the number of currently active collisions for sprite n. If n=0 then
returns the number of sprites that have a currently active collision following a
SPRITE SCROLL command
SPRITE(C, [#]n, m) Returns the number of the sprite which caused the “m”th collision of sprite n.
If n=0 then returns the sprite number of “m”th sprite that has a currently active
collision following a SPRITE SCROLL command.
If the collision was with the edge of the screen then the return value will be:
&HF1 collision with left of screen
&HF2 collision with top of screen
&HF4 collision with right of screen
&HF8 collision with bottom of screen
SPRITE(D ,[#]s1, [#]s2) Returns the distance between the centres of sprites ‘s1’ and ‘s2’ (returns -1 if
either sprite is not active)
SPRITE(E, [#]n Returns a bitmap indicating any edges of the screen the sprite is in contact with:
1 =left of screen, 2=top of screen, 4=right of screen, 8=bottom of screen
Returns the height of sprite n. This function is active whether or not the sprite is
SPRITE(H,[#]n) currently displayed (active).
SPRITE(S) Returns the number of the sprite which last caused a collision. NB if the
number returned is Zero then the collision is the result of a SPRITE SCROLL
command and the SPRITE(C…) function should be used to find how many and
which sprites collided.
SPRITE(T, [#]n) Returns a bitmap showing all the sprites currently touching the requested sprite
Bits 0-63 in the returned integer represent a current collision with sprites 1 to
64 respectively
SPRITE(V,[#]so1, [#]s2) Returns the vector from sprite 's1' to 's2' in radians.
The angle is based on the clock so if 's2' is above 's1' on the screen then the
answer will be zero. This can be used on any pair of sprites that are visible. If
either sprite is not visible the function will return -1.
This is particularly useful after a collision if the programmer wants to make
some differential decision based on where the collision occurred. The angle is
calculated between the centre of each of the sprites which may of course be
different sizes.
Returns the width of sprite n. This function is active whether or not the sprite is
SPRITE(W, [#]n) currently displayed (active).
SPRITE(X, [#]n) Returns the X-coordinate of sprite n. This function is only active when the
sprite is currently displayed (active). Returns 10000 otherwise.
SPRITE(Y, [#]n) Returns the Y-coordinate of sprite n. This function is only active when the
sprite is currently displayed (active). Returns 10000 otherwise.
STR$( number ) Returns a string in the decimal (base 10) representation of 'number'.
or If 'm' is specified sufficient spaces will be added to the start of the number to
STR$( number, m ) ensure that the number of characters before the decimal point (including the
negative or positive sign) will be at least 'm' characters. If 'm' is zero or the
or
number has more than 'm' significant digits no padding spaces will be added.
STR$( number, m, n )
If 'm' is negative, positive numbers will be prefixed with the plus symbol and
or negative numbers with the negative symbol. If 'm' is positive then only the
STR$( number, m, n, c$ ) negative symbol will be used.
'n' is the number of digits required to follow the decimal place. If it is zero the
string will be returned without the decimal point. If it is negative the output
will always use the exponential format with 'n' digits resolution. If 'n' is not
specified the number of decimal places and output format will vary
automatically according to the number.
STRING$( nbr, ascii ) Returns a string 'nbr' bytes long consisting of either the first character of string$
or or the character representing the ASCII value 'ascii' which is an integer or float
number in the range of 0 to 255.
STRING$( nbr, string$ )
TAB( number ) Outputs spaces until the column indicated by 'number' has been reached on the
console output.
TEMPR( pin [,timeout]) Return the temperature measured by a DS18B20 temperature sensor connected
to 'pin' (which does not have to be configured).
TIME$ Returns the current time based on MMBasic's internal clock as a string in the
form "HH:MM:SS" in 24 hour notation. For example, "14:30:00".
To set the current time use the command TIME$ = .
TIMER Returns the elapsed time in milliseconds (eg, 1/1000 of a second) since reset.
The timer is reset to zero on power up or a CPU restart and you can also reset it
by using TIMER as a command. If not specifically reset it will continue to
count up forever (it is a 64 bit number and therefore will only roll over to zero
after 200 million years).
TOUCH(X) Will return the X or Y coordinate of the location currently touched on an LCD
or panel.
TOUCH(Y If the screen is not being touched the function will return -1.
or FT6336 only For the FT6336 TOUCH(X2) and TOUCH(Y2) returns the position of a second
touch location or -1 if no second location is touched.
TOUCH(X2)
or
TOUCH(Y2)
VAL( string$ ) Returns the numerical value of the ‘string$’. If 'string$' is an invalid number
the function will return zero.
This function will recognise the &H prefix for a hexadecimal number, &O for
octal and &B for binary.
BITBANG Replaced by the command DEVICE. For compatibility BITBANG can still be
used in programs and will be automatically converted to DEVICE
POS For the console, returns the current cursor position in the line in characters.
RETURN RETURN concludes a subroutine called by GOSUB and returns to the
statement after the GOSUB.
I/O Pins
Before a serial interface can be used the I/O pins must be defined using the following command for the first
channel (referred as COM1):
SETPIN rx, tx, COM1
Valid pins are RX: GP1, GP13 or GP17
TX: GP0, GP12, GP16 or GP28
And the following command for the second channel (referred to as COM2):
SETPIN rx, tx, COM2
Valid pins are RX: GP5, GP9 or GP21
TX: GP4, GP8 or GP20
TX is data from the Raspberry Pi Pico and RX is data to it. Note that on the WebMite version COM1 and
COM2 are not available on GP20 to GP28
The signal polarity is standard for devices running at TTL voltages. Idle is voltage high, the start bit is voltage
low, data uses a high voltage for logic 1 and the stop bit is voltage high. These signal levels allow you to
directly connect to devices like GPS modules (which generally use TTL voltage levels).
Commands
After being opened the serial port will have an associated file number and you can use any commands that operate
with a file number to read and write to/from it. A serial port can be closed using the CLOSE command.
The following is an example:
SETPIN GP13, GP16, COM1 ' assign the I/O pins for the first serial port
OPEN "COM1:4800" AS #5 ' open the first serial port with a speed of 4800 baud
PRINT #5, "Hello" ' send the string "Hello" out of the serial port
dat$ = INPUT$(20, #5) ' get up to 20 characters from the serial port
CLOSE #5 ' close the serial port
Interrupts
The interrupt subroutine (if specified) will operate the same as a general interrupt on an external I/O pin (see
the chapter Using the I/O pins for a description).
When using interrupts you need to be aware that it will take some time for MMBasic to respond to the interrupt
and more characters could have arrived in the meantime, especially at high baud rates. For example, if you
have specified the interrupt level as 200 characters and a buffer of 256 characters then quite easily the buffer
will have overflowed by the time the interrupt subroutine can read the data. In this case the buffer should be
increased to 512 characters or more.
I/O Pins
Before the I2C interface can be used the I/O pins must be defined using the following command for the first
channel (referred as I2C):
SETPIN sda, scl, I2C
Valid pins are SDA: GP0, GP4, GP8, GP12, GP16, GP20 or GP28
SCL: GP1, GP5, GP9, GP13, GP17 or GP21
Note that on the WebMite version I2C SDA is not available on GP28
And the following command for the second channel (referred to as I2C2):
SETPIN sda, scl, I2C2
Valid pins are SDA: GP2, GP6, GP10, GP14, GP18, GP22 or GP26
SCL: GP3, GP7, GP11, GP15, GP19 or GP27
2
When running the I C bus at above 100 kHz the cabling between the devices becomes important. Ideally the
cables should be as short as possible (to reduce capacitance) and the data and clock lines should not run next to
each other but have a ground wire between them (to reduce crosstalk).
If the data line is not stable when the clock is high, or the clock line is jittery, the I2C peripherals can get
"confused" and end up locking the bus (normally by holding the clock line low). If you do not need the higher
speeds then operating at 100 kHz is the safest choice.
The command I2C CHECK addr can be used to check if a device is present at the address ‘addr’. This will set
the read only variable MM.I2C to 0 if a device responds or 1 if there is no response.
I2C OPEN speed, Enables the I2C module in master mode. The I2C command refers to channel 1
timeout while the command I2C2 refers to channel 2 using the same syntax.
‘speed’ is the clock speed (in KHz) to use and must be either 100, 400 or 1000.
‘timeout’ is a value in milliseconds after which the master send and receive
commands will be interrupted if they have not completed. The minimum value is
100. A value of zero will disable the timeout (though this is not recommended).
I2C WRITE addr, Send data to the I2C slave device. The I2C command refers to channel 1 while the
option, sendlen, command I2C2 refers to channel 2 using the same syntax.
senddata [,sendata ..] ‘addr’ is the slave’s I2C address.
‘option’ can be 0 for normal operation or 1 to keep control of the bus after the
command (a stop condition will not be sent at the completion of the command)
‘sendlen’ is the number of bytes to send.
‘senddata’ is the data to be sent - this can be specified in various ways (all data
sent will be sent as bytes with a value between 0 and 255):
The data can be supplied as individual bytes on the command line.
Example: I2C WRITE &H6F, 0, 3, &H23, &H43, &H25
The data can be in a one dimensional array specified with empty brackets (i.e.
no dimensions). ‘sendlen’ bytes of the array will be sent starting with the first
element. Example: I2C WRITE &H6F, 0, 3, ARRAY()
The data can be a string variable (not a constant).
Example: I2C WRITE &H6F, 0, 3, STRING$
I2C CLOSE Disables the master I2C module and returns the I/O pins to a "not configured" state.
This command will also send a stop if the bus is still held.
I2C SLAVE WRITE Send the data to the I2C master. The I2C command refers to channel 1 while the
sendlen, senddata command I2C2 refers to channel 2 using the same syntax.
[,sendata ..] This command should be used in the send interrupt (ie in the 'send_int' subroutine
when the master has requested data). Alternatively, a flag can be set in the
interrupt subroutine and the command invoked from the main program loop when
the flag is set.
‘sendlen is the number of bytes to send.
‘senddata’ is the data to be sent. This can be specified in various ways, see the I2C
WRITE commands for details.
I2C SLAVE READ Receive data from the I2C master device. The I2C command refers to channel 1
rcvlen, rcvbuf, rcvd while the command I2C2 refers to channel 2 using the same syntax.
This command should be used in the receive interrupt (ie in the 'rcv_int' subroutine
when the master has sent some data). Alternatively a flag can be set in the receive
interrupt subroutine and the command invoked from the main program loop when
the flag is set.
‘rcvlen’ is the maximum number of bytes to receive.
‘rcvbuf’ is the variable to receive the data. This can be specified in various ways,
see the I2C READ commands for details.
‘rcvd’ is a variable that, at the completion of the command, will contain the actual
number of bytes received (which might differ from ‘rcvlen’).
I2C SLAVE CLOSE Disables the slave I2C module and returns the external I/O pins to a "not
configured" state. They can then be configured using SETPIN.
7-Bit Addressing
The standard addresses used in these commands are 7-bit addresses (without the read/write bit). MMBasic will
add the read/write bit and manipulate it accordingly during transfers.
Some vendors provide 8-bit addresses which include the read/write bit. You can determine if this is the case
because they will provide one address for writing to the slave device and another for reading from the slave. In
these situations you should only use the top seven bits of the address. For example: If the read address is 9B
(hex) and the write address is 9A (hex) then using only the top seven bits will give you an address of 4D (hex).
Another indicator that a vendor is using 8-bit addresses instead of 7-bit addresses is to check the address range.
All 7-bit addresses should be in the range of 08 to 77 (hex). If your slave address is greater than this range then
probably your vendor has provided an 8-bit address.
Examples
As an example of a simple communications where the Raspberry Pi Pico is the master, the following
program will read and display the current time (hours and minutes) maintained by a PCF8563 real
time clock chip connected to the second I2C channel:
DIM AS INTEGER RData(2) ' this will hold received data
SETPIN GP6, GP7, I2C2 ' assign the I/O pins for I2C2
I2C2 OPEN 100, 1000 ' open the I2C channel
I2C2 WRITE &H51, 0, 1, 3 ' set the first register to 3
I2C2 READ &H51, 0, 2, RData() ' read two registers
I2C2 CLOSE ' close the I2C channel
PRINT "Time is " RData(1) ":" RData(0)
This is an example of communications between two Raspberry Pi Picos where one is the master and
the other is the slave.
First the master:
SETPIN GP2, GP3, I2C2
I2C2 OPEN 100, 1000
i = 10
DO
i = i + 1
a$ = STR$(i)
I2C2 WRITE &H50, 0, LEN(a$), a$
PAUSE 200
I2C2 READ &H50, 0, 8, a$
PRINT a$
PAUSE 200
LOOP
SUB rint
LOCAL count, a$
I2C2 SLAVE READ 10, a$, count
PRINT LEFT$(a$, count)
END SUB
SUB tint
LOCAL a$ = Time$
I2C2 SLAVE WRITE LEN(a$), a$
END SUB
I/O Pins
Before an SPI interface can be used the I/O pins for the channel must be allocated using the following
commands. For the first channel (referred as SPI) it is:
SETPIN rx, tx, clk, SPI
Valid pins are RX: GP0, GP4, GP16 or GP20
TX: GP3, GP7 or GP19
CLK: GP2, GP6 or GP18
And the following command for the second channel (referred to as SPI2) is:
SETPIN rx, tx, clk, SPI2
Valid pins are RX: GP8, GP12 or GP28
TX: GP11, GP15 or GP27
CLK: GP10, GP14 or GP26
TX is data from the Raspberry Pi Pico and RX is data to it.
Note that on the WebMite version SPI1 and SPI2 are not available on GP20 to GP28
SPI Open
To use the SPI function the SPI channel must be first opened.
The syntax for opening the first SPI channel is (use SPI2 for the second channel):
SPI OPEN speed, mode, bits
Where:
‘speed’ is the speed of the clock. It is a number representing the clock speed in Hz.
'mode' is a single numeric digit representing the transmission mode – see Transmission Format below.
'bits' is the number of bits to send/receive. This can be any number in the range of 4 to 16 bits.
It is the responsibility of the program to separately manipulate the CS (chip select) pin if required.
Transmission Format
The most significant bit is sent and received first. The format of the transmission can be specified by the 'mode'
as shown below. Mode 0 is the most common format.
Mode Description CPOL CPHA
0 Clock is active high, data is captured on the rising edge and output on the falling edge 0 0
1 Clock is active high, data is captured on the falling edge and output on the rising edge 0 1
2 Clock is active low, data is captured on the falling edge and output on the rising edge 1 0
3 Clock is active low, data is captured on the rising edge and output on the falling edge 1 1
For a more complete explanation see: http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
Standard Send/Receive
When the first SPI channel is open data can be sent and received using the SPI function (use SPI2 for the
second channel). The syntax is:
received_data = SPI(data_to_send)
Note that a single SPI transaction will send data while simultaneously receiving data from the slave.
‘data_to_send’ is the data to send and the function will return the data received during the transaction.
‘data_to_send’ can be an integer or a floating point variable or a constant.
Bulk Send/Receive
Data can also be sent in bulk (use SPI2 for the second channel):
SPI WRITE nbr, data1, data2, data3, … etc
or
SPI WRITE nbr, string$
or
SPI WRITE nbr, array()
In the first method 'nbr' is the number of data items to send and the data is the expressions in the argument list
(i.e. 'data1', data2' etc). The data can be an integer or a floating point variable or a constant.
In the second or third method listed above the data to be sent is contained in the 'string$' or the contents of
'array()' (which must be a single dimension array of integer or floating point numbers). The string length, or the
size of the array must be the same or greater than nbr. Any data returned from the slave is discarded.
Data can also be received in bulk (use SPI2 for the second channel):
SPI READ nbr, array()
Where 'nbr' is the number of data items to be received and array() is a single dimension integer array where the
received data items will be saved. This command sends zeros while reading the data from the slave.
SPI Close
If required the first SPI channel can be closed as follows (the I/O pins will be set to inactive):
SPI CLOSE
Use SPI2 for the second channel.
Examples
The following example shows how to use the SPI port for general I/O. It will send a command 80 (hex) and
receive two bytes from the slave SPI device using the standard send/receive function:
PIN(10) = 1 : SETPIN 10, DOUT ' pin 10 will be used as the enable signal
SETPIN GP20, GP3, GP2, SPI ' assign the I/O pins
SPI OPEN 5000000, 3, 8 ' speed is 5 MHz and the data size is 8 bits
PIN(10) = 0 ' assert the enable line (active low)
junk = SPI(&H80) ' send the command and ignore the return
byte1 = SPI(0) ' get the first byte from the slave
byte2 = SPI(0) ' get the second byte from the slave
PIN(10) = 1 ' deselect the slave
SPI CLOSE ' and close the channel
The following is similar to the example given above but this time the transfer is made using the bulk
send/receive commands:
OPTION BASE 1 ' our array will start with the index 1
DIM data%(2) ' define the array for receiving the data
SETPIN GP20, GP3, GP2, SPI ' assign the I/O pins
PIN(10) = 1 : SETPIN 10, DOUT ' pin 10 will be used as the enable signal
SPI OPEN 5000000, 3, 8 ' speed is 5 MHz, 8 bits data
PIN(10) = 0 ' assert the enable line (active low)
SPI WRITE 1, &H80 ' send the command
SPI READ 2, data%() ' get two bytes from the slave
PIN(10) = 1 ' deselect the slave
SPI CLOSE ' and close the channel
Qualifiers
* 0 or more (not escaped)
\+ 1 or more
\? 0 or 1
\{3\} Exactly 3
\{3,\} 3 or more
\{3,5\} 3,4 or 5
Character Classes
\w digits,letters and _
[:word:] digits,letters and _
[:upper:] Upper case letters_
[:lower:] Lower case letters_
[:alpha:] All letters
[:alnum:] Digits and letters
[:digit:] Digits
[:xdigit:] Hexidecimal digits
[:punct:] Puntuation
[:blank:] Space and tab
[:space:] Blank charaters
[:cntrl:] Control charaters
[:graph:] Printed characters
[:print:] Printed chars and spaces
Overview of PIO
A single PIO block has four independent state machines. All four state machines share a single 32 instruction
program area of flash memory. This memory has write-only access from the main system, but has four read
ports, one for each state machine, so that each can access it independently at its own speed. Each state machine
has its own program counter.
Each state machine also has two 32-bit "scratchpad" registers, X and Y, which can be used as temporary data
stores.
I/O pins are accessed via an input/output mapping module that can access 32 pins (but limited to 30 for the
RP2040). All state machines can access all the pins independently and simultaneously.
The system can write data into the input end of a 4-word 32-bit wide TX FIFO buffer. The state machine can
then use pull to move the output word of the FIFO into the OSR (Output Shift Register). It can also use out to
shift 1-32 bits at a time from the OSR into the output mapping module or other destinations. AUTOPULL can
be used to automatically pull data until the TX FIFO is empty or reaches a preset level.
The system can read data from the output end of a 4-word 32-bit wide RX FIFO buffer. The state machine can
then use in to shift 1-32 bits of data at a time from the input mapping module into the ISR (Input Shift
Register). It can also use push to move the contents of the ISR into the FIFO. AUTOPUSH can be used to
automatically push data until the RX FIFO is full or reaches a preset level.
The FIFO buffers can be reconfigured to form a single direction 8-word 32-bit FIFO in a single direction. The
buffers allow data to be passed to and from the state machines without either the system or the state machine
having to wait for the other.
Each of the four state machines in the PIO has four registers associated with it:
• CLKDIV is the clock divider, which has a 16-bit integer divider and an 8-bit fractional divider. This
sets how fast the state machine runs. It divides down from the main system clock.
• EXECCTRL holds information controlling the translation and execution of the program memory
• SHIFTCTRL controls the arrangement and usage of the shift registers
• PINCTRL controls which and how the GPIO pins are used.
The four state machines of a PIO have shared access to its block of 8 interrupt flags. Any state machine can use
any flag. They can set, reset or wait for them to change. In this way they can be made to run synchronously if
required. The lower four flags are also accessible to and from the main system, so the PIO can be controlled or
pass interrupts back.
DMA can be used to pass information to and from the PIO block via its FIFO from the RP2040's memory
A PIO has nine possible programming instructions, but there can be many variations on each one. For example,
Mov can have up to 8 sources, 8 destinations, 3 process operations during the copy, with optional delay and/or
side set operations!
• Jmp Jump to an absolute address in program memory if a condition is true (or instantly).
• Wait Stall operation of the state machine until a condition is true.
Programming PIO
PicoMite firmware programs the PIO state machine memory using one of 3 methods. Each method will be
explained with an example of the exact same program that toggles one of the GPIO pins of the Raspberry Pi
Pico. Which GPIO pin is toggled, is determined by the configuration, not in the program itself.
PIO ASSEMBLE
This command is used to use the build in assembler to generate the program from mnemonics, then write it
directly into PIO memory.
PIO ASSEMBLE 1,".program test" 'a program has to have a name
PIO ASSEMBLE 1,".line 0" 'start the program at line 0
PIO ASSEMBLE 1,"SET PINDIRS,1" 'SET the GPIO line to output
PIO ASSEMBLE 1,"label:" 'define a label called "label"
PIO ASSEMBLE 1,"SET PINS,1" 'SET the GPIO pin high
PIO ASSEMBLE 1,"SET PINS,0" 'SET the GPIO pin low
PIO ASSEMBLE 1,"JMP label" 'JuMP to "label"
PIO ASSEMBLE 1,".end program list" 'end program, list=show result
PIO PROGRAM LINE
This command can be used to program 16bit values to indidual lines (locations) in the PIO memory.
PIO PROGRAM LINE 1,0,&hE081 'SET pin output
PIO PROGRAM LINE 1,1,&hE001 'SET pin high
PIO PROGRAM LINE 1,2,&hE000 'SET pin low
PIO PROGRAM LINE 1,3,&h0001 'JMP to line 1
PIO PROGRAM
This command writes all 32 lines in one PIO from an array. This is useful once a PIO program is debugged. It
is extremely compact.
DIM a%(7)=(&h0001E0000E001E081,0,0,0,0,0,0,0)
PIO PROGRAM 1,a%()
Configuring PIO
The PicoMite firmware can configure each state machine individually. Configuration allows 2 state machines
to run the exact same program lines (eg, an SPI interface) but operate with different GPIO pins and at different
speeds. There are several configuration fields.
FREQUENCY
PicoMite firmware contains a default configuration for each configuration field, except for the frequency. The
frequency is set by a 16 bit CLKDIV divider from the ARM clock. Example: when OPTION CPUSPEED
126000 is set the PIO can run at speeds between 126MHz and 1.922kHz (126000000 / 65536). Be aware that
higher CPU speeds (overclocking) directly impact the state machine frequency.
PIN CONTROL
PicoMite firmware defaults the GPIO pins for use by MMBasic. For the PIO to take ownership of a GPIO pin
MMBasic needs to assign it to PIO as below.
SETPIN GPxx,PIOx (eg, SETPIN gp0,pio1)
'program pio 1 using an array to write the program in PIO memory, and start
Dim a%(7)=(&h0001E000E001E081,0,0,0,0,0,0,0)
PIO program 1,a%()
Note that the MMBasic program ends, but the sound on the buzzer continues. PIO is independent of the ARM
CPU and continues until it is stopped. Entering the MMBasic editor will stop the PIO.
FIFO's
MMBasic and the PIO exchange information using FIFO's. The PIO's PUSH data into the RX FIFO (MMBasic
is the receiver), or PULL data from the TX FIFO (MMBasic is the transmitter).
When PIO is fetching data from the FIFO the data is transferred to the OSR (Output Shift Register), from there
is can be processed. The PIO can push the data from the ISR (Input shift register) into the FIFO. Additionally,
the PIO has 2 registers X and Y that can be used for storage, or counting. PIO cannot add or subtract or
compare.
Data flow:
MMBasic -> FIFO -> OSR -> PIO (or pins)
PIO (or pins) -> ISR -> FIFO -> MMBasic
PIO CLEAR clears all the PIO FIFO's, as does PIO START and PIO INIT MACHINE.
The MMBAsic program doesn't need to wait for data in the FIFO to appear since the RX FIFO can be assigned
an interrupt. The MMBasic interrupt routine can fetch the data from the FIFO.
Similar for TX interrupt in which case MMBasic gets an interrupt when data is needed for the TX FIFO.
PIO INTERRUPT a,b,c,d
a/ PIO (0 or 1)
b/ state machine (0...3)
c/ Name of RX interrupt handler (i.e. "myRX_Interrupt" or 0 to disable)
d/ Name of TX interrupt handler (i.e. "myTX_Interrupt" or 0 to disable)
EXAMPLE PROGRAM 2
Below program explains many of the above presented MMbasic functions and commands. The program reads a
NES controller (SPI) connected to the Raspberry Pi Pico. The NES controller consists of a HEF4021 shift
register connected to 8 push button switches.
Program uses: wrap and wrap target, IN, side set and delay, PUSH, PIO READ. GP0 and GP1 are in SET for
pin direction, and in side set for compact code.
The wiring is as defined in the code:
'PIO program
PIO assemble 1,".program NES" 'a program needs a name
PIO assemble 1,".side_set 2" 'use 2 bits for side set, 3 for ‘delay
PIO assemble 1,".line 0" 'start code at line 0
PIO assemble 1,"SET pindirs,&b11" 'set GP0,GP1 output, side GP0,GP1 ‘low
PIO assemble 1,".wrap target" 'wrap target = top of the loop
PIO assemble 1,"IN null,32 side 2" 'set ISR to 0, GP1 high (load), ‘GP0 low
PIO assemble 1,"SET X,7 side 0" 'set X counter to 7, GP0,GP1 low
PIO assemble 1,"loop:" 'inner loop label
PIO assemble 1,"IN pins,1 side 0" 'shift 1 databit in, keep GP0,GP1 ‘low
PIO assemble 1,"JMP X-- loop side 1" 'jmp to loop, dec. X, GP0 ‘high(clock)
PIO assemble 1,"PUSH side 0 [7]" 'now X=0, PUSH result into FIFO, ‘delay
7
PIO assemble 1,".wrap" 'end outer loop, repeat
PIO assemble 1,".end program list" 'end of program, list result
'configure pio1
p=Pio(pinctrl 2,2,,gp2,gp0,gp0,) 'GP0,GP1 out (SET and SIDE
‘ SET), GP2 IN
f=1e5 '100kHz
s=PIO(shiftctrl 0,0,0,0,0,0) 'shift in from LSB for IN (and
‘OUT)
e=PIO(execctrl gp0,PIO(.wrap target),PIO(.wrap)) 'wrap and wrap target
The DMA will start the state machine automatically and there is no need for a PIO START command. But,
before starting the transfer make sure a fresh PIO INIT MACHINE is done, so the state machine starts at the
required start address.
When a ring buffer is used, it requires special preparation:
PIO MAKE RING BUFFER a, b
Where: a = name of integer buffer
b = size of the array in bytes
Example :
DIM packed%
PIO MAKE RING BUFFER packed%,4096
'configuration
f=1e4 'PIO run at 10kHz
p=Pio(pinctrl 0,0,0,gp0,,,) 'IN base = GP0
e=Pio(execctrl gp0,PIO(.wrap target),PIO(.wrap)) 'wrap 1 to 0, gp0 is
‘default
s=Pio(shiftctrl 0,0,0,0,0,0) 'shift in through LSB, out is not used
'write the configuration, speed 10kHz (data in FIFO 10us after edge GP0)
PIO init machine 1,0,f,p,e,s,0 'start address = 0
EXAMPLE PROGRAM 4
This program runs on RP2350 only and demonstrates the use of the FIFO’s as individual registers. The PIO of
the RP2350 has specific instructions to support this MOV RXFIFO[y],ISR and MOV OSR,RXFIFO[y].
MMBasic can read/write the 4 individual FIFO registers by use of:
PIO WRITEFIFO a, b, c, d
PIO READFIFO( a, b, c)
a/ pio (0 or 1)
b/ state machine (0...3)
c/ nbr (FIFO register 0…3)
d/ data% (32 bit integer value)
The program configures the FIFO for individual reads, then writes some values in these register. It starts the
PIO that updates 2 of the 4 individual FIFO registers. Then MMBasic reads the values to show only 2 register
have changes, and no data shifted (as would happen in RP2040 FIFO).
pio clear 1
f=1e6 '1MHz
'PIO(EXECCTRL a,b,c)
e=pio(execctrl gp0,0,31) 'default value, not actually changed
'PIO(SHIFTCTRL a,b,c,d,e,f,g,h,i,j)
sr=pio(shiftctrl 0,0,0,0,0,0,0,0,0,1) 'read individual RX, RX=4 deep
sw=pio(shiftctrl 0,0,0,0,0,0,0,0,1,0) 'write individual RX, RX=4 deep
'PIO(PINCTRL a,b,c,d,e,f,g)
p=pio(pinctrl 0,0,0,gp0,gp0,gp0,gp0) 'defaultvalue , not actually changed
'run the PIO program. That should (continuously) write to reg 2 and 3 in the FIFO,
but not alter register 0 and 1
pio start 1,0
You can create a sprite in various ways but essentially you are just storing an image in a buffer. The difference
comes when you SHOW the sprite. In this case, first time in, the firmware stores the area of memory (or
display real-estate) that will be replaced by the sprite and then draws the sprite in its place.
Subsequent SHOW commands replace the sprite with the stored background, store the background for the new
location and finally draw the sprite. In this way you can move the sprite over the background without any extra
code.
Collision detection then sits on top of this and looks for the rectangular boundaries of sprites touching to create
an interrupt or a sprite touching the edge of the frame.
Sprites are ordered so the drawing order is held in a lifo. suppose you have sprite 1 overlapped by sprite 2 and
then by sprite 3. If you simply moved sprite 1 then its background would overwrite bits of 2 and 3 – not what
we want. SPRITE SHOW SAFE unwinds the LIFO by removing each sprite in reverse order, moves sprite 1
and then restores first 2 and then 3 on top of it. Finally there is the concept of layers (this is the 4th parameter
in SPRITE SHOW).
The concept of the sprite implementation is as follows:
Sprites are full colour and of any size. The collision boundary is the enclosing rectangle.
Sprites are loaded to a specific number (1 to 64).
Sprites are displayed using the SPRITE SHOW command.
For each SHOW command the user must select a "layer". This can be between 0 and 10.
Sprites collide with sprites on the same layer, layer 0, or the screen edge.
Layer 0 is a special case and sprites on all other layers will collide with it.
The SCROLL commands leave sprites on all layers except layer 0 unmoved.
Layer 0 sprites scroll with the background and this can cause collisions.
There is no practical limit on the number of collisions caused by SHOW or SCROLL commands.
The SPRITE() function allows the user to fully interrogate the details of a collision.
A SHOW command will overwrite the details of any previous collisions for that sprite.
A SCROLL command will overwrite details of previous collisions for ALL sprites.
To restore a screen to a previous state sprites should be removed in the opposite order to which they were
written (ie, last in first out).
Because moving a sprite or, particularly, scrolling the background can cause multiple sprite collisions it is
important to understand how they can be interrogated.
The best way to deal with a sprite collision is using the interrupt facility. A collision interrupt routine is set up
using the SPRITE INTERRUPT command. Eg:
SPRITE INTERRUPT collision
The following is an example program for identifying all collisions that have resulted from either a SPRITE
SHOW command or a SCROLL command
'
' This routine demonstrates a complete interrogation of collisions
'
SUB collision
LOCAL INTEGER i
' First use the SPRITE(S) function to see what caused the interrupt
IF SPRITE(S) <> 0 THEN 'collision of specific individual sprite
'SPRITE(S) returns the sprite that moved to cause the collision
PRINT "Collision on sprite ", SPRITE(S)
process_collision(SPRITE(S))
MMBasic generates a single unique character for the function keys and other special keys on the keyboard.
These are shown in this table as hexadecimal and decimal numbers:
For PS2 and USB keyboards, if the shift key is simultaneously pressed with the function keys F1 to F12 then 40
(hex) is added to the code (this is the equivalent of setting bit 6). For example Shift-F10 will generate DA
The BASIC language was introduced in 1964 by Dartmouth College in the USA as a computer
language for teaching programming and accordingly it is easy to use and learn. At the same time, it
has proved to be a competent and powerful programming language and as a result it became very
popular in the late 70s and early 80s. Even today some large commercial data systems are still written
in the BASIC language (primarily Pick Basic).
The BASIC interpreter used in the PicoMite firmware’s is called MMBasic and is a modern version of
the BASIC language which loosely emulates the Microsoft BASIC interpreter that was popular years
ago.
For a programmer the greatest advantage of BASIC is its ease of use. Some more modern languages
such as C and C++ can be truly mind bending but with BASIC you can start with a one line program
and get something sensible out of it. MMBasic is also powerful in that you can draw sophisticated
graphics, manipulate the external I/O pins to control other devices and communicate with other
devices using a range of built-in communications protocols.
Command Prompt
Interaction with MMBasic is done via the console at the command prompt (ie, the greater than symbol
(>) on the console). On startup MMBasic will issue the command prompt and wait for some
command to be entered. It will also return to the command prompt if your program ends or if it
generated an error message.
When the command prompt is displayed you have a wide range of commands that you can enter and
execute. Typically they would list the program held in memory (LIST) or edit it (EDIT) or perhaps
set some options (the OPTION command). Most times the command is just RUN which instructs
MMBasic to run the program held in program memory.
Almost any command can be entered at the command prompt and this is often used to test a command
to see how it works. A simple example is the PRINT command (more on this later), which you can
test by entering the following at the command prompt:
PRINT 2 + 2
and not surprisingly MMBasic will print out the number 4 before returning to the command prompt.
This ability to test a command at the command prompt is useful when you are learning to program in
BASIC, so it would be worthwhile having a Raspberry Pi Pico loaded with the PicoMite firmware
handy for the occasional test while you are working through this tutorial.
Structure of a BASIC Program
A BASIC program starts at the first line and continues until it runs off the end or hits an END
command - at which point MMBasic will display the command prompt (>) on the console and wait for
something to be entered.
A program consists of a number of statements or commands, each of which will cause the BASIC
interpreter to do something (the words statement and command generally mean the same and are used
interchangeable in this tutorial).
Normally each statement is on its own line but you can have multiple statements in the one line
separated by the colon character (:).
For example;
A = 24.6 : PRINT A
Older BASIC programs used the command REM to start a comment and you can also use that if you
wish but the single quote character is easier to use and more convenient.
The PRINT Command
There are a number of common commands that are fundamental and we will cover them in this
tutorial but arguably the most useful is the PRINT command. Its job is simple; to print something on
the console. This is mostly used to output data for you to see (like the result of calculations) or
provide informative messages.
PRINT is also useful when you are tracing a fault in your program; you can use it to print out the
values of variables and display messages at key stages in the execution of the program.
In its simplest form the command will just print whatever is on its command line. So, for example:
PRINT 54
will display on the console the number 54 followed by a new line.
The data to be printed can be something simple like this or an expression, which means something to
be calculated. We will cover expressions in more detail later but as an example the following:
> PRINT 3/21
0.1428571429
>
would calculate the result of three divided by twenty one and display it. Note that the greater than
symbol (>) is the command prompt produced by MMBasic – you do not type that in.
You need to work through the logic of this example line by line to understand what it is doing.
Essentially it consists of one loop inside another. The inner loop, which increments the variable
nbr2 prints one horizontal line of the table. When this loop has finished it will execute the following
PRINT command which has nothing to print - so it will simply output a new line (ie, terminate the
line printed by the inner loop).
The program will then execute another iteration of the outer loop by incrementing nbr1 and
re-executing the inner loop again. Finally, when the outer loop is exhausted (when nbr1 exceeds 10)
the program will reach the end and terminate.
One last point, you can omit the variable name from the NEXT statement and MMBasic will guess
which variable you are referring to. However, it is good practice to include the name to make it easier
for someone else who is reading the program to understand it. You can also terminate multiple loops
using a comma separated list of variables in the NEXT statement. For example:
FOR var1 = 1 TO 5
FOR var2 = 10 to 13
PRINT var1 * var2
NEXT var1, var2
DO Loops
Another method of looping is the DO…LOOP structure which looks like this:
DO WHILE condition
<statement>
<statement>
LOOP
The INPUT command can also print your prompt for you, so that you do not need a separate PRINT
command. For example, this will work the same as the above program:
INPUT "Length of side 1"; a
INPUT "Length of side 2"; b
PRINT "Length of the hypotenuse is" SQR(a * a + b * b)
Finally, the INPUT command will allow you to input a series of numbers separated by commas with
each number being saved in different variables.
For example:
INPUT "Enter the length of the two sides: ", a, b
PRINT "Length of the hypotenuse is" SQR(a * a + b * b)
If the user entered 12,15 the number 12 would be saved in the variable a and 15 in b.
Another method of getting input from the console is the LINE INPUT command. This will get the
whole line as typed by the user and allocate it to a string variable. Like the INPUT command you can
also specify a prompt. This is a simple example:
LINE INPUT "What is your name? ", s$
PRINT "Hello " s$
We will cover string variables later in this tutorial but for the moment you can think of them as a
variable that holds a sequence of characters. If you ran the above program and typed in John when
prompted the program would respond with Hello John.
Sometimes you do not want to wait for the user to hit the enter key, you want to get each character as
it is typed in. This can be done with the INKEY$ function which will return the value of the character
as a string consisting of just one character or an empty string (ie, contains no characters) if nothing has
been entered.
GOTO and Labels
One method of controlling the flow of the program is the GOTO command. This essentially tells
MMBasic to jump to another part of the program and continue executing from there. The target of the
GOTO is a label and this needs to be explained first.
DO
InpErr:
PRINT
INPUT "Enter a number: "; a
IF a < 2 THEN
PRINT "Number must be equal or greater than 2"
GOTO InpErr
ENDIF
Divs = 0
FOR x = 2 TO SQR(a)
r = a/x
IF r = FIX(r) THEN Divs = Divs + 1
NEXT x
You can test this program by using the editor (the EDIT command) to enter it.
Using your newly learnt skills you could then have a shot at making it more efficient. For example,
because the program counts how many times a number can be divided into the test number it takes a
lot longer than it should to detect a non prime number. The program would run much more efficiently
if it jumped out of the FOR loop at the first number that divided evenly. You could use the GOTO
command to do this or you could use the command EXIT FOR – that would cause the FOR loop to
terminate immediately.
Other efficiencies include only testing the division with odd numbers (by using an initial test for an
even number then starting the FOR loop at 3 and using STEP 2) or by only using prime numbers for
the test (that would be much more complicated).
' Example program to calculate the number of days between two dates
OPTION EXPLICIT
OPTION DEFAULT NONE
DIM STRING s
DIM FLOAT d1, d2
DO
‘ main program loop
PRINT : PRINT "Enter the date as dd mmm yyyy"
PRINT " First date";
INPUT s
' Calculate the number of days including adjustment for leap years
GetDays = (yr * 365) + FIX((yr - 1) / 4)
IF yr MOD 4 = 0 AND mth >= 2 THEN GetDays = GetDays + 1
GetDays = GetDays + Days(mth) + day
END FUNCTION
Note that the line starting LOCAL STRING Month(11) has been wrapped around because of the
limited page width – it is one line as follows:
LOCAL STRING Month(11) = ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec")
This program works by getting two dates from the user at the console and then converting them to
integers representing the number of days since 1900. With these two numbers a simple subtraction
will give the number of days between them.
When this program is run it will ask for the two dates to be entered and you need to use the form of:
dd mmm yyyy.
This screen capture shows what
the running program will look
like.
The main feature of the program
is the defined function
GetDays() which takes a
string entered at the console,
splits it into its day, month and
year components then calculates
the number of days since 1st
January 1900.