So I’ve more or less tidied up my little OS on the PicoCalc. This (the OS, etc.) has been a personal project for me for some years now - a sort of “what if” in a retro parallel/fantasy universe. I started on the 6502, migrated to the 65c816, then to RISC-V via my own emulator (on the '816 system), then a detour via ARM32 and now back to RISC-V.
I’ve always though I’d like something standalone - keyboard, display, storage and while the PicoCalc is not perfect it’s good enough for now. The main thing I don’t have going right now is sound and secondary is Wi-Fi (I’m using a Pico2 plus W from Pimoroni). I’m ignoring the on-board PicoCalc PSRAM and using the PSRAM on the Pico2. I’m almost tempted to remove the PSRAM chip from the main board and re-use the GPIO pin for and LED for the SD card access indicator… Not today though.
The OS is a fairly traditional thing a bit more advanced than CP/M but not as clever as Unix. The systems programming language is BCPL - and it as important (for me!) to be able to compile directly on the device - and as I achieved that on the 6502 and 65816 systems then it was not going to be an issue here. It supports multi-tasking, but that’s not implemented yet on the RISC-V version. I have a plan to take it multi-cpu too which shouldn’t be that hard.
I’ve spent a little bit of time working round some of the features of the PicoCalc - 40 column screen and the weird and wonderful “southbridge” interface. (e.g. the I²C does work at 400Khz, but crashes randomly and the I²C transactions are not what I expected them to be, however it’s all working and I think I’m glad my PicoCalc shipped with the latest software in the STM MCU, although I’ve no idea how to tell)
Now my task to myself is to actually use it directly for a day or 2 and see what works and what doesn’t and what more I need to tweak.
If anyone is interested then follow this thread and let me know. It’s a single .uf2 file and it would be a .tgz file to be unpacked on the SD card (Normal FAT32) It needs a Pico2 (ie. RISC-V) to run and it ought to run without PSRAM but I don’t think there is enough RAM to run the compiler from the internal RAM. The compiler itself is only 48KB, but it’s become a little “greedy” over the years in the RAM it needs for workspace…
Cool project! I must say that BCPL is a blast from the past — any particular reason for this choice of languages? (Of course, one could ask me the same question about my choice of languages.)
I’m sort of creating something that never was - a microprocessor system based on 1980 technology that was capable of self-hosting with a high level language compiler.
I started with the 6502 (Which I first used in 1978) then progressed to the 65816 - (Yes, I know, didn’t appear until 1985, but lets think it could have been earlier). C was established, as were other algol-like languages, but one I used on the 6502 in the early 80s was BCPL. So it seemed easier to get BCPL going on the '816 than to work with the existing C compilers then (i started this round about 2018) and so I just stuck with BCPL and decided I liked it.
CPU wise in the real world we got ARM, but in my fantasy universe Berkley RISC was a thing in the early 80s so for me RISC-V seemed a natural thing.
And that’s about it.
If I could write a C compiler that would target the same bytecode the BCPL compiler produces then I’d do it (and Pascal & FORTRAN for the LoLs), but I’m not a great compiler writer. Maybe one day.
Here is another little demo of my system, warts and all…
One of the earliest things I saw running on an Apple II was a program to generate Moire fringe patterns, so I set about creating something like it here:
// moire.b
// Generate Moire fringes
GET "libhdr.h"
GET "vdu.h"
GET "rubyKeys.h"
GLOBAL
{
gWidth1:ug
gHeight1
gWidth
gHeight
}
LET moire (x,y, stp, col, slow) BE
{
LET w,h = 0,0
vduCls ()
vduGCol (col)
WHILE w < gWidth DO
{
vduLine (x,y, w,0)
vduLine (x,y, w,gHeight1)
IF slow THEN vduUpdate ()
w := w + stp
}
WHILE h < gWidth DO
{
vduLine (x,y, 0,h)
vduLine (x,y, gWidth1,h)
IF slow THEN vduUpdate ()
h := h + stp
}
}
AND doKey () BE
{
LET x = gWidth/2
LET y = gHeight/2
LET inc = 3
LET col = colPink
LET key = ?
LET step = 1
{
moire (x,y, inc, col, FALSE)
key := sardch ()
IF '1' <= key <= '9' THEN
{
step := key - '0'
LOOP
}
IF key = 'q' THEN RETURN
SWITCHON key INTO
{
CASE KEY_ARROW_UP: y := y + step ; ENDCASE
CASE KEY_ARROW_DOWN: y := y - step ; ENDCASE
CASE KEY_ARROW_LEFT: x := x - step ; ENDCASE
CASE KEY_ARROW_RIGHT: x := x + step ; ENDCASE
CASE '+':
CASE '=': inc := inc + 1 ; ENDCASE
CASE '-':
CASE '_': inc := inc - 1 ; ENDCASE
}
// Limits?
IF inc < 1 THEN inc := 1
} REPEAT
}
AND start () = VALOF
{
gWidth := vduProps!vduProps_gWidth
gHeight := vduProps!vduProps_gHeight
gWidth1 := vduProps!vduProps_gWidth - 1
gHeight1 := vduProps!vduProps_gHeight - 1
vduCls ()
doKey ()
RESULTIS 0
}
Comments welcome.
(And it runs out the CapsLock key generates a keycode too (0xC1 - same as the END key) - I’ll need to work out if I can suppress that)