2016-04-28

IPython Notebook on GPS Timing and CDMA


In [1]:
%matplotlib inline

import matplotlib
import numpy as np
import matplotlib.pyplot as plt


GPS Timing

Carrier-phase detection is suppose to yield better timing information than tracking the pseudorandom code stream. The reason for this is supposedly that the higher frequency carrier allows for more accurate measurements of the mismatch between the generated pseduorandom code stream and the broadcasted one. This increase in accuracy comes from sharper peaks in the autocorrelation function.
Lets try this out:

In [2]:
def corr(npoints, repeat):
    A = np.random.randint(0, 2, npoints)
    A = np.repeat(A, repeat)

    xcor = np.correlate(A, A, mode='same')
    plt.figure()
    N = len(A)
    offvec = np.arange(0, N)-N/2
    print offvec.size, xcor.size
    plt.plot(offvec, xcor, 'x-')


    

# generate 5 points each repeating 20 times, a slow signal    
corr(5,20)

# a much faster signal
corr(100,1)




100 100
100 100










It is clear that if you were trying to figure out the sample delay, you are much better off with the faster signal because the it is very obvious when you have the timing right. With the slower signal, you can be a little wrong and still get within a few pc of the correct correlation value.

Code Division Multiplexing

Try out CDM for myself. It is important that -1,1 is used instead of 0,1 because multiplying by 0 is always 0.

In [3]:
def gen_code(N):
    """
    Generatea a random array containing -1 and 1 of size N
    """
    out = np.random.randint(0, 2, N)
    out *= 2
    out -= 1
    return out
    
def code_modulate(signal, stretch=5, carrier=None):
    signal = np.repeat(signal, stretch)
    if carrier is None:
        carrier = gen_code(len(signal))
    
    return np.multiply(signal, carrier), carrier

sig_1 = gen_code(100)
sig_2 = gen_code(100)

out_1, c_1 = code_modulate(sig_1)

# generate an orthogonal array by flipping every other element
c_2 = np.array(c_1)
c_2[::2] = -1*c_1[::2]
out_2, _ = code_modulate(sig_2, carrier=c_2)

out_comb = out_1 + out_2

def plot_sig(s, title=''):
    plt.figure()
    plt.stem(s)
    plt.ylim([min(s)-0.5, max(s)+0.5])
    plt.title(title)
    
plot_sig(sig_1, 'sig_1')
plot_sig(sig_2, 'sig_2')
plot_sig(out_comb, 'combined output')

















In [6]:
def code_demodulate(signal, carrier, stretch=5):
    y = np.multiply(signal, carrier)
    ysubs = np.split(y, len(y)/5)
    ysubs = map(sum, ysubs)
    ysubs = map(lambda x:max(-1, x), ysubs)
    ysubs = map(lambda x:min(1, x), ysubs)    
    return ysubs

x = code_demodulate(out_comb, c_1)
plot_sig(x, 'sig_1 recovered')
plot_sig(sig_1, 'sig_1 expected')

x = code_demodulate(out_comb, c_2)
plot_sig(x, 'sig_2 recovered')
plot_sig(sig_2, 'sig_2 expected')





















Perfect.

In [ ]:



2016-04-17

Arduino-MK with Sparkfun Pro Micro 3.3V

Arduino-Makefile needed coaxing to in order to compile code targeting the SparkFun Pro Micro 3.3V. A major source of headache is the requirement for BOARD_SUB which isn't documented and required diving into the source code, and also the fact the Pro Micro has 2 PIDs for each variant (5V and 3.3V).

Hope this will help someone in the same position as me. This makefile is meant for use on Debian Linux, with Arduino-MK installed via apt-get install arduino-mk.

MONITOR_PORT = /dev/ttyACM0

# this should point to where the sparkfun board definitions are installed
SPF_AVR_PATH = $(HOME)/.arduino15/packages/SparkFun/hardware/avr/1.1.3

# Use own arduino install which is way more advanced than the default 1.0
# installed by arduin-core
ARDUINO_DIR = $(HOME)/arduino-1.6.7

USER_LIB_PATH := $(HOME)/Arduino/libraries

# this is needed to stdint.h exposes needed #defines
CPPFLAGS += -std=gnu++11 

# this is needed so we don't run into __cxa_guard_acquire issues
CPPFLAGS += -fno-threadsafe-statics 


BOARD_TAG          = promicro
BOARD_SUB      = 8MHzatmega32U4
# also Arduino-mk isn't clever enough yet to properly extract PID from
# boards.txt, so we specify it here for now
USB_PID       = 0x9204
ALTERNATE_CORE    = promicro8
ALTERNATE_CORE_PATH = $(SPF_AVR_PATH)
BOOTLOADER_PATH    = caterina
BOOTLOADER_FILE    = Caterina-promicro8.hex
ISP_PROG           = usbasp


