# Fomu: a beginner's guide

FPGAs are pretty cool pieces of hardware for tinkering with, and have become remarkably easy to approach as a hobbyist in recent years. Boards like the TinyFPGA BX don’t require any special hardware to use and can provide a simple platform for modestly-scoped projects or just for learning.

While historically the software tools for programming FPGAs are proprietary and provided by the hardware manufacturer, Symbiflow (enabled and probably inspired by earlier work like Project IceStorm) provides completely free and open-source tooling and documentation for programming some FPGAs, significantly lowering the cost of entry (most vendors provide some free version of their design software but limited to lower-end devices; a license for the non-free version of the software is well into the realm of “if you have to ask, you can’t afford it”) and appearing to yield better results in many cases.1

As somebody who finds it fun to learn new things and experiment with new kinds of creations, FPGAs are quite interesting to me- they’re quite complex devices that enable very powerful creations, with excellent depth for mastery. While I did some course lab work with Altera FPGAs in university (and a little bit of chip design/layout later), I’d call those mostly canned tasks with easily-understood requirements and problem-solving approaches; it was sufficient to familiarize myself with the systems, but not enough to be particularly useful.

The announcement of Fomu caught my interest because I was aware of the earlier Tomu but wasn’t sufficiently interested to try to acquire any hardware. With Fomu however, I’m rather more interested because it enables interesting capabilities for playing with hardware- others have already demonstrated small RISC-V CPUs running in that FPGA (despite its modest logic capacity), for instance.

Even more conveniently for being able to play with Fomu, I’ve been in contact with Mithro who is approximately half of the team behind Fomu and gotten access to a stockpile of “hacker edition” boards that have been hand-assembled but not programmed at all. With slightly early access to hardware, I’ve been able to do some exploration and re-familiarize myself with the world of digital logic design and figure out the hardware.

## Hardware

In summary, Fomu is a small (9.4 by 13 by 0.6 millimeters) circuit board with a Lattice ICE40UP5K-UWG30 FPGA, a 16-megabit SPI Flash for configuration (and other data) storage, a single RGB LED for blinkiness and a 48 MHz MEMS oscillator to provide a clock.

The whole thing is built so it can fit inside a standard USB port. Production boards are meant to ship with a USB bootloader that allows new configurations to be uploaded to the board only via that USB connection, but hacker boards are provided completely unprogrammed (and untested).

### Schematic

Before we can make the hardware do something, we’ll need to understand how everything is put together:

Unfortunately, this schematic leaves some things to be desired. While it does allow us to see what parts are actually on the board and generally how they’re connected, it fails to clearly mark the external connections- power and data lines on the USB connector, test points and utility I/O pads.

The USB connections are easy to figure out, however; it’s a standard pinout so we can easily identify which physical pads on the board correspond to VUSB (5V supply), ground and the two data lines (USBP, USBN). Rather trickier to work out is the function of each of the test points on the board, though there is a provided template for laser-cutting a programming jig which provides some hints:

This jig is meant to be built up by stacking four layers of material, engraving a small pocket in the bottom to hold the board to program and inserting pogo pins in the small holes to contact with the test points on the board. This template helps us in that it has labels for the test points, though! All of the test points are clearly identified, except it’s unclear what voltage is expected on the power supply.

By inspecting the board myself, I eventually determined that the test point for supplying power (marked VCC on the programming jig template) is downstream of the 3.3V regulator (not connected to the USB power supply pad) so it expects 3.3 Volts for programming.

### Convenient pinout diagram

By way of improving the schematic, here’s that same photo of the board with the signal names from the schematic pointed out on each of the pads, and the individual chips pointed out.

And the same in tabular form for easy searching:

Silkscreen Schematic Description
V +3V3 3.3V rail
S CS SPI chip select (active low)
C SCK SPI clock
I MISO SPI MISO
O MOSI SPI MOSI
R CRESET_B FPGA reset (active low)
G GND Ground
1 PIN1 User I/O 1
2 PIN2 User I/O 2
3 PIN3 User I/O 3
4 PIN4 User I/O 4

## Bootstrapping

My first task in attempting to bootstrap a board and load some configuration on it was building a programming jig. Given there was already a template for a laser-cut acrylic one and I have access to a benchtop laser cutter, this was easy:

