Close
0%
0%

Pico Picow

A tiny handheld dev console, with a 12 button keypad, Pi Pico W inside, and 128x64 OLED.

Similar projects worth following
This was an experiment to see how small I could make this thing. The hardware is 95% complete, except for a few small revisions I want to eventually make on the PCB.

Now I am working on the software. It will feature a new interpreted programming language. I wrote TGRK in C, this time I am writing PGRK in Micropython. It's like a dream inside a nightmare!

PGRK will be a variant of the GORK (General Optimized Reusable Keywords) programming language, which I still haven't finished. PGRK is for (Pico General Reusable Keywords), and will differ a bit from the other variants.

The main Idea for the device is to have a command line interpreter for PGRK. A text editor. And a few utilities. I want to make some use of the WiFi onboard.

This device is actually quite simple. A Pi Pico W soldered directly to the PCB, 12 buttons, TP4056 IC and smd components, 14 pin female header for utilizing devices GPIO, and a 0.96" OLED display. As well as a slide switch for cutting the power.

I added some space on the back of the case for a small solar panel, but then I realized that I didn't design the PCB to allow that. If the voltage were high enough from PV, it would power on the Pico W through VBUS ( I need to double check if that is correct). So my solution was to print a snap fit cover for the back.

I think programming on this thing would be tedious, but much less tedious than programming on the Tiny Bit Machine... The programming language and interpreter I am writing for it has 3 key things in mind. 

  1. How do we use the minimal amount of characters in our programs? When using an awkward keypad and programming on a tiny screen that is 8 rows of text 16 characters wide, we don't want to write long variable names or have to put in lots of punctuation or indentation. Ideally with how the GRK family of languages are written, they can be coded with almost no whitespace at all.
  2. It's easy to use. Why write a more complicated programming language than Python? Especially if I am writing it IN Python? PGRK will be simpler than Python, therefore it will be lacking many features that Python or C have. But it will steal from both, as it is written in Python, which is written in C.
  3. It's portable. I intend to create a web interface or implement an FTP server on the device where files can be transferred easily to and from the device. Or be sent directly from one of these devices to another.

Below is the code for the current keymap, I will probably switch it around as time goes on. The idea is to have the most used keys on consecutive layers.

key_map = (('_esc','_caps','_esc',
                            '_space','_pgup','_pgdown',
                            '_del','_up','_enter',
                            '_left','_down','_right'),
                           ('0','1','2',
                            '3','4','5',
                            '6','7','_x',
                            '8','9','_mod'),
                           ('+','-','_x',
                            '*','/','_x',
                            '%','^','_mod',
                            '~','_x','_x'),
                           ('<','>','_x',
                            '!','=','_mod',
                            '&','|','_x',
                            '(',')','_x',
                            ),
                           ('[',']','_mod',
                            '{','}','_x',
                            '`','_','_x',
                            '\\','_x','_x',
                            ),
                           ('G','R','K',
                            'O','I','L',
                            '_x','.',',',
                            '_mod','@','$',
                            ),
                           ('C','P','E',
                            '_x','S','D',
                            '_mod','M','U',
                            '_x','A','B',
                            ),
                           ('_x','V','N',
                            '_mod','X','W',
                            '_x','Y','Z',
                            'J','F','W',
                            ),
                           ('_mod','Q','T',
                            '_x','#','?',
                            '_x','\'','"',
                            'H',':',';',
                            ))

The four buttons on left side of device and four buttons on right side of device are mod keys. If they are pressed and released quickly, they will function as the top layer key. If they are held down, they will activate that mod key's layer, and a tooltip showing the layer will popup on the screen as long as it is held. Here is an example:

/>

  • System Tools

    Gordon6 hours ago 0 comments

    I 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:

    1. [ s.wa] Create wifi AP, using a hard coded ssid and password or a new one
    2. [ s.ws ] scan for wifi networks. running this cmd saves a list of available networks
    3. [ s.wl ] view the list of networks saved in last scan
    4. [ 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]
    5. [ 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

    Gordon2 days ago 0 comments

    I 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

    Gordon01/04/2025 at 23:34 0 comments

    Today 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:

    1.  Storing a string into the KEYWORD "0K'
    2. Initializing the GROUP "G0", which does the following:
      1. Outputting retrieved KEYWORD 0K, which is the prompt for user
      2. Waiting for user input, which is stored in the KEYWORD "1K"
      3. A greeting as well as the users input is then output to user
    3. Initializing the GROUP "G1" which:
      1. Calls G0
      2. 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

    Gordon01/02/2025 at 23:53 0 comments

    I 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:

    1. A string KEYWORD or literal can only be added to or have something added to it, e.g. concatenation
    2.  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.
    3. 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

    Gordon12/30/2024 at 10:51 0 comments

    My 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...

    Read more »

View all 5 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates