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 (J4).

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.

Board with assembled power supplies.
Assembled supplies before testing.

 

Some ICs on perfboard with four wires leaving the board, labeled "GND", "PWM IN", "+9V", and "FET IN".
FET driver bodge assembled on perfboard. Connections are annotated.

Chainloading Truecrypt

I recently purchased a new laptop computer (a Lenovo Thinkpad T520), and wanted to configure it to dual-boot between Windows and Linux.  Since this machine is to be used “on the go”, I also wanted to have full encryption of any operating systems on the device. My choices of tools for this are Truecrypt on the Windows side, and dm_crypt with LUKS on Linux. Mainly due to rather troublesome design on the Windows side of this setup, it was not as easy as I might have hoped. I did eventually get it working, however.

Admonishment

Truecrypt was “Discontinued” in 2014, but still works okay. VeraCrypt is substantially a drop-in replacement if you’re looking for a piece of software that is still actively maintained. As of this update (early 2017) the only non-commercial option for an encrypted Windows system booted from UEFI is Windows’ native BitLocker (with which dual-booting is possible but it won’t be possible to read the encrypted Windows partition from Linux), but if you’re booting via legacy BIOS these instructions should still work for TrueCrypt or VeraCrypt.

Windows

Installing Windows on the machine was easy enough, following the usual installation procedure. I created a new partition to install Windows to filling half of the disk, and let it do its thing. Downloading and installing Truecrypt is similarly easy. From there, I simply chose the relevant menu entry to turn on system encryption.

The first snag appeared when the system encryption wizard refused to continue until I had burned an optical disk containing the recovery information (in case the volume headers were to get corrupted). I opted to copy the iso file to another location, with the ability to boot it via grub4dos if necessary in the future (or merely burn a disc as necessary). The solution to this was to re-invoke the volume creation wizard with the noisocheck option:

C:\Program Files\TrueCrypt>TrueCrypt Format.exe /noisocheck

One reboot followed, and I was able to let TrueCrypt go through and encrypt the system. It was then time to set up Linux.

Linux

Basic setup of my Linux system was straightforward. Arch (my distribution of choice) offers good support for LUKS encryption of the full system, so most of the installation went smoothly.

On reaching the bootloader installation phase, I let it install and configure syslinux (my loader of choice simply because it is easier to configure than GRUB), but did not install it to the MBR. With the installation complete, I had to do some work to manually back up the MBR installed by Truecrypt, then install a non-default MBR for Syslinux.

First up was backing up the Truecrypt MBR to a file:

# dd if=/dev/sda of=/mnt/boot/tc.bs count=1

That copies the first sector of the disk (512 bytes, containing the MBR and partition table) to a file (tc.bs) on my new /boot partition.

Before installing a Syslinux MBR, I wanted to ensure that chainloading the MBR from a file would work. To that end, I used the installer to chainload to my new installation, and used that to attempt loading Windows. The following incantation (entered manually from the syslinux prompt) eventually worked:

.com32 chain.c32 hd0 1 file=/tc.bs

Pulling that line apart, I use the chainloader to boot the file tc.bs in the base of my /boot partition, and load the first partition on my first hard drive (that is, where Windows is installed). This worked, so I booted once more into the installer to install the Syslinux MBR:

# dd if=/usr/lib/syslinux/mbr.bin of=/dev/sda bs=1 count=440 conv=notrunc

This copies 440 bytes from the given file to my hard drive, where 440 bytes is the size of the MBR. The input file is already that size so the count parameter should not be necessary, but one cannot be too careful when doing such modification to the MBR.

Rebooting, that, sadly, did not work. It turns out that the Syslinux MBR merely scans the current hard drive for partitions that are marked bootable, and boots the first one. The Truecrypt MBR does the same thing, which is troublesome– in order for Truecrypt to work the Windows partition must be marked bootable, but Syslinux is unable to find its configuration when this is the case.

Enter albmbr.bin. Syslinux ships several different MBRs, and the alternate does not scan for bootable partitions. Instead, the last byte of the MBR is set to a value indicating which partition to boot from. Following the example from the Syslinux wiki (linked above), then, I booted once more from my installer and copied the altmbr into position:

