I spend a good portion of my free time on personal projects. These projects have covered topics ranging from computer vision and OpenGL to digital logic design and Z80 assembly language. My process usually starts with finding an interesting concept to learn about, and then working on a project that applies it. This page is meant to catalog what I've learned and what I've made.
I spent some time this past summer and spring working on learning the basics of designing an instruction set. I won't formally be learning these topics for a year or two in my college. However, I found myself with enough time to design an emulator and assembler for a fictional instruction set that I designed based on the architecture of the Manchester SSEM. The instruction set is named W832, short for "WASV's 8-bit, 32-address Instruction Set".
The process of deciding on an architecture was essentially a really long Wikipedia Rabbit Hole ranging from orthogonality to one instruction set architectures. The one instruction architectures were very useful to look at as an example of the bare minimum needed for a useful instruction set. Eventually I got my instruction set down to 8 instructions, leaving 5 bits to address 32 bytes of memory. I might also make a W816 instruction set with support for immediate operands, however this would reduce the address bits to 4, leaving only 16 bytes to address memory.
Playing with LEGOs and OpenCVNormalizing and isolating LEGO backplanes using OpenCV. 2017-04-11
I've always loved playing with LEGOs. Some of my earliest memories involve building imaginary robots out of LEGOs on a big red table. Eventually I started building working robots with a LEGO Mindstorm NXT kit that my parents got me. And now I'm at RIT for computer engineering looking for ways to build real robots. Even though I'm at college, I'm still in the 4-99 year old range that is perfect for playing with LEGOs. Although now I've found more organized uses for LEGOs.
One of the ways I've been putting my LEGOs to use is a color-coded LEGO schedule. I can quantify the amount of time I spend on something by looking at how much of each color LEGO is on the calendar. Because it's made of LEGOs, my schedule is always malleable. I can move a block around to account for anything unexpected. However, since every block needs to go somewhere, I can make sure that I'm take the time I need for each project.
However, I find it difficult to keep up with a schedule if I can't see it. Since my LEGO schedule isn't exactly portable, I made a way to automatically crop and correct a photo of my calendar to just show the bricks. I used OpenCV to filter, detect, and warp the images.
An example of a picture of my schedule, and the output of my program.
An overview of my thought process started with finding an effective way to filter out only the green color of the LEGO backplane. Then I used some code from an OpenCV tutorial to find the largest blob of that color. After that, I came up with a simple way to approximate the four corners of the backplane. Using those four corners as anchor points, I can finally use the OpenCV perspective warp function to fit the backplane into it's own image.
Eventually I may look into a way to digitize these images into a format that I can add to a calendar app. But for now, I'm just going to keep playing with LEGOs.
Update: Can Detect Brick Colors2017-05-05
Recently I added another program to the repository for this project. This program takes in the output of the previous program, and uses hue and saturation histograms to categorize each cell by color. I'm going to put this project on hold for a while at this point.
wz80 v1The start of a retrocomputer. 2017-04-05
One of the projects I was working over the last few weeks was a z80 homebrew computer. I call it wz80, short for wasv's z80. Most of the construction of the computer was done during one of CSH's weekend hackathon. Although, I designed the schematics a few days ahead of time.
The layout and modular design is based on Semachthemonkey's RC2014 project. However, instead of building a separate backplane and CPU boad, I put the CPU and reset button on the backplane.
I left room to add a clock circuit in the future. Currently the clock signal is generated by a 555 timer. This makes debugging the hardware much easier. I actually managed to debug a program while it was running by attaching some LEDs to the data lines and turning the clock speed way down. I wrote down each byte as it appeared, and then disassembled the instructions by hand. In the end I had a working z80 computer that could cycle through the LEDs on a 7-segment display.
A few notes for anyone else who wants to build a homebrew computer:
- Start small This isn't the first time I wanted to build a homebrew computer. But it is the first time I managed to design and build one. I intentionally chose a good starting design, and stripped it down to the minimum set of necessary features.
- One thing at a time. Freerun the CPU first, then add a ROM, then basic IO, then RAM.
- Know how you will be storing programs. I ordered a few inexpensive flash chips without realizing how expensive flash programmers were. As a result, I tried to make my own then ended up using an FPGA as a ROM instead.
As one of my engineering professors said, "don't draw more lines in the morning than you can erase in the afternoon." I'd like to add that after 8 PM counts as morning.
I made a change to my reset circuit around 8 PM, and soldered it later than night. By the time I finished assembling the board around 1 AM, I spent another two hours trying to figure out why all the outputs were being held high. After looking at the datasheet, I realized the issue was that change I added.
January 20th, 2016
No functional updates this time, just some more documentation as I prepare to return to college. The basic schematic below should (hopefully) be enough for me to reassemble this project after getting back to college. In addition, I have an updated photo of the hardware layout and a brief 'cheatsheet' for the MCP23017 IO expander I've been using. I got 4 of them for $1.20 each at Digikey.
January 18th, 2016
I've worked out the remaining bugs in keypad reading code. It turns out that the prebuilt keypad I was using was causing an issue. After I rebuilt the keypad circuit with 16 individual buttons, each with a pullup resistor, I was able to work out the remaining software bugs. I went through a few different iterations, gradually adding more debugging code. One iteration involved reading each register on the IO expander hoping to figure out what the state of the device was. It was only after I simplified the code, essentially starting over, that I could figure out how to read the state properly.
The current code displays the hex value read from IO expander and the keycode it matches. I'm still working on a way to get interrupts to work, but I should be able to get my final code to work without them. The code in the keys folder.
January 14th, 2016
The parts came in for the new keypad design. I assembled a circuit with the IO expander and LCD connected to the Arduino through the same i2c bus. Communication appears to be working, but the IO expander isn't picking up any button presses. I spent most of last night and this morning troubleshooting it. See the dev branch on GitHub for my current work. The keys folder will currently show the received state of the IO expander GPIO. I may need to work on how I wired the buttons.
January 12th, 2016
I now have an implementation of the language in the project repository. It also includes a type-independent implementation of a stack in C. Storing values are not yet implemented.
I'm also waiting on parts for a redesigned keypad. The new design will use an i2c IO expander rather than trying to read a keyboard matrix.
January 10th, 2016
So far, I have a few tests in the project repository to verify that the LCD can display characters, and that the keypad can detect keypresses.
The LCD works, and the keypad can detect if a key is pressed. However, I have run into some trouble with scanning the keys. The keypad will occasionally send the wrong keypress to screen (typically one directly above or below the correct key). I believe using some debouncing could solve the problem, or possibly changing the scanning function to only detect a change in keypress.
This is still a work in progress, but I've learned a lot in the process and I look forward to seeing where this goes.
Does not reflect the current state of the project.
During the winter break after my first semester of college, I participated in CSH's 24 hour remote hackathon. This was a great opportunity to develop a project over the course of 24 hours while working with a great group of people across the country.
For my project I worked on an AVR based calculator. My project was a bit overly ambitious for the 24 hour time period. However, I worked out a lot of the initial hardware and some of the basic software. I plan to make progress on this project over the remainder of my vacation.
The calculator runs on an ATmega328 in an Arduino board. However, the software is written using avr-gcc, without the Arduino IDE. I found a handy way to program the Arduino without the IDE. After some research I modified the Makefile provided in the book Make: AVR Programming to load code onto the Arduino from the command line (see the Makefile for details).
The interpreter for the calculator is still a work in progress. I plan to get the basic system finalized before designing a language. The design is based on Reverse Polish Notation (a concept I have worked with in a previous project). In addition to simply displaying a result, the design includes a plan for variables that can be set, added to, and retrieved.
The hardware primarily consists of an LCD, a 15 button key matrix, and the Arduino.
The LCD communicates via a TWI (aka i2c) bus. This is accomplished using a minimal library provided by the Make: AVR Programming tutorial code.
The 15 buttons are wired in a 3x5 matrix (similar to a computer keyboard). The Arduino scans one row at a time, and checks if any keys in that row are pressed, then advances to the next. This reduces the number of pins from 15 to 8 at the expense of slightly more code.
In addition to the key matrix, there is also an 'alt' key. This allows each key to have a primary function and an alternate function. In this case, it allows access to the variables functionality described in the software section.
The book Make: AVR Programming has been a huge help in learning how to write C for the AVRs. It is a great next step after outgrowing the Arduino IDE. With a little modification, it can unlock a lot more power out of a small board. I highly recommend it.