An ARM and a Leg
With a clear goal ahead of me, I trudged my way through a mountain of documentation and sample projects to figure out how to best get an ARM processor working. I'll spare you the details of the hundreds of missteps along the way (I also forgot most of them) and try to outline what I used to get what I now have working.
Of the three brands I had available (Texas Instruments, ST Micro, and Atmel), I decided to use ST Micro's STM32F4 Discovery board. I'm sure the other two are just as awesome, but a lot of my friends have experience with ST parts, so I thought it'd be a good place to start. Besides, if I blew it up, it's pretty cheap to replace at just fifteen dollars. Plus, the board has an integrated debugger that can even be used to debug external boards.
The first thing I needed to do was get my toolchain set up. I'm not a huge fan of graphical IDEs, and a lot of them don't work on OS X anyway, so after some searching, I discovered that I needed arm-none-eabi-gcc to compile my code and openocd and gdb to program it. I don't remember much from installing these applications which probably means that it went smoothly. I think I used Brew, but there are a ton of ways to get it to work.
Arm-none-eabi-gcc works similarly to AVR-GCC, but openocd and gdb were new. One of the greatest benefits to using a modern processor is the ability to use modern debugging tools. Openocd can be configured to open a connection with the built-in debugging hardware through the ST-Link interface, and gdb can then probe around and read register values or pause and unpause the application. This was enormously useful compared to my usual "make this LED blink" method of debugging.
Once my toolchain was set up, I found it pretty easy to communicate with the Discovery board. Openocd came preinstalled with a profile called stm32f4discovery.cfg that had everything ready to go for my development kit.
With the hardware portion figured out, I looked around for software. ST has a standard peripherals library (more on that later), but I found it a little overwhelming and eventually settled on this GIT project which had simply ripped the GPIO toggle project out of the standard peripheral library and configured it to work on its own. The STM32F4 Discovery has its own built-in ST-link programmer, and using a few guides I found online like this one, I was well on my way. I even found an example Makefile that had some compile options at the bottom that allowed me to program my device by using the command "make openocd" and connect the debugger using "make gdb" in another window.
This left me with two options for debugging. Openocd calls on a local file openocd.cfg which tells it what to do. If that file ends in "program main.elf verify reset", it connects to the chip, programs it, and resets. If that line is commented out, it just connects and stays connected requiring me to attach to the session using gdb in another terminal window. Gdb is similarly configured using a local file called ".gdbinit". openocd by itself just programs the device while the combination of the two allows for real debugging.
This was more or less what I used for the entire first half of my project. Once I was satisfied with my proof of concept code, I created my own PCB with a different processor.
The Discovery board is powered by an STM32F407 processor which is a Cortex M4 that's probably a little overpowered for what I needed. Realistically, the part is still pretty cheap and it would have been easier to keep everything the same as it was in the development kit, but I was worried that if I didn't learn how to port code to a properly chosen processor early, I might end up using the F407 as a crutch for all my future projects.
I settled on the STM32f105 for my custom design. This is a Cortex M3 part which is about half the cost of the F407 and has fewer extraneous pins to worry about. Getting it to work of course required using the Standard Peripherals Library mentioned before which actually turned out to not be that bad.
I downloaded the library from here and unzipped it. This library contains code for the entire assortment of STM32F10x parts. Inside the Project/STM32F10x_StdPeriph_Examples/GPIO folder, I found the familiar IOToggle project in its original form which included a few source files and a readme recommending I "Copy all source files to the template folder under Project/STM32F10x_StdPeriph_Template". The template folder had a few files for various toolchains, but I didn't see anything that looked familiar.
The solution I used involved copying the new files to my Discovery template and replacing their counterparts. The project folder contains three sub-folders. "src" contains all of the .c files, "inc" holds all of the .h files, and "lib" has the peripheral library files. The lib folder has its own Makefile and compiles the special processor-specific functions separately from the main application code. If the main Makefile and the lib Makefile are configured correctly, this all happens automatically, and the compiler knows when to drag these special functions into the code that gets programmed to the part.
Of course, this didn't compile on the first try. I had to modify all references to the F407 in my source code as well as the configuration of openocd. I also got some errors when compiling telling me that the library needed to be configured for my specific part. I needed to uncomment some lines in the file stm32f10x.h to let the library know that I was using a "connectivity line" device (more info in AN2557).
This all started working after my second attempt of going through it. I was happy to find that the library is incredibly well organized, and if you do a few things correctly, it tends to just work. There are a lot of specific details that I'm leaving out, so if you'd like to know more, I recommend downloading my project files and poking around. The Makefiles have a bunch of settings that I honestly don't 100% understand at this point, and there were a few small tweaks I needed to perform to the library to set things like my processor speed. I can say that the library is well commented, and I usually didn't need to look any further than a header file to figure out how to configure something.
Thermal printer modules are actually pretty hard to find by themselves. There are a ton of thermal printers out there, but unless you want a full-on label or receipt printer complete with power cable and case, you have to hunt. There are a few options available from sellers on eBay who probably rip them out of the aforementioned thermal printers, but I ended up using the one offered by Adafruit as it was sure to have the best documentation.
Though it didn't come with a proper datasheet, the example project provided by Adafruit outlined all of the necessary commands including most importantly, some decent default configuration settings for things like motor speed and heater temperature. There are actually a lot of levers you can pull on these printers, so it was nice to have a baseline that offered at least decent performance.
It has an attractive front face with an easy to open paper loading door, and most importantly, it has hardware to mount the printer into a panel. I'm not sure what it's meant to mount to exactly, but the 0.5" thick mounting surface I made for it proved to be just barely too thick. I resolved that by getting some 30mm M2.5 screws.
The printer doesn't come with any thermal paper, so I ran across the street to the drugstore to pick up a roll of calculator paper for testing. Unfortunately, they only had 100' rolls which wouldn't fit, so I unraveled half. I then quickly learned that logging calculators do not use thermal paper. They have an ink-ribbon and print on normal paper, so with 50 feet of unraveled paper around my ankles, I went to Amazon and ordered 50 rolls of thermal paper for $20.
When I first started this project, I was planning on using a camera module that I had purchased years prior. Sparkfun used to offer an adorable tiny little CMOS camera module for something like $8, and I had purchased a few for a different project that never got off the ground.
Unfortunately, I think I brought my box of camera modules to some hack-a-thon thing I was participating in while I was in the process of moving, so after about three hours of frantic looking, I concluded that they are lost forever. Oh well, they had terrible documentation anyway.
I instead settled on another Adafruit offering, their JPEG camera:
(Seen here after I accidentally ripped off the crystal oscillator). This guy was especially nice because they offered a few sample images that let me test out my code before even hooking it up.
Not the greatest, but good enough.
The camera module is a JPEG camera meaning that it doesn't spit out data pixel by pixel. Instead, an onboard FPGA compresses the entire image to JPEG format and transmits that over serial. Since I'm just getting used to dealing with file systems, I was surprised to find that simply saving the raw data transmitted over serial to a file and giving that file the .jpg extension is all you need to do to create a JPEG file. In fact, the included Arduino library does exactly that as an Arduino is not powerful enough to decompress a JPEG in any reasonable amount of time.
Communication protocol datasheet here.
On-board video processor datasheet here.
This camera wasn't going to be any fun if it needed to be wall-powered, and the printer required "5-9V" at something like 1-2A. That's a decent amount of power. I guess I shouldn't be surprised. The Gameboy Printer required six AA batteries to operate.
The minimum 5V requirement wasn't going to let me use a standard 3.7V lithium polymer cell. I could have used some step-up circuitry, but this could have been difficult due the erratic current draw of the printer. Really, it wouldn't have been impossible, but since the printer didn't need a specific voltage (testing showed that it worked anywhere within that range), I thought it would be easier to connect it directly to a dual-cell battery with no regulation whatsoever.
This thing is a monster. It's seriously terrifying. 7.4V, 3000mAh, and continuous rated discharge of 4A. That means that it can continuously put out 28 watts. That's almost 30 watts!
Usually with series cell batteries, there's a requirement to keep the cells balanced. Without proper balancing, one cell can wear out faster than the other, and since they're in series, power has to shut off when the first cell reaches the minimum discharge voltage even if the other one still has more charge to offer.
This pack was built to order, so I'm guessing that they've either included some kind of balancing circuitry inside the pack, or the cells they chose are of a specifically matched chemistry to prevent disparity in cell wear. All I need to worry about is that it charges to 8.4V and discharges to 6. It even has built-in battery protection circuitry!
Battery datasheet here.