# printf 'x5' | cat /usr/lib/syslinux/altmbr.bin - | dd bs=1 count=440 conv=notrunc of=/dev/sda

This shell pipeline echoes a single byte of value 5, appends it to the contents of altmbr.bin, and writes the resulting 440 bytes to the MBR on sda. The 5 comes from the partition Syslinux was installed on, in this case the first logical partition on the disk (/dev/sda5).

With that, I was able to boot Syslinux properly and it was a simple matter to modify the configuration to boot either Windows or Linux on demand. Selected parts of my syslinux.cfg file follow:

UI menu.c32

LABEL arch
    MENU LABEL Arch Linux
    LINUX /vmlinuz-linux
    APPEND root=/dev/mapper/Homura-root cryptdevice=/dev/sda6:HomuHomu ro
    INITRD /initramfs-linux.img

LABEL windows
    MENU LABEL Windows 7
    COM32 chain.c32
    APPEND hd0 1 file=/tc.bs

Further resources

For all things Syslinux, the documentation wiki offers documentation sufficient for most purposes, although it can be somewhat difficult to navigate. A message from the Syslinux mailing list gave me the key to making Syslinux work from the MBR. The Truecrypt documentation offered some interesting information, but was surprisingly useless in the quest for a successful chainload (indeed, the volume creation wizard very clearly states that using a non-truecrypt MBR is not supported).

Rewriting SPD

I recently pulled a few SDR (133 MHz) SO-DIMMs out of an old computer.  They sat on my desk for a few days until I came up with a silly idea for something to do with them: rewrite the SPD information to make them only semi-functional- with incorrect timing information, the memory might work intermittently or not at all.

Background

A SO-DIMM.
My sacrificial SO-DIMM.

Most reasonably modern memory modules have a small amount of onboard persistent memory to allow the host (eg your PC) to automatically configure it.  This information is the Serial Presence Detect, or SPD, and it includes information on the type of memory, the timings it requires for correct operation, and some information about the manufacturer.  (I’ve got a copy of the exact specification mirrored here: SPDSDRAM1.2a.)  If I could rewrite the SPD on one of these DIMMs, I could find values that make it work intermittently or not at all, or even report a different size (by modifying the row and column address width parameters).

The SPD memory communicates with the host via SMBus, which is compatible with I2C for my purposes.

The job

Pad Signal
140 VSS (ground)
141 SDA (I2C data)
142 SCL (I2C clock)
143 VCC (+5 Volts)

The hardest part of this quest was simply connecting wires to the DIMM in order to communicate with the SPD ROM.  I gutted a PATA ribbon cable for its narrow-gauge wire and carefully soldered them onto the pads on the DIMM.  Per information at pinouts.ru, I knew I needed four connections, given in the table to the left.

Wires soldered to pads on a SO-DIMM with hot glue on top.
Soldering closeup. Tenuous connections led me to put globs of glue on top to hold everything together.

Note that the pads are labeled on this DIMM, with pad 1 on the left side, and 143 on the right (the label for 143 is visible in the above photo), so the visible side of the board in this photo contains all the odd-numbered pads.  The opposite side of the board has the even-numbered ones, 2-144.  With the tight-pitch soldering done, I put a few globs of hot glue on to keep the wires from coming off again.

DIMM with wires connected to headers on another circuit board.
Connections between the DIMM and Bus Pirate.

With good electrical connections to the I2C lines on the DIMM, it became a simple matter of powering it up and trying to communicate.  I connected everything to my Bus Pirate and scanned for devices:

I2C>(1)
Searching 7bit I2C address space.
Found devices at:
0x60(0x30 W) 0xA0(0x50 W) 0xA1(0x50 R)
I2C>

The bus scan returns two devices, with addresses 0x30 (write-only) and 0x50 (read-write).  The presence of a device with address 0x50 is expected, as SPD memories (per the specification) are always assigned addresses in the range 0x50-0x57.  The low three bits of the address are set by the AS0, AS1 and AS2 connections on the DIMM, with the intention that the host assign different values to these lines for each DIMM slot it has.  Since I left those unconnected, it is reasonable that they are all low, yielding an address of 0x50.

