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)
Turned out when I edited the code to take it to “20” it was just taking too long - by then the line length had dropped to below 1 anyway. That image was generated at a depth of “20” but it never got there as I added a 2nd check to the line length.
(Also interesting was the way I descend with the turns left and right at depth 20 and leave it running to finish it doesn’t return exactly due to cumulative floating point rounding errors!)
Here is the code so-far:
// Turtle tree with recursion
GET "libhdr"
GET "math"
GET "vdu"
LET d2r (d) = d #* M_DEG2R
AND tree (len, ang, lim) BE
{
IF lim < 1 THEN RETURN
turtlePen (1)
turtleMove (len)
turtleTurn (ang)
tree (len * 67/100, ang, lim-1)
turtleTurn (#- 2.0 #* ang)
tree (len * 67/100, ang, lim-1)
turtleTurn (ang)
turtleMove (-len)
turtlePen (0)
}
AND start () = VALOF
{
turtleInit ()
turtleMoveTo (160,0)
tree (80, d2r (45.0), 10)
RESULTIS 0
}
Mostly because interest in it has been pretty much zero and I’ve treated it as a personal hobby - my own interpretation of a parallel/fantasy universe where we started with the 6502 in the 70s, moved to the 65c816 earlier than when it really came out, then RISC (Berkley RISC early 80s for example).
So I developed a board for a dead CPU (the 65c816) using a dead language…
However in the past couple of weeks I have had interest from 1 or 2 others (not here, but elsewhere) so I have been putting my mind to publishing it. It will not be open source (sorry). I’ve done that in the past and been overwhelmed by it all to the point I suffered health issues, pulled the lot and walked away.
So with that in-mind - how would it work? Start with a .uf2 file, so you’d need to be able flash that into a Pico2 (This uses RISC-V, so needs a Pico-2) then unpack a .tgz file into the root of the SD card. It won’t affect anything else on the SD card. It creates a new top level directory called BCPL and everything lives under that.
Currently it’s using PSRAM (Not the on-board waste of space PSRAM, but PSRAM on a Pico2 board) but I’m looking at being able to detect it at boot time. It may not be possible to run the compiler though - I’ll need to make some checks. When running there is some 60K words (so 240KB) or RAM free and the compiler is a bit greedy in the space it needs…
I see.
It is an interesting point. Isn’t it that without being open source it is harder to make people curious about it?
Yes, I am interested in trying this material.
you have raised a very good point though. This started for me as a little personal idea/hobby o a dead cpu with a dead language (not that that was the reasons, it just worked out that way in the early days) and I posted about it for a while on my own blog The 6502, 6507 and 65816 | Gordons Projects until it turned more into a software project.
I’m busy for the next 2 weeks with a local festival involving lots of horsey stuff and what not but I’ll give some thought to making a “release”.
And.. While the system is fully capable of self supporting (well, BCPL only) It’s advantageous to have a Linux host for two things - one is a “smart terminal” program that I hook to the serial port which has a few diagnostics sent to it, and it acts as a file-transfer host to exchange files with the SD card (I don’t pass-through the SD card to the USB, so it’s not mountable) The other is the ability to run the BCPL compiler on the Linux host - handy to edit larger files if needed, although I often get into a cycle of edit on host, ftp to PicoCalc and compile and run from there. I have used my own little editor on the device, but sometimes I prefer vim on my Linux host.
I guess there are lots of little things that I’ve done and adapted over the time.