Blog

Adjust Xfig figure depths with figdepth

John Peck
Published

Xfig's depth settings can create some headaches when you use figure libraries. Library figures can use depths that conflict with your current drawing. Say I have this drawing of the Teensy Audio Board and a red circle,

Teensy audio board and a red circle

...and then I move the red circle over the board:

Overlapping objects without depth correction

This is clearly not what I want. The circle has a depth of 50, and the board has depths between 10 and 60. The circle ends up on top of some objects and not others. If you were using PowerPoint, you would just select Bring to Front or Send to Back to arrange the objects. But Xfig requires setting the depth of each member object individually, which you should really do with a script like figdepth.

Using figdepth

Figdepth has some options, the most important of which is the minimum depth argument

Figdepth command options

...which sets the depth of the topmost object in a fig file. The script simply increments all depths by some number to make this minimum depth to be your setting. You will, of course, need to have everything you want to modify in its own fig file. You can then run figdepth like

Figdepth use

...to write your new depth-adjusted figure. Use Xfig's merge command to bring the new figure into your old drawing. My new drawing looks like this:

Fixed overlap

...with all objects in the Teensy Audio Board at a deeper depth than the red circle.

How does it work?

The Fig file format is really simple, which is one reason why I like Xfig so much. You can figure out what kind of object each line describes by looking at the first character. You then figure out which number in the line is the object's depth and increment it. The switch statement below shows how one line is processed.

proc increase_object_depth { xfig_line depth_increase} {
    # Return a new xfig line with the depth increased
    #
    # Arguments:
    #   xfig_line -- Single line from an xfig file
    #   depth_increase -- Amount to increase the depth
    set entry_list [split $xfig_line]
    set first_character [lindex $entry_list 0]
    switch $first_character {
    "0" {
        # Color object -- nothing to do
        return $xfig_line
    }
    "1" {
        # Ellipse
        set depth_index 6
        set old_depth [get_object_depth $xfig_line]
        set new_depth [expr $old_depth + $depth_increase]
        set new_entry_list [lset entry_list $depth_index $new_depth]
        set new_line [join $new_entry_list]
        return $new_line
    }
    "2" {
        # Polyline (also imported picture bounding boxes)
        set depth_index 6
        set old_depth [get_object_depth $xfig_line]
        set new_depth [expr $old_depth + $depth_increase]
        set new_entry_list [lset entry_list $depth_index $new_depth]
        set new_line [join $new_entry_list]
        return $new_line
    }
    "3" {
        # Spline
        set depth_index 6
        set old_depth [get_object_depth $xfig_line]
        set new_depth [expr $old_depth + $depth_increase]
        set new_entry_list [lset entry_list $depth_index $new_depth]
        set new_line [join $new_entry_list]
        return $new_line
    }
    "4" {
        # Text
        set depth_index 3
        set old_depth [get_object_depth $xfig_line]
        set new_depth [expr $old_depth + $depth_increase]
        set new_entry_list [lset entry_list $depth_index $new_depth]
        set new_line [join $new_entry_list]
        return $new_line
    }
    "5" {
        # Arc
        set depth_index 6
        set old_depth [get_object_depth $xfig_line]
        set new_depth [expr $old_depth + $depth_increase]
        set new_entry_list [lset entry_list $depth_index $new_depth]
        set new_line [join $new_entry_list]
        return $new_line
    }
    "6" {
        # Compound -- nothing to do
        return $xfig_line
    }
    default {
        # Some non-object -- nothing to do
        return $xfig_line
    }
  }
}

Having trouble with cmdline?

Figdepth uses the cmdline package from tcllib to handle command line arguments. I usually run scripts out of Eshell in Emacs, so I have this in my .emacs:

eshell setup

...to set the TCLLIBPATH environment variable. This tells Tcl where to find Tcllib's packages.

Where is the figdepth script?

Figdepth is part of my xfigart repository.

Making Vpp and Vrms units in LaTeX with siunitx

John Peck
Published

The siunitx package for LaTeX makes it easy to handle units in both normal and math modes. I end up needing units like Vrms when talking about electronics, so I add this in my preamble:

\usepackage{siunitx}

\DeclareSIUnit \vrms {\ensuremath{\mathrm{V_{rms}}}}
\DeclareSIUnit \vpp {\ensuremath{\mathrm{V_{pp}}}}

...to define these units to siunitx. I can then invoke the units with something like

free air.  I drove them to about \SI{9}{\vpp}.

where I know siunitx will then make the proper space between the number and the unit. This all renders like this:

Vpp rendered to pdf

...in the PDF output.

Mounting the Teensy 4.0 on its Audio Adaptor Board

John Peck
Published

I've been wanting to experiment with audio signal processing on the Teensy, so I bought a Teensy 4.0 and an Audio Adaptor Board. I had to do a bit of research to find the right headers to plug one board into the other. I ended up with the headers listed below.

Samtec part Digi-Key part
SSQ-114-03-T-S SAM1206-14-ND

