<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Dsp on Dayio.dev</title><link>https://dayio.dev/tags/dsp/</link><description>Recent content in Dsp 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/dsp/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></channel></rss>