README.md (10830B)
1 # ESOP: Essential Stack-Operated Phone 2 3 ESOP is a specification and a reference implementation of a minimalist mobile phone running upon the stack-based [Uxn](https://wiki.xxiivv.com/site/uxn.html) VM. 4 5 ESOP was created as a result of reducing the vastly universal [SPARTA](https://gitlab.com/suborg/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. 6 7 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`. 8 9 ## Hardware specification 10 11 ESOP's hardware was largely inspired by Nokia 5110 family and some other ideas collected elsewhere. Besides the speakerphone and microphone used for GSM calls, ESOP features: 12 13 - a monochrome 84x48 screen with controllable backlight; 14 - a 16-key keypad (`0-9`, `*`, `#`, `A` (Advance), `B` (Back), `C` (Cancel), `D` (Do)); 15 - a removable battery with controllable status; 16 - a mono audio beeper; 17 - 64K (65536 bytes) of addressable memory fully available to the currently running app. 18 19 The 64K of memory are arranged as follows (size is specified in bytes in decimal): 20 21 Addresses |Size |Purpose 22 -----------|-----|------------------- 23 `0000-fbff`|64512|Uxn application RAM 24 `fc00-fcff`|256 |Uxn work stack 25 `fd00-fdff`|256 |Uxn return stack 26 `fe00-fff7`|504 |Video memory 27 `fff8-ffff`|8 |Control block 28 29 Every ESOP implementation must emulate the exact same memory layout as per this table. 30 31 ## Control block 32 33 Unlike Uxn/Varvara or Uxn/SPARTA, Uxn/ESOP only exposes the control block ports (`00` to `07`) for `DEI` and `DEO` instructions. When calling these instructions, the control block memory area is automatically updated accordingly. 34 35 In Uxntal, the ESOP's control block would be described as follows: 36 37 ``` 38 |00 @Control [ &framevec $2 &io $2 &random $1 &status $1 &sound $1 &syscall $1 ] 39 ``` 40 41 The fields of the control block are: 42 43 - Frame vector (`00-01`) - the port to set the vector to be run on each frame (60 frames per second); 44 - Input/output (`02-03`) - the port to read input status bits of every key on the keypad and to output pixels at given coordinates; 45 - Random/debug port (`04`) - the port to trace debug information on output and retrieve a random byte value on input; 46 - Status port (`05`) - the port to get the information on battery and get/set screen brightness level; 47 - Sound port (`06`) - the port to perform mono audio beeper operations; 48 - Syscall port (`07`) - the port to run system calls to the phone's underlying operating system. 49 50 Implementation note: direct writing to or reading from the control block memory area may have the same effect as calling the corresponding `DEO`/`DEI` instructions. E.g. if the application directly stores a byte into `#ffff`, the runtime may consider it writing to the `07` control port and process it as a system call. For now, this rule is not enforced and `DEO`/`DEI` instructions are the main source of truth when interacting with control block, but this can (and most likely will) change in the future specification versions. 51 52 ## Screen output 53 54 All the 4032 pixels of 84x48 screen are allocated in the 504-byte video memory of ESOP (`#fe00-#fff7`) in the left-to-right, top-to-bottom, high-to-low order. To output a pixel at the given coordinates using memory manipulation opcodes, the app must calculate the appropriate byte position itself and then set the corresponding bit within that byte. This process is made easier by reusing I/O port `02-03` with the `DEO2` instruction where you can directly pass X and Y coordinates of the pixel to light it up. 55 56 Every frame (60 times per second), the following actions must be performed in the particular order: 57 58 1. All 504 bytes in the video memory block are set to `#00`. 59 2. If the control port short `00-01` is not zero, the frame vector is run from that address. All graphics operations, be it direct video memory modification or the pixel draw calls, must be done within the frame vector. 60 3. The actual screen contents get updated according to the resulting video memory contents when the frame vector is finished. 61 62 Due to shared nature of the I/O device port, the handler responsible for pixel output in the ESOP implementation must preserve the input state between port write calls, i.e. save it before the processing and restore afterwards. 63 64 Standard input/output ports of Varvara are not supported in ESOP. 65 66 ## Keypad input 67 68 When in input mode, the 16 bits of the input ports (`02` and `03`) have the following mapping: 69 70 Bit|15 |14 |13|12|11|10|9|8|7|6|5|4|3|2|1|0 71 ---|---|---|--|--|--|--|-|-|-|-|-|-|-|-|-|- 72 Key|`#`|`*`|D |C |B |A |9|8|7|6|5|4|3|2|1|0 73 74 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. 75 76 ## Random/debug port 77 78 The `04` 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. 79 80 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 `04` port (or `#fffc` memory address) must be considered truly random and not derived from anything else. 81 82 ## Status port 83 84 The `05` port is divided as follows: 85 86 Bits |7 |6-4 |3 |2-0 87 -------|---------------|-------------|----------------|-------------------- 88 Meaning|Charger plugged|Battery level|Keypad BL switch|Screen BL brightness 89 90 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. 91 92 The lower nibble (bits 0 to 3) of the status can be modified from the application, and the runtime should attempt to change the screen backlight brightness level, where 7 is the highest and 0 means backlight off, and toggle the keypad backlight switch as well if supported. 93 94 Note: emulated environments are allowed to always return `ff` when this port is read from, which means emulating a fully charged phone with external power supply connected on the maximum screen brightness and backlit keypad. 95 96 ## Sound output 97 98 ESOP supports monophonic sound output with a beeper controllable via `06` 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 the value `30`. Setting the port value to `00` must stop the sound. 99 100 Note: this specification does not enforce any particular waveform to be used for playing the notes, but in emulated ESOP environments, a square wave is recommended as the closest option for phone beeper emulation. 101 102 ## System calls 103 104 ESOP supports up to 32 different system calls (syscalls), with up to 7 byte parameters each. The command byte passed to the `07` port is arranged as follows: 105 106 Bits |7-5 |4-0 107 -------|--------------------|---------- 108 Meaning|number of parameters|syscall ID 109 110 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 `0a` with four byte (or two short) parameters expected to pass afterwards using the same `07` port. 111 112 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. 113 114 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. 115 116 The only system call required to be implemented in any ESOP-compatible runtime is `1f`, the halting call. In addition to that, system calls can extend the basic ESOP functionality with: 117 118 - serial/debug port I/O; 119 - persistent/flash memory I/O (up to 16 MB), operating with 256-byte pages or individual bytes; 120 - setting and getting datetime information; 121 - initiating and receiving GSM voice calls; 122 - sending DTMF signals during active voice calls; 123 - active voice call manipulation (terminate, hold/unhold, bridge); 124 - sending SMS messages; 125 - sending USSD queries; 126 - polling for incoming SMS messages; 127 - polling for incoming USSD messages; 128 - polling for incoming WEA messages; 129 - reading the network information; 130 - STK calls; 131 - loading and invoking other Uxn/ESOP programs from the persistent memory. 132 133 On call completion, the `07` port value must be set to zero by the ESOP runtime. 134 135 ### Recommended syscall table 136 137 ID |Params |Command|Meaning 138 ------|-----------------|-------|---------------------------------- 139 `00` |1b [data] |`20` |Write a byte to serial/debug port 140 `01` |1s [addr] |`41` |Read a byte from serial/debug port 141 `02` |1b 3b [data addr]|`82` |Write a byte under the 3-byte flash address 142 `03` |1s 3b [addr addr]|`a3` |Read a byte under the 3-byte flash address 143 `04` |1b 3b [page addr]|`84` |Write a page under the 3-byte flash address 144 `05` |1b 3b [page addr]|`85` |Read a page under the 3-byte flash address 145 `06` |1s [addr] |`46` |Read the current system time/date information (see below) into the address 146 `07` |1s [addr] |`47` |Set the current system time/date information (see below) from the address 147 `08-1d`| | |(reserved) 148 `1e` |1b 3b [flag addr]|`9e` |Load and run another Uxn/ESOP application from flash address according to the flags 149 `1f` |None |`1f` |Halt (required) 150 151 ### Datetime syscall implementation notes 152 153 The `46` and `47` calls, where implemented, should operate on 10 bytes of memory addressed by the value passed to them. 154 The layout of these 10 bytes is similar to the one defined in Uxn/Varvara and Uxn/SPARTA specs: 155 156 - `00-01`: year 157 - `02`: month 158 - `03`: day 159 - `04`: hour 160 - `05`: minute 161 - `06`: second 162 - `07`: day of the week 163 - `08-09`: day of the year 164 - `0a`: DST flag for the local time 165 166 ## Credits 167 168 Spec and reference implementation developed by Luxferre in 2022, released into the public domain. 169 170 Made in Ukraine.