A device with address 0x30 is interesting, and indicates that this memory may be writable.  As a first test, however, I read some data out to verify everything was working:

I2C>[0xa0 0][0xa1 rrr]
I2C START CONDITION
WRITE: 0xA0 ACK
WRITE: 0 ACK
I2C STOP CONDITION
I2C START CONDITION
WRITE: 0XA1 ACK
READ: 0x80 ACK
READ: 0x08 ACK
READ: 0x04 ACK

I write 0 to address 0xA0 to set the memory’s address pointer, and read out the first three bytes.  The values (0x80 0x08 0x04) agree with what I expect, indicating the memory has 128 bytes written, is 256 bytes in total, and is type 4 (SDRAM).

Unfortunately, I could only read data out, not write anything, so the ultimate goal of this experiment was not reached.  Attempts to write anywhere in the SPD regions were NACKed (the device returned failure):

I2C>[0xA0 0 0]
I2C START CONDITION
WRITE: 0xA0 ACK
WRITE: 0 ACK
WRITE: 0 NACK
I2C STOP CONDITION
I2C>[0x50 0 0]
I2C START CONDITION
WRITE: 0x50
WRITE: 0 ACK
WRITE: 0 NACK
I2C STOP CONDITION

In the above block, I attempted to write zero to the first byte in memory, which was NACKed.  Since that failed, I tried the same commands on address 0x30, with the same effect.

With that, I admitted failure on the original goal of rewriting the SPD.  A possible further attempt to at least program unusual values to a DIMM could involve replacing the EEPROM with a new one which I know is programmable.  Suitable devices are plentiful- one possible part is Atmel’s AT24C02C, which is available in several packages (PDIP being most useful for silly hacks like this project, simply because it’s easy to work with), and costs only 30 cents per unit in small quantities.

SSL enabled

I just enabled SSL on this site in a fit of paranoia. It shouldn’t cause any problems, but please let me know if you notice something that’s broken. Normal browsing shouldn’t be affected, but site login is forced to SSL. My (self-signed) certificate has SHA1 fingerprint 6c:e4:77:91:e8:59:f8:d1:fd:ea:cf:87:6b:af:ce:3b:19:be:fa:b5.

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 the 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.

Static libpng on win32 with CMake

Working on mkg3a upgrades for libpng more, I was getting unusual crashes with the gnuwin32 libpng binaries (access violations when calling png_read_int()).  It turned out that the libpng dll was built against an incompatible C runtime, so I had to build static libraries.  With the official libpng source distribution (and zlib), building static libraries was reasonably easy.  Using the MSVC make tool in the libpng source tree, I first had to build zlib. The default build (for some reason) doesn’t build the module containing _inflate_fast, so I had to add inffast.obj to the OBJS in zlib/win32/Makefile.msc (this manifested as an unexported symbol error when linking a program against zlib). Building it then was easy, using nmake in the Visual Studio toolkit:

zlib-1.2.5> nmake -f win32/Makefile.msc

With zlib built, copy zlib.h and zlib.lib out of the source directory and into wherever it will be used.

For libpng, we first have to modify the makefile, since the one included uses unusual options. Change CFLAGS to read CFLAGS=/nologo /MT /W3 -I..zlib for some sane options. The include path also needs to be updated to point to your zlib.h. In my case, that makes it -I..include. The rest of the procedure for building libpng is very similar to that for zlib:

lpng158> nmake -f scripts/Makefile.msc

Building against libpng then requires png.h, pngconf.h, pnglibconf.h and png.lib. To build against these libraries, I simply put the include files in an ‘include’ directory, the .lib files in a ‘lib’ directory, and pointed cmake at it.

Warnings about runtime libraries when linking a program against these static libraries is an indication that you’ll probably see random crashes, since it means theses static libraries are using a different version of the runtime libraries than the rest of your program. I was this problem manifested as random heap corruption. Changing CFLAGS (in the makefiles) to match your target configuration as set in Visual Studio and rebuilding these libraries will handle that problem.

Ika Okonomiyaki

I cooked a bit of an experiment tonight: okonomiyaki with squid.  Preparing the squid took a long time, but I was very pleased with how it turned out in the end.