It’s a little bit ugly because the pogo pins I had ready access too are too small to nicely fit in the laser-cut holes so I had to carefully glue them in place.

Actually programming a board can be done with the fomu-flash utility running on a Raspberry Pi. I conveniently had a Raspberry Pi 2 to hand, so a little wiring to the Pi’s GPIO header had a jig that should work. Unfortunately, it didn’t- all I got out when trying to make it identify the on-board flash chip was 1s:

fomu-flash -i Manufacturer ID: unknown (ff) Memory model: unknown (ff) Memory size: unknown (ff) Device ID: ff Serial number: ff ff ff ff Status 1: ff Status 2: ff Status 3: ff I gave up on that hardware after spending a while experimenting with it, and decided to design a custom programming jig that might be a little easier to ensure pin alignment is good. This is a little bit tricky because the minimum pitch of the test points is just 1.8 mm, which is not large enough for the 0.1-inch (2.54 mm) DuPont connectors commonly used for prototyping and desirable in this case because they’re very easy to connect to the Raspberry Pi’s GPIO header. ### A better jig Fortunately, I also have access to rather sophisticated prototyping tools and had some nice parts handy from other projects. In particular, a Form 2 stereolithographic 3D printer and some good pogo pins, Preci-dip 90155-AS. I computer-modeled a jig to be 3d-printed that should be both compact and robust, pictured below (see the end of this post for downloadable resources): ### Features The design takes great advantage of the flexibility of 3d printing for fabrication: it is easy to install the pogo pins off-vertical by making the (press-fit) holes at an arbitrary angle; this would be very difficult with conventional fabrication, but it allows the spacing of the pins at the top of the jig to be large enough that 2.54mm connectors can be used, despite the pad spacing on the board being only 1.8mm. On the bottom side, there are several narrow features that act as a shelf to support the board (which is 0.6mm thick) so its outside surface is flush with the bottom surface of the jig. A semicircular boss on one side mates with the cutout on the PCB to key the jig so it is obvious when the board is correctly oriented in the jig. A small cutout on one edge allows a tool to be inserted to pull the board out if needed, because the fit is close enough that it might stick sometimes (or a tool could be pushed through from the top). As a manufacturability consideration, the top surface has a slant between opposite corners. This improves the print quality on a Form 2- because dimensions on that side are not critical the part is designed to be printed with that side “down” (actually up, once in the printer) and supports attached to it on that end. By allowing the printer to gradually build up a slope rather than immediately build a plane, it can better produce the intended shape- an earlier version of the design with a flat top had a very rough finish because large and thin layers of material tend to warp until enough material is built up to be self-supporting. The choice of pogo pins in particular is key, since they’re made with a small shoulder and retaining barbs that allow them to be easily press-fit into a connector shell: The one downside of these pins is the short tail, intended for mounting to a circuit board. While the aforementioned DuPont connectors can be mated to the tail, they are not very secure and come off at the slightest force. A revised design choosing parts for their function and not just immediate availability might prefer to use a part like 90101-AS, which is intended for wire termination rather than board mounting- then wires can be securely attached to the pin rather than tenuously placed on it. My workaround that didn’t involve buying more parts was carefully gluing the wires in place, which seems to work okay. ## Programming Having built a jig that I could be confident would work correctly, we now return to the problem of actually programming the board. Connecting the new jig to my Raspberry Pi in the same way I did the first one, it failed in the same way- reading all 1s. At this point I was rather stumped, with a few possible explanations for the problems: 1. Both jigs are unreliable 2. I’m wiring the jigs up incorrectly 3. Software on my Pi is configured incorrectly 4. All of the Fomus I tried were faulty To discount the first two possibilities, I was able to borrow Mithro’s professionally-built jig that already had a Raspberry Pi 3 connected to it. I didn’t have any credentials to log in to that Pi and use it interactively however, so I was limited to checking its wiring and carefully ensuring I connected my Pi to the jig in the same way, then try programming again. This also failed. Having tried that I had to assume my Pi was somehow misconfigured, since it seemed increasingly unlikely that I was doing anything wrong and it seemed implausible that all of my boards were faulty. I eventually took the SD card out of the other jig’s Pi and inspected the software it would run by connecting it to another computer. This amounted to the same fomu-flash program I was using, so I inspected the system configuration in /boot/config.txt and found a variety of non-default options that seemed plausibly useful. Ultimately, I found some magic words: dtparam=spi=on This option makes the kernel on the Pi expose a hardware-assisted SPI peripheral, which seems like an obvious missing option until you realize that fomu-flash actually bit-bangs SPI because the hardware support is insufficient for this application. In any case, I did find that turning that option on makes everything work correctly:  fomu-flash -i
Memory model: AT25SF161 (86)
Memory size: 16 Mbit (01)
Device ID: 14
Serial number: ff ff ff ff
Status 1: 02
Status 2: 00
Status 3: ff

