Basic programs the PicoCalc

Should be able to convert this to font 7 and add a screenshot function to one of the F keys

You an save a screenshot by pressing s or S

Hi @M57,

I took a look at your “Elite” and noticed that there are various places where you (or Claude) do something like this:

FONT #7
TEXT 10, 190, "Docking Alignment: ", "LT", 1

Which is a bit idiosyncratic because you are setting the default font to #7 but then explicitly writing in font #1 in the TEXT statement.

Best wishes,

Tom

1 Like

Howdy Tom, I set that while changing the text size for the screen, theres a few others like this that ive came across so far, most if not all should be fixed on fridays patch. Good catch, thank you :slight_smile:

1 Like

Thinking of making a Scrabble dictionary on the PicoCalc. Would likely require some interesting optimizations. Just the eight letter word list is 600k+ in the source format of JSON.

2 Likes

using inspiration from Dictionary Compression - Kevin Cox when i went to make my port of wordle for palm OS i used base 26 indexed by the first two letters, maybe that could help: palmdle/scripts/generate_wordlist.py at main · Lana-chan/palmdle · GitHub

2 Likes

File paging works wonders for the pico’s. You can search a text document for any information without the document being loaded into memory. Thats more or less how PicoPub works.

1 Like

Spirograph

This project draws spirograph-style curves (hypotrochoids and epitrochoids) on PicoCalc using MMBasic. You can adjust gear parameters and the pen offset, and render figures with cyclic color (HSV toRGB) as they draw.

Normal workflow: you first see the UI to tweak parameters; when you press SPACE the UI hides and the curve is drawn; if you press any key while drawing, you return to the UI to keep iterating.

Controls in the UI:

  • H / E: Hypotrochoid / Epitrochoid mode.
  • A / Z: increase / decrease R1.
  • S / X: increase / decrease R2.
  • D / C: increase / decrease D.
  • SPACE: draw the curve (UI hides).
  • Any key while drawing: interrupt and return to the UI.
  • B: clear screen and show help/UI again.
  • ESC: quit.

Tip: pick a simple ratio for R1 and R2 (e.g., 80/20) to get neat, closed figures.

5 Likes

Elite on Picocalc?

2 Likes

I love this! I had a Spirograph kit I got for my birthday when I was like 6. I haven’t had a chance to use this app, is there a way to screenshot? if there isn’t, you should totally add one.

It’s the hardest programming I’ve done in a minute. Graphics are trash due to the frame buffering problem, its laggy and looks bad as of now however, in the near future I hope to have a somewhat working / picocalc friendly version maybe some form of an RTS version of Elite?

1 Like

A wonderfully small program that’s perfect for testing the PicoCalc. My kids love it, and I’ve already spent an hour enjoying it myself. Thanks for your work!

1 Like

For all new PicoCalc users, I’ve created a few small tutorials over the past few months. You can either check them out on GitHub or click the links to watch a short video about each one and download the code via the comment section or on Github:

MMBasic Tutorials:
TuT 01: Funny Steps in MMBasic https://youtube.com/shorts/-sGcW_dJaNE
Tut 02: Animation https://youtube.com/shorts/tUGIiMFLdl8
Tut 03: Circles and Tone https://youtube.com/shorts/MVs_x1FJkAY
Tut 03.1: Circles https://youtube.com/shorts/sneTEUPdg04
Tut 04: For…Next loop https://youtube.com/shorts/i4u_CZh0syg
Tut 05: Fonts!!! https://youtube.com/shorts/SHzSE7JqeGo
Tut 06: Collision https://youtube.com/shorts/_nq2zqfaXAo
Tut 07: Variables - Astro Loop https://youtube.com/shorts/-leiRnJdaZ8
Tut 08: Game Leveldesign_Picodash https://youtube.com/shorts/3lu0YVqm2RQ
Tut 09: MMBAsic Editor Copy&Paste https://youtube.com/shorts/dhU87ebS2Cs
Tut 10: Servo Control with Picocalc https://youtube.com/shorts/lT6V3seDM8Q
Tut 11: Flash Micropython to PicoCalc https://youtube.com/shorts/sFOv4v-ptiE
Tut 12: Minecraft Skin Editor https://youtube.com/shorts/XHZ8bOElKgY

