Sunday, September 6, 2020

Display copernicus sentinel 1 space packet headers as a table with gtkmm


I am working on a project to visualize the raw radar data of the Copernicus Sentinel 1 satellite.

The data comes in a binary format with header information. Each row in the following figure contains header information of one "space packet":

This source code parses the header information and renders the data as a table in a GTK TreeView:

 https://github.com/plops/cl-cpp-generator2/blob/b13e3afbb30a5958f8e2a6d45b35523f02d32fed/example/33_copernicus_gtk/source/vis_00_base.cpp

The column titles are quite long. In order to fit the table better on the screen I shorten the strings in the table header. The full column title is displayed as a tooltip.

 

I find it surprisingly difficult to express this in gtkmm.

 

Next I want to plot some of the data. I found a dataset that was acquired in stripmap mode and contains several good point spread functions (ships in water).



Sunday, August 16, 2020

Google Protocol Buffers for serial communication with a microcontroller


For a while now I was thinking about implementing a protobuf based binary protocol in the firmware of a microcontroller.

This would have the following advantages:

proto files as specification
parser generators for many languages (python, c)
versioning/backward compatibility
speed up transfer


As a proof of concept I implemented a single message that the microcontroller will send to the host computer using the following packet.
The packet starts with 5 "U" characters and ends with 5 "0xff" bytes:

0x55 0x55 0x55 0x55 0x55 <len_lsb> <len_msb> <payload_bytes...> 0xff 0xff 0xff 0xff 0xff


This preamble looks good in the logic analyzer and I think I can eventually use it for baudrate estimation.


A 16 bit packet length is included and the payload data is encoded using a google protocol buffer file:
https://github.com/plops/cl-cpp-generator2/blob/master/example/29_stm32nucleo/source/simple.proto


syntax = "proto2";
import "nanopb.proto";
message SimpleMessage {
required uint32 id = 1;
required uint32 timestamp = 2;
required uint32 phase = 3;
repeated int32 int32value = 4;
required int32 sample00 = 5;
...
required int32 sample59 = 64;
};





The packet encoder on the MCU is using https://github.com/nanopb/nanopb. It generates encoders and parsers that are compatible with google protocol buffers but the code is C instead of C++ and the code size is small.


https://github.com/plops/cl-cpp-generator2/blob/master/example/29_stm32nucleo/source/boilerplate/main.c



The packet is generated around line 524 (search for "SimpleMessage").


Initially I couldn't figure out how to fill a variable length array. That is why have samle00..sample59 variables. Later I learned how to store an array in int32value line 531, using callback the callback encode_int32.


The python code
https://github.com/plops/cl-cpp-generator2/blob/master/example/29_stm32nucleo/source2/run_00_uart.py

feeds all received bytes into a finite state machine that searches for the five "U" character preamble, parses the packet length and decodes the payload data with code that is autogenerated by google protobuf from simple.proto.

 

Received packets look like this after decoding:


id: 1431655765
timestamp: 4281899953 
phase: 16
int32value: 42
int32value: 43
int32value: 44
int32value: 45
int32value: 46
int32value: 47
int32value: 48
int32value: 49
int32value: 50
int32value: 51
sample00: 193
sample01: 193
...
sample52: 206
sample53: 1999
sample54: 1776
sample55: 300
sample56: 205
sample57: 196
sample58: 193
sample59: 190






The MCU code itself solves a toy problem. I generate output like this:
4095 0 0 4095 0 0 0 4095 0 0 0 ...
on the DAC and read it back with the ADC. Each sample of the ADC is integrated for 2.5cycles of the 80MHz system clock


I shift the ADC trigger relative to the DAC output clock with a PWM timer.


My goal was to investigate the influence of the DAC output buffer.



With buffer the ADC samples do not change much when the ADC acquires the data with a delay after the DAC has settled:

 
 
 
Without DAC buffer the ADC signal gets lower the longer the duration between DAC output instance and ADC acquisition trigger.
 

Sunday, July 12, 2020

ARPACK sparse eigenvalues and GPU

I am trying to learn how to find eigenvalues and eigenvectors of a sparse matrix. A good example problem are electronic orbitals of the hydrogen atom. This paper gives a good introduction:


https://www.mdpi.com/2218-2004/6/2/22/pdf
The structure of the matrix is like this:


A CUDA kernel that implements the matrix vector product looks like this: 

I use ARPACK++ with its reverse communication interface to compute the matrix vector products on the an RTX 2060 GPU.
 The results are similar to the benchmark results listed in the paper:
The radial component of the wavefunction of the ground state looks like this:


The source code is available on github:
 Note that the C++ and CUDA code is generated from Common Lisp source https://github.com/plops/cl-cpp-generator2/blob/master/example/27_sparse_eigen_hydrogen/gen00.lisp.