To prepare the squid, simply pull to separate the body from the head.  Most of the innards will stay attached to the head.  Chop the tentacles off just below the eyes, and remove any tough bits (beak maybe) from the inner ring on the tentacles.  Remove the pen (which keeps the squid from flopping about while alive) from the body and slice into rings.  Clean any remaining guts out of the rings.  For cooking the squid, I put it over medium-high heat for between 20 and 25 minutes.  Added a fair amount of soy sauce throughout.

The pancake batter was approx. 2 cups of flour, 1.25 cups of water, 4 eggs, and a fair amount of finely chopped cabbage.  Doing it again, I would err towards chopping the cabbage to finely, since the larger pieces were a bit odd.  Preparing the pancakes was as simple as cooking them on the griddle until no longer gooey.

Final assembly consisted of topping a pancake with mayonnaise and some stir fry sauce (I didn’t have any real okonomiyaki sauce, but my stir-fry sauce worked well as a substitute).  Some chopped green onion on top of that, then top with the squid.  Some pineapple on the side helped offset the assault of savory flavors from everything else with a bit of sweetness.

Gallery

High-availability /home revisited

About a month ago, I wrote about my experiments in ways to keep my home directory consistently available. I ended up concluding that DRBD is a neat solution for true high-availability systems, but it’s not really worth the trouble for what I want to do, which is keeping my home directory available and in-sync across several systems.

Considering the problem more, I determined that I really value a simple setup. Specifically, I want something that uses very common software, and is resistant to network failures. My local network going down is an extremely rare occurence, but it’s possible that my primary workstation will become a portable machine at some point in the future- if that happens, anything that depends on a constant network connection becomes hard to work with.

If an always-online option is out of the question, I can also consider solutions which can handle concurrent modification (which DRBD can do, but requires using OCFS, making that solution a no-go).

Rsync

rsync is many users’ first choice for moving files between computers, and for good reason: it’s efficient and easy to use.  The downside in this case is that rsync tends to be destructive, because the source of a copy operation is taken to be the canonical version, any modifications made in the destination will be wiped out.  I already have regular cron jobs running incremental backups of my entire /home so the risk of rsync permanently destroying valuable data is low.  However, being forced to recover from backup in case of accidental deletions is a hassle, and increases the danger of actual data loss.

In that light, a dumb rsync from the NAS at boot-time and back to it at shutdown could make sense, but carries undesirable risk.  It would be possible to instruct rsync to never delete files, but the convenience factor is reduced, since any file deletions would have to be done manually after boot-up.  What else is there?

Unison

I eventually decided to just use Unison, another well-known file synchronization utility.  Unison is able to handle non-conflicting changes between destinations as well as intelligently detect which end of a transfer has been modified.  Put simply, it solves the problems of rsync, although there are still situations where it requires manual intervention.  Those are handled with reasonable grace, however, with prompting for which copy to take, or the ability to preserve both and manually resolve the conflict.

Knowing Unison can do what I want and with acceptable amounts of automation (mostly only requiring intervention on conflicting changes), it became a simple matter of configuration.  Observing that all the important files in my home directory which are not already covered by some other synchronization scheme (such as configuration files managed with Mercurial) are only in a few subdirectories, I quickly arrived at the following profile:

root = /home/tari
root = /media/Caring/sync/tari

path = incoming
path = pictures
path = projects
path = wallpapers

Fairly obvious function here, the two sync roots are /home/tari (my home directory) and /media/Caring/sync/tari (the NAS is mounted via NFS at /media/Caring), and only the four listed directories will be syncronized. An easy and robust solution.

I have yet to configure the system for automatic syncronization, but I’ll probably end up simply installing a few scripts to run unison at boot and when shutting down, observing that other copies of the data are unlikely to change while my workstation is active.  Some additional hooks may be desired, but I don’t expect configuration to be difficult.  If it ends up being more complex, I’ll just have to post another update on how I did it.

Update Jan. 30: I ended up adding a line to my rc.local and rc.shutdown scripts that invokes unison:

su tari -c "unison -auto home"

Note that the Unison profile above is stored as ~/.unison/home.prf, so this handles syncing everything I listed above.