`hackrf-open`

. This delay was mainly because I had a shaky understanding of some of the Racket FFI concepts and functions, so I had to go back and relearn several things, especially relating to handling C pointers in Racket. Another thing that is interesting: In C you are expected to manually allocate and deallocate memory, and signal errors via an integer return value, whereas in Scheme we are expecting the memory management to happen automatically, with errors being signaled by exceptions, so there is some work to be done bridging between to two ideas.
Anyway, `hackrf-open`

was a good step as it gives you access to the hackrf_device pointer, which has to be passed to most of the other hackrf control functions.

racket@hackrf.rkt> (define dev (hackrf-open)) racket@hackrf.rkt> dev #<cpointer:hackrf_device>

If you run (exit) or assign something else to `dev`

, the program will run `hackrf_close`

on `#<cpointer:hackrf_device>`

.

git clone git://git.librehacker.com/pub/git/hackrf-rkt.git

]]>```
racket@hackrf.rkt> (hackrf-init)
0
racket@hackrf.rkt> (define dl (get-hackrf-device-list))
racket@hackrf.rkt> (hackrf-device-count dl)
1
racket@hackrf.rkt> (hackrf-serial-numbers dl)
'("000000000000000087c867dc29903e5f")
racket@hackrf.rkt>
racket@hackrf.rkt> (hackrf-usb-board-ids dl)
'(USB_BOARD_ID_HACKRF_ONE)
racket@hackrf.rkt> (hackrf-usb-device-index dl)
'(0)
racket@hackrf.rkt> (hackrf-usb-devices dl)
'(#<cpointer>)
```

There are a few earlier boards that are also supported by this interface besides just the HackRF One.

I’m coding for the version of libhackrf in Debian Stretch, which I’ve discovered is a few years older than the master branch. Maybe after finishing these binds I’ll create a new Git branch for the newer library, and update the bindings for it.

Here is the repo:

git clone git://git.librehacker.com/pub/git/hackrf-rkt.git

]]>- DHCPv6
- Autoconfigured Addresses (SLAAC)
- Stable
- EUI64
- stable-privacy

- Privacy temporary addresses

- Stable

Quick review: an IPv6 address will have a 64 bit prefix portion, specifying the network (e.g., 2001:470:b:449) and a 64 bit suffix portion, specifying the host (e.g., 1e6f:65ff:feac:7d41).

(I skipped over static addresses as that is boring.)

DHCPv6 is listed first simply because it is the least interesting of those listed. This is the traditional way to receive an IP address, where a DHCP server on your network just picks one for you. I don’t like this approach — why depend on a DHCP server when we have IPv6 autoconfiguration? The only advantage I see is that DHCP servers I work with usually pick a shorter, easier to remember suffix, if you happen to want to memorize it. E.g., I received 2001:470:b:449::2d3, where ::2d3 is the suffix.

Stable SLAAC addresses are auto-configured, but according to a deterministic algorithm, such that you can rely on your IP address being the same every time. This is important if running a server, or for some firewall rules. The EUI64 algorithm generates this IP address by joining your network prefix to a modified form of the MAC address for your network interface. Since your MAC address is usually hardcoded into the hardware, you can rely on that not changing (often) and also figure it out in advance if you need to do so. E.g, my MAC address is 1c:6f:65:ac:7d:41, on network 2001:470:b:449, so my EUI64 address is 2001:470:b:449:1e6f:65ff:feac:7d41. ♬ *here’s my number, so ping me maybe* ♫

Stable EUI64 addresses are a problem if you need privacy, because your IP suffix will remain the same on every ethernet or Wi-Fi network you visit, making it rather easy to track you. If you set your host’s network connection to use privacy temporary addresses (this might be the default) your system will generate a new IP address for you periodically, with a random suffix, and use one of these when you make a new connection.

There is also available a compromise between EUI64 and privacy temporary addresses, called stable-privacy. This generates an IP address for you deterministically based on some information on your system and some information in your network environment. Consequently, you get a different IP address for each network you visit, but it is the same address always paired to each network. Part of the formula involves a secret key on your host, so in principle the process can’t be fully reversed. So, basically, you get to be a different person on each network, but they recognize you when you come back.

In Gnome desktop (my version at least) you don’t get very much control of these options from the GUI widget. In my experience it is better to learn how to use the nmcli(1) command-line tool to control Network Manager directly.

]]>`git clone git://git.librehacker.com/pub/hackrf-rkt.git`

This was something of an adventure, as (1) I found, and had to fix myself, a bug in Debian Stretch’s *git-daemon-run* package, and (2) the git-daemon config syntax was not quite intuitive to me, such that I had to tweak my parameters about five times while watching the system log, in order to export my repo.