I reported the bug and made a note of this in the documentation so hopefully nobody else has to deal with that problem in the future, even if the root cause is mystifying.

## Success!

With the ability to talk to the configuration flash, it’s then possible to write an actual bitstream. To avoid needing to write one myself, it’s easy to take the LED blinker example from the fomu-tests repository:

fomu-tests/blink$make FOMU_REV=hacker ... Info: constrained 'rgb0' to bel 'X4/Y31/io0' Info: constrained 'rgb1' to bel 'X5/Y31/io0' Info: constrained 'rgb2' to bel 'X6/Y31/io0' Info: constrained 'clki' to bel 'X6/Y0/io1' Warning: unmatched constraint 'spi_mosi' (on line 5) Warning: unmatched constraint 'spi_miso' (on line 6) Warning: unmatched constraint 'spi_clk' (on line 7) Warning: unmatched constraint 'spi_cs' (on line 8) Info: constrained 'user_1' to bel 'X12/Y0/io1' Info: constrained 'user_2' to bel 'X5/Y0/io0' Info: constrained 'user_3' to bel 'X9/Y0/io1' Info: constrained 'user_4' to bel 'X19/Y0/io1' Warning: unmatched constraint 'usb_dn' (on line 13) Warning: unmatched constraint 'usb_dp' (on line 14) ... Info: Device utilisation: Info: ICESTORM_LC: 33/ 5280 0% Info: ICESTORM_RAM: 0/ 30 0% Info: SB_IO: 5/ 96 5% Info: SB_GB: 1/ 8 12% Info: ICESTORM_PLL: 0/ 1 0% Info: SB_WARMBOOT: 0/ 1 0% Info: ICESTORM_DSP: 0/ 8 0% Info: ICESTORM_HFOSC: 0/ 1 0% Info: ICESTORM_LFOSC: 0/ 1 0% Info: SB_I2C: 0/ 2 0% Info: SB_SPI: 0/ 2 0% Info: IO_I3C: 0/ 2 0% Info: SB_LEDDA_IP: 0/ 1 0% Info: SB_RGBA_DRV: 1/ 1 100% Info: ICESTORM_SPRAM: 0/ 4 0% ... Built 'blink' for Fomu hacker$ fomu-flash -w blink.bin
Erasing @ 018000 / 01969a  Done
Programming @ 01959a / 01969a  Done
$fomu-flash -v blink.bin Reading @ 01969a / 01969a Done Programming that to the board yields a blinking LED as expected, so I’ve achieved success in the basic form of this project by getting the FPGA to do something. Further exploration will involve writing gateware with Migen rather than straight Verilog (because I find Verilog to be rather tedious to write) and trying to build a system around a RISC-V CPU (because that sounds interesting). ## Resources If you want to make your own copy of the programming jig or just explore it, you’ve got several options: • View the model at OnShape. This will allow you to view and make changes to the parametric model, which is what you’ll need to make most useful changes to it. • View the STL online. A quick and dirty way to get an interactive view of the model. • Download the STL. If you just want to try to 3D print your own, this is all you need. It may also be useful if you want to make changes using a 3d modeling program (rather than a CAD program). • Download a Solidworks part file. This was just exported from OnShape, but you might prefer this if you want to use SolidWorks to edit the model. All of the official documentation for Fomu is available on Github. For basic information (such as what I referred to when writing up this project), that’s a great starting point. I designed the programming jig in OnShape which is a pretty good and very convenient CAD tool. 1. FPGA vendors don’t publish all the information required to build configuration bitstreams for their hardware, possibly because they wish to support their side business in selling design tool licenses- this despite the fact that (anecdotally, since I can’t recall where I saw it) many FPGA developers say that vendor tooling is one of the biggest annoyances in their work. The open-source tools require a fair amount of painstaking reverse-engineering of chips to create! [return] # MAX5214 Eval Board I caught on to a promotion from AVNet last week, in which one may get a free MAX5214 eval board (available through August 31), so hopped on it because really, why wouldn’t I turn down free hardware? I promptly forgot about it until today, when a box arrived from AVNet. ## What’s on the board The board features four Maxim ICs: • MAX8510- small low-power LDO. Not terribly interesting. • MAXQ622- 16-bit microcontroller with USB. I didn’t even know Maxim make microcontrollers! • MAX5214- 14-bit SPI DAC. The most interesting part. • MAX6133- precision 3V LDO (provides supply for the DAC) The MAXQ622 micro (U2) is connected to a USB mini-B port for data, and USB also supplies power for the 5V rail. The MAX8510 (U4) supplies power for the microcontroller and also the MAX6133 (U3). The microcontroller acts as a USB bridge to the MAX5214 DAC (U1), which it communicates with over SPI. The SPI signals are also broken out to a 4-pin header (J6). ## Software The software included with the board is fairly straightforward, providing a small variety of waveforms that can be generated. It’s best demonstrated photographically, as below. Those familiar with National Instruments’ LabView environment will probably recognize that this interface is actually just a LabView VI (Virtual Instrument). ## Hacking Rather more interesting than the stock software is the possibility of reprogramming the microcontroller. Looking at the board photos, we can see that there’s a header that breaks out the JTAG signals. With the right tools, it shouldn’t be very difficult to write a custom firmware to open up a communication protocol to the device (perhaps change its device class to a USB CDC for easier interfacing). Reprogramming the device requires some sort of JTAG adapter, but I can probably make a Bus Pirate do the job. With some custom software, this could become a handy little function generator- its precision is good and it has a handy USB connection. On the downside, the slew rate on the DAC is not anything special (0.5V/µs, -3dB bandwidth is 100 kHz), and its output current rating is pretty pathetic (5 mA typical). With a unity-gain amplifier on the output though, it could easily drive decent loads and act as a handy low-cost waveform generator. Let’s get hacking? # A divergence meter note Somebody had asked me about the schematics for my divergence meter project. All the design files are in the mercurial repository on Bitbucket, but here’s a high-resolution capture of the schematic for those unable or unwilling to use Eagle to view the schematic: dm-rev1.1.png. Be advised that this version of the schematic does not reflect the current design, as I have not updated it with a FET driver per my last post on this project. On the actual project front, I haven’t been able to test the FET driver bodge yet. Maybe next weekend.. # Divergence meter: high-voltage supply and FET drivers I got some time to work on the divergence meter project more, now that the new board revision is in. I assembled the boost converter portion of the circuit and plugged in a signal generator to see what sort of performance I can get out of it. The bad news: I was rather dumb in choosing a FET, so the one I have is fast, but can’t be driven fully on with my 3.3V MSP430. Good news is that with 5V PWM input to the FET, I was able to handily get 190V on the Nixie supply rail. Looking at possible FET replacements, I discovered that my choice of part, the IRFD220, appears to be the only MOSFET that Mouser sell that’s available in a 4-pin DIP package. Since it seems incredibly wasteful to create another board revision at this point, I went ahead with designing a daughterboard to plug in where the FET currently does. I got some ICL7667 FET driver samples from Maxim and have assembled this unit onto some perfboard, but have not yet tested it. Given I was driving the FET with a 9V square wave while testing, it’s possible that I blew out the timer output to the FET on my microcontroller while testing. Next time I get to work on this, I’ll be exercising that output to see if I blew it with high voltages, and connecting up the perfboard driver to try the high voltage supply all driven on-board. # D-meter updates I’ve been able to do some more work on the divergence meter now. The university’s labs made short work of the surface-mount soldering, but there were some hitches in the assembly and testing phase, in which I discovered some of the part footprints were wrong, and it was a bit of trouble getting the programmer working. I was able to work around most of the bad footprints, but some of them were barely salvageable, since the through-holes were too small. I was able to drill them out on the drill press in the lab, but that left me with very small contact areas to solder to, so I had a few hideous solder joints. After getting the power supply portions of the board soldered came getting the MSP430 talking to my MSP430 Launchpad, which I’m using as a programmer. Initial attempts to program the micro were met with silence (and mspdebug reporting no response from the target), but the problem turned out to be due to using cables that were too long- I had simply clipped test leads onto the relevant headers, yielding a programming cable that was around 1 meter long, while the MSP430 Hardware Tools User’s Guide (SLAU278) indicates that a programming cable should not exceed 20 cm in length. I assembled a shorter cable in response (by soldering a few wires onto the leads of a female 0.1” socket) and all was well. The most recent snag in assembly was the discovery that I had botched some of the MSP430’s outputs. I had connected the boost converter’s PWM input to Timer A output 0 on the micro, but I discovered while writing the code to control the boost converter that it’s impossible to output PWM on output module 0, due to the assignment of SFRs for timer control. The user’s manual for the chip even mentions this, but I simply failed to appreciate it. I could have cut a few traces and performed a blue wire fix, but it seemed like a very poor solution, and I was still concerned about the poor contact on the other vias I had to drill out, so I bit the bullet and created a new revision of the board with correct footprints for all the parts, and a more comprehensive ground plane (hopefully reducing inductive spiking on the optocoupler control lines). I’ve now sent revision 1.1 out to be made, so improved boards will be here in a few weeks. Until then, I’ll be working on the software a bit more, and hopefully updating this post with photographs. # Divergence meter progress One project which I’ve been working on since about October and just got around to creating a project page for is the divergence meter. There’s not a lot to see there yet, but I’ve recorded my notes on what the design needs and the outline for the control and power supply module. I ordered the PCB in early December in the hopes that they would be available for me to work on while in Wauwatosa during the semester break. That didn’t pan out, so unfortunately the whole project won’t move until next week, when I return to Houghton and can get my boards from the mailbox. My batch of nixie tubes arrived earlier than expected, however, and I got the components to populate the board in mid-November. All I need is the boards and some time to solder, while hoping I don’t completely botch the job of soldering a 38-TSOP package, especially since that chip (the MSP430F2272) cost me$5.  Photos follow.

