B9X Electronics Documentation
B9X Basic Language Reference
A complete guide to the B9X Basic language, including variables, expressions, operators, statements, control flow, functions, and practical examples.
How to use this reference
Start with Chapters 1–6 to learn the language. Use Chapters 7–16 as the function reference. Chapter 17 shows complete patterns, and the appendices collect limits and quick-reference tables.
Conventions
| Notation | Meaning |
|---|---|
| name | A numeric variable or identifier. |
| name$ | A string variable or string-returning function. |
| expression | A numeric expression. |
| string-expression | A string literal, string variable, string function, or concatenation. |
| [ optional ] | Optional syntax in this manual only; do not type the brackets. |
| … | Additional statements or arguments. |
Contents
- 1. Language fundamentals
- 2. Values, variables, and arrays
- 3. Expressions and operators
- 4. Statements and control flow
- 5. Subroutines and user functions
- 6. Core string functions
- 7. Formatting and time
- 8. Mathematics
- 9. GPIO, timing, ADC, and temperature
- 10. Display, motion, WAV, and local TTS
- 11. OpenAI text, transcription, and TTS
- 12. Infrared remote control
- 13. WS2812 LEDs
- 14. MQTT
- 15. Additional supplied functions
- 16. Protected key variables
- 17. Complete programming patterns
- Appendix A. Language limits
- Appendix B. Quick reference
1. Language fundamentals
Program structure
A program is a sequence of executable statements plus optional SUB and FUNCTION definitions. Most simple statements end with a semicolon. Block delimiters such as THEN, ELSE, ENDIF, DO, WEND, NEXT, END SUB, and END FUNCTION do not use semicolons.
' A minimal B9X Basic program
let greeting$ = "Hello from B9X";
counter = 3;
print greeting$;
print counter;
Lexical rules
| Item | Rule |
|---|---|
| Numeric identifier | Starts with A–Z, a–z, or underscore; remaining characters may also include digits. |
| String identifier | Uses the same identifier rules and ends with $. |
| Stored name length | 31 characters maximum. |
| Numeric literal | Decimal integer, decimal fraction, or scientific notation, such as 12, 3.5, or 1.2e-3. |
| String literal | Text enclosed in double quotes. |
| Statement terminator | A semicolon ends assignments, DIM, PRINT, CALL, and RETURN. |
| Names | Names are case-sensitive. Use the exact function spelling shown in this reference. |
Comments
The lexer accepts three comment forms.
' apostrophe comment to end of line
// C++-style comment to end of line
/* block comment
across lines */
Truth values
B9X Basic has no separate Boolean type. Zero is false; any nonzero numeric value is true. Comparisons and logical operations produce numeric 0 or 1.
2. Values, variables, and arrays
Numeric values
All ordinary numeric variables and numeric function values use double-precision floating-point numbers. Integer-oriented functions discard any fractional portion when they require a whole number.
x = 12.5;
scientific = 1.2e3;
negative = -7;
print x + scientific;
String values
A string variable is identified by a trailing $. Its usable value is limited to 512 characters. String assignment requires LET.
let first$ = "B9X";
let message$ = first$ + " Basic";
print message$;
Assignment
count = 1;
let count = count + 1;
let label$ = "ready";
Numeric arrays
DIM creates a one-dimensional numeric array. The declared bound is inclusive: DIM sample[10]; creates indices 0 through 10. Array indices are numeric expressions converted to integers. String arrays are not implemented.
dim samples[9];
for i = 0 to 9 do
samples[i] = i ** 2;
next
print samples[4];
Scope and lifetime
Variables created outside a function are global. FUNCTION parameters temporarily use their own values and are restored when the call returns. A function can read or modify other global variables. SUB has no parameters.
3. Expressions and operators
Operator precedence
The table is ordered from highest precedence to lowest. Parentheses override the normal order.
| Precedence | Operators | Meaning | Associativity |
|---|---|---|---|
| 1 | ( ) | Grouping and function calls | — |
| 2 | + – NOT ! | Unary sign and logical negation | Right |
| 3 | ** | Exponentiation | Right |
| 4 | * / | Multiplication and division | Left |
| 5 | + – | Addition/subtraction; + also concatenates strings | Left |
| 6 | < <= > >= | Relational comparison | Left |
| 7 | == != | Equality and inequality | Left |
| 8 | AND && | Logical AND | Left |
| 9 | OR || | Logical OR | Left |
Arithmetic expressions
result = 2 + 3 * 4; ' 14
power = 2 ** 3 ** 2; ' 512: exponentiation groups right
average = (a + b) / 2;
Comparison and logical expressions
if temperature >= 25 and enabled == 1 then
print "warm and enabled";
endif
different = value != previous;
inactive = not enabled;
String expressions
The + operator concatenates string expressions. String functions can be nested and concatenated.
let full$ = left$("B9X Basic", 3) + " " + str$(42);
print full$;
4. Statements and control flow
PRINT writes one numeric or string expression to the B9X Basic output.
print 2 + 2;
print "ready";
print fmt$(12.5, "0.00");
IF / THEN / ELSE / ENDIF
if distance < 20 then
print "near";
else
print "far";
endif
ELSE is optional. Blocks can contain any supported statements, including nested IF, WHILE, and FOR blocks.
WHILE / DO / WEND
count = 0;
while count < 5 do
print count;
count = count + 1;
wend
FOR / TO / STEP / NEXT
FOR initializes its numeric control variable, tests it against the inclusive limit, executes the body, and adds the step. STEP defaults to 1. Positive and negative steps are supported. DO may be included or omitted after the loop header.
for i = 1 to 5 do
print i;
next
for j = 10 to 0 step -2
print j;
next
Blocks
Braces form an explicit statement block and may be empty. Normal IF/WHILE/FOR examples do not require braces.
{
x = 1;
print x;
}
Unavailable classic BASIC statements
The attached grammar does not define GOTO, GOSUB, INPUT, DATA/READ, SELECT CASE, BREAK, CONTINUE, or line-numbered program flow. Use structured blocks, SUB, and FUNCTION instead.
5. Subroutines and user functions
SUB
A SUB is a named, argument-free procedure. Invoke it with CALL. RETURN; exits early; reaching END SUB also returns.
sub blink()
setHigh(2);
wait(100);
setLow(2);
end sub
call blink();
Numeric FUNCTION
function clamp(value, low, high)
if value < low then
return low;
endif
if value > high then
return high;
endif
return value;
end function
print clamp(120, 0, 100);
String FUNCTION
A string-returning function name ends in $. Parameters may be numeric or string parameters ending in $. Return a string expression.
function greeting$(name$)
return "Hello, " + name$;
end function
let text$ = greeting$("B9X");
print text$;
Function-call rules
- A user FUNCTION may accept up to 8 parameters.
- Parameter types are determined by whether the parameter name ends in $.
- A missing numeric return falls back to 0; a missing string return falls back to an empty string.
- Place a FUNCTION definition before code that calls it.
6. Core string functions
LEN
len(text$)
Returns the number of characters in a string.
Example:
print len("B9X"); ' 3
Returns: Numeric character count.
LEFT$
left$(text$, count)
Returns up to count characters from the left side of text$.
Notes: Negative counts act as zero; counts longer than the source are capped.
Example:
let a$ = left$("B9X Basic", 3); ' "B9X"
Returns: A string.
RIGHT$
right$(text$, count)
Returns up to count characters from the right side of text$.
Notes: Negative counts act as zero; counts longer than the source are capped.
Example:
let a$ = right$("B9X Basic", 5); ' "Basic"
Returns: A string.
MID$
mid$(text$, start, count)
Extracts count characters beginning at the 1-based start position.
Notes: Positions are 1-based and the result is clipped at the string boundary.
Example:
let a$ = mid$("B9X Basic", 5, 5); ' "Basic"
Returns: A string.
CHR$
chr$(code)
Creates a one-character string from a numeric byte value.
Notes: Values above 255 are masked to 8 bits; negative values become 0.
Example:
let newline$ = chr$(10);
Returns: A one-character string.
ASC
asc(text$)
Returns the byte value of the first character.
Example:
print asc("A"); ' 65
Returns: A numeric byte code; an empty string yields 0.
STR$
str$(number)
Converts a number to compact text using %g-style formatting.
Example:
let n$ = str$(12.5); ' "12.5"
Returns: A string.
VAL
val(text$)
Parses a leading decimal floating-point number from text.
Example:
print val("12.5 volts"); ' 12.5
Returns: The parsed number; 0 if parsing cannot begin.
INSTR
instr(text$, find$)
instr(start, text$, find$)
Searches text$ for find$. The two-argument form starts at the beginning; the three-argument form starts at a 1-based position.
Notes: An empty search string returns 1 in the two-argument form or the requested start position in the three-argument form.
Example:
print instr("B9X Basic", "Basic"); ' 5
print instr(6, "banana", "a"); ' 6
Returns: The 1-based match position, or 0 when not found.
7. Formatting and time
FMT$
fmt$(number, format$)
Formats a number using familiar numeric-format characters.
Example:
print fmt$(1234.5, "#,##0.00"); ' 1,234.50
print fmt$(0.256, "0.0%"); ' 25.6%
Returns: The formatted string.
FMT$ format tokens
| Token | Meaning |
|---|---|
| 0 | Required digit; displays zero when no digit is present. |
| # | Optional digit. |
| . | Decimal separator. |
| , | Thousands grouping. |
| % | Multiplies by 100 and appends a percent sign. |
| + at start | Forces a sign for positive values. |
| E or e | Scientific notation. |
| positive;negative;zero | Selects separate format sections. |
| "text" | Quoted literal text. |
| \character | Escapes the next format character. |
HOUR
hour()
Returns the local clock hour, 0–23. The value uses the date and time configured for the B9X Basic system.
Example:
print hour();
Returns: A number.
MINUTE
minute()
Returns the local minute, 0–59. The value uses the date and time configured for the B9X Basic system.
Example:
print minute();
Returns: A number.
SECOND
second()
Returns the local second, 0–59. The value uses the date and time configured for the B9X Basic system.
Example:
print second();
Returns: A number.
MONTH
month()
Returns the local month, 1–12. The value uses the date and time configured for the B9X Basic system.
Example:
print month();
Returns: A number.
DAY
day()
Returns the local day of month. The value uses the date and time configured for the B9X Basic system.
Example:
print day();
Returns: A number.
YEAR
year()
Returns the four-digit local year. The value uses the date and time configured for the B9X Basic system.
Example:
print year();
Returns: A number.
8. Mathematics
ABS
abs(x)
Absolute value.
Example:
print abs(-3.5);
Returns: 3.5.
MIN
min(a, b)
Smaller argument.
Example:
print min(4, 9);
Returns: 4.
MAX
max(a, b)
Larger argument.
Example:
print max(4, 9);
Returns: 9.
ROUND
round(x)
Nearest integral value using the C math library’s rounding rule.
Example:
print round(2.6);
Returns: 3.
SQRT
sqrt(x)
Square root.
Notes: Inputs outside the mathematical domain produce the C math library’s non-finite result.
Example:
print sqrt(81);
Returns: 9.
EXP
exp(x)
e raised to x.
Example:
print exp(1);
Returns: Approximately 2.71828.
LOG
log(x)
Natural logarithm.
Notes: Inputs outside the mathematical domain produce the C math library’s non-finite result.
Example:
print log(exp(1));
Returns: Approximately 1.
LOG10
log10(x)
Base-10 logarithm.
Notes: Inputs outside the mathematical domain produce the C math library’s non-finite result.
Example:
print log10(1000);
Returns: 3.
SIN
sin(radians)
Sine.
Example:
print sin(0);
Returns: 0.
COS
cos(radians)
Cosine.
Example:
print cos(0);
Returns: 1.
TAN
tan(radians)
Tangent.
Example:
print tan(0);
Returns: 0.
ASIN
asin(x)
Inverse sine in radians.
Notes: Inputs outside the mathematical domain produce the C math library’s non-finite result.
Example:
print asin(1);
Returns: Approximately 1.5708.
ACOS
acos(x)
Inverse cosine in radians.
Notes: Inputs outside the mathematical domain produce the C math library’s non-finite result.
Example:
print acos(1);
Returns: 0.
ATAN
atan(x)
Inverse tangent in radians.
Example:
print atan(1);
Returns: Approximately 0.7854.
SINH
sinh(x)
Hyperbolic sine.
Example:
print sinh(0);
Returns: 0.
COSH
cosh(x)
Hyperbolic cosine.
Example:
print cosh(0);
Returns: 1.
RND
rnd(minimum, maximum)
Random integer in the inclusive range.
Notes: maximum must be greater than or equal to minimum.
Example:
roll = rnd(1, 6);
Returns: An integer-valued number.
MODULO
modulo(a, b)
C integer remainder after both arguments are truncated to integers.
Notes: The divisor must not be zero.
Example:
print modulo(17, 5);
Returns: 2.
9. GPIO, timing, ADC, and temperature
WAIT
wait(milliseconds)
Pauses the current B9X Basic program for the requested number of milliseconds.
Notes: Other background services can continue while the program is waiting.
Example:
wait(250);
Returns: The supplied millisecond value.
GETTICKS
getTicks(mode)
Reads elapsed operating time. Mode 0 returns seconds, 1 milliseconds, and 2 microseconds.
Example:
start = getTicks(1);
wait(50);
print getTicks(1) - start;
Returns: Elapsed time as a number; an unsupported mode returns 0.
MAKEINPUT
makeInput(gpio)
Configures a positive GPIO number as an input with an internal pulldown.
Notes: GPIO 0 and negative values are not changed.
Example:
makeInput(4);
Returns: The GPIO argument.
GETINPUT
getInput(gpio)
Reads a positive GPIO input.
Example:
if getInput(4) == 1 then
print "high";
endif
Returns: 0 or 1; for a nonpositive argument the argument itself is returned.
MAKEOUTPUT
makeOutput(gpio)
Configures a positive GPIO number as an output.
Example:
makeOutput(2);
Returns: The GPIO argument.
SETHIGH
setHigh(gpio)
Sets a positive GPIO output to logic 1.
Example:
setHigh(2);
Returns: The GPIO argument.
SETLOW
setLow(gpio)
Sets a positive GPIO output to logic 0.
Example:
setLow(2);
Returns: The GPIO argument.
INITADC
initADC()
Prepares analog-to-digital conversion for use.
Example:
initADC();
Returns: 1.
READADCRAW
readADCRaw(channel)
Reads a raw ADC conversion from the ADC channel number.
Example:
raw = readADCRaw(3);
Returns: Raw ADC count.
READADCMV
readADCMV(channel)
Reads a calibrated ADC result in millivolts.
Example:
millivolts = readADCMV(3);
Returns: Millivolts.
DEINITADC
deinitADC()
Releases the analog-to-digital converter when it is no longer needed.
Example:
deinitADC();
Returns: 1.
READTEMPERATURE
readTemperature(gpio)
Reads a DS18B20 temperature sensor connected to the specified GPIO.
Example:
temperature = readTemperature(18);
print fmt$(temperature, "0.0");
Returns: Temperature in degrees Celsius.
10. Display, motion, WAV, and local TTS
DISPLAYINIT
displayInit(sda_gpio, scl_gpio)
Prepares a 128×64 SSD1306 OLED display at I²C address 0x3C.
Example:
displayInit(8, 9);
Returns: 1.
DISPLAYTEXT
displayText(text$)
Displays text on the OLED.
Notes: A line is displayed when ~ is reached. End every line, including the final line, with ~.
Example:
displayText("B9X~Basic~ready~");
Returns: 1.
MOTIONINIT
motionInit(port, tx_gpio)
Prepares the supported motion-distance sensor using the selected port and transmit GPIO.
Example:
motionInit(1, 17);
Returns: 1.
MOTIONGETDISTANCE
motionGetDistance()
Reads the latest measured distance.
Example:
distance = motionGetDistance();
Returns: The reported distance.
PLAYINIT
playInit(bclk_gpio, ws_gpio, data_gpio)
Prepares WAV audio playback on the selected pins.
Example:
playInit(5, 4, 6);
Returns: The initialization result.
PLAY
play(filename$)
Starts playback of a WAV file.
Notes: Use an uncompressed 44.1-kHz, 16-bit stereo PCM WAV file.
Example:
play("/spiffs/alert.wav");
Returns: The playback result.
ISPLAYING
isPlaying()
Tests whether WAV playback is active.
Example:
while isPlaying() != 0 do
wait(20);
wend
Returns: Nonzero while busy; 0 when idle.
TTSINIT
ttsInit(port, busy_gpio, tx_gpio, rx_gpio)
Prepares a local SYN6988 speech module.
Example:
ttsInit(1, 7, 17, 18);
Returns: The initialization result.
TTSISBUSY
ttsIsBusy()
Tests whether the local SYN6988 module is speaking.
Example:
while ttsIsBusy() != 0 do
wait(20);
wend
Returns: Nonzero while busy; 0 when idle.
TTSSPEAK
ttsSpeak(text$)
Sends text to the local SYN6988 speech module.
Example:
ttsSpeak("System ready.");
Returns: 1 after submission.
11. OpenAI text, transcription, and TTS
OAIXINIT
oaixInit(api_key$)
Prepares OpenAI text questions using the supplied API key.
Example:
ok = oaixInit(b9x_key1$);
Returns: 1 on success or 0 on failure.
OAIXASKQUESTION
oaixAskQuestion(request_id, question$)
Queues a text question. request_id is an application-defined numeric tag passed into the worker request.
Example:
queued = oaixAskQuestion(1, "Name one moon of Mars.");
Returns: 1 if queued; 0 if the queue is unavailable or full.
OAIXGETANSWER$
oaixGetAnswer$()
Polls for the next completed text answer.
Example:
let answer$ = "";
while len(answer$) == 0 do
let answer$ = oaixGetAnswer$();
wait(50);
wend
print answer$;
Returns: The answer string, or an empty string when no answer is ready.
VRXINIT
vrxInit(bclk_gpio, ws_gpio, data_gpio, record_seconds, api_key$)
Initializes INMP441/I²S recording and OpenAI transcription.
Example:
ok = vrxInit(5, 4, 6, 5, b9x_key1$);
Returns: 1 on success or 0 on failure.
VRXTRANSCRIBE
vrxTranscribe(request_id)
Queues one record-and-transcribe operation.
Example:
queued = vrxTranscribe(100);
Returns: 1 if queued; 0 if it could not be queued.
VRXGETTRANSCRIPT$
vrxGetTranscript$()
Polls for the next completed transcript.
Example:
let transcript$ = "";
while len(transcript$) == 0 do
let transcript$ = vrxGetTranscript$();
wait(50);
wend
print transcript$;
Returns: Transcript text, or an empty string while no result is ready.
TTSXINIT
ttsxInit(bclk_gpio, ws_gpio, data_gpio, api_key$, voice$, instructions$)
Prepares OpenAI text-to-speech and audio output.
Example:
ttsxInit(5, 4, 6, b9x_key1$, "marin", "Speak clearly.");
Returns: 1 when ready.
TTSXSPEAK
ttsxSpeak(text$)
Queues text for OpenAI speech synthesis and playback.
Notes: Each submitted message can contain up to 255 characters.
Example:
if ttsxSpeak("Hello from B9X.") == 0 then
print "TTS queue busy";
endif
Returns: 1 if accepted; 0 if busy or unavailable.
Reliable question-to-speech pattern
oaixInit(b9x_key1$);
ttsxInit(5, 4, 6, b9x_key1$, "marin", "Speak naturally.");
oaixAskQuestion(1, "What is the capital of Michigan?");
let answer$ = "";
while len(answer$) == 0 do
let answer$ = oaixGetAnswer$();
wait(50);
wend
' Queue the completed answer exactly once.
accepted = ttsxSpeak(answer$);
print answer$;
12. Infrared remote control
IRINIT
irInit(gpio)
Starts nonblocking infrared reception on the data pin of a demodulated 38-kHz receiver.
Example:
irInit(15);
Returns: 1 when reception starts.
IRGETCODE
irGetCode()
Polls immediately for a decoded IR event and returns its command when confidence is greater than 90.
Example:
code = irGetCode();
if code >= 0 then
print code;
endif
Returns: Command number, or -1 when no sufficiently confident event is available.
The infrared receiver supports common remote-control formats, including Sony/SIRC used by Sony Bravia remotes. IRGETCODE returns the decoded command number.
13. WS2812 addressable LEDs
WS2812INIT
ws2812Init(gpio, led_count)
Creates a WS2812 strip instance.
Example:
strip = ws2812Init(48, 8);
Returns: A positive handle on success; 0 on failure.
WS2812FILL
ws2812Fill(handle, red, green, blue)
Sets every pixel to one RGB color.
Example:
ws2812Fill(strip, 0, 0, 32);
Returns: 0 on success; otherwise an error code.
WS2812SETPIXEL
ws2812SetPixel(handle, index, red, green, blue)
Sets one zero-based pixel.
Example:
ws2812SetPixel(strip, 0, 32, 0, 0);
Returns: 0 on success; otherwise an error code.
WS2812SHOW
ws2812Show(handle)
Updates the strip with all color changes made so far.
Example:
ws2812Show(strip);
Returns: 0 on success; otherwise an error code.
WS2812CLEAR
ws2812Clear(handle)
Turns off every pixel on the strip.
Example:
ws2812Clear(strip);
Returns: 0 on success; otherwise an error code.
WS2812ISBUSY
ws2812IsBusy(handle)
Tests whether a strip transmission is active.
Example:
while ws2812IsBusy(strip) != 0 do
wait(1);
wend
Returns: Nonzero while busy; 0 when idle.
14. MQTT
INITMQTTCLIENT
initMQTTClient(uri$, username$, password$)
Starts an MQTT connection with the supplied server address and credentials.
Example:
initMQTTClient("mqtt://broker.local", "user", "password");
Returns: 1 when startup succeeds; otherwise an error value.
MQTTCLIENTSUBSCRIBE
mqttClientSubscribe(topic$)
Subscribes to a topic at QoS 0.
Example:
id = mqttClientSubscribe("b9x/input");
Returns: A message identifier, or a negative error value.
MQTTCLIENTUNSUBSCRIBE
mqttClientUnsubscribe(topic$)
Removes a topic subscription.
Example:
id = mqttClientUnsubscribe("b9x/input");
Returns: A message identifier, or a negative error value.
MQTTCLIENTPUBLISH
mqttClientPublish(topic$, payload$)
Publishes a payload at QoS 1 with retain disabled.
Example:
id = mqttClientPublish("b9x/status", "ready");
Returns: A message identifier, or a negative error value.
MQTTCLIENTGETMESSAGE$
mqttClientGetMessage$()
Polls for one MQTT event.
Notes: TYPE can be DATA, CONNECT, DISCONNECT, SUBSCRIBED, UNSUBSCRIBED, PUBLISHED, or ERROR.
Example:
let event$ = mqttClientGetMessage$();
if len(event$) > 0 then
print event$;
endif
Returns: An empty string if none is ready; otherwise [TYPE][id][topic][data].
15. Additional supplied functions
These simple functions are included for testing mixed numeric and string arguments.
USER1
user1(x)
Doubles its numeric argument.
Example:
print user1(10); ' 20
Returns: x × 2.
USER2
user2(a, b)
Adds two numeric arguments.
Example:
print user2(10, 20); ' 30
Returns: a + b.
USERMIX
usermix(text$, number)
Combines a string-length calculation with a number.
Example:
print usermix("ABC", 10); ' 13
Returns: number plus the character count of text$.
USERMIX$
usermix$(text$, number)
Combines text and a number into one string.
Example:
let result$ = usermix$("ABC", 10); ' "ABC 10"
Returns: text$, a space, and the number.
16. Protected key variables
B9X Basic provides five predefined string values for passwords, API keys, and similar settings:
b9x_key1$
b9x_key2$
b9x_key3$
b9x_key4$
b9x_key5$
Each can hold up to 512 characters and can be passed directly to functions such as oaixInit, vrxInit, and ttsxInit. Values can be set or replaced through the B9X Basic setup menu without displaying the existing value.
17. Complete programming patterns
Nonblocking state machine
Use a state variable so an asynchronous request is submitted once and polled later.
state = 0;
let answer$ = "";
while 1 do
if state == 0 then
if oaixAskQuestion(1, "Give one short fact.") == 1 then
state = 1;
endif
endif
if state == 1 then
let answer$ = oaixGetAnswer$();
if len(answer$) > 0 then
print answer$;
state = 2;
endif
endif
if state == 2 then
' Do not queue again unless a new event resets state.
endif
wait(50);
wend
GPIO event with debounce
makeInput(4);
last = getInput(4);
while 1 do
current = getInput(4);
if current != last then
wait(20);
current = getInput(4);
if current != last then
print current;
last = current;
endif
endif
wait(5);
wend
IR-controlled LEDs
irInit(15);
strip = ws2812Init(48, 8);
while 1 do
code = irGetCode();
if code == 21 then
ws2812Fill(strip, 32, 0, 0);
ws2812Show(strip);
endif
if code == 22 then
ws2812Clear(strip);
endif
wait(10);
wend
Common mistakes
| Symptom | Likely cause | Correction |
|---|---|---|
| Parse error after a simple statement | Missing semicolon. | Add ; after assignment, DIM, PRINT, CALL, or RETURN. |
| Comparison behaves incorrectly | Used = instead of ==. | Use == for equality. |
| String assignment parse error | LET omitted. | Write LET name$ = expression;. |
| Repeated speech or requests | Queue function called every loop pass. | Submit once and move to a polling state. |
| Empty async result | Work is not complete yet. | Poll with a delay; empty string means no queued result. |
| OpenAI HTTP 401 | Invalid key or voice name passed as key. | Pass a real API key in api_key$ and the voice separately. |
| Audio resource busy | Two audio features were started at the same time. | Finish or stop one audio operation before starting another. |
| Array error | Index outside 0..declared bound. | Validate indices before access. |
Appendix A. Language limits
| Language item | Maximum |
|---|---|
| String value | 512 characters |
| Identifier | 31 characters |
| Numeric arrays | 64 |
| Elements in each numeric array | 1024; indices 0 through 1023 |
| User FUNCTION definitions | 64 |
| Parameters in a user FUNCTION | 8 |
| OpenAI TTS message | 255 characters per submission |
These limits are important when planning larger B9X Basic programs.
Appendix B. Quick reference
Statement forms
name = expression;
let name = expression;
let name$ = string-expression;
dim array[upper_bound];
array[index] = expression;
print expression;
print string-expression;
if expression then ... [else ...] endif
while expression do ... wend
for name = start to limit [step step] [do] ... next
sub name() ... [return;] ... end sub
call name();
function name(parameters) ... return expression; ... end function
function name$(parameters) ... return string-expression; ... end function
Function index
| Category | Functions |
|---|---|
| Strings | len, left$, right$, mid$, chr$, asc, str$, val, instr, fmt$ |
| Date/time | hour, minute, second, month, day, year, getTicks |
| Math | abs, min, max, round, sqrt, exp, log, log10, sin, cos, tan, asin, acos, atan, sinh, cosh, rnd, modulo |
| GPIO/sensors | makeInput, getInput, makeOutput, setHigh, setLow, initADC, readADCRaw, readADCMV, deinitADC, readTemperature |
| Task timing | wait |
| Display/motion/audio | displayInit, displayText, motionInit, motionGetDistance, playInit, play, isPlaying |
| Local TTS | ttsInit, ttsIsBusy, ttsSpeak |
| OpenAI | oaixInit, oaixAskQuestion, oaixGetAnswer$, vrxInit, vrxTranscribe, vrxGetTranscript$, ttsxInit, ttsxSpeak |
| Infrared | irInit, irGetCode |
| WS2812 | ws2812Init, ws2812Fill, ws2812SetPixel, ws2812Show, ws2812Clear, ws2812IsBusy |
| MQTT | initMQTTClient, mqttClientSubscribe, mqttClientUnsubscribe, mqttClientPublish, mqttClientGetMessage$ |
| Additional supplied functions | user1, user2, usermix, usermix$ |
About this reference
This manual documents the B9X Basic language, its statements, and its available functions. For product information, updates, and support, visit b9xelectronics.com.
The information provided here by B9X Electronics (‘we,’ ‘us,’ or ‘our’), in this document,
is for general informational purposes only. All information in this document
is provided in good faith, however, we make no representation or warranty of any kind,
express or implied, regarding the accuracy, adequacy, validity, reliability, availability,
or completeness of any information in this document. Under no circumstance shall we have any liability
to you for any loss or damage of any kind incurred as a result of the use of this document
or reliance on any information provided in this document.