Anyway, the clone should work from any IPv4 or IPv6 address, though I only tested IPv6. Let me know if there is a problem with IPv4 access.

]]>```
#lang racket/base
(require ffi/unsafe
ffi/unsafe/define)
(define-ffi-definer define-hackrf (ffi-lib "libhackrf"))
(define-hackrf hackrf_init (_fun -> _int))
(define-hackrf hackrf_exit (_fun -> _int))
(define _hackrf_device_list_t-pointer (_cpointer 'hackrf_device_list_t))
(define-hackrf hackrf_device_list (_fun -> _hackrf_device_list_t-pointer))
(define-cstruct _hackrf_device_list_st ([serial_numbers _pointer]
[usb_board_ids _pointer]
[usb_device_index _pointer]
[devicecount _int32]
[usb_devices _pointer]
[usb_devicecount _int32]))
```

This ties into the C API from hackrf.h (ADDAPI and ADDCALL are blank except in Windows):

```
struct hackrf_device_list {
char **serial_numbers;
enum hackrf_usb_board_id *usb_board_ids;
int *usb_device_index;
int devicecount;
void **usb_devices;
int usb_devicecount;
};
typedef struct hackrf_device_list hackrf_device_list_t;
extern ADDAPI int ADDCALL hackrf_init();
extern ADDAPI int ADDCALL hackrf_exit();
extern ADDAPI hackrf_device_list_t* ADDCALL hackrf_device_list();
```

And here is a demo function to get the device count:

```
(define (hackrf-device-count)
(hackrf_device_list_st-devicecount
(ptr-ref (hackrf_device_list)
_hackrf_device_list_st)))
```

With my HackRF plugged in:

racket@hackrf-ffi.rkt> (hackrf_init) 0 racket@hackrf-ffi.rkt> (hackrf-device-count) 1

After unplugging it:

racket@hackrf-ffi.rkt> (hackrf-device-count)

0

You see there is the unit circle, plus the other circles branching off to each side:

The Hermatian matrix template for this particular pencil is elegant:

where n is the x coordinate of the center of each circle (or the complex number center, not having an imaginary component).

Here is Racket code used to generate the plot:

```
(require math/array)
(require math/matrix)
(require plot)
(define (matrix-circle-radius M)
(let ([A (array-ref M #[0 0])]
[d (matrix-determinant M)])
(sqrt (/ d (* -1 (* A A))))))
(define (matrix-circle-center M)
(let ([C (array-ref M #[1 0])]
[A (array-ref M #[0 0])])
(/ C (* -1 A))))
(define (circle-isoline x y r c)
(isoline
(lambda (x_ y_) (sqrt (+ (sqr (- x_ x)) (sqr (- y_ y))))) r
#:color c
#:width 2))
(define (elipt-plot-demo)
(plot
(map (lambda (C)
(circle-isoline (real-part (first C))
(imag-part (first C))
(second C)
(list 30 160 210)
))
(map (lambda (M)
(list (matrix-circle-center M)
(matrix-circle-radius M)))
(map (lambda (n)
(matrix+
(matrix-scale (array #[#[0 1] #[1 0]]) n)
(array #[#[1 0] #[0 -1]])))
(range 2.5 -3 -0.5))))
#:x-min -5
#:x-max 5
#:y-min -5
#:y-max 5
#:width 400
#:height 400))
```

]]>where

, , and

with the circles represented as Hermitian matrices .

The point is, in the end you come up with this single number which represents whether the smaller circle is inside the first, overlapping the first, just touching the first, or outside the first. Here are the cases:

common invariant > 1 : smaller circle contained withing the greater circle

common invariant = 1 : touching from the inside

-1 > common invariant > 1 : overlapping at two points

common invariant = -1 : touching from the outside

common invariant < -1 : completely outside

Here is Racket code used for calculations and plotting:

```
(require math/array)
(require math/matrix)
(require plot)
(define (circle-to-matrix zC r)
(let ([B (* -1 (conjugate zC))]
[mzC (magnitude zC)])
(matrix [[ 1 B ]
[ (conjugate B) (- (* mzC mzC) (* r r)) ]])))
;; gothic C - 212d
;; delta - 394
(define (invariant ℭ1 ℭ2)
(let* ([Δ1 (matrix-determinant ℭ1)]
[Δ2 (matrix-determinant ℭ2)]
[A1 (array-ref ℭ1 #[0 0])]
[B1 (array-ref ℭ1 #[0 1])]
[C1 (array-ref ℭ1 #[1 0])]
[D1 (array-ref ℭ1 #[1 1])]
[A2 (array-ref ℭ2 #[0 0])]
[B2 (array-ref ℭ2 #[0 1])]
[C2 (array-ref ℭ2 #[1 0])]
[D2 (array-ref ℭ2 #[1 1])]
[Δ12 (* 0.5 (+ (* A1 D2)
(* A2 D1)
(* -1 B1 C2)
(* -1 B2 C1)))])
(/ Δ12 (* (sqrt Δ1) (sqrt Δ2)))))
(define (circle-isoline x y r)
(isoline
(lambda (x_ y_) (sqrt (+ (sqr (- x_ x)) (sqr (- y_ y))))) r))
(define (circles-invariant-plot x1 y1 r1 x2 y2 r2 min max)
(let ([C1 (circle-to-matrix (make-rectangular x1 y1) r1)]
[C2 (circle-to-matrix (make-rectangular x2 y2) r2)])
(plot-file
(list
(circle-isoline x1 y1 r1)
(circle-isoline x2 y2 r2)
(point-label (vector (+ min (* (- max min) 0.1))
(+ min (* (- max min) 0.9)))
(number->string (invariant C1 C2)) #:point-size 0))
"out.png"
#:x-min min
#:x-max max
#:y-min min
#:y-max max
#:width 400
#:height 400)))
```

]]>As far as the actual math involved, this YouTube* video was very helpful:

Compute Fourier Series Representation of a Function

*I don’t actually use the YouTube Website directly because of the massive amounts of proprietary JavaScript involved, but instead use youtube-dl to download the video.)*

He converts an off-on type of function to a fourier series. After the integration, we get this:

I translated that into some plots in Racket, to give the visual idea. Say we only add in a single sinusoid:

Then, another:

And a few more:

And a lot more:

And finally, hundreds of them:

It cannot quite perfectly represent the function, because the Fourier series adds an extra point in between the switch from off to on (and back), whereas the original just jumps from 0 to 1 (and back).

Here is the Racket code for those interested (I did not bother to optimize):

```
#lang racket
(require plot)
(define (pulse x l)
(letrec ([pulse_
(lambda (acc n)
(if (> n l) acc
(pulse_
(+ acc
(/ (* 2
(sin (* (+ (* 2 n) 1) pi x)))
(* (+ (* 2 n) 1) pi)))
(+ n 1))))])
(pulse_ 0.5 0)))
(define (pulseplot l)
(plot
(function (lambda (x) (pulse x l)) -1 3)))
```

]]>Where B = – A𝛾̅, C = -A𝛾, and D = A(𝛾𝛾̅-𝜌²), so that A and D are real numbers, and B and C are complex numbers. For normal circles, you will have A=1, though you can scale the matrix to have other (non-zero) values of A and still have the same circle. (If A is zero, you end up with a straight line, or some other mysterious thing that is not a circle.)

The simple case is the unit circle:

Which is

More exotic is the circle away from the origin, centered at 10+10i, i.e., (10, 10), with radius 3:

Here is some code to generate the matrix in Racket, and to put it back:

```
lang racket
(require math/array)
(require math/matrix)
(define (circle-to-matrix zC r)
(let ([B (* -1 (conjugate zC))]
[mzC (magnitude zC)])
(matrix [[ 1 B ]
[ (conjugate B) (- (* mzC mzC) (* r r)) ]])))
(define (matrix-circle-radius M)
(let ([A (array-ref M #[0 0])]
[d (matrix-determinant M)])
(sqrt (/ d (* -1 (* A A))))))
(define (matrix-circle-center M)
(let ([C (array-ref M #[1 0])]
[A (array-ref M #[0 0])])
(/ C (* -1 A))))
```

racket@circle.rkt> (circle-to-matrix 0 1)

(array #[#[1 0] #[0 -1]])

racket@circle.rkt> (matrix-circle-radius (circle-to-matrix 0 1))

1

racket@circle.rkt> (matrix-circle-center (circle-to-matrix 0 1))

0

Why is this significant? I think Schwerdtfeger is going to cover that on page 2. :)

I visited a railroad museum today, and I saw a display showing how the piston is linked to the train wheel. For fun and learning I wanted to model the basic mathematics of how the linkage moves with the wheel and the piston, without looking up the answer on the Internet. That part seemed very simple:

Since l and p are fixed length, it was a matter of simple trigonometry, as seen above. Then I threw the math into a simple Racket program to simulate the movement. That part not hard, but it took an hour or two to add enough lines and circles to make the graphic look half-way decent. Here is a video recording of it running (about 10 seconds):

Here is the source code packaged with the video:

ftp://lavender.qlfiles.net/Racket/piston-driven-wheel.7z

One interesting part of the math is the connection point of l and p (see the diagram above). Until you get very long lengths of l, you get something close to the cosine function but not quite the same.

]]>