見出し画像

TWSNMP開発日誌:電波とか周波数の勉強のための図書館に行く

浦和レッズ ACL決勝進出! おめでとう!
昨日はエキサイティングな試合を観て、今朝は起きるのが遅くなりました。
モバイル版のマニュアルを書きましたが、いろいろバグを見つけたのでいつか修正しなければと思っています。

昨日から始めた夏休みの自由研究、RTL-SDR

を動かす実験ですが、昨日は、

をみてMacでFMラジオを聞くところまでできました。

NACK5を聞いた

埼玉県民なら聞き覚えのある周波数 79.5Mhz(NACK5)を設定すれば、ラジをが聞けました。ちょうど浦和レッズのACLの試合について話しているところでした。
Macで波形をみながらラジオが聞けるのは楽しいので今朝はいろいろな周波数を試してみました。少しだけソフトの使い方も慣れてきました。

本題のRTL-SDRを使ってソフトを作るために

のサンプルを試してみました。Macに

をインストールすれば、簡単に動作しました。
しかし、サンプルのソースコード

	dev, err := rtl.Open(0)
	if err != nil {
		log.Fatalf("Failed to open device: %s", err.Error())
	}
	defer dev.Close()

	sampleRate := 170000
	outputRate := 32000
	postDownsample := 4

	sampleRate *= postDownsample
	frequency := int(79.5e6)
	downsample := 1000000/sampleRate + 1
	captureRate := downsample * sampleRate
	captureFreq := frequency + 16000 + captureRate/4

	fmt.Fprintf(os.Stderr, "Oversampling input by: %dx\n", downsample)
	fmt.Fprintf(os.Stderr, "Oversampling output by: %dx\n", postDownsample)
	fmt.Fprintf(os.Stderr, "Sampling at %d Hz\n", captureRate)
	fmt.Fprintf(os.Stderr, "Tuned to %d Hz\n", captureFreq)

	if err := dev.SetSampleRate(uint(captureRate)); err != nil {
		log.Fatalf("Failed to set sample rate: %s", err.Error())
	}

	if err := dev.SetCenterFreq(uint(captureFreq)); err != nil {
		log.Fatalf("Failed to set center freq: %s", err.Error())
	}

	if err := dev.ResetBuffer(); err != nil {
		log.Fatalf("Failed to reset buffers: %s", err.Error())
	}

	rotate90 := &dsp.Rotate90Filter{}
	lowPass1 := &dsp.LowPassDownsampleComplexFilter{Downsample: downsample}
	fmDemod := &dsp.FMDemodFilter{}
	lowPass2 := &dsp.LowPassDownsampleRationalFilter{Fast: sampleRate, Slow: outputRate}

	stopChan := make(chan bool)

	bytes := make([]byte, bufferSize*2)
	samples := make([]complex64, bufferSize)
	pcm := make([]float32, bufferSize)

	dev.ReadAsync(nBuffers, bufferSize, func(buf []byte) bool {
		select {
		case _ = <-stopChan:
			return true
		default:
		}

		n := len(buf)
		n /= 2
		dsp.Ui8toc64(buf, samples[:n])

		var samples2 []complex64
		samples2 = rotate90.Filter(samples[:n])
		samples2 = lowPass1.Filter(samples2)
		n = fmDemod.Demodulate(samples2, pcm)
		var pcm2 []float32
		pcm2 = lowPass2.Filter(pcm[:n])
		// if pcm2, err = lowPass3.Filter(pcm2); err != nil {
		// 	log.Fatal(err)
		// }
		dsp.F32toi16ble(pcm2, bytes, 1<<14)
		if _, err := os.Stdout.Write(bytes[:len(pcm2)*2]); err != nil {
			log.Fatal(err)
		}

		return false
	})

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt, os.Kill)
	<-signalChan
	close(stopChan)

を読んでも、出てくるパラメータの意味がよくわかりません。
わからないままプログラムをつくるわけにはいかないので、電波とか周波数とか、真面目に勉強しようと思いました。最初は初歩的な本を読むのが一番なので、節約のために図書館に行きました。

図書館で借りた本

借りた本の著者をよく見ると、なんとなく見覚えのある名前でした。30年ぐらい前、CQ出版の座談会でお会いして方でした。懐かしい。

午後は、これらの本を読んで基礎のお勉強です。

明日に続く


開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。