<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Sdr on Dayio.dev</title><link>https://dayio.dev/tags/sdr/</link><description>Recent content in Sdr on Dayio.dev</description><generator>Hugo</generator><language>en-us</language><copyright>© Dayio</copyright><lastBuildDate>Sun, 17 May 2026 11:15:03 +0200</lastBuildDate><atom:link href="https://dayio.dev/tags/sdr/index.xml" rel="self" type="application/rss+xml"/><item><title>Decoding GPS signal with GO (part 3)</title><link>https://dayio.dev/posts/decoding-gps-signals-with-go-part-3/</link><pubDate>Sun, 17 May 2026 11:15:03 +0200</pubDate><guid>https://dayio.dev/posts/decoding-gps-signals-with-go-part-3/</guid><description>&lt;p&gt;In the last article, we saw how to catch the satellite’s signal using our gold codes and some trickery to handle their movements in the sky using Doppler compensation and phase shifting. However, this comes at a cost. It&amp;rsquo;s slow as hell. And we need to improve this if we want to decode our packets fast.&lt;/p&gt;
&lt;h2 id="the-need-for-speed-acquisition-optimization"&gt;The Need for Speed (Acquisition Optimization)&lt;/h2&gt;
&lt;p&gt;First, let&amp;rsquo;s benchmark the first version:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;now&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Now&lt;/span&gt;() 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;...&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;prn&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;prn&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt;; &lt;span style="color:#a6e22e"&gt;prn&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;bestPhase&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;bestDoppler&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;snr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;gps&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Acquire&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;outputComplex&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;prn&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;sampleRate&lt;/span&gt;) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#f92672"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Processing took %v\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Since&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;now&lt;/span&gt;)) 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ make run
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go build -o bin/gps-decoder cmd/gps-decoder/main.go
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./bin/gps-decoder
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Satellite PRN &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt; found ! Phase: &lt;span style="color:#ae81ff"&gt;792&lt;/span&gt; | Doppler: -5000.00 | SNR: 8.71
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Satellite PRN &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; found ! Phase: &lt;span style="color:#ae81ff"&gt;636&lt;/span&gt; | Doppler: -2000.00 | SNR: 12.41
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Satellite PRN &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt; found ! Phase: &lt;span style="color:#ae81ff"&gt;587&lt;/span&gt; | Doppler: 4000.00 | SNR: 11.78
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Satellite PRN &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; found ! Phase: &lt;span style="color:#ae81ff"&gt;906&lt;/span&gt; | Doppler: 0.00 | SNR: 16.16
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Satellite PRN &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; found ! Phase: &lt;span style="color:#ae81ff"&gt;1140&lt;/span&gt; | Doppler: 0.00 | SNR: 13.52
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Satellite PRN &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt; found ! Phase: &lt;span style="color:#ae81ff"&gt;1168&lt;/span&gt; | Doppler: 5000.00 | SNR: 8.11
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Processing took 52.352300506s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="goroutines-to-the-rescue"&gt;Goroutines to the rescue&lt;/h3&gt;
&lt;p&gt;Alright, 52 seconds on an AMD Ryzen 7 PRO 6850U with 8 cores and 16 threads is slow. So now we will run the acquire method concurrently. To do so, we will define a struct for our acquisition data and then distribute them on a channel for later use. This way, we will use all of our cores.&lt;/p&gt;</description></item><item><title>Decoding GPS signal with GO (part 2)</title><link>https://dayio.dev/posts/decoding-gps-signals-with-go-part-2/</link><pubDate>Sat, 09 May 2026 16:12:12 +0800</pubDate><guid>https://dayio.dev/posts/decoding-gps-signals-with-go-part-2/</guid><description>&lt;p&gt;I&amp;rsquo;ve started by analyzing what I&amp;rsquo;ll use and not use, for my personal enrichment I don&amp;rsquo;t want to use a GPS or a library that will do it all for me and play Lego bricks.&lt;/p&gt;
&lt;p&gt;First of all, we need a structure for our project and a pretty Makefile to help us automate some things&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gps-decoder/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── bin/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── cmd/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── gps-decoder/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── main.go
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── data/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── internal/ 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── dsp/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── gps/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── go.mod
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── LICENSE
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Makefile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── README.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ll split the DSP (Digital Signal Processing) and GPS processing in separate folders as the I/Q Signal can be used without GPS and vice versa.&lt;/p&gt;</description></item><item><title>Decoding GPS signal with GO (part 1)</title><link>https://dayio.dev/posts/decoding-gps-signals-with-go-part-1/</link><pubDate>Mon, 27 Apr 2026 13:48:32 +0200</pubDate><guid>https://dayio.dev/posts/decoding-gps-signals-with-go-part-1/</guid><description>&lt;p&gt;&lt;em&gt;Disclaimer: I&amp;rsquo;m not a spatial engineer and I&amp;rsquo;m learning as write this article, I have notions of linear Algebra that&amp;rsquo;s it&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="introduction-the-gps-geometry-paradox"&gt;Introduction: The GPS Geometry Paradox&lt;/h2&gt;
&lt;p&gt;I was out for a run yesterday, and looking down at my Garmin watch, I wondered how can a device this small pinpoint my exact location, pace and elevation so precisely ?&lt;/p&gt;
&lt;p&gt;I looked into how the Global Positioning System (GPS) works, and the underlying concept is pretty clever. In pure theory, you only need signals from three satellites to calculate a 2D position (latitude and longitude). One satellite gives you the current time, two give you a line of position and with three, by measuring the tiny differences in the arrival times of their radio signals, you can estimate your exact position on Earth.&lt;/p&gt;</description></item></channel></rss>