Micropython Tutorials:
Tut 1: Drawing Commands in MicroPython https://youtube.com/shorts/FZlIU81eDWY
Tut 2: Flower Animation in Mycropython https://youtube.com/shorts/9l2e5ybXaVk
Tut 3: Colors in Micropython https://youtube.com/shorts/61xNUKeSKC0
Tut 4: Wireless lan in Micropython https://youtube.com/shorts/RBKdni3pr88
Tut 5: RSS News Feed & Atomic Clock https://youtube.com/shorts/_6_OgBv2lCM
Tut 6: File Access in Mycropython via os module https://youtube.com/shorts/vfCNapNRqjk

10 Likes

In a moment of self hating, and anger at xmodem adding nulls to the ends of things that are transfered.

I wrote tar, in mmbasic. I know I know I shouldnt hate myself this much, and I should just drink more. But whats done is done.

Does anyone have any intrest in it? Otherwise I will keep it to myself.

6 Likes

There is no reason for the self hate, you had a problem and you solved it, that is programing in a nutshell. Post it, someone will find it useful.

4 Likes

Please make this available somewhere under a free software license – someone may find it useful.

1 Like

So for now, here is tar.

It works good added to the library via library save.

just type tar from the command line for a simple help screen.

to make compatable files in unix
use
tar -H ustar

Usage:
tar “Command”, “Tarname”, “filepattern”

Commands are
t lisT files in a far
x eXtract files in a tar
c Create new tar

When you are extracting files it does not use a wild card match. The filepattern is just a instr function so to extract all bmp’s from thistar.tar would be

tar “x”,”thistar.tar”,”bmp”

Any questions just ask.

’ Copyright (C) 2025 Aaron Addison

’ This program is free software: you can redistribute it and/or modify
’ it under the terms of the GNU General Public License as published by
’ the Free Software Foundation, either version 3 of the License, or
’ (at your option) any later version.

’ This program is distributed in the hope that it will be useful,
’ but WITHOUT ANY WARRANTY; without even the implied warranty of
’ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
’ GNU General Public License for more details.

’ You should have received a copy of the GNU General Public License
’ along with this program. If not, see https://www.gnu.org/licenses/.

Sub tar c$, f$, o$
opt$ = o$
If c$ = “” Then
Print “TAR in MMbasic by Aaron Addison”
Print "using file specifications from "
Print “wikipedia”
Print “to make compatable files in unix”
Print “use”
Print "tar -H ustar "
Print “”
Print “Usage:”
Print "tar "Chr$(34)“Command"Chr$(34)”, ";
Print Chr$(34)“Tarname"Chr$(34)”, "Chr$(34);
Print "filepattern"Chr$(34)
Print
Print “Commands are”
Print “t lisT files in a far”
Print “x eXtract files in a tar”
Print “c Create new tar”
Exit Sub
EndIf

'Open f$ For input As #1

If c$ = “t” Then
Open f$ For input As #1

Print "Listing of "f$
For a = 1 To 9000
readnextheader
'Print fname$
If fname$ = “” Then
Close #1
Exit Sub
Exit For
EndIf
listcurheader
advancetonextrecord
Next

EndIf

If c$ = “x” Then
Open f$ For input As #1
Print "Extracting "f$
For a = 1 To 9000
readnextheader
If fname$ = “” Then
Close #1
Exit For
EndIf
listcurheader
savenextrecord
Next
EndIf

If c$ = “c” Then
Print “Create archive “f$
If f$ <> “” Then Open f$ For output As #1
If opt$ = “” Then opt$=”*”
x$=Dir$(opt$,file)
Print x$
For z=1 To 10000
If z=1 Then x$=Dir$(opt$,file)
If z>1 Then x$=Dir$()
If x$=“” Then Exit For
fname$=x$
Print x$
buildheader
Print #1, header1$;
Print #1, header2$;
Print #1, header3$;