One I find the time to assemble the control board, the software should come together pretty quickly.  Just a matter of time now..

# Some Chronos Documentation

Moving on from my previous post (in which I muttered sullenly about brain-dead packaging of software for Linux), I began hacking on my Chronos proper tonight. Read on for some juicy tidbits.

## Initial build

The first order of business was to set up a toolchain targeting MSP430. Since I’m running Arch on my primary development system, it was a simple matter to build gcc-msp430 from the AUR.

With that, I was ready to try compiling things. I assumed (correctly) that the provided firmware would not build on GCC without modification, but a little googling pointed me to OpenChronos, which effectively takes the stock firmware, makes it build with any of several compilers (TI’s compiler included with CCS, IAR’s, and GCC). Come to think of it, LLVM has an experimental MSP430 backend that might be interesting to try out.

One git checkout and an invocation of make later, and I was staring at a screenful of errors. “How auspicious,” I thought. The first part of the fix was easy– I simply needed msp430-libc for some of the more specialized functions that don’t map well into straight C- things like interrupt handling (which is in msp430-libc’s signal.h for some reason) or machine-specific delays.

The remaining compilation errors after grabbing libc were rather more troublesome, however. There were two main classes of problem.

• Uses of types at some specific bit-width (such as uint16_t). These were easily resolved by strategic inclusion of stdint.h, but I’m not very happy with how I had to do it. Spraying header inclusions all over the source code is a poor way to fix things.
• Large delay constants. There were two cases in the radio control code which adjusted the microcontroller’s voltage regulator, which then requires a rather long delay before the system can be considered stable again. The solution in code is simply to delay for as many as ~800000 clock cycles. Normally that wouldn’t be a problem, but some of the delay constants were larger than the input type to the __delay_cycles function could hold. My hacky solution was to split those into two calls of half the length, which seemed to work out OK.

