Files
esop/README.md
T
2022-07-28 18:18:00 +03:00

8.6 KiB

ESOP: Essential Stack-Operated Phone

ESOP is a specification and a reference implementation of a minimalist mobile phone running upon the stack-based Uxn VM.

ESOP was created as a result of reducing the vastly universal SPARTA specs to the bare minimum that would be the easiest to implement and support (but still retain the phone's usability) and rearranging everything to have the smallest memory footprint possible. However, ESOP cannot be viewed as a stripped-down version of SPARTA, as it uses completely different principles of interfacing with the phone components and the only thing it has in common with SPARTA is using Uxn as the core ISA.

As with Uxn/Varvara and Uxn/SPARTA, Uxn/ESOP applications are written in Uxntal so the recommended source code suffix is .tal, but the recommended file suffix for Uxn/ESOP binaries is .eso.

Hardware specification

ESOP's hardware was largely inspired by Nokia 5110 family and some other ideas collected elsewheree. Besides speakerphone and microphone used for GSM calls, ESOP features:

  • a monochrome 84x48 screen with controllable backlight;
  • a 16-key keypad (0-9, *, #, A (Advance), B (Back), C (Cancel), D (Do));
  • a removable battery with controllable status;
  • a mono audio beeper;
  • 64K (65536 bytes) of addressable memory fully available to the currently running app.

The 64K of memory are arranged as follows (size is specified in bytes in decimal):

Addresses Size Purpose
0x0000-0xfbff 64512 Uxn application RAM
0xfc00-0xfcff 256 Uxn work stack
0xfd00-0xfdff 256 Uxn return stack
0xfe00-0xfff7 504 Video memory
0xfff8-0xffff 8 Control block

Every ESOP implementation must emulate the exact same memory layout as per this table.

Control block

Unlike Uxn/Varvara or Uxn/SPARTA, Uxn/ESOP only exposes the control block ports (0x00 to 0x07) for DEI and DEO instructions. When calling these instructions, the control block memory area is automatically updated accordingly.

In Uxntal, the ESOP's control block would be described as follows:

|00 @Control [ &framevec $2 &input $2 &random $1 &status $1 &sound $1 &syscall $1 ]

The fields of the control block are:

  • Frame vector (0x00-0x01) - the port to set the vector to be run on each frame (60 frames per second);
  • Input (0x02-0x03) - the port to read input status bits of every key on the keypad;
  • Random/debug port (0x04) - the port to trace debug information on output and retrieve a random byte value on input;
  • Status port (0x05) - the port to get the information on battery and get/set screen brightness level;
  • Sound port (0x06) - the port to perform mono audio beeper operations;
  • Syscall port (0x07) - the port to run system calls to the phone's underlying operating system.

Implementation note: direct writing to or reading from the control block memory area must have the same effect as calling the corresponding DEO/DEI instructions. E.g. if the application directly stores a byte into 0xffff, the runtime must consider it writing to the 0x07 control port and process it as a system call.

Screen output

All the 4032 pixels of 84x48 screen are allocated in the 504-byte video memory of ESOP (0xfe00-0xfff7) in the left-to-right, top-to-bottom, high-to-low order. To output a pixel at the given coordinates, the app must calculate the appropriate byte position itself.

The actual screen contents get updated 60 times per second according to the video memory. Before this process, the frame vector is run, if set in the corresponding control port (0x00-0x01).

Standard input/output ports are not supported.

Keypad input

The 16 bits of the input port (0x02-0x03) have the following mapping:

Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Key # * D C B A 9 8 7 6 5 4 3 2 1 0

The A (Advance), B (Back), C (Cancel) and D (Do) keys should be implemented within runtimes and apps as having Nokia 5110 semantics: A maps to Up/Forward, B maps to Down/Back, C maps to Cancel and D maps to Navi/Action key.

Random/debug port

The 0x04 port must return a random byte from 0 to 255 when read from, and initiate the stack trace print to the runtime when written to. Since standard output is not supported by ESOP, it is up to the runtime to decide where to output the debug information.

Just like with SPARTA, it's entirely up to the implementation to choose the randomness source, to implement a truly random or a secure enough pseudorandom generator. From the Uxn/ESOP application standpoint, the byte value obtained from the 0x04 port (or 0xfffc memory address) must be considered truly random and not derived from anything else.

Status port

The 0x05 port is divided as follows:

Bits 7 6-4 3-0
Meaning Charger plugged Battery level Screen backlight brightness

The higher nibble (bits 4 to 7) is used to indicate the status of charging and battery level. This nibble is read-only and must be ignored on modification.

The lower nibble (bits 0 to 3) of the status can be modified from the application, and the runtime should attempt to change the backlight brightness level, where 15 is the highest and 0 means backlight off.

Sound output

ESOP supports monophonic sound output with a beeper controllable via 0x06 port. As long as the port value is non-zero, the beeper must emit a sound wave of the specified frequency. The frequency is specified in semitones relative to A4 (440 Hz), with A4 itself being located at 0x30 value.

System calls

ESOP supports up to 32 different system calls (syscalls), with up to 7 byte parameters each. The command byte passed to the 0x07 port is arranged as follows:

Bits 7-5 4-0
Meaning number of parameters syscall ID

Number of parameters determines how many subsequent writes to the syscall port the runtime must process as parameter pass as opposed to the syscall invokation. For instance, if we run #8a #07 DEO, it means we're starting the syscall 0x0a with four byte (or two short) parameters expected to pass afterwards using the same 0x07 port.

To distinguish between command byte and parameter byte, command byte must never be equal to zero. I.e. a hypothetical syscall with ID 0 and no parameters would be invalid by definition.

The syscall port cannot be read from, but runtime has the full access to application's memory during the syscall, and can write some information into it as the result.

The only system call required to be implemented in any ESOP-compatible runtime is 0x1f, the halting call. In addition to that, system calls can extend the basic ESOP functionality with:

  • serial/debug port I/O;
  • persistent/flash memory I/O (up to 16 MB), operating with 256-byte pages or individual bytes;
  • setting and getting datetime information;
  • initiating and receiving GSM voice calls;
  • sending DTMF signals during active voice calls;
  • active voice call manipulation (terminate, hold/unhold, bridge);
  • sending SMS messages;
  • polling for incoming SMS messages;
  • polling for incoming USSD messages;
  • polling for incoming WEA messages;
  • reading the network information;
  • STK calls;
  • loading and invoking other Uxn/ESOP programs from the persistent memory.

On call completion, the 0x07 port value must be set to zero by the ESOP runtime.

ID (hex) Params Command Meaning
00 1b [data] 0x20 Write a byte to serial/debug port
01 1s [addr] 0x41 Read a byte from serial/debug port
02 1b 3b [data addr] 0x82 Write a byte under the 3-byte flash address
03 1s 3b [addr addr] 0xa3 Read a byte under the 3-byte flash address
04 1b 3b [page addr] 0x84 Write a page under the 3-byte flash address
05 1b 3b [page addr] 0x85 Read a page under the 3-byte flash address
06 1s [addr] 0x46 Read the current system time/date information (5 bytes/40 bits, Unix time) into the address
07 1s [addr] 0x47 Set the current system time/date information (5 bytes/40 bits, Unix time) from the address
08-1d (reserved)
1e 1b 3b [flag addr] 0x8e Load and run another Uxn/ESOP application from flash address according to the flags
1f None 0x1f Halt (required)

Credits

Spec and reference implementation developed by Luxferre in 2022, released into the public domain.

Made in Ukraine.