Showing posts with label 8 bit. Show all posts
Showing posts with label 8 bit. Show all posts

Sunday, September 20, 2026

Creating a fast Basic interpreter

        For a retro boot-to-basic computer, I’d need an actual Basic interpreter. My first idea was to just grab an open-source implementation online somewhere and just port it over to my system, rather than reinvent the wheel myself. There had to be something suitable out there already, right?

        After a bit of searching, I decided to use Tony Wang’s MY-BASIC. This seemed idea –lightweight, packaged in a single code and header file, and easy to expand with hardware-specific commands. I copied it into my project, ported it over to deal with the idiosyncrasies of the MPLAB compiler, and added a handful of commands to make it work with the USB keyboard and text display. The trickiest part was converting it into a retro style line number dependent Basic instead of its more modern structured text style.


        This seemed to work great at first. I tried a few simple “Hello World” programs, and then coded a simple text mode Game of Life engine as a demo. This ran, but it was a lot slower than I expected, taking several seconds to calculate a single frame of the simulation. Well, that’s to be expected, I thought. Interpreted basic is slow, even on a modern 32 bit 200mhz CPU.


        The real problem came when I tried to write more complex programs. When I got to about 100 lines of code, the interpreter ran out of memory and crashed, even though most of the MCU’s 512KB of memory was set aside for it.

        It turned out that MY-BASIC is just not very memory-efficient. From looking through the code, there’s a lot of overhead to everything it does. It’s just not all that well optimized for microcontrollers with limited memory space like the one I was using.

        I looked at a few other options, but ultimately decided that I’d have to code my own Basic interpreter. One that was optimized for a lightweight memory footprint and high speed. It would turn out to be be my own unique dialog of Basic, as I looked at Commodore and Microsoft Basic for guidance but ended up reworking a few aspects of the language as I saw fit.

        The main guideline of my Basic interpreter would be to pre-calculate everything as much as possible. I was inspired by the tokenization pass that was performed by the Basic interpreter on Commodore machines, as well as the way that Python interpreters pre-process scripts into an easier to execute form. My Basic interpreter would scan every line of the program, first tokenizing them, and then processing them into a simple stack-orientated byte code, which would be what the actual execution process then ran.
The first step taken after the user types the RUN command, is actually to save the user’s entered program onto the attached SD card, clearing the memory space that would be taken up by the raw text. That file is then read back a line at a time, each line being processed by the tokenizer and parser.

        The tokenizer skims through each line, and breaks it down into a list of tokens. This is the part of the code that recognizes commands and functions, creates variable names and allocates space for variables as needed, and also recognizes strings and data and places those in specialized memory spaces.

        For example, the Basic line:

    b = 2*a*b+cb
will be broken down into the following list of tokens:
    [Index of variable b] [Assignment] [Integer 2] [Multiply operator] [Index of variable a] [Multiply operator] [Index of variable b] [Addition operator] [Index of variable cb]

        Each token is a 32 bit value, broken up into individual fields that can indicate token type (such as operator, variable, syntax, etc) and type within that token (such as type of operator, index of the variable, etc.). There is some complex logic in the tokenizer to distinguish different uses of syntax characters like equals signs and parentheses. The tokenizer will also catch many basic syntax errors and halt the process with an error message.

        After tokenizing, the list of tokens is handed to the parser. This code takes the list of tokens and converts it into a list of commands, which will be run by a virtual machine during runtime. This command language was chosen to be run as fast as I can get it to run, and also to take up minimal space in memory. Each command in the command list is a 32 bit value, which can have additional data for immediate parameters stored as part of the 32 bit command. Commands can also be followed by physical addresses in memory, as during the parsing process the addresses of variables, procedures, and operators are looked up and stored directly in the command list.

        Our previous Basic line, after going through the tokenizer and parser, will result in the following command list:

[Push variable contents to stack] [Address of variable a]
[Operation with immediate value 2] [Address of multiplication operator]
[Push variable contents to stack] [Address of variable b]
[Operation on top two values of stack] [Address of multiplication operator]
[Push variable contents to stack] [Address of variable ab]
[Operation on top two values of stack] [Address of addition operator]
[Pop top of stack to variable] [Address of variable b]

        This list of 14 instructions takes up 56 bytes. This is admittedly more than the 12 bytes of the raw Basic text, but it is much faster to execute than parsing the Basic itself every time that line needs to be run.
