This avoids havinf `hdiutil eject` complaining that the resource is busy Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
93 KiB
Overview
DB50X on DM32
The DB50X project intends to rebuild and improve the user experience of the legendary HP48 family of calculators, notably their "Reverse Polish Lisp" (RPL) language with its rich set of data types and built-in functions.
This project is presently targeting the SwissMicro DM32 calculator and leveraging its built-in software platform, known as DMCP. This is presumably the calculator you are currently running this software on.
Table of contents
- Using the on-line help
- State of the project
- Design overview
- Keyboard interaction
- Soft menus
- Differences with other RPLs
- Built-in help
- Acknowledgements and credits
State of the project
This is currently UNSTABLE software. Please only consider installing this if you are a developer and interested in contributing. Please refer to the web site of the project on GitHub for details and updates.
Design overview
The objective is to re-create an RPL-like experience, but to optimize it for the existing DM32 physical hardware. The DM32 keyboard layout is really different compared to the DB50X expected layout. For example, the DM32 does not have unshifted arrow keys, and has two shift keys. For that reason, when running DB50X on a DM32, it is highly recommended to use a keyboard overlay.
Compared to the original HP48, the DM32 has a much larger screen, but no annunciators (it is a fully bitmap screen). It has a keyboard with dedicated soft-menu (function) keys, but no arrow keys (whereas the HP48 has four), lacks a dedicated alpha key, and has no space key (SPC on the HP48).
Keyboard interaction
The keyboard differences force us to revisit the user interaction with the calculator compared to the HP48:
-
When running DB50X on the DM32, the blue shift key cycles between three states, Shift (shown in the documentation as 🟨), Right Shift (shown in the documentation as 🟦) and no shift. The physical yellow shift key is actually used as a down/right cursor key, and will be shown as ▶︎ in the rest of this document. Similarly, the XEQ key is used as an up/left cursor key, and will be shown as ◀︎ in the rest of this document. This remapping of keys appears necessary because RPL calculators like the HP48 are command-line oriented and absolutely need at least two unshifted cursor keys. Sacrificing a physical shift key while preserving two shifted function seems like the best compromise.
-
A first press on the shift key is shown as 🟨 in the documentation, and activates functions shown in yellow in the keyboard overlay. A second press is shown as 🟦 in the documentation, and activates functions shown in blue in the keyboard overlay. On the screen, the shift state is indicated in the header area. When a soft menu is visible on the screen, the selected row of functions is highlighed.
-
Since RPL uses alphabetic entry (also called Alpha mode) a lot more frequently than on RPN models like the HP41 or HP42, making it quickly accessible seems important, so there are three distinct ways to activate it.
-
Using 🟨 ◀︎ and 🟨 ▶︎ moves the cursor up and down. When not editing, ▶︎ and ▶︎ behave like ▲ and ▼ on the HP48, i.e. ◀︎ enters the interactive stack (not yet implemented) and ▶︎ edits the object on the first level of the stack.
-
Long-pressing arrow keys, the ← (also known as Backspace) or text entry keys in Alpha mode activates auto-repeat.
-
Long-pressing keys that would directly trigger a function (e.g. SIN), including function keys associated with a soft-menu, will show up the built-in help for the corresponding function.
Alpha mode
Entering alphabetic characters is done using Alpha mode. These alphabetic characters are labeled on the right of each key on the DM32's keyboard.
When Alpha mode is active, an ABC indicator shows up in the annunciator area at the top of the screen. For lowercase entry, the indicator changes to abc.
There are three ways to enter Alpha mode:
-
The first method is to use 🟨 ENTER as indicated by the ALPHA yellow label on the DM32 ENTER key. This cycles between Alpha ABC, Lowercase abc and Normal entry modes.
-
The second method is to hold 🟨 for more than half a second. This cycles between Alpha ABC and Normal entry modes, and cannot be used to type lowercase characters.
-
The third method is to hold one of the arrow keys ◀︎ or ▶︎ while typing on the keyboard. This is called transient alpha mode because Alpha mode ends as soon as the arrow key is released. Using ◀︎ enters uppercase characters, while ▶︎ uses lowercase characters.
There is no equivalent of the HP48's "single-Alpha" mode. Alpha mode is either transient (when you hold one of the arrow keys) or sticky (with 🟨 ENTER or by holding 🟨).
Alpha mode is cancelled when pressing ENTER or EXIT.
Since the DM32's alphabetic keys overlap with the numeric keys (unlike the HP48), as well as with operations such as × and ÷, using 🟨 in Alpha mode brings back numbers. This means 🟨 cannot be used for lowercase, but as indicated above, there are two other methods to enter lowercase characters.
Using 🟨 or 🟦 in combination with keys other than the numeric keypad gives a variety of special characters.
Key mapping
Using DB50X with the DM32 is quite difficult without a keyboard overlay.
In particular, an unfortunate difference between the DM32 and the keyboard
layout used by DB50X is that the placement of all letters after M
is shifted
by one position on the keyboard, and the first row of scientific functions
(starting with square root and ending with Σ+) is inconsistent. The reason is
that the layout for DB50X is heavily based on the DM-42 model.
Also, while the DM32 has two shift keys, a blue and a yellow one, it lacks dedicated cursor movement arrow keys, a limitation that is visible in the calculator's firmware menus. While the two arrow shift keys would be welcome, not having arrow keys for cursor movement is just not an option. As a result, only the blue shift key is kept as a shift key, and the yellow shift key is converted to an arrow key, along with the DM32 XEQ key.
In the rest of this document, the shift key is referred to as 🟨, and pressing it twice is referred to as 🟦, irrespective of the appearance of the physical shift key on your particular hardware.
DB50X keyboard overlays for SwissMicros calculators are already available.
Soft menus
The DM32 has 6 dedicated soft-menu keys at the top of the keyboard. Most of the advanced features of DB50X can be accessed through these soft menus. Soft menu keys have no label on the physical calculator, but in this documentation, they may sometimes be referred to as F1 through F6.
Menus are organized internally as a hierarchy, where menus can refer to other menus. A special menu, MainMenu, accessible via the 🟦 Σ+, contains all other menus.
Menus can contain up to 18 entries at once, 6 being directly accessible, 6 more being shown when using the 🟨 key, and 6 more with 🟦. Three rows of functions are shown on screen, with the active row highlighted.
A long press on a function key invokes the on-line help for the associated function.
When a menu contains more than 18 entries, then the F6 function key turns into
a ▶︎
, and 🟨 F6 turns into ◀
︎. These keys can be used to
navigate across the available menu entries. This replaces the NXT and PREV
keys on HP calculators.
The VariablesMenu (RCL key) is special in the sense that:
-
Selecting an entry evaluates that menu entry, for example to run a program
-
The 🟨 function recalls its name without evaluating it.
-
The 🟦 function stores into the variable.
Differences with other RPLs
Multiple implementations of RPL exist, most of them from Hewlett-Packard. A good reference to understand the differences between the various existing implementations from HP is the HP50G Advanced User's Reference Manual.
There are a number of intentional differences in design between DB50X and the HP48, HP49 or HP50G's implementations of RPL. There are also a number of unintentional differences, since the implementation is completely new.
User interface
-
DB50X features an extensive built-in help system, which you are presently using. Information for that help system is stored using a regular markdown file named
/HELP/DB50X.md
, stored in the calculator's flash storage. -
DB50X features auto-completion for commands while typing, through the Catalog key (CatalogMenu).
-
Many RPL words exist in short and long form, and a user preference selects how a program shows. For example, the Negate command, which the HP48 calls
NEG
, can display, based on user preferences, asNEG
,neg
,Neg
orNegate
. In the help, it will be shown as Negate (NEG). -
The DB50X dialect of RPL is not case sensitive, but it is case-respecting. For example, if your preference is to display built-in functions in long form, typing
inv
orINV
will show up asInvert
in the resulting program. This means that the space of "reserved words" is larger in DB50X than in other RPL implementations. Notably, on HP's implementations,DUP
is a keyword but you can useDuP
as a valid variable name. This is not possible in DB50X.
Representation of objects
-
Internally, the calculator deals with various representations for numbers. Notably, it keeps integer values and fractions in exact form for as long as possible to optimize both performance and memory usage. This is somewhat similar to what the HP49 and HP50 implemented, where there is a difference between
2
(whereTYPE
returns 28) and2.
(whereTYPE
return 0). -
The calculator features at least 3 floating-point precisions using 32-bit, 64-bit and 128-bit respectively, provided by the DMCP's existing Intel Binary Decimal Floating-Point library. The 128-bit format gives the calculator 34 significant digits of precision, like the DM32. DB50X may support other formats in the future, like the arbitrary-precision floating-point found in newRPL.
-
Based numbers with an explicit base, like
#123h
keep their base, which makes it possible to show on stack binary and decimal numbers side by side. Mixed operations convert to the base in stack level X, so that#10d #A0h +
evaluates as#AAh
. Based numbers without an explicit base change base depending on theBase
setting, much like based numbers on the HP48. -
The storage of data in memory uses a denser format than on the HP48. Therefore, objects will almost always use less space on DB50X. Notably, the most frequently used functions and data types consume only one byte on DB50X, as opposed to 5 nibbles (2.5 bytes) on the HP48.
-
Numerical equality can be tested with
=
, whereas object equality is tested using==
. For example,0=0.0
is true, but0==0.0
is false, because0
is an integer whereas0.0
is a floating-point.
Alignment with the DM32
-
DB50X borrows to the DM32 the idea of special variables, which are variables with a special meaning. For example, the
Precision
special variable is the current operating precision for floating point, in number of digits. While there is aSetPrecision
command, it is also possible to use'Precision' STO
. This does not imply that there is an internalPrecision
variable somewhere. Special variables are available for most settings. -
All built-in soft-key menus are named, with names ending in Menu. For example, the VariablesMenu is the menu listing global variables in the current directory. There is no menu number, but the Menu special variable holds the name of the current menu, and LastMenu the name of the previous one.
-
The DB50X also provides full-screen setup menus, taking advantage of the DM32 existing system menus. It is likely that the same menu objects used for softkey menus will be able to control system menus, with a different function to start the interaction.
-
The whole banking and flash access storage mechanism of the HP48 will be replaced with a system that works well with FAT USB storage. It should be possible to directly use a part of the flash storage to store RPL programs, either in source or compiled form.
List operation differences
The application of a same operation on arrays or matrices has never been very consistent nor logical across RPL models from HP.
-
On HP48 and HP50,
{ 1 2 3 } 4 +
gives{1 2 3 4}
. However,{ 1 2 3} 4 *
gives a type error on the HP48 but applies the operation to list elements on the HP50, yielding{ 4 8 12}
. -
For arrays,
[ 1 2 3 ] 4 +
fails on both the HP48 and HP50, but[ 1 2 3 ] 4 *
works. -
The HP50 has a
MAP
function, which works both for list and matrices.[ 1 2 3 ] « 3 + »
will return[ 4 5 6 ]
, and{ 1 2 3 } « 3 * »
will return{ 3 6 9 }
. That function has no direct equivalent on the HP48.
DB50X considers lists as bags of items and treat them as a whole when it makes sense, whereas arrays are focusing more on the values they contain, and will operate on these items when it makes sense. Therefore:
-
{ 1 2 3 } 4 +
gives{ 1 2 3 4 }
,{ 1 2 3 } 2 -
gives{ 1 3 }
(not yet implemented), and{ 1 2 3 } 3 ×
gives{ 1 2 3 1 2 3 1 2 3 }
. The÷
operator is equivalent to theListDivide
function, and partitions a list in chunks of the given size and returns the number of partitions so generated (the last partition being possibly shorter), i.e.{ 1 2 3 4 5 } 2 ÷
will generate{1 2} {3 4} {5} 3
on the stack (this is not yet implemented). -
[ 1 2 3 ] 4 +
gives[ 5 6 7 ]
,[ 1 2 3 ] 2 -
gives[ -1 0 1 ]
,[ 1 2 3 ] 3 ×
gives[ 3 6 9 ]
and[ 1 2 3 ] 5 ÷
gives[ 1/5 2/5 3/5 ]
.
Vectors and matrices differences
-
On DB50X, vectors like
[ 1 2 3 ]
are very similar to lists. The primary difference is the behavior in the presence of arithmetic operators. On lists, addition is concatenation, e.g.{ 1 2 3} { 4 5 6} +
is{ 1 2 3 4 5 6 }
, whereas on vectors represents vector addition, e.g.[1 2 3] [4 5 6] +
is[5 7 9]
. However, unlike on the HP original implementation, a vector can contain any type of object, so that you can do[ "ABC" "DEF" ] [ "GHI" "JKL" ] +
and obtain[ "ABCGHI" "DEFJKL" ]
. -
Size enforcement on vectors only happens during these operations, not while you enter vectors from the command line. It is legal in DB50X to have a non-rectangular array like
[[1 2 3] [4 5]]
, or even an array with mixed objects like[ "ABC" 3 ]
. Size or type errors on such objects may occur if/when arithmetic operations are performed. -
In particular, a matrix is nothing but a vector of vectors. DB50X also supports arrays with dimensions higher than 2, like
[[[1 2 3]]]
. -
As a consequence, The
GET
andGETI
functions work differently on matrices. Consider a matrix like[[ 7 8 9 ][ 4 5 6 ][ 1 2 3 ]]
. On the HP48, running1 GET
on this object gives7
, and the valid range of index values is 1 through 9. On DB50X, that object is considered as an array of vectors, so1 GET
returns[7 8 9]
. This is intentional. The behavior of{ 1 1 } GET
is identical on both platforms, and is extended to multi-dimensional arrays, so that[[[4 5 6]]] { 1 1 2 } GET
returns5
. -
Matrices and vectors can contain integer values or fractions. This is closer to the HP50G implementation than the HP48's. In some cases, this leads to different results between the implementations. If you compute the inverse of
[[1 2 3][4 5 6][7 8 9]
on the HP48, you get a matrix with large values, and the HP48 finds a small, but non-zero determinant for that matrix. The HP50G produces a matrix with infinities. DB50X by default produces aDivide by zero
error. -
DB50X accept matrices and vectors as input to algebraic functions, and returns a matrix or vector with the function applied to all elements. For example,
[a b c] sin
returns[ 'sin a' 'sin b' 'sin c' ]
. -
Similarly, DB50X accept operations between a constant and a vector or matrix. This applies the same binary operation to all components of the vector or matrix.
[ a b c ] x +
returns[ 'a+x' 'b+x' 'c+x' ]
. Consistent with that logic,inv
works on vectors, and inverts each component, so that[1 2 3] inv
gives[1/1 1/2 1/3]
.
Equations handling differences
-
The DB50X dialect of RPL accepts equations with "empty slots". During equation evaluation, the value of these empty slots will be taken from the stack. In the equation, a slot is represented as
()
. -
For example, the equation
()+sin(cos())
will read two values from the stack. If evaluated in a stack that containsA
andB
, it will evaluate aA+sin(cos(B))
. -
This feature is an accident of implementation. It is recommended to use local variables to more precisely control where stack input is used in the equation. Ideally, you should write the above equation as
→ a b 'a+sin(cos(b))'
if you want better compatibility with other RPL implementations.
Unicode support
DB50X has almost complete support for Unicode, and stores text internally using the UTF-8 encoding. The built-in font has minor deviations in appearance for a few RPL-specific glyphs.
Overall, a text file produced by DB50X should appear reliably in your
favorite text editor, which should normally be GNU Emacs. This is notably the
case for state files with extension .48S
which you can find in the STATE
directory on the calculator.
Help
The DB50X project includes an extensive built-in help, which you are presently
reading. This help is stored as a HELP/DB50X.md
file on the calculator. You
can also read it from a web browser directly on the GitHub page of the project.
The Help
command makes it possible to access the built-in help in a contextual
way. It is Bound to 🟦 +. If the first level of the stack contains a text
corresponding to a valid help topic, this topic will be shown in the help
viewer. Otherwise, a help topic corresponding to the type of data in the stack
will be selected.
The DB50X help viewer works roughly similarly to the DM32's, but with history tracking and the ability to directly access help about a given function by holding a key for more than half a second.
To navigate the help on the calculator, use the following keys:
-
The soft menu keys at the top of the keyboard, references as F1 through F6, correspond to the functions shown in the six labels at the bottom of the screen.
-
While the help is shown, the keys ◀︎ and ▶︎ on the keyboard scroll through the text.
-
The F1 key returns to the Home (overview).
-
The F2 and F3 keys (labels
Page▲
andPage▼
) scroll the text one full page at a time. -
The F4 and F5 keys (labels
Link▲
andLink▼
) select the previous and next link respectively. The keys ÷ and 9 also select the previous link, while the keys × and 3 can also be used to select the next link. -
The F6 key correspond to the
←Menu
label, and returns one step back in the help history. The ← key achieves the same effect. -
To follow a highlighted link, click on the ENTER key.
Acknowledgements and credits
DB50X is Free Software, see the LICENSE file for details. You can obtain the source code for this software at the following URL: https://github.com/c3d/DB50X-on-DM32.
Authors
This software is (C) 2022-2023 Christophe de Dinechin and the DB50X team.
Additional contributors to the project include:
- Camille Wormser
- Jeff, aka spiff72
The authors would like to acknowledge
- Hewlett and Packard
- The Maubert Team
- Museum of HP calculators
- HPCalc
- The newRPL project
- The WP43 and C47 projects
- SwissMicro's DMCP
- Intel Decimal Floating-Point Math Library v2.2
This work was placed by Christophe de Dinechin under the patronage of Carlo Acutis
Hewlett and Packard
Hand-held scientific calculators changed forever when Hewlett and Packard asked their engineers to design and produce the HP35, then again when their company introduced the first programmable hand-held calculator with the HP65, and finally when they introduced the RPL programming language with the HP28.
Christophe de Dinechin, the primary author of DB50X, was lucky enough to meet both Hewlett and Packard in person, and this was a truly inspiring experience. Launching the Silicon Valley is certainly no small achievement, but this pales in comparison to bringing RPN and RPL to the world.
The Maubert Team
Back in the late 1980s and early 1990s, a team of young students with a passion for HP calculators began meeting on a regular basis at or around a particular electronics shop in Paris called "Maubert Electronique", exchanging tips about how to program the HP28 or HP48 in assembly language or where to get precious technical documentation.
It started with Paul Courbis, who carefully reverse-engineered and documented the internals of RPL calculators, encouraging his readers to boldly cut open these wonderful little machines to solder IR receivers acting as makeshift PC connection tools, or to waste countless hours debugging video games.
There were more serious efforts as well, notably the HP48 Metakernel, which completely reinvented the HP48 user interface, making it both much faster and better. It is fair to see DB50X as a distant descendent from such efforts. The Metakernel was the work of many now well-known names in the HP community, such as Cyrille de Brébisson, Jean-Yves Avenard, Gerald Squelart and Étienne de Foras. Many of these early heroes would go on to actually change the history of Hewlett-Packard calculators for the better.
The original author of DB50X, Christophe de Dinechin, was part of this loose team, focusing on cross-development tools, which he used at the time to write several games for the HP48, notably PacMan or Lemmings clones. If DB50X exists, it's largely because of that community.
HP Museum
The HP Museum not only extensively documents the history of RPN and RPL calcuators, it also provides a very active forum for calculator enthusiasts all over the world.
HPCalc
Much of the work from early enthusiasts can still be found on hpcalc.org to this day.
Back in the 1990s, long before Internet was widely available, HP48 programs were busily swapped over floppy disks, or propagated from machine to machine using the built-in infrared ports. This may have been the first case of large-scale viral distribution of software. This is probably the reason why all this software. which originated from all over the world, can still be downloaded and used today.
newRPL project
newRPL is a project initiated by Claudio Lapilli to implement a native version of RPL, initially targeting ARM-based HP calculators such as the HP50G.
DB50X inherits many ideas from newRPL, including, but not limited to:
- Implementing RPL natively for ARM CPUs
- Adding indicators in the cursor to indicate current status
- Integrating a catalog of functions to the command line
A first iteration of DB50X started as a branch of newRPL, although the current implementation had to restart from scratch due to heavy space constraints on the DM32.
WP43 and C47 projects
The DB50X took several ideas and some inspiration from the WP43 and C47 projects.
Walter Bonin initiated the WP43 firwmare for the DM32 as a "superset of the legendary HP42S RPN Scientific".
C47 (initially called C43) is a variant of that firmware initiated by Jaco Mostert, which focuses on compatibility with the existing DM32, notably with respect to keyboard layout.
DB50X borrowed at least the following from these projects:
- The very idea of writing a new firmware for the DM32
- The idea of converting standard Unicode TrueType fonts into bitmaps (with some additional contributions from newRPL)
- How to recompute the CRC for QSPI images so that the DM32 loads them, thanks to Ben Titmus
- At least some aspects of the double-shift logic and three-level menus
- The original keyboard layout template and styling, with special thanks to DA MacDonald.
SwissMicros DMCP
SwissMicros offers a range of RPN calculators that emulate well-known models from Hewlett-Packard. This includes the DM32, which is currently the primary target for the DB50X firmware.
Special thanks and kudos to Michael Steinmann and his team for keeping the shining spirit of HP RPN calculators alive.
The DM32 version of the DB50X software relies on SwissMicro's DMCP SDK, which is released under the following BSD 3-Clause License:
Copyright (c) 2015-2022, SwissMicros All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Intel Decimal Floating-Point Math
Floating-point computations in DB50X take advantage of Intel's decimal floating-point math library, which is released with the following end-user license agreement:
Copyright (c) 2018, Intel Corp.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice, his list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Introduction to RPL
The original RPL (Reverse Polish Lisp) programming language was designed and implemented by Hewlett Packard for their calculators from the mid-1980s until 2015 (the year the HP50g was discontinued). It is based on older calculators that used RPN (Reverse Polish Notation). Whereas RPN had a limited stack size of 4, RPL has a stack size only limited by memory and also incorporates programmatic concepts from the Lisp programming language.
The first implementation of RPL accessible by the user was on the HP28C, circa 1987, which had an HP Saturn processor. More recent implementations (e.g., HP49, HP50g) run through a Saturn emulation layer on an ARM based processor. These ARM-based HP calculators would be good targets for a long-term port of DB50X.
DB50X is a fresh implementation of RPL on ARM, initially targetting the SwissMicros DM32 calculator. This has implications on the design of this particular implementation of RPL.
The RPL stack
The RPL stack can grow arbitrarily in size.
By convention, and following RPN usage, this document gives the names X
, Y
,
Z
and T
to the first four levels of the stack. This is used to describe the
operations on the stack with synthetic stack diagrams showing the state of the
stack before and after the operation.
For example, the addition of two objects in levels 1 and 2 with the result deposited in stack level 1 can be described in synthetic form using the following stack diagram:
Y
X
▶ Y+X
The duplication
Algebraic mode
Unlike earlier RPN calculators, RPL includes complete support for algebraic
objects written using the standard precedence rules in mathematics. In RPL,
algebraic expressions are placed between ticks. For example, '2+3×5'
will
evaluate as 17
: the multiplication 3×5
, giving 15
, is performed before the
addition 2+15
, which gives 17
.
Algebraic expressions are not evaluated automatically. The R/S key (bound to the Evaluate function) will compute their value.
Integers
The DB50X version of RPL distinguishes between integer values, like 123
, and
decimal values, like 123.
Integer values are represented
internally in a compact and efficient format, saving memory and making
computations faster. All values between -127 and 127 can be stored in two bytes.
All values between -16383 and 16383 in three bytes.
Integers can be as large as memory permits.
Big integers
The DB50X version of RPL can perform computations on arbitrarily large integers,
limited only by available memory, enabling for example the exact computation of
100!
and making it possible to address problems that require exact integer
computations, like exploring the Syracuse conjecture.
Decimal numbers
Decimal numbers are used to represent values with a fractional part. DB50X supports three decimal numbers, using the 32-bit, 64-bit and 128-bit binary decimal representation. In memory, all decimal numbers use one additional byte: a 32-bit decimal number uses 5 bytes, a 128-bit binary decimal number uses 17 bytes.
The 32-bit format offers a 7 digits mantissa and has a maximum exponent of 96. The 64-bit format offers a 16 digits mantissa and has a maximum exponent of 384. The 128-bit format offers a 34 digits mantissa and a maximum exponent of 6144.
The Precision command selects the default precision.
Note that a future implementation of DB50X is expected to feature variable-precision decimal numbers similar to newRPL.
Based numbers
Based numbers are used to perform computations in any base. The most common bases used in computer science, 2, 8, 10 and 16, have special shortcuts. The Bases Menu list operations on based numbers.
Like integers, based numbers can be arbitrary large. However, operations on based numbers can be truncated to a specific number of bits using the STWS command. This makes it possible to perform computations simulating a 16-bit or 256-bit processor.
Complex numbers
Complex numbers can be represented in rectangular form or polar form.
The rectangular form will show as something like 2+3ⅈ
on the display, where
2
is the real part and 3
is the imaginary part. The polar form will show as
something like 1∡90°
on the display, where 1
is the modulus and 90°
is the
argument. The two forms can be mixed and matched in operations. The calculator
typically selects the most efficient form for a given operation.
Available operations on complex numbers include basic arithmetic, trigonometric, logarithms, exponential and hyperbolic functions, as well as a few specific functions such as conj or arg. These functions are available in the Complex Menu.
Equations
Algebraic expressions and equations are represented between quotes, for example
X+1
or A+B=C
. Many functions such as circular functions, exponential, logs
or hyperbolic functions can apply to algebraic expressions.
Lists
Lists are sequence of items between curly braces, such as { 1 'A' "Hello" }
.
They can contain an arbitrary number of elements, and can be nested.
Operations such as sin
apply to all elements on a list.
Vectors and matrices
Vector and matrices represent tables of numbers, and are represented between
square brackets, for example [1 2 3]
for a vector and [[1 2] [3 4]
for a 2x2
matrix.
Vector and matrices follow their own arithmetic rules. Vectors are one-dimensional, matrices are two-dimensional. DB50X also supports tables with a higher number of dimensions, but only offers limited operations on them.
DB50X implements vector addition, subtraction, multipplication and division, which apply component-wise. Multiplication and division are an extension compared to the HP48.
DB50X also implements matrix addition, subtraction, multiplication and
division. Like on the HP48, the division of matrix A
by matrix B
is
interpreted as left-multiplying A
by the inverse of B
.
As another extension, algebraic functions such as sin
apply to all elements in
a vector or matrix in turn.
Units
Unit objects represent values with an associated unit. They are represented
using the _
operator, e.g. 1_km/s
, although on display this operator is
shown as a thin space, e.g. 1 km/s
.
Menus
Menus display at the bottom of the screen, and can be activated using the keys
on the top row of the calculator. Menus can refer to other menus. The calculator
keeps a history of the menus you visited previously, and you can return to an
earlier menu with the BackMenu
function.
Here are the main menus in DB50X, in alphabetical order.
MainMenu
The Main menu gives access to all the functions in your calculator, sorted by cathegory. It includes the following submenus:
- Math: Mathematical operations
- Symb: Symbolic operations
- Units: Unit conversions
- System: System configuration
- Prog: Programming
- Vars: User variables
MathMenu
The Math menu gives access to mathematical functions like SIN in your calculator. It includes the following submenus:
- Arith: Arithmetic functions
- Base: Based numbers
- Trans: Transcendental functions
- Stats: Statistics
- Lists: List operations
- Matrix: Matrices and vectors
- Solve: Numerical solver
VariablesMenu (VARS)
The variables menu displays the variables in the current directory. It is a three row menu, where for each variable:
- The primary function evaluates the variable
- The first shifted function recalls the variable
- The second shifted function stores in the variable
VariablesMenuExecute
Hitting the primary function in the Vars menu evaluates the corresponding variable.
VariablesMenuRecall
Hitting the first shifted function in the Vars menu will recall the corresponding variable on the stack.
VariablesMenuStore
Hitting the second shifted function in the Vars menu will store the top of stack in the corresponding variable.
ToolsMenu
The ToolsMenu
maps to the A key (Σ+ on the original DM32 keyboard).
It invokes a context-dependent menu adapted to the top level of the stack.
LastMenu
The LastMenu
function, which is the shifted function for the _ A _ key,
returns back in the history of past visited menus.
Operations with Angles
TAGDEG
Mark a number as an angle in degrees
TAGRAD
Mark a number as an angle in radians
TAGGRAD
Mark a number as an angle in grads (gons)
TAGDMS
Mark a number as an angle in DMS (DD.MMSS)
ANGTODEG
Convert an angle to degrees
ANGTORAD
Convert an angle to radians
ANGTOGRAD
Convert an angle to grads (gons)
ANGTODMS
Convert an angle to DMS (DD.MMSS)
TORECT
Convert vector or complex to cartesian coordinates
TOPOLAR
Convert vector or complex to polar coordinates
TOSPHER
Convert vector or complex to spherical coordinates
Arithmetic
+ (add)
Add two values.
- For integer, fractional, decimal or complex numbers, this performs the
expected numerical addition. For example,
1 2 +
is3
. - For equations and symbols, build a sum, eliminating zero additions if autosimplify is active.
- For lists, concatenate lists, or add objets to a list. For example,
{ A } { B } +
is{ A B }
, and{ A B C } "D" +
is{ A B C "D" }
. - For text, concatenate text, or concatenate the text representation of an
object to an existing text. For example
"X" "Y" +
gives"XY"
, and"X=" 1 +
gives"X=1"
.
- (sub)
Subtract two values
- For integer, fractional, decimal or complex numbers, this performs the
expected numerical subtraction. For example,
1 2 -
is-1
. - For equations and symbols, build a difference, eliminating subtraction of 0 if autosimplify is active.
+ (add)
Add two values.
- For integer, fractional, decimal or complex numbers, this performs the
expected numerical addition. For example,
1 2 +
is3
. - For vectors and matrices, add individual elements. For example,
[ 1 2 3 ] [ 4 5 6 ] +
is[ 5 7 9 ]
. - For equations and symbols, build a sum, eliminating zero additions when autosimplify is active.
- For lists, concatenate lists, or add objets to a list. For example,
{ A } { B } +
is{ A B }
, and{ A B C } "D" +
is{ A B C "D" }
. - For text, concatenate text, or concatenate the text representation of an
object to an existing text. For example
"X" "Y" +
gives"XY"
, and"X=" 1 +
gives"X=1"
.
- (sub)
Subtract two values
- For integer, fractional, decimal or complex numbers, this performs the
expected numerical subtraction. For example,
1 2 -
is-1
. - For vectors and matrices, subtract individual elements. For example,
[ 1 2 3 ] [ 1 3 0 ] -
is[ 0 -1 3 ]
. - For equations and symbols, build a difference, eliminating subtraction of 0 when autosimplify is active.
× (*, mul)
Multiply two values.
- For integer, fractional, decimal or complex numbers, this performs the
expected numerical multiplication. For example,
3 2 *
is6
. - For vectors, multiply individual elements (this is a deviation from HP48).
For example,
[ 1 2 3 ] [ 4 5 6 ] +
is[ 4 10 18 ]
. - For matrices, perform a matrix multiplication.
- For a matrix and a vector, apply the matrix to the vector.
- For equations and symbols, build a product, eliminating mulitplication by 1 or 0 when autosimplify is active.
- For a list and a positive integer, repeat the list For example,
{ A } 3 *
is{ A A A }
. - For a text and a positive integer, repeat the text. For example
"X" 3 *
gives"XXX"
.
÷ (/, div)
Divide two values two values
- For integer, build a fraction. For example
1 7 /
gives1/7
. - For fractional, decimal or complex numbers, this performs the
expected numerical division. For example,
1. 2. /
is0.5
. - For vectors, divide individual elements. For example,
[ 1 2 3 ] [ 3 2 1 ] /
is[ 1/3 1 3 ]
. - For equations and symbols, build a ratio, eliminating division by one and division of 0 when autosimplify is active.
↑ (^, pow)
Raise to the power
- For integer, fractional, decimal or complex numbers, this raises the
value in level 2 to the value in level 1. For example,
2 3 ↑
is8
. - For vectors, raise individual elements in the first vector to the power of the corresponding element in the second vector.
- For equations and synbols, build an expression, eliminating special cases when autosimplify is active.
xroot
Raise to the inverse power. X Y xroot
is equivalent to X Y inv pow
.
Integer arithmetic and polynomials
SETPREC
Set the current system precision
GETPREC
Get the current system precision
FLOOR
Largest integer less than the input
CEIL
Smallest integer larger than the input
IP
Integer part of a number
FP
Fractional part of a number
MODSTO
Set the current system modulo for all MOD operations
MODRCL
Get the current system modulo
POWMOD
Power operator MOD the current system modulo
MOD
Remainder of the integer division
SQ
Square of the input
NEXTPRIME
Smallest prime number larger than the input
FACTORIAL
Factorial of a number
ISPRIME
Return true/false (1/0) if a number is prime or not
MANT
Mantissa of a real number (M*10exp)
XPON
Exponent of a number represented as (M*10exp)
SIGN
Sign of a number, -1, 0 or 1.
For complex numbers, returns a unit number on the unit circle with the same argument as the original number.
PERCENT
Percentage of a number
PERCENTCH
Percentage of change on a number
PERCENTTOT
Get percentage of a total
GCD
Greatest common divisor
LCM
Least common multiple
IDIV2
Integer division, get quoteiant and remainder
IQUOT
Quotient of the integer division
ADDTMOD
Addition operator MOD the current system modulo
SUBTMOD
Subtraction operator MOD the current system modulo
MULTMOD
Multiplication operator MOD the current system modulo
PEVAL
Evaluation of polynomial given as vector of coefficients
PCOEF
Coefficients of monic polynomial with the given roots
IEGCD
Extended euclidean algorithm
IABCUV
Find integers u,v to solve au+bv=c
PTCHEBYCHEFF
Nth Tchebycheff polynomial
PLEGENDRE
Nth Legendre polynomial
PHERMITE
Nth Hermite polynomial as used by physics
PTCHEBYCHEFF2
Nth Tchebycheff polynomial of the second kind
PHERMITE2
Nth Hermite polynomial as used in probabilities
DIV2
Polynomial euclidean division as symbolic
PDIV2
Polynomial euclidean division as coefficient vector
PDER
Derivative of polynomial as coefficient vector
PINT
Integration of polynomials as coefficient vector
PMUL
Multiplication of polynomials as coefficient vectors
PADD
Addition of polynomials as coefficient vector
PSUB
Subtraction of polynomials as coefficient vector
MIN
Smallest of 2 objects
MAX
Largest of 2 objects
RND
Round a number to the given number of figures
TRNC
Truncate a number to the given number of figures
DIGITS
Extract digits from a real number
PROOT
All roots of a polynomial
PREVPRIME
Largest prime smaller than the input
FACTORS
Factorize a polynomial or number
Base functions
Evaluate (EVAL)
Evaluate the object at stack level 1.
Mapped to the _ R/S _ key
X
▶ Result of X
evaluation
Drop
Negate (NEG)
Negate the value in level 1.
Mapped to the _ +/- _ key
X
▶ 0-X
Invert (INV)
Invert the value in level 1
Mapped to the _ 1/X _ key
X
▶ 1/X
Bitwise operations
STWS
Store current word size in bits (0-63)
RCWS
Recall the currnent word size in bits
BOR
Bitwise OR operation
BAND
Bitwise AND operator
BXOR
Bitwise XOR operation
BLSL
Bitwise logical shift left
BLSR
Bitwise logical shift right
BASR
Bitwise arithmetic shift right
BRL
Bitwise rotate left
BRR
Bitwise rotate right
BNOT
Bitwise inversion of bits
BADD
Bitwise addition with overflow
BSUB
Bitwise subtraction with overflow
BMUL
Bitwise multiplication
BDIV
Bitwise integer division
BNEG
Bitwise negation
Bitmaps
TOSYSBITMAP
Comments
STRIPCOMMENTS
Remove all comments from a compiled program
Operations with Complex Numbers
RE
Real part of a complex number
IM
Imaginary part of a complex number
ARG
Argument of a complex number
CONJ
Conjugate of a complex number
CPLX2REAL
Split Complex into two Reals
REAL2CPLX
Make Complex from real and imaginary parts
Lists, Matrix and String commands
PUT
Replace an item in a composite
PUTI
Replace an item and increase index
GET
Extract an item from a composite
GETI
Extract an item and increase index
HEAD
Extract the first item in a composite
TAIL
Removes the first item in a composite
OBJDECOMP
Explode an object into its components
REPL
Replace elements in a composite
POS
Find the position of an element in a composite
NPOS
Find object in a composite, starting from index N
POSREV
Find the position of an element, starting from the end
NPOSREV
Find the position from the end, starting at index N
SUB
Extract a group of elements from a composite
SIZE
Number of elements in a composite
RHEAD
Returns the last element from the composite
RTAIL
Removes the last element from the composite
Constants
PICONST
ICONST
ECONST
JCONST
Variables
Variables are named storage for RPL values.
Store (STO)
Store an object into a global variable
Recall (RCL)
Recall the contents of a variable
StoreAdd (STO+)
Add to the content of a variable
StoreSubtract (STO-)
Subtract from the contents of a variable
StoreMultiply (STO×)
Multiply contents of a variable
StoreDivide (STO÷)
Divide the content of a variable
Increment (INCR)
Add one to the content of a variable
Decrement (DECR)
Subtract one from content of a variable
Purge
Delete a global variable from the current directory
Remark: Purge
only removes a variable from the current directory, not the
enclosing directories. Since Recall will fetch variable values from
enclosing directories, it is possible that 'X' Purge 'X' Recall
will fetch a
value for X
from an enclosing directory. Use PurgeAll if you want
to purge a variable including in enclosing directories.
PurgeAll
Delete a global variable from the current directory and enclosing directories.
Remark: If a variable with the same name exists in multiple enclosing
directories, PurgeAll
may purge multiple variables. Use Purge if you
want to only purge a variable in the current directory.
CreateDirectory (CRDIR)
Create new directory
PurgeDirectory (PGDIR)
Purge entire directory tree
UpDirectory (UPDIR)
Change current directory to its parent
HomeDirectory (HOME)
Change current directory to HOME
DirectoryPath (PATH)
Get a path to the current directory
Variables (VARS)
List all visible variables in a directory
ALLVARS
List all variables in a directory
ORDER
Sort variables in a directory
QUOTEID
Add single quotes to a variable name
UNQUOTEID
Remove single quotes from a variable name
HIDEVAR
Hide a variable (make invisible)
UNHIDEVAR
Make a hidden variable visible
CLVAR
Purge all variables and empty subdirectories in current directory
LOCKVAR
Make variable read-only
UNLOCKVAR
Make variable read/write
RENAME
Change the name of a variable
TVARS
List variables of a specific type
TVARSE
List all variables with extended type information
SADD
Apply command ADD to the stored contents of the variable
SPROP
Store a property to a variable
RPROP
Recall a property of a variable
PACKDIR
Pack a directory in an editable object
Errors and error handlers
EXITRPL
Panic exit - abort the RPL engine.
EVAL1NEXT
Perform EVAL1 on the next object in a secondary and skips it
RESUME
End error handler and resume execution of main program
DOERR
Issue an error condition
ERRN
Recall the previous error code
ERRM
Recall the previous error message
ERR0
Clear previous error code
HALT
Halt the execution of RPL code
CONT
Continue execution of a halted program
SST
Single-step through a halted program, skip over subroutines
SSTIN
Single-step through a halted program, goes into subroutines
KILL
Terminate a halted program
SETBKPOINT
Set a breakpoint on a halted program
CLRBKPOINT
Remove a breakpoint
DBUG
Halt the given program at the first instruction for debugging
BLAMEERR
Issue an error condition, blame other program for it
EXIT
Early exit from the current program or loop
Flow control
If
The if
statement provides conditional structurs that let a program make decisions. It comes in two forms:
-
if
conditionthen
true-clauseend
: This evaluates condition and, if true, evaluates true-clause. -
if
conditionthen
true-clauseelse
false-clauseend
: This evaluates condition and, if true, evaluates true-clause, otherwise evaluates false-clause.
A condition is true if:
- It is a number with a non-zero value
- It is the word
True
A condition is false if:
- It is a number with a zero value
- It is the word
False
CASE
Conditional CASE ... THEN ... END THEN ... END END statement
THENCASE
Conditional CASE ... THEN ... END THEN ... END END statement
ENDTHEN
Conditional CASE ... THEN ... END THEN ... END END statement
ENDCASE
Conditional CASE ... THEN ... END THEN ... END END statement
FOR
Loop FOR ... NEXT/STEP statement
START
Loop START ... NEXT/STEP statement
NEXT
Loop FOR/START ... NEXT statement
STEP
Loop FOR/START ... STEP statement
DO
Loop DO ... UNTIL ... END statement
UNTIL
Loop DO ... UNTIL ... END statement
ENDDO
Loop DO ... UNTIL ... END statement
WHILE
Loop WHILE ... REPEAT ... END statement
REPEAT
Loop WHILE ... REPEAT ... END statement
ENDWHILE
Loop WHILE ... REPEAT ... END statement
IFERR
Conditional IFERR ... THEN ... ELSE ... END statement
THENERR
Conditional IFERR ... THEN ... ELSE ... END statement
ELSEERR
Conditional IFERR ... THEN ... ELSE ... END statement
ENDERR
Conditional IFERR ... THEN ... ELSE ... END statement
FORUP
Loop FORUP ... NEXT/STEP statement
FORDN
Loop FORUP ... NEXT/STEP statement
Menus, Flags and System Settings
SETLOCALE
Change the separator symbols
SETNFMT
Change the display format for numbers
SF
Set a flag
CF
Clear a flag
FCTEST
Test if a flag is clear
FSTEST
Test if a flag is set
FCTESTCLEAR
Test if a flag is clear, then clear it
FSTESTCLEAR
Test if a flag is set, then clear it
TMENU
Display the given menu on the active menu area
TMENULST
Display the given menu on the menu area the user used last
TMENUOTHR
Display the given menu on the menu are the user did not use last
MENUSWAP
Swap the contents of menu areas 1 and 2
MENUBK
Display the previous menu on the active menu area
MENUBKLST
Display the previous menu on the area the user used last
MENUBKOTHR
Display the previous menu on the area the user did not use last
RCLMENU
Recall the active menu
RCLMENULST
Recall the menu the user used last
RCLMENUOTHR
Recall the menu the user did not use last
DEG
Set the angle mode flags to degrees
GRAD
Set the angle mode flags to grads (gons)
RAD
Set the angle mode flags to radians
DMS
Set the angle mode to DMS (as DD.MMSS)
ASNKEY
Assign a custom definition to a key
DELKEY
Remove a custom key definition
STOKEYS
Store and replace all custom key definitions
RCLKEYS
Recall the list of all custom key definitions
TYPEE
Get extended type information from an object
GETLOCALE
Get the current separator symbols
GETNFMT
Recall the current display format for numbers
RCLF
Recall all system flags
STOF
Store and replace all system flags
VTYPE
Get type information on the contents of a variable
VTYPEE
Get extended type information on the contents of a variable
FMTSTR
Do →STR using a specific numeric format
Fonts
FNTSTO
Install a user font for system use
FNTRCL
Recall a system font
FNTPG
Purge a user-installed system font
FNTSTK
Recall name of current font for stack area
FNT1STK
Recall name of current font for stack level 1
FNTMENU
Recall name of current font for menu area
FNTCMDL
Recall name of current font for command line area
FNTSTAT
Recall name of current font for status area
FNTPLOT
Recall name of current font for plot objects
FNTFORM
Recall name of current font for forms
STOFNTSTK
Change current font for stack area
STOFNT1STK
Change current font for stack level 1
STOFNTMENU
Change current font for menu area
STOFNTCMDL
Change current font for command line area
STOFNTSTAT
Change current font for status area
STOFNTPLOT
Change current font for plot objects
STOFNTFORM
Change current font for forms
FNTHELP
Recall name of current font for help
FNTHLPT
Recall name of current font for help title
STOFNTHELP
Change current font for help text
STOFNTHLPT
Change current font for help title
Graphic commands
DB50X features a number of graphic commands. While displaying graphics, the stack and headers will no longer be updated.
Coordinates
DB50X recognizes the following types of coordinates
-
Pixel coordinates are specified using based numbers such as
#0
, and correspond to exact pixels on the screen, and . Pixels are counted starting from the top-left corner of the screen, with the horizontal coordinate going from10#0
to10#399
, and the vertical coordinate going from10#0
to10#239
. -
User unit coordinates are scaled according to the content of the
PPAR
orPlotParameters
reserved variables. -
Text coordinates are given on a square grid with a size corresponding to the height of a text line in the selected font. They can be fractional.
Coordinates can be given using one the following object types:
-
A complex number, where the real part represents the horizontal coordinate and the imaginary part represents the vertical coordinate.
-
A 2-element list or vector containing the horizontal and vertical coordinates.
-
A 1-element list of vector containing one of the above.
For some operations, the list or vector can contain additional parameters beyond
the coordinates. The selection of unit or pixel coordinates is done on a per
coordinate basis. For exmaple, { 0 0 }
will be the origin in user coordinates,
in the center of the screen if no PPAR
or PlotParameters
variable is
present.
Note that unlike on the HP48, a complex value in DB50X can contain a based number.
ClearLCD (cllcd)
Clear the LCD display, and block updates of the header or menu areas.
DrawText (disp)
Draw the text or object in level 2 at the position indicated by level 1. A text is drawn without the surrounding quotation marks.
If the position in level 1 is an integer, fraction or real number, it is
interpreted as a line number starting at 1 for the top of the screen. For
example, "Hello" 1 disp
will draw Hello
at the top of the screen.
If the position in level 1 is a complex number or a list, it is interpreted as
specifying both the horizontal or vertical coordinates, in either pixel or unit
coordinates. For example "Hello" { 0 0 } disp
will draw Hello
starting in
the center of the screen.
Text is drawn using the stack font by default, using the foreground and background patterns.
If level 1 contains a list with more than 2 elements, additional elements provide:
-
A font number for the text
-
An erase flag (default true) which indicates whether the background for the text should be drawn or not.
-
An invert flag (default false) which, if set, will swap the foreground and background patterns.
For example, "Hello" { #0 #0 0 true true } DrawText
will draw Hello
in the
top-left corner (#0 #0
) with the largest (editor) font (font identifier 0
),
erasing the background (the first true
), in reverse colors (the second
true
).
DrawLine (line)
Draw a line between two points specified by level 1 and level 2 of the stack.
The width of the line is specified by LineWidth. The line is drawn using the foreground pattern.
PlotParameters (PPAR)
The PlotParameters
reserved variable defines the plot parameters, as a list,
with the following elements:
-
Lower Left coordinates as a complex (default
-10-6i
) -
Upper Right coordinates as a complex (default
10+6i
) -
Independent variable name (default
x
) -
Resolution specifying the interval between values of the independent variable (default
0
). A binary numnber specifies a resolution in pixels. -
Axes which can be a complex giving the origin of the axes (default
0+0i
), or a list containing the origin, the tick mark specification, and the names of the axes. -
Type of plot (default
function
) -
Dependent variable name (default
y
)
Local Variables
LSTO
Store to a new local variable
LRCL
Recall content of local variable
HIDELOCALS
Hide local variables from subroutines
UNHIDELOCALS
Unhide local variables from subroutines
INTERNAL_NEWNLOCALS
Arbitrary data containers
MKBINDATA
Create binary data container object
BINPUTB
Store bytes into binary data object
BINGETB
Extract binary data as list of bytes
BINPUTW
Store 32-bit words into binary data object
BINGETW
Extract data from a binary data object as a list of 32-bit words
BINPUTOBJ
Store an entire object into a binary data container
BINGETOBJ
Extract an entire object from a binary data container
BINMOVB
Copy binary data block into a binary data object
BINMOVW
Copy 32-bit words between binary data objects
User Libraries
CRLIB
Create a library from current directory
ATTACH
Install a library
DETACH
Uninstall a library
LIBMENU
Show a menu within a library
LIBMENUOTHR
Show library menu in the other menu
LIBMENULST
Show library menu in the last used menu
LIBSTO
Store private library data
LIBRCL
Recall private library data
LIBDEFRCL
Recall private data with default value
LIBCLEAR
Purge all private data for a specific library
Operations with Lists
TOLIST
Assemble a list from its elements
INNERCOMP
Split a list into its elements
CMDDOLIST
Do a procedure with elements of lists
DOSUBS
Do a procedure on a subset of a list
MAP
Do a procedure on each element of a list, recursively
MAPINNERCOMP
Do a procedure on each element recursively, return individual elements
STREAM
Do a procedure on consecutive elements of a list
DELTALIST
First differences on the elements of a list
SUMLIST
Sum of all elements in a list
PRODLIST
Product of all elements in a list
ADD
Concatenate lists and/or elements
SORT
Sort elements in a list
REVLIST
Reverse the order of elements in a list
ADDROT
Add elements to a list, keep only the last N elements
SEQ
Assemble a list from results of sequential procedure
Operations with Matrices and vectors
TOARRAY
Assemble an array from its elements
ARRAYDECOMP
Split an array into its elements
TOCOL
Split an array into column vectors
ADDCOL
Instert a column into an array
REMCOL
Remove a column from an array
FROMCOL
Assemble a matrix from its columns
TODIAG
Extract diagonal elements from a matrix
FROMDIAG
Create a matrix with the given diagonal elements
TOROW
Split an array into its row vectors
ADDROW
Insert a row into an array
REMROW
Remove a row from an array
FROMROW
Assemble an array from its rows
TOV2
Assemble a vector from two values
TOV3
Assemble a vector from three values
FROMV
Split a vector into its elements
AXL
Convert a matrix to list and vice versa
BASIS
Find vectors forming a basis of the subspace represented by the matrix
CHOLESKY
Perform Cholesky decomposition on a matrix
CNRM
Column norm (one norm) of a matrix
CON
Assemble an array with given constant value
COND
Column norm condition number of a matrix
CROSS
Cross produce of vectors
CSWP
Swap two columns in a matrix
DET
Determinant of a matrix
DIAGMAP
DOT
Internal product (dot product) of vectors
EGV
EGVL
Compute the eigenvalues of a matrix
GRAMSCHMIDT
HADAMARD
Multiply corresponding elements in a matrix
HILBERT
Assemble a Hilbert symbolic array
IBASIS
Find a basis of the intersection of two vector spaces
IDN
Assemble an identity matrix
IMAGE
Find a basis of the image of a linear application
ISOM
JORDAN
KER
Find a basis for the kernel of a linear application
LQ
LSQ
LU
LU factorization of a matrix
MAD
MKISOM
PMINI
Minimal polynomial of a matrix
QR
QR Decomposition of a matrix
RANK
Rank of a matrix
RANM
Assemble a matrix with random numbers
RCI
Multiply a row by a constant
RCIJ
Multiply a row by a constant and add to other row
RDM
Change dimensions of an array
REF
Reduce matrix to echelon form (upper triangular form)
RNRM
Row norm (infinity norm) of a matrix
RREF
Fully reduce to row-reduced echelon form
RREFMOD
RSD
Residual R=B-AX' on a system AX=B
RSWP
Swap two rows in a matrix
SCHUR
SNRM
SRAD
SVD
SVL
SYLVESTER
TRACE
Sum of the items in the diagonal of a matrix
TRAN
Transpose a matrix
TRN
Complex conjugate transpose of a matrix
VANDERMONDE
LDUP
Decompose A into LDUP such that PA=LD-1*U
MMAP
Apply expression or program to the elements of a matrix
Numerical functions
∫ (Integrate)
Perform a numerical integration of a function for a specified variable on a
numerical interval. For example 2 3 'X*(X-3)' 'X' Integrate
returns -7/6
.
The function takes four arguments:
- The lower bound of the integration range
- The higher bound of the integration range
- The program or expression to evaluate
- The integration variable
Root
Root-finder command. Returns a real number that is a value of the specified
variable for which the specified program or algebraic object most nearly
evaluates to zero or a local extremum. For example, 'X^2=3' 'X' 0
returns
X:1.732050807568877293527446341953458
.
The function takes three arguments:
- The program or expression to evaluate
- The variable to solve for
- An initial guess, or a list containing an upper and lower guess.
Cycle
Cycle through various representations of the object on the first level of the stack.
- Polar <-> Rectangular for complex numbers
- Decimal <-> Fraction
- Integer <-> Based (cycles through the 2, 8, 10 and 16 base)
- Array <-> List <-> Program
- Text <-> Symbol
Scalable plots and graphics
BEGINPLOT
Initialize a new current plot object
EDITPLOT
Set the current plot object to the given graphic
ENDPLOT
Finish current plot object and leave it on the stack
STROKECOL
Change the current stroke color
STROKETYPE
Change current stroke type
FILLCOL
Change the current fill color
FILLTYPE
Change the current fill type
FILL
Fill the last polygon
STROKE
Draw the outline of the last polygon
FILLSTROKE
Draw the outline and fill the last polygon
MOVETO
Move current coordinates
LINETO
Draw a line
CIRCLE
Draw a circle
RECTANG
Draw a rectangle
CTLNODE
Add a control node to the current polygon
CURVE
Draw a curve using all previous control points
BGROUP
EGROUP
DOGROUP
BASEPT
TRANSLATE
ROTATE
SCALE
CLEARTRANSF
SETFONT
TEXTHEIGHT
TEXTOUT
INITRENDER
Set which library will be used as default renderer
DORENDER
Render a graphics object using the current renderer
PANVIEW
Shift the center of viewport to render graphics
ROTVIEW
SCLVIEW
Set scale to render graphics
VIEWPORT
VIEWALL
SD Card
SDRESET
Reset the file system module
SDSETPART
Set active partition
SDSTO
Store a an object into a file
SDRCL
Recall an object from a file
SDCHDIR
Change current directory
SDUPDIR
Change to parent directory
SDCRDIR
Create a new directory
SDPGDIR
Delete an entire directory
SDPURGE
Delete a file
SDOPENRD
Open a file for read-only operation
SDOPENWR
Open a file for writing
SDOPENAPP
Open a file in append mode
SDOPENMOD
Open a file in modify mode
SDCLOSE
Close an open file
SDREADTEXT
Read text from an open file (UTF-8 encoding)
SDWRITETEXT
Write text to a file (UTF-8 encoding)
SDREADLINE
Read one line of text from a file
SDSEEKSTA
Move position to given offset from start of file
SDSEEKEND
Move position to given offset from end of file
SDSEEKCUR
Move position to given offset from the current point.
SDTELL
Get the current position
SDFILESIZE
Get the file size in bytes
SDEOF
Return true if last operation reached end of file
SDOPENDIR
Open a directory to scan entries
SDNEXTFILE
Get the next entry in a directory that is a file
SDNEXTDIR
Get the next entry in a directory that is a subdirectory
SDNEXTENTRY
Get the next entry in a directory
SDMOVE
Move or rename a file
SDCOPY
Copy a file
SDPATH
Get the path to current directory
SDFREE
Get the free space in the current volume
SDARCHIVE
Create a full calculator backup on a file
SDRESTORE
Restore from a backup stored in a file
SDGETPART
Get the current partition number
Settings
The calculator has a number of user-configurable settings:
The current preferences can be retrieved and saved using the Modes
command.
Modes
Returns a program that will restore the current settings. This program can be saved into a variable to quickly restore a carefully crafted set of preferences. Note that the calculator automatically restores the mode when it loads a state.
Display settings
The display mode controls how DB50X displays numbers. Regardless of the display mode, numbers are always stored with full precision.
DB50X has five display mode (one more than the HP48)s:
StandardDisplay (STD)
Display numbers using full precision. All significant digts to the right of the decimal separator are shown, up to 34 digits.
FixedDisplay (FIX)
Display numbers rounded to a specific number of decimal places.
ScientificDisplay (SCI)
Display numbers in scientific notation, i.e. with a mantissa and an exponent. The mantissa has one digit to the left of the decimal separator and shows the specified number of decimal places.
EngineeringDisplay (SCI)
Display nunmbers as a mantissa with a sepcified number of digits, followed by an exponent that is a multiple of 3.
SignificantDisplay (SIG)
Display up to the given number of digits without trailing zero. This mode is
useful because DB50X can compute with large precision, and it may be useful to
not see all digits. StndardDisplay
is equivalent to 34 SignificantDisplay
,
while 12 SignificantDisplay
should approximate the HP48 standard mode using
12 significant digits.
StandardExponent
Select the maximum exponent before switching to scientific notation. The default value is 9, meaning that display uses scientific notation for exponents outside of -9..9.
MinimumSignificantDigits
Select the minimum number of significant digits before switching to scientific notation in FIX
mode.
The default value is 0, which is similar to how HP calculators before the HP Prime perform. For example, with 2 FIX
, the value 0.055
will display as 0.06
, and 0.0055
will display as 0.01
.
A higher value will switch to scienfic mode to show at least the given number of digits. For instance, with 2 FIX
, if the value is 1
, then 0.055
will still display as 0.06
but 0.0055
will display as 5.50E-3
. If the value is 2
, then 0.055
will display as 5.5E-2
. A setting of 1
correspond to what the HP Prime does.
A value of -1
indicates that you do not want FIX
mode to ever go to scientific notation for negative exponents. In that case, 0.00055
will display as 0.00
.
TrailingDecimal
Display a trailing decimal separator to distinguish decimal from integer types. With this setting, 1.0
will display as 1.
. This can be disabled with NoTrailingDecimal.
NoTrailingDecimal
Hide the trailing decimal separator for decimal values with no fractional part. In that mode, 1.0
and 1
will both display identically, although the internal representation is different, the former being a floating-point value while the latter is an integer value.
FancyExponent
Display the exponent in scientific mode using a fancy rendering that is visually similar to the normal mathematical notation.
ClassicExponent
Display the exponent in scientific mode in a way reminiscent of classical HP48 calculators, for example 1.23E-4
.
Angle settings
The angle mode determines how the calculator interprets angle arguments and how it returns angle results.
DB50X has four angle modes:
- Degrees: A full circle is 360 degress
- Radians: A full circle is 2π radians
- Grads: A full circle is 400 radians
- PiRadians: Radians shown as multiple of π
Degrees (DEG)
Select degrees as the angular unit. A full circle is 360 degrees.
Radians (RAD)
Select radians as the angular unit. A full circle is 2π radians, and the angle is shown as a numerical value.
Grads (GRAD)
Select grads as the angular unit. A full circle is 400 grads.
PiRadians (PIRAD)
Select multiples of π as the angular unit. A full circle is 2π radians, shown as a multiple of π.
Command display
DB50X can display commands either using a short legacy spelling, usually
identical to what is used on the HP-48 series of calculators, or use an
alternative longer spelling. For example, the command to store a value in a
variable is called STO
in the HP-48, and can also be spelled Store
in DB50X.
Commands are case insensitive, and all spellings are accepted as input irrespective of the display mode.
DB50X has four command spelling modes:
- Lowercase: Display
sto
- Uppercase: Display
STO
- Capitalized: Display
Sto
- Long form: Display
Store
LowerCase
Display comands using the short form in lower case, for example sto
.
UpperCase
Display comands using the short form in upper case, for example STO
.
Capitalized
Display comands using the short form capitalized, for example Sto
.
LongForm
Display comands using the long form, for example Store
.
Decimal separator settings
The decimal separator can be either a dot (1.23
) or a comma (1,23
).
DecimalDot
Select the dot as a decimal separator, e.g. 1.23
DecimalComma
Select the comma as a decimal separator, e.g. 1,23
Precision settings
Precision
Set the default computation precision, given as a number of decimal digits. For example, 7 Precision
will ensure at least 7 decimal digits for compuation, and 1.0 3 /
will compute 0.3333333
in that case.
In the current implementation, this selects one of three decimal formats:
- The
decimal32
for up to 7 digits mantissa and an exponents up to 96 - The
decimal64
for up to 16 digits mantissa and an exponents up to 384 - The
decimal128
for up to 34 digits mantissa and an exponents up to 6144
The intent in the long run is to allow arbitrary precision like in newRPL.
Base settings
Integer values can be reprecended in a number of different bases:
- Binary is base 2
- Ocgtal is base 8
- Decimal is base 10
- Hexadecimal is base 16
Binary (BIN)
Selects base 2
Octal (OCT)
Selects base 8
Decimal (DEC)
Selects base 10
Hexadecimal (HEX)
Selects base 16
Base
Select an arbitrary base for computations
StoreWordSize (STWS)
Store the word size for binary computations
WordSize (RCWS)
Recall the word size for binary computations
MaxRewrites
Defines the maximum number of rewrites in an equation.
Equations rewrites can go into infinite loops, e.g. 'X+Y' 'A+B' 'B+A' rewrite
can never end, since it keeps rewriting terms. This setting
indicates how many attempts at rewriting will be done before erroring out.
MaxBigNumBits
Define the maxmimum number of bits for a large integer.
Large integer operations can take a very long time, notably when displaying them
on the stack. With the default value of 1024 bits, you can compute 100!
but
computing 200!
will result in an error, Number is too big
. You can however
compute it seting a higher value for MaxBigNumBits
, for example
2048 MaxBigNumBits
.
ToFractionIterations (→QIterations, →FracIterations)
Define the maximum number of iterations converting a decimal value to a
fraction. For example, 1 →FracIterations 3.1415926 →Frac
will give 22/7
,
whereas 3 →FracIterations 3.1415926 →Frac
will give 355/113
.
ToFractionDigits (→QDigits, →FracDigits)
Define the maximum number of digits of precision converting a decimal value to a
fraction. For example, 2 →FracDigits 3.1415926 →Frac
will give 355/113
.
User interface
Various user-interface aspects can be customized, including the appearance of Soft-key menus. Menus can show on one or three rows, with 18 (shifted) or 6 (flat) functions per page, and there are two possible visual themes for the labels, rounded or square.
ThreeRowsMenus
Display menus on up to three rows, with shift and double-shift functions showns above the primary menu function.
SingleRowMenus
Display menus on a single row, with labels changing using shift.
FlatMenus
Display menus on a single row, flattened across multiple pages.
RoundedMenu
Display menus using rounded black or white tabs.
SquareMenus
Display menus using square white tabs.
CursorBlinkRate
Set the cursor blink rate in millisecond, between 50ms (20 blinks per second) and 5000ms (blinking every 5 seconds).
States
The calculator can save and restore state in files with extension .48S
.
This feature is available through the Setup
menu (Shift-0
).
The following information is stored in state files:
- Global variables
- Stack contents
- Settings
Numeric solvers
NUMINT
Numerical integration (adaptive Simpson)
ROOT
Root seeking within an interval
MSOLVE
Multiple non-linear equation solver/optimization search
BISECT
Root seeking (bisection method)
Stack manipulation
Clear
Remove all objects from the stack
Depth
Get the current stack depth
Drop
Remove an object from the stack
Drop2
Remove two objects form the stack
DropN
Remove N objects from the stack, N being given in level 1.
Duplicate (DUP)
Duplicate an object on the stack
Duplicate2 (DUP2)
Duplicate two objects on the stack
DuplicateTwice (DUPDUP)
Duplicate the same object twice on the stack
DuplicateN (DUPN)
Duplicate a group of N objects, N being given in stack level 1
LastArguments (LASTARG)
Put the last arguments back on the stack
LastX
Put the last first argument on the stack.
This command does not exist on HP RPL calculators, and is here to make it easier to adapt RPN programs that use LastX a bit more often.
Undo
Restore the stack to its last state before executing an interactive command. Note that this command can be used from a program, but it will restore the state prior to program execution.
NDUPN
Replicate one object N times and return N
NIP
Remove object at level 2 on the stack
Over
Duplicate object at level 2 on the stack
PICK
Duplicate object at position N on the stack
PICK3
Duplicate object at level 3 on the stack
ROLL
Move object at level N to level 1
ROLLD
Move object from level 1 to level N
ROT
Move object from level 3 to level 1
SWAP
Exchange objects in levels 1 and 2
Mapped to X⇆Y key
Y
X
▶ X
Y
UNPICK
Move object from level 1 to level N.
UNROT
Move object from level 1 to level 3
IFT
Evaluate objects on the stack conditionally
IFTE
Evaluate objects on the stack conditionally
STKPUSH
Push a snapshot of the current stack on the undo stack
STKPOP
Pop a stack snapshot from the undo stack
STKDROP
Drop a snapshot from the undo stack
STKPICK
Copy snapshot in level N to the current stack
STKDEPTH
Get the depth of the undo stack
STKNEW
Push a snapshot of the current stack on the undo stack and clears the current stack
Statistics
RDZ
Initialize random number generator with a seed
RAND
Generate a random real number
Operations with Strings
TOUTF
Create a Utf8 string from a list of code points
FROMUTF
List all code points in a Utf8 string
TOSTR
Decompile any object (convert to string)
FROMSTR
Compile a string into RPL objects
SREV
Reverse the characters on a string
NTOKENS
Number of tokens in a string
NTHTOKEN
Token at position N in a string
NTHTOKENPOS
Position of token N in a string
TRIM
Remove characters at end of string
RTRIM
Remove characters at start of string
SSTRLEN
Length of string in characters
STRLENCP
Length of string in Unicode code points
TONFC
Normalize a string to Unicode NFC
SREPL
Find and replace text in a string
TODISPSTR
Decompile formatted for display
TOEDITSTR
Decompile formatted for edit
Operations with Symbolic Expressions
Rewrite
Applies an arbitrary transformation on equations. The first argument is the equation to transform. The second argument is the pattern to match. The third argument is the replacement pattern. Patterns can contain variable names, which are substituted with the corresponding sub-expression.
In the matching pattern, variables with a name that begins with i
, j
, k
,
l
, m
, n
, p
or q
must match a non-zero positive integer. When such a
match happens, the expression is evaluated after rewrite in order to compute
values such as 3-1
.
Additionally, variables with a name that begins with u
, v
or w
must
be unique within the pattern. This is useful for term-reordering rules,
such as 'x*u*x' 'x*x*u'
, which should not match a*a*a
where it is a no-op.
Eq
From
To
▶ Eq
Examples:
'A+B+0' 'X+0' 'X' rewrite
returns'A+B'
'A+B+C' 'X+Y' 'Y-X' rewrite
returns'C-(B-A)
'(A+B)^3' 'X^N' 'X*X^(N-1)' rewrite
returns(A+B)*(A+B)^2
.
AutoSimplify
Enable automatic reduction of numeric subexpressions according to usual
arithmetic rules. After evaluating AutoSimplify
'X+0
' will evaluate as 'X'
and 'X*1-B*0'
witll evaluate as 'X'
.
The opposite setting is NoAutoSimplify
NoAutoSimplify
Disable automatic reduction of numeric subexpressions according to usual
arithmetic rules. After evaluating NoAutoSimplify
, equations such as'X+0
'
or X*1-B*0
will no longer be simplified during evaluation.
The opposite setting is AutoSimplify
RULEMATCH
Find if an expression matches a rule pattern
RULEAPPLY
Match and apply a rule to an expression repeatedly
→Num (→Decimal, ToDecimal)
Convert fractions and symbolic constants to decimal form.
For example, 1/4 →Num
results in 0.25
.
→Frac (→Q, ToFraction)
Convert decimal values to fractions. For example 1.25 →Frac
gives 5/4
.
The precision of the conversion in digits is defined by
→FracDigits, and the maximum number of iterations for the
conversion is defined by →FracDigits
RULEAPPLY1
Match and apply a rule to an expression only once
TRIGSIN
Simplify replacing cos(x)^2+sin(x)^2=1
ALLROOTS
Expand powers with rational exponents to consider all roots
CLISTCLOSEBRACKET
RANGE
Create a case-list of integers in the given range.
ASSUME
Apply certain assumptions about a variable to an expression.
Time, Alarms and System Commands
SETDATE
Set current system date in MM.DDYYYY
DATEADD
Add days to a date in MM.DDYYYY
SETTIME
Set current time as HH.MMSS
TOHMS
Convert decimal time to HH.MMSS
FROMHMS
Convert time in HH.MMSS to decimal
HMSADD
Add time in HH.MMSS format
HMSSUB
Subtract time in HH.MMSS format
TICKS
Return system clock in microseconds
TEVAL
Perform EVAL and measure elapsed time
DATE
Current system date as MM.DDYYYY
DDAYS
Number of days between dates in MM.DDYYYY
TIME
Current time in HH.MMSS
TSTR
ACK
Acknowledge oldest alarm (dismiss)
ACKALL
Acknowledge (dismiss) all alarms
RCLALARM
Recall specified alarm
STOALARM
Create a new alarm
DELALARM
Delete an existing alarm
FINDALARM
Get first alarm due after the given time
Version
Return DB50X version information as text.
▶ "Version information"
FreeMemory
Return the number of bytes immediately available in memory, without performing a cleanup of temporary values (garbage collection).
See also: GarbageCollect, FreeMemory
AvailableMemory (MEM)
Return the number of bytes available in memory.
Remark: The number returned is only a rough indicator of usable memory. In particular, recovery features consume or release varying amounts of memory with each operation.
Before it can assess the amount of memory available, AvailableMemory
removes
objects in temporary memory that are no longer being used. Like on the HP48, you
can therfore use MEM
DROP
to force garbage collection. However, there is
also a dedicated command for that, GarbageCollect.
See also: FreeMemory, GarbageCollect
GarbageCollect
Perform a clean-up of temporary objects and return number of bytes reclaimed.
In order to speed up normal operations, temporaries are only discarded when necessary to make room. This clean-up process, also called garbage collection, occurs automatically when memory is full. Since garbage collection can slow down calculator operation at undesired times, you can force it to occur at a desired time by executing GarbageCollect.
See also: FreeMemory, Purge
Bytes
Return the size of the object and a hash of its value. On classic RPL systems, teh hash is a 5-nibbles CRC32. On DB50X, the hash is a based integer of the current wordsize corresponding to the binary representation of the object.
For example, the integer 7
hash will be in the form #7xx
, where 7
is the
value of the integer, and xx
represents the integer type, as returned by the
Type command.
X
▶ Hash
Size
Type
Return the type of the object as a numerical value. The value is not guaranteed
to be portable across versions of DB50X (and pretty much is guarantteed to not
be portable), nor to ever match the value returned by the TYPE
command on the
HP48.
Note The TypeName command returns the type as text, and this is less likely to change from one release to the next.
TypeName
Return the type of the object as text. For example, 12 type
returns
"integer"
.
PEEK
Low-level read memory address
POKE
Low level write to memory address
NEWOB
Make a new copy of the given object
USBFWUPDATE
PowerOff (OFF)
Turn calculator off programmatically
SystemSetup
Display the built-in system setup
SaveState
Save the machine's state to disk, using the current state if one was previously loaded. This is intended to quickly save the state for example before a system upgrade.
Tagged objects
Tagged objects are a way to indicate what a value represents, using a tag
between colons and preceding the object. For example, :X:3
is a tagged
integer, where the tag is X
and the object is 3
.
When displayed on the stack, tags are shown without the leading colon for
readability. For example, the object above shows as X:3
on the stack.
→Tag (ToTag)
Apply a tag to an object. The tag is in level 1 as text or name. The object to
be tagged is in level 2. For example, "Hello" 1 →Tag
results in :Hello:1
.
Like on the HP calculators, it is possible to next tags.
Tag→ (FromTag)
Expand a tagged object in level 1 into its object and tag. The object will be in level 2, the tag will be in level 1 as a text object.
For example, :Hello:1 Tag→
results in "Hello"
in level 1 and 1
in level 2.
DeleteTag (DTAG)
Remove a tag from an object. For example, :Hello:1 DeleteTag
results in 1
.
If there is no tag, the object is returned as is.
Transcendental functions
SIN
Compute the sine
COS
Compute the cosine
TAN
Compute the tangent
ASIN
Compute the arcsine
ACOS
Compute the arccosine
ATAN
Compute the arctangent
ATAN2
Compute arctangent(y/x)
LN
Compute natural logarithm
EXP
Compute exponential function
SINH
Compute the hyperbolic sine
COSH
Compute the hyperbolic cosine
TANH
Compute the hyperbolic tangent
ASINH
Compute the hyperbolic arcsine
ACOSH
Compute the hyperbolic arccosine
ATANH
Compute the hyperbolic arctangent
LOG
Compute logarithm in base 10
ALOG
Compute anti-logarithm in base 10
SQRT
Compute the square root
EXPM
Compute exp(x)-1
LNP1
Compute ln(x+1)
PINUM
Numeric constant π with twice the current system precision
User Interface
COPYCLIP
Copy an object to the clipboard
CUTCLIP
Move an object to the clipboard
PASTECLIP
Insert the clipboard contents on the stack
Wait
Wait for a key press or a time lapse.
When the argument is greater than 0, interrupt the program for the given number of seconds, which can be fractional.
When the argument is 0 or negative, wait indefinitely until a key is pressed. The key code for the key that was pressed will be pushed in the stack. If the argument is negative, the current menu will be displayed on the screen during the wait.
KEYEVAL
Simulate a keypress from within a program
KEY
Get instantaneous state of the keyboard
DOFORM
Take a variable identifier with a form list
EDINSERT
Insert given text into the editor
EDREMOVE
Remove characters in the editor at the cursor position
EDLEFT
Move cursor to the left in the editor
EDRIGHT
Move cursor to the right in the editor
EDUP
Move cursor up in the editor
EDDOWN
Move cursor down in the editor
EDSTART
Move cursor to the start of text in the editor
EDEND
Move cursor to the end of text in the editor
EDLSTART
Move cursor to the start of current line in the editor
EDLEND
Move cursor to the end of current line in the editor
EDTOKEN
Extract one full word at the cursor location in the editor
EDACTOKEN
Extract one word at the left of cursor location (suitable for autocomplete)
EDMODE
Change the cursor mode in the editor
SETTHEME
Set system color theme
GETTHEME
Operations with Units
UDEFINE
Create a user-defined unit
UPURGE
Delete a user-defined unit
UVAL
Numeric part of a unit object
UBASE
Expand all unit factors to their base unit
CONVERT
Convert value from one unit to another
UFACT
Expose a group of units within a unit object (factor)
TOUNIT
Apply a unit to an object
ULIST
List all user-defined units
USB Communications
USBSTATUS
Get status of the USB driver
USBRECV
Receive an object through USB link
USBSEND
Send an object through the USB link
USBOFF
Disable USB port
USBON
Enable USB port
USBAUTORCV
Receive an object and execute it
USBARCHIVE
Create a backup on a remote machine
USBRESTORE
Restore a backup from a remote machine
#######################################
target
###################################### TARGET = db48x PLATFORM = dmcp VARIANT = dm42 SDK = dmcp/dmcp PGM = pgm
######################################
building variables
###################################### OPT=release
Alternatives (on the command line)
OPT=debug -g
OPT=small -Os
OPT=fast -O2
OPT=faster -O3
OPT=fastest -O4 -Ofast
Experimentally, O2 performs best on DM32
(see https://github.com/c3d/DB50X-on-DM32/issues/66)
Warning: macOSX only
MOUNTPOINT=/Volumes/$(VARIANT)/ EJECT=sync; sync; sync; hdiutil eject $(MOUNTPOINT) PRODUCT_NAME=$(shell echo $(TARGET) | tr "[:lower:]" "[:upper:]") PRODUCT_MACHINE=$(shell echo $(VARIANT) | tr "[:lower:]" "[:upper:]")
#######################################
pathes
#######################################
Build path
BUILD = build/$(VARIANT)/$(OPT)
Path to aux build scripts (including trailing /)
Leave empty for scripts in PATH
TOOLS = tools
CRC adjustment
CRCFIX = $(TOOLS)/forcecrc32/forcecrc32
FLASH=$(BUILD)/$(TARGET)_flash.bin QSPI =$(BUILD)/$(TARGET)_qspi.bin
VERSION=$(shell git describe --dirty=Z --abbrev=5| sed -e 's/^v//g' -e 's/-g/-/g') VERSION_H=src/$(PLATFORM)/version.h
#==============================================================================
Primary build rules
#==============================================================================
default action: build all
all: $(TARGET).$(PGM) help/$(TARGET).md @echo "# Built $(VERSION)"
dm32: dm32-all dm32-%: $(MAKE) PLATFORM=dmcp SDK=dmcp5/dmcp PGM=pg5 VARIANT=dm32 TARGET=db50x $*
installation steps
COPY=cp install: install-pgm install-qspi install-help $(EJECT) @echo "# Installed $(VERSION)" install-fast: install-pgm $(EJECT) install-pgm: all $(COPY) $(TARGET).$(PGM) $(MOUNTPOINT) install-qspi: all $(COPY) $(QSPI) $(MOUNTPOINT) install-help: help/$(TARGET).md $(COPY) help/$(TARGET).md $(MOUNTPOINT)help/
sim: sim/$(TARGET).mak cd sim; make -f $(<F) sim/$(TARGET).mak: sim/$(TARGET).pro Makefile $(VERSION_H) cd sim; qmake $(<F) -o $(@F) CONFIG+=$(QMAKE_$(OPT))
sim: sim/gcc111libbid.a
recorder/config.h
help/$(TARGET).md
fonts/EditorFont.cc
fonts/StackFont.cc
fonts/HelpFont.cc
keyboard
.ALWAYS
clangdb: sim/$(TARGET).mak .ALWAYS cd sim && rm -f *.o && compiledb make -f $(TARGET).mak && mv compile_commands.json ..
keyboard: Keyboard-Layout.png Keyboard-Cutout.png sim/keyboard-db48x.png help/keyboard.png doc/keyboard.png Keyboard-Layout.png: DB50X-Keys/DB50X-Keys.001.png cp $< $@ Keyboard-Cutout.png: DB50X-Keys/DB50X-Keys.002.png cp $< $@ sim/keyboard-db48x.png: DB50X-Keys/DB50X-Keys.001.png convert $< -crop 698x878+151+138 $@ %/keyboard.png: sim/keyboard-db48x.png cp $< $@
QMAKE_debug=debug QMAKE_release=release QMAKE_small=release QMAKE_fast=release QMAKE_faster=release QMAKE_fastest=release
TTF2FONT=$(TOOLS)/ttf2font/ttf2font $(TTF2FONT): $(TTF2FONT).cpp $(TOOLS)/ttf2font/Makefile src/ids.tbl cd $(TOOLS)/ttf2font; $(MAKE) TARGET=release sim/gcc111libbid.a: sim/gcc111libbid-$(shell uname)-$(shell uname -m).a cp $< $@
dist: all
cp $(BUILD)/$(TARGET)_qspi.bin .
tar cvfz $(TARGET)-v$(VERSION).tgz $(TARGET).$(PGM) $(TARGET)_qspi.bin
help/.md STATE/.48S
@echo "# Distributing $(VERSION)"
$(VERSION_H): $(BUILD)/version-$(VERSION).h cp $< $@ $(BUILD)/version-$(VERSION).h: $(BUILD)/.exists Makefile echo "#define DB50X_VERSION "$(VERSION)"" > $@
#BASE_FONT=fonts/C43StandardFont.ttf
BASE_FONT=fonts/FogSans-ddd.ttf
fonts/EditorFont.cc: $(TTF2FONT) $(BASE_FONT)
$(TTF2FONT) -s 48 -S 80 -y -10 EditorFont $(BASE_FONT) $@
fonts/StackFont.cc: $(TTF2FONT) $(BASE_FONT)
$(TTF2FONT) -s 32 -S 80 -y -8 StackFont $(BASE_FONT) $@
fonts/HelpFont.cc: $(TTF2FONT) $(BASE_FONT)
$(TTF2FONT) -s 18 -S 80 -y -3 HelpFont $(BASE_FONT) $@
help/$(TARGET).md: $(wildcard doc/.md doc/calc-help/.md doc/commands/*.md) Makefile
mkdir -p help &&
cat $^ |
sed -e '//,//s/$(PRODUCT_MACHINE)/DM32/g' | \