Monthly Archive for January, 2013

I hate backups.

Ah, backups. I hate backups. Everyone hates backups. But the only thing worse than taking backups is not taking backups.

I have a couple of scripts that I’ve written to take backups of my life and now I’ve gotten them to a point where I think other people might find them useful.

I used to use dar. dar is pretty cool because it lets you perform incremental, encrypted backups. It’s pretty not-cool because it’s hard as hell to use. In fact, I’ve never been able to get incremental backups working with encryption. I’ve gotten tired of trying.

So I decided to go back to the one true archiving utility, tar. Few people know that tar actually also supports incremental backups using the [cci]\g[/cci] command. So, for example, you can do:

[cc]$ tar -czp -g incrlist.snar -f first-backup.tgz /some/directory[/cc]

Edit files and stuff, and when you want to do the next backup, do

[cc]$ tar -czp -g incrlist.snar -f second-backup.tgz[/cc].

You can then restore these backups by first restoring first-backup.tgz and then second-backup.tgz, using the [cci]-g[/cci] switch as before. This will even delete files that you deleted between taking first-backup and second-backup.

Okay, cool, so let’s make that into a script. I wrote a script for backing up my home directory and other important stuff on my hard drive to an external drive. Unfortunately, I was running out of space on my RAID array, so I incorporated 640GB of a 1TB drive that I used to use as a “buffer zone” for backups into another drive for the array. So, now I just issue my backups directly to my external drive.

The system generates one full backup each month and then incremental backups for the rest of that month. It’s configured by sourcing a config file that sets the appropriate variables. An example config file might look like this:

[cc]backupdir=/mnt/backup
targetdir=/home/me
prefix=home
excludes=”–exclude=.VirtualBox –exclude=*.pkg.tar*”[/cc]

Line 1 specifies where to store the backup (and look for an existing full backup from the same month to diff against). 2 says what to backup. 3 specifies a prefix name to apply to the archive. Finally, 4 offers the ability to exclude files. Config files can use the variable [cci]$scriptdir[/cci] to reference the directory that the backup script is stored in and [cci]$configdir[/cci] to reference the directory the config file is stored in.

You can even specify commands to run before and after the backup by filling in the functions [cci]precmd()[/cci] and [cci]postcmd()[/cci]:

[cc]precmd() {
echo “This is run before tar.”
}

postcmd() {
echo “This is run after tar.”
}[/cc]

So what about encryption? Well, since I only take backups to one specific drive, I’ve decided to opt for drive-level encryption with LUKS/dm-crypt. This is a far more robust solution that has also proven to be secure.

I’ll talk about how I back up my server at some other point.

Making Xilinx Suck Less: A VHDL Preprocessor

Oh VHDL, you make my life so wonderful. I just want to be able to enable or disable different debugging features at compile time. But no, there’s no real preprocessor support in the VHDL world.

So my solution was to write a wrapper script that fakes out GCC into using its preprocessor and then generating a new VHDL file. It takes two files as input: the [cci]prj[/cci] file you would use for XST and a [cci]config[/cci] file that has a bunch of key=value pairs that get passed as directives for the GCC preprocessor.

For each file, it then invokes the following magic:

[cc lang=”bash”]gcc -Dwhatever=whatever -traditional-cpp -E -x c -P -C file.vhd[/cc]

This causes GCC to treat the VHDL file as just a generic C file and only processes the standard preprocessor directives like [cci lang=”c”]#if[/cci].

It then saves the result to a new file. So if you were processing [cci]file.vhd[/cci], it would generate (by default) [cci]file.gen.vhd[/cci]. It stores these files in the same directory as their pre-preprocessed versions.

Finally it creates a new [cci]prj[/cci] file that you should pass into XST.

So, it’s super easy to use. All you need to do is run [cci lang=”bash”]vhd-preproc.py -p /path/to/project.prj -c /path/to/config[/cci] and all your files will be preprocessed.

ACRIS 2.0 Firmware

So close and yet so far… Long story short: after assembling everything and fixing a whole host of firmware problems, ACRIS boards are about 0.002″ away from being done. Yup, one of the hole sizes is wrong, but other than that, the boards are perfect!

