-
Small Updates
02/10/2025 at 19:52 • 0 commentsHaven't done much on projects since back from my trip. But I did fix some issues with the wifi, so it is much more stable now.
I also made it so device will enter deepsleep after 1 minute of no button presses. The deep sleep state that it goes into must use less power than I previously thought, because it was in this state for nearly one entire day and barely used any battery... maybe 5%. I haven't done many tests, but the main purpose of this state is if the user forgets to turn it off the battery won't just drain uselessly.
Unrelated to this project: My brother I was visiting is an electrician, and one of the jobs we went to there had been a lightning strike near the house. We swapped out some outlets and switches at the site, as well as an automatic yard sprinkler control box. I was curious what had been damaged in the box. And upon opening it saw many exploded capacitors and transistors, as well as traces that had been completely blown off the board. I got a couple pictures and may make a page post with my findings as it was interesting.
I am really wishing I would have started this project in C instead of python. But I will continue work on it until the interpreter and device code is finished in python before moving on to C. My goal is to make the GRK code compatible with the python and C implementations of the interpreter... The C version will also have a PC version, and can run a GRK program file by doing something like "./grk test.grk", or just running "./grk" or "grk.exe" if on PC, which will load the GRK console.
I am not too familiar with Windows command line options, but when using a linux environment I like creating alias's for my own programs to make things simpler.
-
Video of Project Current State
01/21/2025 at 05:57 • 0 comments -
Going Forward
01/20/2025 at 18:07 • 0 commentsI will be on a trip til the end of the month so will not be working on any projects during that time. But I have some thoughts on the future of this project and the interpreter as a whole.
I am going to rename the language to just GRK. The initial version will be written in python, then I plan on making a version in C. Both implimentations will be available on my github in the same repository.
I think micropython is fine for most cases on embedded devices such as Pico W if wanting to make something quick, or it's a small project. But as python is very inefficient on memory, with a larger project it is not very good. I am already having memory issues I need to sort out with what I have running and it's really hard to track down where it's happening. So far it is almost entirely to do with using the urequests library for fetching data from the internet. I think I can optimize it in python, but if I were using C I doubt I'd have run into this issue yet as the total available memory would be much greater before even fetching the html request.
When I wrote TGRK in C for attiny85, if I remember correctly I think the entire interpreter only used about 100-150 bytes of memory (not counting program memory, which in TGRK is set at 127 bytes). Granted TGRK does have a fraction of the features GRK will, but with this project, for it to work reliably I need to be able to manage the memory myself.
A simple example is an integer variable for setting different modes. Let's say we have modes 0-3. In python this will automatically be several bytes. In C we can make sure it is only 1 byte by setting type as uint8_t. If we want 8 flags that can be 1 or 8, we can save that in a single byte and manipulate the bits in that byte. I need to lookup how many bytes micropython uses for a boolean. it has to be more than 1 considering how python stores variables.
I have not used the C SDK for Pico or Pico W, so I will be setting that up and driving into that after the python implementation is finished.
-
Browser Based Programming
01/17/2025 at 22:58 • 0 commentsThe title is just about one feature I've added, but there are a lot of new features, so many in fact I may forget about some.
I have been having so much fun adding device features I have still not touched the interpreter.
I will not list interpreter commands here as there are no new ones. But I do intend to make many or all of these system commands accessible from the interpreter.
A picture of the browser tool:
Below is the list of all system commands up to this point.
Pico PicoW Device Specific Commands:
s.w: If this command is run like this, and no ssid and password is currently set, it will scan for networks, then check if there are any saved networks that are available. if so it will automatically connect. If there is already a ssid and password set, it will try that first.
- s.ws: Scans for available wifi networks
- s.wc<n>: Connect to network "n" from scanned list. Acts the same as "s.w" if no argument provided.
- s.wl: Display the scanned list of networks on screen
- s.wx: Turn off wifi module
- s.wa: Create a WiFi AP, prompts user for ssid and password.
s.s: Creates a webserver, outputs IP address of server to screen. Webserver has a text area field that programs can be written into. If server receives program data, it replaces all the html characters with appropriate characters, and outputs it to screen. As of now it automatically appends to programs list. I will make this optional in future. As well add option for executing program immediately. Entering "end" into browser text area will shut down server.
s.g: Currently running this as is will connect to "https://g0730n.com" and output "success" if it receives a 200 code back.
- s.g<url>: Currently works the same as above, except any url can be fetched: "s.ghackaday.io"
- s.gt: Fetches time from NTP server, updates system clock.
- s.gw: Fetches weather data from API, saves data to text file as it is good for 48 hrs.
s.t: Displays current date and time
- s.ta: Non functional at moment, but will be used for alarms and timers.
s.c: Displays weather graph of saved weather data.
s.r: Not sure if is needed... Shuts down second core that scans keys, does a machine reset. Was having issues with connecting in Thonny so this was an attempt to deal with that. I did find a method that worked. So I dont think this is needed. But I will use this in future to do a reboot.
s.z: Device sleep command, called as is without arguments, device will turn off oled, wifi, and enter deepsleep indefinitely. Pressing ESC button wakes device. RTC time does not increment in this mode. I have not tested yet, but this mode should only use 1-2mA of power.
- s.z<n>: Turns off screen and WiFi as above, calls "time.sleep_ms(n)", n being 0-70 minutes. Will be used in alarm and timer modes in future. This method of sleep does not save a ton of power, but better than nothing. Drops machine.freq() to 20mhz before entering this sleep mode, then goes back to whatever it was before after finishing the sleep cycle.
s.f<n>: Set the machine frequency. n being 20-250(mhz)
-
Experimenting With API's
01/15/2025 at 16:14 • 0 commentsBefore I go back to working on the interpreter I decided to add some more system features.
"s.g" can be used to fetch a URL if connected to the internet.
"s.s" Will create a server and allow client to load a web page either over Pico AP or through LAN depending on Pico W's connection state. The web page has a single text area for writing a program and uploading to device. WIP
"s.gw" will call weather API, get the next 48 hours of data. 48 data points of Temperature, Humidity, Cloud Cover, and Chance of Precipitation. The API I am using can be fined tuned for many different weather data points but these were what I thought I would find most useful.
"s.c" will show a graph of this weather data:
In the photo above the randomly scattered data points are from the cloud cover plot line. the lower it is on the screen the sunnier it is. The numbers on left hand side are for % of (clouds, humidity, chance of precipitation) or temperature in Fahrenheit.
Connection to internet over wifi, on initial connection RTC time will be synced with NTP. This can then be retrieved by the command "s.t".
-
System Tools
01/15/2025 at 01:55 • 0 commentsI discovered that I didn't lose as much progress as I thought.
Currently every feature that is available in the PC developement version is available and working on device.
I am trying to figure out a good way to keep the interpreter separate from the devices code. In the sense that routines for handling the devices wifi connection or printing a line out to the OLED should be accessible from the interpreter while running on the device, but not while running it on PC.
I decided to create an option from the device commandline to type
"s.<system command>"
Currently all I have implimented is a command line utility on device that can:
- [ s.wa] Create wifi AP, using a hard coded ssid and password or a new one
- [ s.ws ] scan for wifi networks. running this cmd saves a list of available networks
- [ s.wl ] view the list of networks saved in last scan
- [ s.wc<n> ] connect to the network of number specified from networks in list, this will prompt for a password. if command is run without a number, it will try to connect to the last saved network running [ s.w ] will do the same thing as [ s.wc]
- [ s.wx ] turns off wifi, whether AP or Client, it goes off. I have it set up so only AP or client can be run at same time.
I will later impliment a save file on flash that will have different saved settings including saved networks and passwords. when running [ s.w ] in that case it will automatically scan and see if there is a saved network that matches, then connect.
I have also created a new function specific to the Pico Picow for easier printing of lines and getting input from anywhere in the devices code. While running the interpreter, the device is basically always stuck in an input mode. But I realized these system tools will need the ability for input that can be accessed out of the interpreters command line.
I really want to get back to adding functions for the interpreter, but wanted to make sure 100% that it was all going to work on the device okay before I went any further. So far so good. I have a better backup system I am using right now too.
-
Version Control
01/13/2025 at 17:00 • 0 commentsI stayed up late last night working on the interpreter. I made a lot of really good progress. But this is real life and often times there is good news and bad news.
I moved the entire interpreter into a class. I am not sure why I didnt start it out this way, but I realized it was inevitable and the longer I went without doing it the more tedious it would be.
I spent a lot of time working on error handling, and was able to impliment and catch syntax errors that would before freeze the interpreter.
I then decided to make the first port of the PC developement interpreter to the Pico Picow. This was also going great. It was exciting to finally be able to write commands on the devices console. I added a larger command history on the device, from it remembering the last command to remembering the last 8.
And then as I was testing it on the Pico device, I went to save it again and somehow overwrite the last several hours of work. I know I was tired but this was unacceptable. I need to use a better version control than just saving multiple copies at random times. I did not lose all my work, just from wherenI started porting it to the device.
So, these features I speak of exist, but I will have to re write them. Once I get back to where I was with the code, I will make a video as that was a good level of functionality to demonstrate the device.
-
Groups
01/04/2025 at 23:34 • 0 commentsToday I wrote the code for GROUPS, as I described in an earlier post that they are essentially functions that use the keywords G<n> (n can be 0-99).
I was having issues if I wanted to call a group from inside a group, where the last group would think it was creating a new group, but I figured that out, and now it's working as it should. Some example code:
0K $Enter Your Name$ G0@ O 0K I 1K O$Hello$, 1K,$!$ @ G1@ G0 LG@ G1
This code demonstrates:
- Storing a string into the KEYWORD "0K'
- Initializing the GROUP "G0", which does the following:
- Outputting retrieved KEYWORD 0K, which is the prompt for user
- Waiting for user input, which is stored in the KEYWORD "1K"
- A greeting as well as the users input is then output to user
- Initializing the GROUP "G1" which:
- Calls G0
- Loops G1
I figured out how to make GROUPS callable from within other groups when I was coding TGRK. When calling a GROUP, a list holds the return address from where that GROUP was called from. When the called group reaches it's ending "@" symbol, it pops the last address from the list, which will be in the right order, and sets the program counter to that address.
Below is an idea of several different ways we could write this code on the Pico Picow, either going for the most compact, or the most readable... keeping in mind 16 characters is the widest line that can be displayed on the screen:
0K$Enter Your Na me$G0@O$Hello $, 1K,$!$@G1@O0KI1K G0@G2@G1LG@G2 ---------------- 0K $Enter Your Name$ G0@ O$Hello $, 1K, $!$ @ G1@ O 0K I 1K G0 @ G2@ G1 LG @ G2
To be able to format the code as above, I had to remove the feature where we can add whitespace by adding a space after the OUTPUT comma " O$Hi$, $there!$" will now output "Hithere!". I think that was a cool feature so I am going to look into some way of reintroducing it, but for now, just adding the space in the string literal or KEYWORD is enough.
I think next I will work on Conditional Operators.
-
Debugging and Loops
01/02/2025 at 23:53 • 0 commentsI added a debugging function because it was getting crazy to debug when something went wrong. Parsing directly from a string takes a lot of steps. Now if I have debugging on, if there is an error I can see exactly what went wrong (sorta).
I added the "L" and "LG" builtin KEYWORDS for LOOP and LOOP_GROUP. Here is how they work:
0K 100 : <O 0K> L @ <0K 100 : O 0K> LG
The code enclosed with "< >" will be looped.
"L" will scroll the program counter until it reaches a SEPERATOR ":" symbol.
"LG" will scroll the program counter back until it reaches a GROUP "@" symbol, this allows for repeating a GROUP as many times as wanted. All KEYWORDS being global, effectively this can be very useful.
it's pretty simple and works as intended.
I also have assigning a value of a KEYWORD to another keyword setup:
12K 2K
The above sets the value of 12K to the value of 2K. I need to work on parsing math operators next. In the original GORK, my plan for the rules of math operators to be as such:
- A string KEYWORD or literal can only be added to or have something added to it, e.g. concatenation
- If a string of keywords and literals are added together, and there is a string in there, the final result will be a string. If there is no string, if there are no floats, it will be an integer, otherwise it will be a float.
- Adding 1 to keyword 1K looks like this "1K + 1", there is no need for ++ or += or "1K = 1K+1" like in C or Python. The goal is to reduce as many characters needed to write a program.
4K 12 - 2 + $ Day's until January $ + 12 + $th$ [VALID: 4K = $10 Day's until January 12th$ ) ] 2K 128 2K + 4 / 12 - 16 * 1.234 [VALID: 2K = 108.589] [INVALID OPERATIONS] 4K $Howdy$ - 10
-
Once Again I am Writing an Interpreter From Scratch
12/30/2024 at 10:51 • 0 commentsMy dream of writing a programming language that uses virtually no whitespace and as little symbols as possible is coming true.
I have been playing around with the syntax a bit and found something to my liking. I will post a snippet of what I already have implemented and working in code, as well as a snippet of how I envision the larger syntax to look. It will look very similar to TGRK. TGRK was made the way it was for a very specific application. I think PGRK will be more universal.
Once I have it fully written in Python, I plan on writing it again in C.
On my Github, the original GORK programming language I started, I had the same concepts in mind that I wanted to accomplish, and was making some good progress on it, but, at the time, my knowledge of C was very limited. This was the second small project I was attempting after starting to learn C. So I ended up setting it aside, and started with MGRK, then that was too much, so moved on to SMGRK, which eventually turned into TGRK.
Enough history, I will get those code snippets.
The following piece of code will interpret and execute with the code I have running now, in any of the following whitespace configurations. Programming on a tiny device with a tiny screen, having the shortest possible keyword names as well as the ability to reduce whitespace to a minimum is a plus. Have you ever tried to read a large code page on a small screen? It is very frustrating.
On the Pico Picow, the line widths will be fixed to a maximum of 16 characters wide. There are several reasons for this. At this point I don't think I want to enable any wrapping, or having any text reach off the screen. The point is to have it all visible, and miniaturized enough that a lot can fit on that 16x8 character page.
0K20248K30O$Its December$, 8K,$th$, 0KI1KO1K 0K 2024 8K 30 O $Its December$, 8K,$th$, 0K I 1K O 1K
What we have here is basic KEYWORD (variable) storage and retrieval, as well as some input and output.
Executed in the Python REPL, it outputs the following message, offers the user input which stores in the 1K KEYWORD, then outputs the message the user entered.
Creating and assigning a KEYWORD is done with "<n>K<value>" n can be any number from 0-99, and the value formats are as following:
An integer or float immediately following the K, or with any amount of whitespace between:
3K2045 3K 0 3K 72 3K 2.4928 3K 42
The above are all valid. A string is created by using the $ symbol instead of quotes. It just made sense to do this.
12K $This is a string.$ 12K $ This is another string. We can format however we want. $
Input will be like Python's input() function, which is completely blocking and can be typed into until the enter button is pressed. In PGRK, the input keyword is a single "I", immediately followed by the keyword we are storing the entered string into. I plan on adding keywords for getting individual keys and button presses for the Pico Picow, but as I am wanting to make a command line interface first, this will be helpful.
I 1K
The above takes input and stores it in the 1K keyword. It's that simple.
Output is even funnier! Output is done with a single "O" followed by the data we want to send out. On the Pico Picow, this means it will be getting sent to a function that displays it on the OLED display. But for testing, it gets printed to the python command line.
Output one value:
O123
Output two values, if there are more than one value to be sent out, they are separated by a comma. I was thinking about how I may or may not want to have spaces between these values. EASY. If you want a space, just add it after the comma. Adding more than one space will not add extra spaces. But if you don't want a space, don't add one and the data is contiguous.
O $Hell$,0
Output with spaces, also visualized how It would look trying to enter something that long on a small screen.
OK3 1K2 O $Only$, OK, $d ays$, $until$, $ January,$, 1K O $Only$, OK, $days$, $until$, $January,$, 1K
There is no need to tell the interpreter to stop outputting the data. Once it reaches the last comma, it puts out the last value and passes the program pointer back to the main interpreter.
The above is what I have gotten working so far. Below are some concepts of how the rest of the syntax and functionality will look.
KEYWORDS:
- <n>K<value> = general purpose reusable keywords. As explained above can handle various data types. Assigning any value to them is done by calling the KEYWORD, followed by the data we want to assign. Whether it be another keyword, or other data. Copy value of 2K into 0K: [ 0K2K ]They will also be available to be used as arrays. Just make a regular keyword with a first value, then follow it with commas like with the Output: [ 1K 20,40,60,80,100 ]. I have not implemented this, and am not sure how calling it would look. Maybe if we want to get the 3rd element we would do something like: [ 1K3? ], then to assign to that index: [ 1K3?<value> ]... We'll see.
- G<n> = Groups (functions). Are initialized with the "G", then their number, then the @ symbol followed by its code block, ending with another @ symbol. This is basically identical to TGRK. An example, [ G0 @ <group code> @ ] then called with its name [ G0 ]. There is no passing of parameters, as all KEYWORDS are global. A keyword that is specific to a group is the "LG" keyword...
- LG = Loop Group. When this Keyword is called, it scrolls the program pointer back to the start of the groups code block.
- L = Loop. This is a regular loop. Just like in TGRK. When it is called, it will move the program counter backwards until it hits a SEPERATOR symbol, or a group block symbol "@". I may rename it to R for REWIND... That brings us to our conditional operators, because without a condition, a loop will most likely be infinite.
- > Greater Than, the following example checks if the following comparison is true, and if not skips forward until it hits a separator or group block symbol [0K1000 : > 0K100 0K-1 O0K L: ] Using the ":" symbol as a separator, this will check if the 0K Keyword is greater than 100, if so, subtract one, output the new number, then repeat. Once it is down to 99, it skips past the separator and the program counter goes on it's merry way. All other comparison operators work in the same format as above.
- < Less Than
- >= Greater or equal than
- <= Less than or equal to
- = Equal to......................................Assignments never use the equals signs in the GORK family, so we can use it for comparisons.
- ! Not equal to
- & AND(for combining comparisons, not bit manipulation)
- ? OR (for combining comparisons, not bit manipulation)
- : SEPERATOR. I was thinking of using the period symbol, but then realized if we were placing a floating point number in there somewhere, the interpreter could get confused along the way. So for now the ":" it is.
- MATH OPERATORS
- + Adding in PGRK is like in TGRK. We just bring up the KEYWORD we want to add to and then ad to it [ 0K+1 ]. This format is used for all the operators.
- - Subtract
- * Multiply
- / Divide
- % Modulus
- ^ Exponent
- ~ Random
There will be a lot of built in functions specific to the Pico Picow device, such as wifi handling, etc. various command line builtins that will be specific to controlling the hardware.
That's about all I have right now, have a happy new year and until next time!