Before I move on from the C64 user port for a while, I wanted to do a project where the computer actually read a value from the environment and analyzed it. Also, I wanted to spend a little effort fixing up my kludgy SPI implementation, and give it a better workout by reading several inputs from the MCP3008 simultaneously.
Disclaimer: We know from the movie Terminator that the T100 runs on a system using 6502 assembly language. If you try this at home, there is a small but nonzero chance of creating SkyNet.
In this case, though, I’m starting small. I kept my potentiometer input circuit from last week, since I figured I could use it as an adjustable value. For a second input, I attached a photoresistor to input 4 of the 3008. The photoresistor’s resistance changes depending on how much light is shining on its surface, and we use the same voltage-divider technique as last week to use the resistance to control the voltage on the 3008’s input pin.
In the software, the main loop reads the values of the potentiometer and the photoresistor and prints a “The lights are on” message if the photoresistor is higher. The potentiometer acts as a variable threshold, so you can adjust the input for the ambient light level. I recorded the video below in the afternoon, so the light level coming in through the windows was somewhere in the 600-700 range. I could set the threshold lower than that, so the “lights on” message played until I covered the photoresistor with my hand, or set the threshold higher, so the lights were off until I aimed a flashlight directly at the photoresistor’s face. I’ve left the program running as I write this, and the display is cycling off and back to on every time a cloud passes in front of the sun.
In all honesty, adding the input was trivial – it was formatting the output all from assembly language that was the hard part. If I was in more of a hurry, or less interested in challenging myself, I would’ve done most of that from BASIC, and just called the assembly language routines to sample the data. But one of the things I still don’t have a very good intuitive sense for is how to do complex numeric comparisons using the fairly limited branch instructions of the 6510.
Since all the data I read from the ADC was 10 bits wide, all my comparisons had to be done in two steps, with a high and low byte. I also decided to clean up my output by right-justifying the numbers as I printed them out, which required even more comparisons to decide how much padding to use.
The complicated thing is that the 6502 branch instructions aren’t explicit numeric statements like “branch if less than”. The comparison instruction, CMP, subtracts the two numbers you’re comparing and sets the CPU’s Status Register. Then, you use instructions like BEQ (“branch if result equals zero”), BCS (“branch if carry set”), or BPL (“branch if result positive”).
Your options end up being a little strange. BEQ and BCS map to equality and “Greater than or equal to” relations, and they have complements for inequality and “Less than”. But sometimes you have to combine several branches, or change the order of arguments to a comparison, to get the result you need. If you haven’t done that very much, or you’re even a little sleepy, it’s easy to make a mistake.
I’ve got some newer hardware I’d like to talk about in the next couple weeks, but before I take a break from the retrocomputing I’d like to give a link to CBMPrgStudio. This is a really nice PC-based cross-development IDE for Commodore 8-bit computers. It’s a lot faster than a native assembler, and it really speeds up development to not have to reload your assembler every time your program scribbles over the wrong part of memory. I said back when I started this blog that I’m not a purist, so I’m more than happy to take advantage of newer tools like this that make it easier to get to the fun part of retrocomputing.