```
In [1]:
```%matplotlib inline
import numpy as np
import scipy.signal
import matplotlib.pyplot as plt

```
In [2]:
```x = np.fromfile('/home/daniel/Descargas/DSLWP-B_PI9CAM_2018-08-12T06_58_02_436.4MHz_40ksps_complex.raw', dtype='complex64')

The 250bps GMSK signal is converted down to baseband and lowpass filtered to 800Hz.

```
In [3]:
```fs = 40e3
f = 1500
x = x * np.exp(-1j*2*np.pi*np.arange(x.size)*f/fs).astype('complex64')
h = scipy.signal.firwin(1000, 0.01).astype('float32')
x = scipy.signal.lfilter(h, 1, x).astype('complex64')

Perform arctangent FSK demodulation.

```
In [4]:
```s = np.diff(np.angle(x).astype('float32'))

Correct for phase wrapping.

```
In [5]:
```s[s > np.pi] -= 2*np.pi
s[s < -np.pi] += 2*np.pi

We extract the soft bits by guessing the correct clock phase and decimating. No pulse shaping matched filtering has been done, and tracking of the clock frequency doesn't seem necessary either. The separation between the bits 1 and 0 is good enough for demodulation without bit errors.

Note that we correct for the clock drift and for frequency offset and drift. This simple open loop clock recovery is enough to get good separation between the bits.

```
In [6]:
```phase = 50
softbits = s[np.int32(np.arange(phase,s.size,160 - 0.0005))]
softbits = softbits + 1e-8 * np.arange(softbits.size) - 0.005 # correction for frequency offset and drift
plt.plot(softbits,'.')
plt.axhline(y = 0, color='green')
plt.ylim([-0.03,0.03]);

```
```

Soft bits are now converted to hard bits.

```
In [7]:
```bits = (softbits > 0)*1

```
In [8]:
```asm = np.unpackbits(np.array([0x03,0x47,0x76,0xC7,0x27,0x28,0x95,0xB0], dtype='uint8'))
asm_diff = asm[:-1] ^ asm[1:]
asm_diff[1::2] ^= 1

```
In [9]:
```asm_corr = scipy.signal.correlate(2*bits-1, 2*asm_diff.astype('float')-1)
plt.plot(asm_corr)

```
Out[9]:
```

Note that all the ASMs have correlated without any bit errors.

```
In [10]:
```asm_corr[asm_corr > 40]

```
Out[10]:
```

```
In [11]:
```asm_corr[asm_corr > 40].size

```
Out[11]:
```

We now look at the distances between the ASMs. DSLWP-B uses Turbo codewords of 3576 symbols. Since the ASM is 64 bits long and Turbo codewords are transmitted back-to-back, without any gap between them, we expect a distance of 3640 bits.

Note that before we have stated that the ASM is 63 bits long. This is because the GMSK precoder is differential, so the first bit of the ASM is not defined, as it depends on the preceding data. Thus, we only use the 63 bits of the ASM that are fixed when doing the correlation.

Below we show the distances between the ASMs.

```
In [12]:
```np.diff(np.where(asm_corr > 40)[0])

```
Out[12]:
```

We see that there are no problems with Turbo words being cut short.