After a while to figure out the compilation problems, I was able to build a firmware image. After the struggles I had with unpacking TI’s sample code and demo applications, it was fortunately painless to actually run them. I just ensured I had Tcl/Tk installed and ran the Chronos Control Center application. Putting the Chronos itself into WBSL (Wireless BootStrap Loader) mode and clicking a few times was easy, and I quickly got my new firmware image flashed onto the CC430.

## Preparing for mods

Now that I had a known-working toolchain, it was time to get to work actually implementing some of the toy features I wanted to add. Since the single most interesting feature of the hardware is the radio (although the low-power capabilities of the MSP430 are quite shiny as well), I set out to see how I could communicate with the watch from my PC.

One of the USB dongles that comes packaged with the Chronos is a USB wireless access point, basically just a CC1111 (6801 core with USB and RF transciever). I understand that earlier revisions of the demo applications didn’t include source code for the software running on the CC1111, but the current release includes it. Some people had taken a bit of trouble to reverse-engineer the communications, but that alone isn’t very useful documentation. With that in mind, I set out to document for myself how to communicate with the RF access point and go through that to talk to the Chronos.

Setting up communications is easy, fortunately. The CC1111 is programmed to enumerate as a USB CDC, so one must only open the virtual serial port it creates with a 115200 bps baud rate with 8 data bits and 1 stop bit. (If that’s not terse enough for you: 115200 baud, 8n1.)