include /usr/share/arduino/Arduino.mk

Cheers,
Steve

2016-04-13

Method Forwarding in Objective-C Pitfall

A common pitfall of trying to use message forwarding in Objective-C is forgetting to implement

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

in addition to

- (void)forwardInvocation:(NSInvocation *)anInvocation

Another problem is that sometimes calling objects will use

- (BOOL)respondsToSelector:(SEL)aSelector

to determine if your proxy object can respond to a particular selector. The problem is that even if you forward that selector, because the message isn't actually sent, the default implementation of respondsToSelector will return NO, causing the forwarding to fail. Therefore you should also override respondsToSelector.

Cheers,
Steve

2016-03-23

Permission Denied When Programming Arduino Micro/SparkFun Pro Micro

I recently started having trouble with Arduino 1.6.x not being able to program Arduino Micro or SparkFun Pro Micro, with avrdude complaining about permission denied when trying to open /dev/ACM0.

The usual solutions to this is to add oneself to the dialup group, or mess around in /etc/udev/rules.d/99-arduino.rules.

None of these worked for me. However Arduino is able to program the micros fine if I run it as root, which clued me into that fact that there is some finite time between the kernel creating /dev/ttyACM0 and udev rules having effect. Specifically, udevd is a userspace daemon, and therefore necessary runs sometime after the kernel as created the relevant device node.

The problem is thus: Arduino IDE opens /dev/ttyACM0 at 1200bps and immediately closes it. This is causes the ATmega32u4 to reset itself, causing the serial port to disappear. When the bootloader runs, it presents itself as a usb-serial device, and /dev/ttyACM0 appears again. Reappearance of /dev/ttyACM0 causes the Arduino IDE to launch avrdude, which immediately tries to open /dev/ttyACM0 and fails because udev hasn't had time to process all the rules and assign the correct permissions etc.

The solution then is to introduce a delay before running avrdude, or even better, let udev let us known when it is done, which is much more robust. This can be done using

udevadm settle -t 1

Which waits for the udev to "settle", and the -t 1 specifies a maximum wait time of 1 second.

I hit upon the idea of wrapping avrdude in a shellscript and then adding the above line before avrdude, and that was when I discovered that hardware/tools/avr/bin/avrdude is already a shellscript! This made things much easier. 

My Arduino IDE's avrdude script now looks like:

$ cat hardware/tools/avr/bin/avrdude
#!/bin/bash

udevadm settle -t 1

export LD_LIBRARY_PATH="`dirname "$0"`/../lib/"
exec -a "$0" "`dirname "$0"`/avrdude_bin" "$@"

Programming of Arduino Micro and SparkFun Pro Mini is now flawless under Xubuntu 15.10.

Cheers,
Steve

Thinkpad Mute Buttons and Xubuntu

I recently acquired a used Lenovo X220 for use as a linux laptop, and needed the following in my openbox configuration XML to make the hardware speaker and mic mute buttons work:

  <!-- Modified for X220 -->
  <keybind key="XF86AudioMute">
    <action name="Execute">
      <command>pactl set-sink-mute 0 toggle</command>
    </action>
  </keybind>
  <keybind key="XF86AudioMicMute">
    <action name="Execute">
      <command>pactl set-source-mute 1 toggle</command>
    </action>
  </keybind>

Sources and sinks can be discovered using:

pactl list sources
pactl list sinks

For me there was only one sink, and two sources, the first of which is some kind of virtual source that monitors the microphone, while the second source is the microphone itself.

Something that is interesting is that both speaker and mic mute buttons have a central light that lights up when mute is active, and this seems tied to the hardware. This makes me trust that when the mute buttons are used they actually do something.

Hope this helps some people.

2016-03-02

Notes on Migrating a Linux Install

Some issues I ran into when trying to move a Linux install from a 500 GB drive to a smaller 120 G SSD:


  • When duplicating the filesystem, make sure that /proc exists, otherwise when you boot the new drive the kernel will complaint that /proc is missing and it can't create the virtual file system
  • In grub-rescue, (hd0,msdos2) is /dev/sda2, and (hd0,msdos1) is /dev/sda1
  • When specifying initrd be sure not to accidentally select the vmlinuz image again
  • After you have fixed grub and find that booting is taking longer than expected, check that the UUID in /etc/initramfs-tools/conf.d/resume is the UUID of your swap partition. Check using sudo blkid