Open x$ For input As #2
For filecopy = 1 To fsize
ccrt$=Input$(1,2)
Print #1,ccrt$;
Next
filesize=fsize
If fsize <> 0 Then fsize=Int(((fsize-1) / 512)+1)*512
padding=fsize-filesize
Do While padding > 0
Print #1,Chr$(0);
padding=padding -1
Loop
Close #2

'Print Len(header$)
Next

EndIf
padding = 1024
Do While padding > 0
Print #1,Chr$(0);
padding=padding-1
Loop

Close #1
End Sub

Sub buildheader
Open fname$ For input As #3
fsize=Lof(#3)
Close #3
'Print fname$ “size” size$
fname$=nullpad$(fname$,100)
fmode$=mpad$(“600”,8)
oid$=mpad$(“1750”,8)
gid$=mpad$(“1750”,8)
size$=mpad$(Oct$(fsize),12)

header$=fname$+ fmode$+oid$+gid$+size$
modif$=mpad$(“15063020162”,12)
checksum$=" "
header$=fname$+ fmode$+oid$+gid$+size$+modif$+checksum$+“:”
ftype$=“0”
lname$=nullpad$(“”,100)
ustar$=mpad$(“ustar”,6)
oun$=nullpad$(“basic”,32)
ogn$=oun$
dmj$=nullpad$(“”,8)
dmi$=nullpad$(“”,8)
fnpre$=nullpad$(“”,155)
trash$=nullpad$(“”,12)

header1$=fname$+ fmode$+oid$+gid$+size$+modif$+checksum$+ftype$
header2$=lname$+ustar$+“00”+oun$+ogn$+dmj$+dmi$
header3$=fnpre$+trash$

check=0
For ch= 1 To Len(header1$)
check=check+Asc(Mid$(header1$,ch,1))
'Print check
Next ch
For ch= 1 To Len(header2$)
check=check+Asc(Mid$(header2$,ch,1))
'Print check
Next ch
For ch= 1 To Len(header3$)
check=check+Asc(Mid$(header3$,ch,1))
'Print check
Next ch

checksum$=mpad$(Oct$(check),7)+" "

'Print checksum$;

header1$=fname$+ fmode$+oid$+gid$+size$+modif$+checksum$
header2$=ftype$+lname$+ustar$+“00”+oun$+ogn$+dmj$+dmi$
header3$=fnpre$+trash$

End Sub

Sub readnextheader
fname$=Input$(100,#1) '0 100 File path and name
fmode$=Input$(8,#1) '100 8 File mode (octal)
oid$=Input$(8,#1) '108 8 Owner’s numeric user ID (octal)
gid$=Input$(8,#1) '116 8 Group’s numeric user ID (octal)
size$=Input$(12,#1) '124 12 File size in bytes (octal)
modif$=Input$(12,#1) '136 12 Last modification time in num
checksum$=Input$(8,#1) '148 8 Checksum for header record
ftype$=Input$(1,#1) '156 1 Link indicator (file type)
lname$=Input$(100,#1) '157 100 Name of linked file
ustar$=Input$(6,#1) '257 6 UStar indicator, “ustar”, then NUL
usver$=Input$(2,#1) '263 2 UStar version, “00”
oun$=Input$(32,#1) '265 32 Owner user name
ogn$=Input$(32,#1) '297 32 Owner group name
dmj$=Input$(8,#1) '329 8 Device major number
dmi$=Input$(8,#1) '337 8 Device minor number
fnpre$=Input$(155,#1) '345 155 Filename prefix
trash$=Input$(12,#1)

Do While Asc( Mid$(fname$,Len(fname$),1)) = 0
fname$=Mid$(fname$,1, Len(fname$)-1)
If Len(fname$) = 0 Then Exit Do
Loop
End Sub

Sub listcurheader
Select Case ftype$
Case “0”
Print "File ";
Case “5”
Print "Dir ";
’ Mkdir fname$
End Select

Print fname$;
fnamepad=30-Len(fname$)
If fnamepad < 0 Then fnamepad = 0
Print String$(fnamepad,32);

Print " ";
For tempd = 1 To Len(oun$)
If Mid$(oun$,tempd,1) <> Chr$(0) Then Print Mid$(oun$,tempd,1);
Next
Print “/”;
For tempd = 1 To Len(ogn$)
If Mid$(ogn$,tempd,1) <> Chr$(0) Then Print Mid$(ogn$,tempd,1);
Next

Print " “;
'Print " " Len(fname$) " “;
'Print size$;
size$=”&O”+sizE$
'Print size$;
Print Val(size$)

End Sub

Sub advancetonextrecord
flen=Val(size$)
If flen <> 0 Then flen=Int(((flen-1) / 512)+1)*512
'Print flen

Do While flen > 0
fonecont$=Input$(1,#1)
'Print fonecont$;
'If fonecont$ = Chr$(10) Then Print

flen=flen-1
Loop
If flen <> 0 Then fonecont$=Input$(flen,#1)
'Print fonecont$

End Sub

Sub savenextrecord
flen=Val(size$)
If flen <> 0 Then flen=Int(((flen-1) / 512)+1)*512
padding=flen-Val(size$)
flen=Val(size$)
extract=0
If opt$ = “” Then extract = 1

If opt$ <> “” Then
If Instr(LCase$(fname$),LCase$(opt$)) > 0 Then
extract=1
If MM.Info(exists dir fname$) = 0 Then
If ftype$ = “5” Then Mkdir fname$
EndIf
EndIf
EndIf
If extract =1 Then
If MM.Info(exists dir fname$) = 0 Then
If ftype$ = “5” Then Mkdir fname$
EndIf
EndIf

If extract =1 Then Open fname$ For output As #2
Do While flen > 0
fonecont$=Input$(1,#1)
If extract =1 Then Print #2 , fonecont$;
flen=flen-1
Loop
If extract =1 Then Close #2
Do While padding > 0
fonecont$=Input$(1,#1)
padding=padding-1
Loop

End Sub

Function mpad$(dat$,lent)
Do While Len(dat$) < lent-1
dat$=“0”+dat$
Loop
dat$=dat$+Chr$(0)
mpad$=dat$
End Function

Function zeropad$(dat$,lent)
Do While Len(dat$) < lent
dat$=“0”+dat$
Loop
zeropad$=dat$
End Function

Function nullpad$(dat$,lent)
Do While Len(dat$) < lent
dat$=dat$+Chr$(0)
Loop
nullpad$=dat$

End Function

2 Likes

For those living within Picocalc mmbasic, I made a clock.
I set it to launch with a function key, and when I get tired of programming, I just gaze at it.

'Clock for PicoCalc MMBasic

CLS

'=== present time
Dim hh As integer
Dim mm As integer
Dim ss As integer
'=== past time
Dim hh_ As integer
Dim mm_ As integer
Dim ss_ As integer

'=== parameters of clock hands
Const x0=160
Const y0=160
Const lh=70
Const lm=130
Const ls=130
Const l_=-10
Const th=-8
Const tm=-3
Const ts=-1

'=== draw clock hands
Sub DrawHour hour%,minute%,second%,c%
  hour_=hour%+minute%/60.0+second%/3600.0
  theta=Pi/6.0*hour_
  Line x0+l_*Sin(theta),y0-l_*Cos(theta),x0+lh*Sin(theta),y0-lh*Cos(theta),th,c%
End Sub

Sub DrawMinute hour%,minute%,second%,c%
  minute_=minute%+second%/60.0
  theta=Pi/30.0*minute_
  Line x0+l_*Sin(theta),y0-l_*Cos(theta),x0+lm*Sin(theta),y0-lm*Cos(theta),tm,c%
End Sub

Sub DrawSecond hour%,minute%,second%,c%
  theta=Pi/30.0*second%
  Line x0+l_*Sin(theta),y0-l_*Cos(theta),x0+ls*Sin(theta),y0-ls*Cos(theta),ts,c%
End Sub

'=== parameters of clock face
Const l1=150
Const l2=140
Const t1=-2
Const t2=-4

'=== draw clock face (numbers)
Sub DrawClockFace
  Font 3
  Color RGB(white)
  For i=1 To 12
    Text x0+l2*Sin(Pi/6.0*i),y0-l2*Cos(Pi/6.0*i),Str$(i),cm
  Next i
End Sub

'=== draw clock face (markers)
Sub DrawClockFace2
  '1,2,4,5,7,8,10,11
  For i=1 To 10 Step 3
    x=Sin(Pi/6.0*i)
    y=Cos(Pi/6.0*i)
    Line x0+l1*x,y0-l1*y,x0+l2*x,y0-l2*y,t1,RGB(grey)
    Line x0-l1*x,y0-l1*y,x0-l2*x,y0-l2*y,t1,RGB(grey)
  Next i
  '3,9,6
  Line x0+l1,y0,x0+l2,y0,t2,RGB(grey)
  Line x0-l1,y0,x0-l2,y0,t2,RGB(grey)
  Line x0,y0+l1,x0,y0+l2,t2,RGB(grey)
  '12
  Line x0+t2,y0-l1,x0+t2,y0-l2,t2,RGB(grey)
  Line x0-t2,y0-l1,x0-t2,y0-l2,t2,RGB(grey)
End Sub

'=== erase old clock hands
Sub EraseClockHands
  DrawHour   hh_,mm_,ss_,RGB(black)
  DrawMinute hh_,mm_,ss_,RGB(black)
  'DrawSecond hh_,mm_,ss_,RGB(black)
End Sub

'=== draw new clock hands
Sub DrawClockHands
  DrawHour   hh,mm,ss,RGB(lightgrey)
  DrawMinute hh,mm,ss,RGB(lightgrey)
  'DrawSecond hh,mm,ss,RGB(lightgrey)
  Pixel x0,y0,RGB(black)
  hh_=hh
  mm_=mm
  ss_=ss
End Sub

'=== read Time$
Sub ReadTime
  hh=Val(Left$(Time$,2))
  mm=Val(Mid$(Time$,4,2))
  ss=Val(Right$(Time$,2))
End Sub

'=== time signal (1 shot)
Sub TimeSignal
  If mm=0 Then
    Play tone 998,1002
    Pause 500
    Play stop
  End If
End Sub

'=== time signal (2 shots)
Sub TimeSignal2
  If mm=0 Then
    Play tone 2000,0
    Pause 70
    Play stop
    Pause 130
    Play tone 2000,0
    Pause 70
    Play stop
  End If
End Sub

'=== clock process
Sub ClockProc
  EraseClockHands
  ReadTime
  DrawClockFace2
  DrawClockHands
  TimeSignal2
End Sub

'***** MainProgram from here

ReadTime
DrawClockFace2
DrawClockHands

Do
  ReadTime
Loop Until ss=0

SetTick 60000,ClockProc,1

ClockProc

Do
Loop
6 Likes

This is one of those programs that should be assigned to an F key.

Why did you rem out the second hands? It looked like you just ignored the seconds, and I could not understand how you could just stare at it. I was surprised to see that you had remarked out the seconds. Also, I did not hear any beeps.

Now, I need to get my PicoCalc to get the current time at each boot.

Thank you for this.

This is one of those programs that should be assigned to an F key.

Thank you!

Why did you rem out the second hands?

I started building it to refresh the screen every second, but I couldn’t figure out how to use the framebuffer, so the screen flickered. I’ve commented out the code to display the second hand once I fix it.

Also, I did not hear any beeps.

The beep sounds at times like 1:00, 2:00, 3:00, etc.