I used these headers in the photo shown below.

Teensy 4.0 on Audio Adaptor

A cheap 4-channel 0 โ†’ 10V output with Tcl and MODBUS

John Peck
Published

I've been interested in fieldbusses lately, and MODBUS in particular is used by some pretty cheap hardware modules. It also offers "driverless" communication โ€” you don't need a .dll or .so file to talk to your hardware. The hardware I've been experiementing with is shown below:

Hardware overview

...and can be bought from eBay for around 50 USD. I found some very useful code on the Tcl wiki and was able to write and read from registers with a USB/RS-485 adaptor. The RTU-307C user's manual implies that you can change the RS-485 baud from 9600, but I wasn't able to figure out how that works.

After some more help from The Tcler's Wiki, I put together a GUI to demonstrate MODBUS communication with the RTU-307C module. The animation below shows the GUI next to an oscilloscope (yelloscope) display. The wiki helped me get the mouse wheel to move those sliders.

Elliot with Yellowscope

Links

Source: Repository on Gitlab

Prevent ATMega328P crashes with a stack monitor

John Peck
Published

The ATmega328P is used on the Arduino UNO, the Nano, and on many other mass-produced microcontroller boards. But it has only 2048 bytes of SRAM, which is shared between the stack and storage for things like local variables. Bizarre behavior can happen if the SRAM needed for variable storage overlaps that needed for the stack, but it's hard to understand how much space these variables will use until the program is actually running. This is where Michael McTernan's stack monitor is useful.

The stack monitor "paints" SRAM storage registers with a magic value before application code executes. You can then check for unused stack memory during execution by counting up these magic values. Here's some debug output from my Diamond firmware running on the EVL-510:

debug trace

The unused SRAM is initially 200 bytes, but falls to 179 after turning the volume knob. Changing the volume calls a few functions that allocate local variables in SRAM. These get cleaned up when the function exits, but the stack monitor can see that the memory was used. The idea is to exercise as much of the system as you can and then make sure you still have some unused memory.

I call the function with a scheduler made from avr-simple-scheduler. The code block below shows adding the stack reporting function to the scheduler with a period of 5s. I could have made this even longer, since I only need the report to run after I've excercised as much as I can.

if (strcmp( LOG_LEVEL, "debug" ) == 0) {
    // Start the task to monitor free memory
    OS_TaskCreate(&system_report_stack_free, 5000, BLOCKED);
}

EVL-510: First look

John Peck
Published

This desktop speaker turned out well, and I asked Jack at Prime Images Photography to take some real product photos. There's lots of interesting stuff here, including the volume knob's state machine and some handy prototyping tools from Mikroe. I'll get into these in some later posts.

EVL-510 hero shot

EVL-510 rear panel

Yelloscope: Fork of Syscomp Design's CGR-201 software

John Peck
Published

I have a few devices from Syscomp Electronic Design that I use for experimenting and debugging. The CGR-201, shown below, is one of these.

CGR-201 ISO

Syscomp sadly lost one of its founders, Peter Hiscocks, and won't be releasing any new products. I forked their CircuitGear software (screenshot below) to make some of the changes I wanted, and to start packaging the software as single-file executables for Linux. My fork is here:

https://gitlab.com/eventuallabs/yelloscope

...and you can download single-file executable releases here:

https://gitlab.com/eventuallabs/yelloscope/-/releases

screenshot

A note about running the software

You can always run from source with

tclsh main.tcl

in the src directory. But you'll need Tcl, Tk, and some helper packages. The single-file executable release contains all of these.

Once you download the executable, you'll have to give yourself permission to run it with something like

chmod a+x yelloscope-1.0.0-linux-x86_64

and your user will have to be in the right group for the software to access the hardware. For me, on Ubuntu, this group is dialout. I added myself to the group with

sudo adduser john dialout

...and then I had to reboot.

A note on making Starpacks

Starkits and Starpacks are ways of packaging Tcl programs to reduce or eliminate dependencies. The makefile in the Yelloscope repository shows how I automate creating Linux starpacks from Tcl sources. It's customized for my environment though, and you'll have to change some paths to make it work. I'll be happy to help if you reach out.

Xfigart: Oscilloscope probe

John Peck
Published

This is a generic oscilloscope probe from the xfigart library. Get the source for this and many other images by cloning or downloading the library.

xfigart pic

Fix Xfig's landscape postscript output for printing

John Peck
Published

It's important to get the page orientation correct if you think your Xfig output might ever be printed. I was trying to make a cable drawing inside a titleblock with Xfig. The postscript output viewed by qpdfview is shown below.

raw ps output

You can see that this will never print properly, and the ps2pdf command simply gives you a pdf version of the same problem. Ghostscript's ps2write device can fix the orientation with:

gs -dSAFER -dBATCH -sDEVICE=ps2write -dNOPAUSE -sOutputFile=out.ps xfig_input.ps

where the other command-line options are documented here. This produces the output below:

fixed ps output

...which can be converted to pdf and printed.