Jeff Epler's blog

28 July 2018, 13:19 UTC

GPSDO: An attempt that is too simple

Since I have all the components—a GPS timesource, a voltage controlled OCXO, and a microcontroller with some DACs—I thought I'd try to make a simple GPS Disiplined Oscillator.

read more…

24 July 2018, 2:18 UTC

keyestudio gps shield as frequency counter

Superficially similar to the elecrow GPS shield at the time of writing it's available from ebay for around $20.

I chose this model because it has a ublox GPS module and a header with signals marked "GP" and "EX". EX should be external interrupt, and it opens the possibility of a simple GPS-disciplined frequency counter.

It comes with a small antenna, short cable. One of those godawful laptop style connectors, and no provision for directly soldering a better one. Sigh.

read more…

15 July 2018, 15:59 UTC

Fun with frequency

I've been playing around with frequency sources and generators. Related bits include:

Nothing earth shattering or super fancy, but it is still pretty amazing to be able to heat or cool the AD9850's (non-compensated) XO and see the digital frequency meter change. And it was gratifying to find that the OCXO can be tuned quite easily to 10,000,000MHz.

The PLJ frequency counter is adequate to its task. Supposedly it has a VC-TCXO, and while it has just a single turn adjustment for frequency, I was able to get it to consistently read 10,000,000MHz from OCXO and from GPS; the next day, it had drifted down to 9,999,999. Still, that's down in the .1ppm and is probably to be expexcted.

I found that when tuning the OCXO, it was much more useful to use the scope to visualize the changing relative phases of the two signals, than to use this particular frequency meter which needs a 1s gate time to measure a 10MHz signal at a precision of 1Hz, and can't do anything more precise than that.

To tune the OCXO, I set the GPS-referenced RF generator to 10MHz and hooked both up to the scope. With a time base of 100ns and a persistence of 10s, it's not only easy to fine tune the circuit, but a hand-wave estimate of the error by looking at the persisted signal. If it's 1 div wide, then the relative error between the two frequencies is 100ns/10s = 10ppb = 10 milliHz @ 10MHz.

The scope has a 1kHz signal for probe compensation and it also includes the signal generator option. To my surprise, the frequency error of the probe compensation was MUCH smaller than the frequency error of the signal generator!


30 April 2018, 22:42 UTC

All integers 0 through 1,000,000 from short, digitless dc programs

I now have solutions for all the numbers in this range. The longest program required is 12 bytes. The final program found was for the number 966422: "BABAd*EC/C+n"

I consider the 23 characters " ~^-/*+|ABCDdEFIinOorvz", but prune all prefixes which are invalid due to stack underflow. 2312 is around 2.2×1016 or 254, but best guess my various programs have considered only around 5×1012 or 242 due to this pruning. Still, the process (including iteratively developing the search program) has taken several months!

What's next? I guess there's always the "fours puzzle", dc edition.

      4 4n
     10 In
      0 zn
     44 44n
      2 4vn
      1 4zn
      3 Ivn
    444 444n
      6 44vn
     40 4I*n

Files currently attached to this page:



23 April 2018, 2:50 UTC

Code size for bit reversing algorithms

I want to add support for "LSB first" to bitbang SPI in circuitpython. Probably the best way to do this is to optionally reverse the bits in each byte according to a flag setting.

Code space is always at a premium, so I investigated several code fragments for bit reversal to find out which was smallest on arm and xtensa. These code fragments are gathered from the internet. The loop is the smallest alternative on both architectures, but the 16-element look up table is not much bigger (on arm, the difference is bigger on xtensa) and is probably faster.

arm-none-eabi-gcc-7.2.1 -Os -mthumb

   text    data     bss     dec     hex filename
     40       0       0      40      28 bitrev_loop.o
     44       0       0      44      2c bitrev_lut16.o
     44       0       0      44      2c bitrev_shifts1.o
     44       0       0      44      2c bitrev_twiddle1.o

xtensa-lx106-elf-gcc-4.8.5 -Os

   text    data     bss     dec     hex filename
     40       0       0      40      28 bitrev_loop.o
     53       0       0      53      35 bitrev_lut16.o
     57       0       0      57      39 bitrev_shifts1.o
     52       0       0      52      34 bitrev_twiddle1.o

Files currently attached to this page:

bitrev_loop.c138 bytes
bitrev_lut16.c281 bytes
bitrev_shifts1.c193 bytes
bitrev_twiddle1.c178 bytes


26 March 2018, 23:51 UTC

Fuzz-testing CircuitPython

I've been hacking on CircuitPython lately. A lot of what I've done is fix bugs found by afl. Here's how to try it for yourself:

I recommend that you use a throwaway virtual machine for this, because at one point afl-fuzz learned how to create files in the filesystem! that was a big surprise, waking up to a directory full of filenames like "tesppppppppppppppppppppppppppppptfile"!

First, make sure you can build circuitpython's unix port. The steps are, approximately,

  1. Clone circuitpython
  2. git submodule update --init --recursive
  3. make -C ports/unix -j5 deplibs
  4. make -C ports/unix -j5
(you can review the .travis.yml file in the CircuitPython source tree for the packages they install on top of a regular Ubuntu system to get it building)

Note that the executable is ports/unix/micropython even when you have cloned circuitpython.

Next, get afl from If you can, follow the instructions in llvm_mode/README.llvm to get afl-clang-fast. Now, clean and rebuild:

  1. make -C ports/unix clean
  2. make -C ports/unix CC=/path/to/afl-clang-fast -j5 deplibs
  3. make -C ports/unix CC=/path/to/afl-clang-fast -j5
(If you couldn't use afl-clang-fast, then use CC=afl-clang or CC=afl-gcc)

Prepare the testcases directory for afl-fuzz. I used a number of tests from tests/basic:

  1. mkdir testcases
  2. cp tests/basics/*.py testcases

And start the fuzzer:

  1. /path/to/afl-fuzz -i testcases -o findings -- ports/unix/circuitpython

If you have any good findings, drop by the adafruit circuitpython discord and let us know about them! Even better if you fix them.


17 February 2018, 17:31 UTC

Watch Repairs

My friend, "Time Guy" Chris Radek has gotten back into the watch repair business! He writes:

After a 15-year break, I'm now accepting repair work again!

I do everything from routine cleaning and oiling (full disassembly and inspection, multi-stage ultrasonic cleaning, reassembly and correct oiling using appropriate modern synthetic oils, timing and adjustment as necessary) of automatic and manual-wind wrist and pocket watches to manufacture of unavailable parts for chronographs or repeaters.

I specialize in Accutron tuning fork watches and I have a large stock of parts and many years of experience working on them.

Please contact me and tell me how I can help you. If you are a collector I've previously worked for, I'd especially like to hear from you.

His work winding new coils for Accutron watches is particularly exciting; he tells me he's heard of just one other person doing this in the last 20 years. These particular watch parts are otherwise irreplacable.


10 February 2018, 2:58 UTC

Finding all numbers produced by short, digitless 'GNU dc' programs

Stream of consciousness updates: More bugs in my search program, found and excised. More, shorter numbers. Maybe all 10-character programs.

A few years ago, possibly in 2014, I saw this code golf problem, which invites you write a short program that prints "2014"—the caveat being, the program may not contain any digits in its source code.

read more…

6 August 2017, 2:26 UTC

poc: Python OCE Composer

12 July 2017, 14:34 UTC

MP Select Mini: Heated Bed Repair

19 March 2017, 20:16 UTC

Time Reversed Cosmology

All older entries
Website Copyright © 2004-2018 Jeff Epler