With virtual serial communications up, the upper-level protocol is rather easy- it consists of packets of at least 3 bytes each, where the first one is always 0xFF. Byte 2 provides a command ID, and byte 3 specifies the total packet size, including the overhead (so the minimum valid size is 3). Anything more in the message is interpreted based on the command ID.

### Command IDs

There are a number of command IDs defined, but only a few that are of particular interest. In the hopes that somebody else will find it useful, I include my raw notes on the command bytes below.

As a little bit of context, the system can run on either of two different radio protocols. TI’s SimpliciTI is a protocol designed mainly for communication between low-power nodes in a network, while BlueRobin is a radio protocol developed by IAR Systems, notable with the Chronos because it allows communication with a heart rate monitor developed by BMi GmbH.

Command bytes:
BM_GET_PRODUCT_ID
Dumps 32-bit product ID into the usb buffer
BM_GET_STATUS
returns system_status (some file-scope var?)
== bluerobin
BM_RESET
Turns off bluerobin
BM_START_BLUEROBIN
Start bluerobin (set a flag, actually), stop simpliciti if that's going
BM_SET_BLUEROBIN_ID
BM_GET_BLUEROBIN_ID
BM_SET_HEARTRATE
BM_SET_SPEED
== simpliciti RX
BM_START_SIMPLICITI
Start simpliciti, stop bluerobin if that's going
BM_GET_SIMPLICITIDATA
Dump the 4 bytes from the simpliciti_data buffer to USB
also mark simpliciti data as read
If no pending data, usb_buffer[PACKET_BYTE_FIRST_DATA] = 0xFF
BM_SYNC_START
nop
BM_SYNC_SEND_COMMAND
copy packet from USB to simpliciti buffer and flag for tx ready
BM_SYNC_GET_BUFFER_STATUS
1-byte payload packet out, = var simpliciti_sync_buffer_status
copy simpliciti_data buffer out to USB
BM_STOP_SIMPLICITI
Flag to turn off simpliciti

== WBSL
BM_START_WBSL
flag to start WBSL, turn off bluerobin/simpliciti if active
BM_STOP_WBSL
stop wbsl, turn off LED
BM_GET_WBSL_STATUS
copy back var wbsl_status
BM_GET_PACKET_STATUS_WBSL
copy back var wbsl_packet_flag or WBSL_ERROR if wbsl is off
copy back max number of bytes allowed in wbsl payload
BM_SEND_DATA_WBSL
set wbsl_packet_flag to WBSL_PROCESSING_PACKET
deocode packet and spew it to the 430
== self-test
BM_INIT_TEST
BM_NEXT_TEST
BM_GET_TEST_RESULT
BM_WRITE_BYTE
write a byte to the access point's Flash memory
first data byte is the value to write
second and third are address, little-endian (2 is lsb, 3 => msb)
must be in test mode (precede this with BM_INIT_TEST)


(Command and system status constants are defined in BM_API.h, FWIW.)

Knowing all the commands, it’s pretty easy to pull out the useful ones. BM_START_SIMPLICITI makes the access point switch into SimpliciTI mode, and sending BM_SYNC_START allows direct communication through the radio link with BMSYNC{SEND,READ}_BUFFER functions.

## More.. later

This is as far as I’m going to go with this adventure for today, but there’s more to come in the coming days (hopefully, assuming my motivation holds out). This is just preliminary documentation– I’m hoping to create a more formal set of documents providing a whirlwind overview of how to get hacking on the Chronos, but I feel this is an excellent start.