As an additional optimization, there is a final sweep through the code that identifies GOTO and GOSUB statements and replaces the associated line number with the address of that line in memory. This eliminated the need to search through the program list for the actual address every time a GOTO or GOSUB is encountered, although there still needs to be that capability for jumping to a line number that’s calculated at runtime.


        The resulting Basic interpreter is fast, running my Game of Life demo about 30 times faster than Tony Wang’s MY-BASIC. And it’s much more memory-efficient, I’ve written programs over 600 lines long without getting close to the memory limitations. I’d call it a success, for a part of the project that I never intended to develop from the start it’s working really well.

        The source code for the project can be found here.

Monday, June 8, 2015

Building my PSP (PiStation Portable) Retropie gaming station.



After seeing this project on Thingiverse, I decided to build my own portable Retropie gaming console.  It looked easy enough to do, there were software builds available ready to install on a SD card, and it would be an excuse for me to gain more experience with Linux and on the Raspberry Pi.  Of course, I couldn’t just build the existing design as-is, eventually redesigning the entire case for the features I wanted.  I really wanted to improve the ergonomics and packaging efficiency of the design, to make something that would fit well in my hands and be easy to play and that wouldn’t be any larger or heavier than absolutely necessary, something that I could sit and play on a long car or train ride for hours without getting hand cramps.  I also wanted some features lacking on the designs I saw, including built-in battery charging, headphone jack, and a USB port available for loading ROMS.

I designed the printed parts in Solidworks.  I've been slowly teaching myself Solidworks over the last half a year, after finally getting completely fed up with the terrible 3D drawing capabilities of AutoCAD.  AutoCAD is a fine 2D drafting program, but a terrible 3D drawing program, and I'd been hitting against its limitations for a while.

Of course, I bought the original parts for this project about a week before the Raspberry Pi 2 was announced.  The Pi 2 would have made certain parts easier, having more processing power, more convenient mounting holes, and more USB ports, but I decided to press ahead with the parts I already had rather than start over with new parts.  If I build another one of these, I’ll redesign it for the Pi 2.

Nearly all of the parts came from Adafruit, the main exception being the video screen which is a cheap car backup camera.  The screen claims to need a 12V input, but I found that it runs just fine on 5V - the 3.3V switching regulator on the screen interface PCB still handles the lower voltage.  It does get a bit warm, and I suspect that there are parts in the regulator that are running more current that intended at the lower voltage.

I initially was going to use the same cheap multi-color membrane pushbuttons that everyone seems to use, but after trying them didn’t like the way they felt.  Too stiff and too clickey for my tastes.  I decided to use these slightly more expensive illuminated mechanical pushbuttons instead.  They cost more and take up a lot more space behind the panel, but they have a really smooth action and actual mechanical contacts inside instead of a membrane switch.  Being illuminated in a range of colors was a nice added cosmetic bonus.  I’m still using one of the membrane buttons for a control mode switch, and intend to use a second for a power switch once I get the soft power circuit working.

The controls are all managed through a Teensy 2.0 acting as a joystick/keyboard USB device.  The Raspberry Pi doesn’t have analog input, and I wanted an analog joystick, so the USB solution was the easiest way to go.  

I originally had a design involving 2 analog joysticks plus a D-pad and about a dozen buttons before coming to my senses and realizing that a single joystick and 8 buttons were enough for any game I’d be emulating.

There is one additional button not being directly used by the joystick.  This button is an input to the Teensy which changes its mode from a joystick to a keyboard.  When in keyboard mode, the joystick is mapped to arrow keys, and the buttons are mapped to a handful of selected keyboard buttons:  escape, return, tab, and some of the function keys.  This lets me navigate the setup menus and file transfer utilities without having to plug in an external keyboard.  The second USB port on the Pi is still accessible from the outside of the case, so I can still plug a keyboard in if I need to.  Mostly the external USB port is to be used to transfer game ROMs with a USB thumb drive.


Originally I planned to use a large 5V USB power pack for power.  This did not work out well.  These battery packs are designed for charging cell phones and don’t like to be used for other purposes.  The output protection circuit trips very easily, I wasn’t able to get it to play nice with a Mausberry soft power switch, and trying to use an audio amplifier to power speakers would trip the battery off when any loud sound played.  The voltage output from this pack is badly regulated, the screen would flicker as the voltage varied and there was a lot of noise in the audio from the Pi when using it.  It was also impossible to play games while charging the battery - when the charger was active the voltage output would get very low and erratic, the screen would flicker and the audio buzz, and plugging or unplugging the charge cord would cause a momentary power interruption that would reset the Pi.  










