From 53a36856badb9d58c4e92d509cb2d52e94f8c925 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Mon, 10 Mar 2025 23:09:56 +0100 Subject: [PATCH] add the script --- .gitignore | 4 +- src/waveforms.c | 4 +- src/waveforms.h | 5 +- waveform/Pydemod/README.md | 11 +++ waveform/Pydemod/src/gen_wave.py | 80 +++++++++++++++++++ waveform/Pydemod/src/pydemod/__init__.py | 0 waveform/Pydemod/src/pydemod/app/__init__.py | 0 waveform/Pydemod/src/pydemod/app/rds.py | 11 +++ .../Pydemod/src/pydemod/filters/__init__.py | 0 .../Pydemod/src/pydemod/filters/shaping.py | 64 +++++++++++++++ waveform/Pydemod/src/waveforms.c | 8 ++ waveform/Pydemod/src/waveforms.h | 7 ++ 12 files changed, 190 insertions(+), 4 deletions(-) create mode 100644 waveform/Pydemod/README.md create mode 100644 waveform/Pydemod/src/gen_wave.py create mode 100644 waveform/Pydemod/src/pydemod/__init__.py create mode 100644 waveform/Pydemod/src/pydemod/app/__init__.py create mode 100644 waveform/Pydemod/src/pydemod/app/rds.py create mode 100644 waveform/Pydemod/src/pydemod/filters/__init__.py create mode 100644 waveform/Pydemod/src/pydemod/filters/shaping.py create mode 100644 waveform/Pydemod/src/waveforms.c create mode 100644 waveform/Pydemod/src/waveforms.h diff --git a/.gitignore b/.gitignore index a4930d7..0fe84ca 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,6 @@ Module.symvers Mkfile.old dkms.conf -build/ \ No newline at end of file +build/ +*.pyc +__pycache__/ \ No newline at end of file diff --git a/src/waveforms.c b/src/waveforms.c index 660197f..d615df6 100644 --- a/src/waveforms.c +++ b/src/waveforms.c @@ -1,7 +1,9 @@ -/* This file was automatically generated by "generate_waveforms.py". +/* This file was automatically generated by "gen_wave.py". (C) 2014 Christophe Jacquet. + Modified by kuba201 Released under the GNU GPL v3 license. */ float waveform_biphase[24] = {0.002532628775852384, -6.480266785053461e-18, -0.004522551385450683, 2.807603181808536e-17, 0.00940690688173742, -2.1836329850641248e-17, -0.025868993924777907, -1.1701083086090883e-17, 0.1552139635486674, 0.4, 0.5432488724203361, 0.4, 0.0, -0.4, -0.5432488724203361, -0.4, -0.1552139635486674, 1.1701083086090883e-17, 0.025868993924777907, 2.1836329850641248e-17, -0.00940690688173742, -2.807603181808536e-17, 0.004522551385450683, 6.480266785053461e-18}; + diff --git a/src/waveforms.h b/src/waveforms.h index 4f3efb4..67bab7e 100644 --- a/src/waveforms.h +++ b/src/waveforms.h @@ -1,7 +1,8 @@ -/* This file was automatically generated by "generate_waveforms.py". +/* This file was automatically generated by "gen_wave.py". (C) 2014 Christophe Jacquet. + Modified by kuba201 Released under the GNU GPL v3 license. - */ +*/ extern float waveform_biphase[24]; diff --git a/waveform/Pydemod/README.md b/waveform/Pydemod/README.md new file mode 100644 index 0000000..73ccf90 --- /dev/null +++ b/waveform/Pydemod/README.md @@ -0,0 +1,11 @@ +Pydemod +------- + +Pydemod is a set of Python libraries and tools for demodulating radio signals. It does not intend to compete with full-featured packages such as GNU Radio. Instead, it strives to allow radio enthusiasts to gain hands-on experience with modulation schemes. + +Pydemod relies on [NumPy](http://numpy.scipy.org/)/[SciPy](http://www.scipy.org/). + +Pydemod is licensed under the terms of the [GNU GPL v3](https://www.gnu.org/copyleft/gpl.html). + +---- +_Pydemod is developed by [Christophe Jacquet](http://www.jacquet80.eu/), [F8FTK](http://f8ftk.tk)._ diff --git a/waveform/Pydemod/src/gen_wave.py b/waveform/Pydemod/src/gen_wave.py new file mode 100644 index 0000000..2389cad --- /dev/null +++ b/waveform/Pydemod/src/gen_wave.py @@ -0,0 +1,80 @@ +#!/usr/bin/python + + +# PiFmRds - FM/RDS transmitter for the Raspberry Pi +# Copyright (C) 2014 Christophe Jacquet, F8FTK +# +# See https://github.com/ChristopheJacquet/PiFmRds +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This program generates the waveform of a single biphase symbol +# +# This program uses Pydemod, see https://github.com/ChristopheJacquet/Pydemod + +import pydemod.app.rds as rds +import numpy +import io +import matplotlib.pyplot as plt + +sample_rate = 9500 + +outc = io.open("waveforms.c", mode="w", encoding="utf8") +outh = io.open("waveforms.h", mode="w", encoding="utf8") + +header = u""" +/* This file was automatically generated by "gen_wave.py". + (C) 2014 Christophe Jacquet. + Modified by kuba201 + Released under the GNU GPL v3 license. +*/ + +""" + +outc.write(header) +outh.write(header) + +def generate_bit(name): + offset = int(sample_rate*0.004) # 190 khz = 760 + count = int(offset / 10**(len(str(offset)) - 1)) # 760 / 100 = 7 + l = int(sample_rate / 1187.5) // 2 # 16/2 = 8 + + sample = numpy.zeros(count*l) + sample[l] = 1 + sample[2*l] = -1 + + # Apply the data-shaping filter + sf = rds.pulse_shaping_filter(l*16, sample_rate-1) + shapedSamples = numpy.convolve(sample, sf) + + out = shapedSamples[offset-l*count:offset+l*count] #[offset:offset+l*count] + #plt.plot(sf) + #plt.plot(shapedSamples) + plt.plot(out) + plt.show() + + outc.write(u"float waveform_{name}[{size}] = {{{values}}};\n\n".format( + name = name, + values = u", ".join(map(str, out / 2.5)), + size = len(out))) + # note: need to limit the amplitude so as not to saturate when the biphase + # waveforms are summed + + outh.write(u"extern float waveform_{name}[{size}];\n".format(name=name, size=len(out))) + + +generate_bit("biphase") + +outc.close() +outh.close() \ No newline at end of file diff --git a/waveform/Pydemod/src/pydemod/__init__.py b/waveform/Pydemod/src/pydemod/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/waveform/Pydemod/src/pydemod/app/__init__.py b/waveform/Pydemod/src/pydemod/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/waveform/Pydemod/src/pydemod/app/rds.py b/waveform/Pydemod/src/pydemod/app/rds.py new file mode 100644 index 0000000..2d45dd9 --- /dev/null +++ b/waveform/Pydemod/src/pydemod/app/rds.py @@ -0,0 +1,11 @@ +# This file is part of Pydemod +# Copyright Christophe Jacquet (F8FTK), 2014 +# Licence: GNU GPL v3 +# See: https://github.com/ChristopheJacquet/Pydemod + +import numpy + +import pydemod.filters.shaping as shaping + +def pulse_shaping_filter(length, sample_rate): + return shaping.rrcosfilter(length, 1, 1/(2*1187.5), sample_rate+1) [1] \ No newline at end of file diff --git a/waveform/Pydemod/src/pydemod/filters/__init__.py b/waveform/Pydemod/src/pydemod/filters/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/waveform/Pydemod/src/pydemod/filters/shaping.py b/waveform/Pydemod/src/pydemod/filters/shaping.py new file mode 100644 index 0000000..29766d6 --- /dev/null +++ b/waveform/Pydemod/src/pydemod/filters/shaping.py @@ -0,0 +1,64 @@ +# This file is part of Pydemod +# Copyright Christophe Jacquet (F8FTK), 2014 +# Licence: GNU GPL v3 +# See: https://github.com/ChristopheJacquet/Pydemod +# +# Contains code from CommPy, used under the terms of the GPL +# https://github.com/veeresht/CommPy/blob/master/commpy/filters.py +# (c) 2012 Veeresh Taranalli + +import numpy + +# The following function is from: +# https://github.com/veeresht/CommPy/blob/master/commpy/filters.py +# See also: https://en.wikipedia.org/wiki/Root-raised-cosine_filter +def rrcosfilter(N, alpha, Ts, Fs): + """ + Generates a root raised cosine (RRC) filter (FIR) impulse response. + + Parameters + ---------- + N : int + Length of the filter in samples. + + alpha: float + Roll off factor (Valid values are [0, 1]). + + Ts : float + Symbol period in seconds. + + Fs : float + Sampling Rate in Hz. + + Returns + --------- + + h_rrc : 1-D ndarray of floats + Impulse response of the root raised cosine filter. + + time_idx : 1-D ndarray of floats + Array containing the time indices, in seconds, for + the impulse response. + """ + + T_delta = 1/float(Fs) + time_idx = ((numpy.arange(N)-N/2))*T_delta + sample_num = numpy.arange(N) + h_rrc = numpy.zeros(N, dtype=float) + + for x in sample_num: + t = (x-N/2)*T_delta + if t == 0.0: + h_rrc[x] = 1.0 - alpha + (4*alpha/numpy.pi) + elif alpha != 0 and t == Ts/(4*alpha): + h_rrc[x] = (alpha/numpy.sqrt(2))*(((1+2/numpy.pi)* \ + (numpy.sin(numpy.pi/(4*alpha)))) + ((1-2/numpy.pi)*(numpy.cos(numpy.pi/(4*alpha))))) + elif alpha != 0 and t == -Ts/(4*alpha): + h_rrc[x] = (alpha/numpy.sqrt(2))*(((1+2/numpy.pi)* \ + (numpy.sin(numpy.pi/(4*alpha)))) + ((1-2/numpy.pi)*(numpy.cos(numpy.pi/(4*alpha))))) + else: + h_rrc[x] = (numpy.sin(numpy.pi*t*(1-alpha)/Ts) + \ + 4*alpha*(t/Ts)*numpy.cos(numpy.pi*t*(1+alpha)/Ts))/ \ + (numpy.pi*t*(1-(4*alpha*t/Ts)*(4*alpha*t/Ts))/Ts) + + return time_idx, h_rrc diff --git a/waveform/Pydemod/src/waveforms.c b/waveform/Pydemod/src/waveforms.c new file mode 100644 index 0000000..f91b354 --- /dev/null +++ b/waveform/Pydemod/src/waveforms.c @@ -0,0 +1,8 @@ + +/* This file was automatically generated by "generate_waveforms.py". + (C) 2014 Christophe Jacquet. + Released under the GNU GPL v3 license. +*/ + +float waveform_biphase[24] = {0.002532628775852384, -6.480266785053461e-18, -0.004522551385450683, 2.807603181808536e-17, 0.00940690688173742, -2.1836329850641248e-17, -0.025868993924777907, -1.1701083086090883e-17, 0.1552139635486674, 0.4, 0.5432488724203361, 0.4, 0.0, -0.4, -0.5432488724203361, -0.4, -0.1552139635486674, 1.1701083086090883e-17, 0.025868993924777907, 2.1836329850641248e-17, -0.00940690688173742, -2.807603181808536e-17, 0.004522551385450683, 6.480266785053461e-18}; + diff --git a/waveform/Pydemod/src/waveforms.h b/waveform/Pydemod/src/waveforms.h new file mode 100644 index 0000000..17eae23 --- /dev/null +++ b/waveform/Pydemod/src/waveforms.h @@ -0,0 +1,7 @@ + +/* This file was automatically generated by "generate_waveforms.py". + (C) 2014 Christophe Jacquet. + Released under the GNU GPL v3 license. +*/ + +extern float waveform_biphase[24];