esop

Essential Stack-Operated Phone (concept)
git clone git://git.luxferre.top/esop.git
Log | Files | Refs | README | LICENSE

commit f2bad1455f1224db7a69afae9fe6dd11f2338dcf
parent 626b31bb4b32b0d38a686e68cfc371a915a1e4f8
Author: Luxferre <lux@ferre>
Date:   Sun, 31 Jul 2022 10:25:53 +0300

revamping datetime draft

Diffstat:
MREADME.md | 19+++++++++++++++++--
Mweb/esop-ext.js | 47++++++++++++++++++++++++++++++++++++++---------
Mweb/esop-web-app.js | 4+---
3 files changed, 56 insertions(+), 14 deletions(-)

diff --git a/README.md b/README.md @@ -142,12 +142,27 @@ ID |Params |Command|Meaning `03` |1s 3b [addr addr]|`a3` |Read a byte under the 3-byte flash address `04` |1b 3b [page addr]|`84` |Write a page under the 3-byte flash address `05` |1b 3b [page addr]|`85` |Read a page under the 3-byte flash address -`06` |1s [addr] |`46` |Read the current system time/date information (5 bytes/40 bits, Unix time) into the address -`07` |1s [addr] |`47` |Set the current system time/date information (5 bytes/40 bits, Unix time) from the address +`06` |1s [addr] |`46` |Read the current system time/date information (see below) into the address +`07` |1s [addr] |`47` |Set the current system time/date information (see below) from the address `08-1d`| | |(reserved) `1e` |1b 3b [flag addr]|`9e` |Load and run another Uxn/ESOP application from flash address according to the flags `1f` |None |`1f` |Halt (required) +### Datetime syscall implementation notes + +The `46` and `47` calls, where implemented, should operate on 10 bytes of memory addressed by the value passed to them. +The layout of these 10 bytes is similar to the one defined in Uxn/Varvara and Uxn/SPARTA specs: + +- `00-01`: year +- `02`: month +- `03`: day +- `04`: hour +- `05`: minute +- `06`: second +- `07`: day of the week +- `08-09`: day of the year +- `0a`: DST flag for the local time + ## Credits Spec and reference implementation developed by Luxferre in 2022, released into the public domain. diff --git a/web/esop-ext.js b/web/esop-ext.js @@ -172,19 +172,48 @@ function ESOPExtensions() { //syscalls + //thanks to Toastrackenigma for the idea + function isDST(d, y) { + var jan = new Date(y, 0, 1).getTimezoneOffset(), + jul = new Date(y, 6, 1).getTimezoneOffset() + return Math.max(jan, jul) !== d.getTimezoneOffset() + } + //thanks to user2501097 for the idea + function daysIntoYear(y, m, d) { + return (Date.UTC(y, m, d) - Date.UTC(y, 0, 0)) / 86400000 + } + + function fillDTbuf(addr) { + var now = new Date(), + year = now.getFullYear(), + month = now.getMonth() + 1, + day = now.getDate(), + hour = now.getHours(), + minute = now.getMinutes(), + second = now.getSeconds(), + dotw = now.getDay(), + doty = daysIntoYear(year, month - 1, day), + dstflag = 0|isDST(now, year) + vm.setram(addr, year >> 8) + vm.setram(addr+1, year&255) + vm.setram(addr+2, month) + vm.setram(addr+3, day) + vm.setram(addr+4, hour) + vm.setram(addr+5, minute) + vm.setram(addr+6, second) + vm.setram(addr+7, dotw) + vm.setram(addr+8, doty >> 8) + vm.setram(addr+9, doty&255) + vm.setram(addr+10, dstflag) + + } + function runSyscall(vm, buf) { var call = buf[0] if(call === 0x00) //simulate writing a byte to the debug port console.log('[DBG] ' + ('00' + buf[1].toString(16)).slice(-2)) - else if(call === 0x06) { //read datetime info into 5 bytes starting from addr - //not very optimal but a future-proof approach for now - var tm = ('00' + (0|(Date.now()/1000)).toString(16)).slice(-10).match(/.{2}/g).map(function(x){return parseInt(x, 16)}), - targetaddr = (buf[1]<<8)|buf[2] - vm.setram(targetaddr, tm[0]) - vm.setram(targetaddr+1, tm[1]) - vm.setram(targetaddr+2, tm[2]) - vm.setram(targetaddr+3, tm[3]) - vm.setram(targetaddr+4, tm[4]) + else if(call === 0x06) { //read datetime info into 10 bytes starting from addr + fillDTbuf((buf[1]<<8)|buf[2]) } else if(call === 0x1f) //halt call, required for all implementations vm.active = false diff --git a/web/esop-web-app.js b/web/esop-web-app.js @@ -4,15 +4,13 @@ function main() { var devCfg = { audio: null, canvas: document.getElementById('C') //JS-specific implementation canvas DOM reference - } + }, vm = UxnCore(), ext = ESOPExtensions() document.getElementById('apprun').addEventListener('click', function() { var fileObj = document.getElementById('appselect').files[0] if(fileObj.name.endsWith('.eso')) { var rdr = new FileReader() rdr.onload = function() { - var vm = UxnCore() - var ext = ESOPExtensions() devCfg.audio = new (window.AudioContext || window.webkitAudioContext) vm.boot() ext.setup(vm, devCfg)