That battery pack was also a giant inconvenient brick that I had trouble fitting in the case.  

 After several frustrating weeks trying to get it to work I switched to a discrete battery and power boost /charger board, which works much better.












I still haven’t managed to get a soft power function working, with power on via button and power off automatically after shutting down Linux. The Mausberry doesn’t seem to have any easy way to work with the boost/charger board, so I’m working on my own latch circuit that uses the enable pin on the boost regulator.  It shouldn’t be hard to get to work, but until then I’m just using a toggle switch for manual power control.

The audio noise went away when I changed the battery, but the audio quality is still not great.  This is mostly due to the default audio output on a Raspberry Pi being rudimentary at best, but also apparently partly due to the game emulators not being quite powerful enough to smoothly reproduce the audio output on some of the consoles.  The SNES is especially bad, when there is a lot of movement on the screen the audio output gets really choppy.  If I really cared I could install a HifiBerry I2S plugin board, and then overclock the Pi to better handle SNES emulation.

I went through a lot of design iterations getting the shape right.  I wanted something that I could print in as few pieces as possible, with controls that were comfortable for my large adult man hands.  Widely spaced mechanical buttons and an smoothly-acting analog joystick won out over a D-pad and membrane buttons, even if it made the wiring and placement harder.  I struggled with getting everything to fit until I decided to solder the video, power, and USB connections directly to the Raspberry Pi board rather than use the provided connectors.  This saved a tremendous amount of space, especially for the composite video feed, although it means the Pi isn’t likely to be re-used for another project now.


The other breakthough on the design was having the video screen front panel outside the printed case.  I figured that it had a nice-looking front bezel already, so why not use it as-is?  Fitting the screen outside the case rather than wrapping the case around it saved space and made the packaging easier.  With directly soldered connections to the Pi I was able to fit the Pi, Teensy joystick board, battery, and power boost/charge board entirely in the space behind the screen.  That just left small extensions on either side for the joystick and buttons.  This was the point that I decided on the “PiStation Portable” name.  I hadn’t originally intended to model it after a PSP, everything just came together that way.  Ironically PSP games are quite hard to emulate, well beyond the capabilities of a Raspberry Pi.


The end result is quite compact and comfortable to hold, and I was just barely able to print the front and back halves as single pieces on my 3D printer.  It was very tight - the case is about 237mm wide at the widest point, and my printer has a 250mm diameter circular print area, so it was coming really close to the edges of the print space.  It did take several tries to get the back case to print successfully, it has some really difficult overhangs.






I’m running a standard copy of Emulationstation 2.6 on an 8gb flash drive.  I know that 3.0 is out now, but it looks like changing over to that will mean having to replace all of my ROMs from scratch.

So far I have Atari 2600 games working very well.  I found a ROM pack of what appears to be every 2600 game ever made and installed it - they only take up a few kilobytes each, so I had plenty of room.  Most of them haven’t aged well, but I do still enjoy Yar’s Revenge.  I have managed to get the Gameboy and Gameboy Colors emulators to work, but Gameboy Advance emulation still doesn’t work.









NES emulation seems to be the sweet spot for this design - there are a lot of fun games available, and the Pi emulates the NES very well.  













SNES emulation works, but the framerate suffers at times and the audio is choppy.  Getting MAME working will be my next goal, I should be able to play a lot of the older classic arcade games on this.

The only remaining hardware changes I intend to make to this one are to try to figure out a soft power switch as mentioned above, and to add a low battery light to the front panel.  There is a low battery light on the power management board, but it’s shining out the back of the case at the moment.  I need to find a spot to put another light visible from the front, so I have some warning to save my game and shut down before the battery dies.

If I had to do this over from scratch now, I’d start with a Raspberry Pi 2.0.  More USB ports, faster processor, better audio circuitry, and a more compact SD card slot.  It would mean a significant redesign of the case, and probably different wiring for the video and audio connections.  I’d also try to fit miniature speakers in somehow, so I could at least have some sound without having to plug in headphones.  An amplifier board and volume control would also be nice - the full volume output of the Pi is still fairly quiet.  The joystick/keyboard mode switch should probably be a small slide switch instead of a button, but other than that the ergonomics are perfect.



Plans, such as they are, are posted here.