Buuuuut ignoring that, I’m very happy with the results. Take a look:

So what you have there is, among other things, 12-bit resolution! That’s right; the new firmware finally supports the full 4096 levels of brightness of the LED drivers instead of 256.

The new firmware supports a couple of commands: low res setting (8-bit like before) and high res setting (12-bit). For each of these, there is a subcommand to set either all LEDs on the board to be the same color or each LED separately.

The protocol is not very complicated: [cci]SYNC CMD ARG0 ARG1 … ARGn[/cci]

[cci]SYNC[/cci] is now [cci]0x55[/cci] instead of [cci]0xAA[/cci]. I made this revision backwards compatible by making the command the old [cci]SYNC[/cci] command. That way, as long as you send the new [cci]SYNC[/cci] command before that (which would just get ignored by the old firmware), you can still control both firmwares at the same time. This is probably entirely unnecessary, but whatever. I thought it was cute.

I describe how the commands work in detail in the firmware README.

The high res commands pack 12-bit values into a series of bytes and then those values are unpacked in the firmware. The code is not super fast, but it’s not horrible either. I wish I could do some kind of hashing thing to speed up the unpacking process, but the memory requirements there would be ginormous.

The new command system isn’t the only thing that I added. One common failure mode in the past was that the voltage would sag causing the micro to stop running and then the LED drivers would go full brightness. The problem was that when you plugged the board back in, they would retain that state and it would happen all over again. I thought the fix was to just add a pull-up to the blank pin which is usually just controlled by the micro. This would prevent the pin from floating when the micro was browning out and would therefore shut the drivers off. However after I tested this fix out (BTW I forgot to solder one of the resistor pads down so I was very confused for a while why it wasn’t pulling up at all) the failure changed to just continually resetting the micro followed by a brief draw of high current and voltage sagging.

The problem turned out to be that I completely forgot to clear out the LED driver shift registers BEFORE starting them… just a totally stupid error on my part that’s been since fixed.

After I finished writing this new firmware, I used a little pre-processor magic to handle the hardware differences between the two board revisions. So, making with [cci]BRDREV=1[/cci] makes the project for the first revision and [cci]BRDREV=2[/cci] makes it for the second version. This allows me to have unified firmware.

I want to do a few more things with the firmware. E.g. I want to add some commands that would allow me to read the status of a board back on the bus. The hardware is now all there to do this and it would be good to know when the board is overheating. I could also add firmware-side brightness limiting when overheating occurs. I also need to finish the bootloader at some point — it still lacks a mechanism for verification.

After getting everything running, I finally was able to solve the question that had been bothering me the most: would my board be able to sustain 5.4A, the maximum current for all channels?

For this test, I hooked up separate 5V for the logic and started the LED power voltage out low. I then told the LED controllers to output full brightness and started ramping up the voltage. Small problem: the resistive loss on the wire was sizable as the current draw grew. I had to get up to around 11V output to hit the correct voltage drop for the LEDs on the other side. Things got a little melty but I sustained this for almost a minute before turning it back down as I wasn’t heatsinking the drivers at all. The point is that the board itself could handle that kind of current… I feel like I actually designed something correctly for once. 🙂

Here is a list of the things that the new board revision fixes:

  • screw terminal option for LED outputs
  • if you don’t want to do that, then you can twist and solder the wires to the board securely
  • data direction pins on the RS485 chips have pull-ups on them to prevent multiple devices from trying to drive the bus on system startup
  • blank pin on the LED drivers has a pull-up on it to prevent the drivers from trying to drive the LEDs before the system has started sending data to them
  • power connectors have the right pin ordering
  • power planes reduce noise and can handle the full current rating of the drivers
  • error pins of the tlc are brought back to the micro in order to read thermal errors
  • cleaner routing
  • board fits within iteadstudio’s 10cm x 10cm $35 color soldermask option

I’m planning on doing one minor revision to the board to address these problems:

  • power connector + slot is too small
  • soldermask accidentally applied over the back terminals
  • some silkscreening is illegible

I probably won’t ever order that revision unless I somehow need more LED controllers for something. Maybe an externally-funded project? Hopefully?