Last active
September 7, 2019 13:56
-
-
Save k3kaimu/28f42c3f5aef7312f1adad47982416f2 to your computer and use it in GitHub Desktop.
QPSK-OFDM modulation and demodulation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.stdio; | |
import std.random; | |
import std.complex; | |
import std.numeric; | |
alias Bit = ubyte; | |
alias C = Complex!float; | |
void main() | |
{ | |
// 100ビットのランダム情報を生成 | |
auto bits = makeRandomBits(rndGen, 100); | |
writeln(bits); | |
// QPSK変調(50シンボル) | |
auto qpsk = modQPSK(bits); | |
writeln(qpsk); | |
// OFDM変調(サブキャリア数10,FFTサイズ32,CP長5) | |
auto ofdm = modOFDM(qpsk, 32, 10, 5); | |
// OFDM復調 | |
auto scs = demodOFDM(ofdm, 32, 10, 5); | |
// QPSK復調 | |
auto recvQPSK = demodQPSK(qpsk); | |
writeln(recvQPSK); | |
} | |
Bit[] makeRandomBits(ref Random rnd, size_t n) | |
{ | |
Bit[] bits = new Bit[n]; | |
foreach(i; 0 .. n) | |
bits[i] = rnd.uniform01() > 0.5 ? 1 : 0; | |
return bits; | |
} | |
C[] modQPSK(in Bit[] bits) | |
in(bits.length % 2 == 0) | |
{ | |
C[] qpsk = new C[bits.length / 2]; | |
foreach(i, ref e; qpsk) { | |
int I = bits[i*2+0] == 0 ? 1 : -1; | |
int Q = bits[i*2+1] == 0 ? 1 : -1; | |
e = C(I, Q); | |
} | |
return qpsk; | |
} | |
Bit[] demodQPSK(in C[] sym) | |
{ | |
Bit[] bits = new Bit[sym.length * 2]; | |
foreach(i, e; sym) { | |
bits[i*2+0] = e.re > 0 ? 0 : 1; | |
bits[i*2+1] = e.im > 0 ? 0 : 1; | |
} | |
return bits; | |
} | |
C[] modOFDM(in C[] subcarriers, size_t nFFT, size_t nSC, size_t nCP) | |
in(subcarriers.length % nSC == 0) | |
in(nSC % 2 == 0) | |
in(nSC < nFFT) | |
{ | |
Fft fftObj = new Fft(nFFT); | |
C[] signal = new C[subcarriers.length / nSC * (nFFT + nCP)]; | |
C[] fftbuf = new C[nFFT]; | |
foreach(i; 0 .. subcarriers.length / nSC) { | |
auto sym = signal[i*(nFFT+nCP) .. (i+1)*(nFFT+nCP)]; | |
auto scHigh = fftbuf[1 .. 1 + nSC/2]; | |
auto scLow = fftbuf[$ - nSC/2 .. $]; | |
auto sc = subcarriers[i*nSC .. (i+1)*nSC]; | |
fftbuf[] = C(0); | |
scHigh[] = sc[0 .. $/2]; | |
scLow[] = sc[$/2 .. $]; | |
fftObj.inverseFft(fftbuf, sym[nCP .. nCP + nFFT]); | |
sym[0 .. nCP] = sym[$ - nCP .. $]; | |
} | |
return signal; | |
} | |
C[] demodOFDM(in C[] signal, size_t nFFT, size_t nSC, size_t nCP) | |
in(signal.length % (nFFT + nCP) == 0) | |
in(nSC % 2 == 0) | |
in(nSC < nFFT) | |
{ | |
Fft fftObj = new Fft(nFFT); | |
size_t totSym = signal.length / (nFFT + nCP); | |
C[] subcarriers = new C[totSym * nSC]; | |
C[] fftbuf = new C[nFFT]; | |
foreach(i; 0 .. totSym) { | |
auto sc = subcarriers[i * nSC .. (i+1) * nSC]; | |
auto sym = signal[(nFFT + nCP) * i + nCP .. (nFFT + nCP) * (i+1)]; | |
fftObj.fft(sym, fftbuf); | |
sc[0 .. nSC / 2] = fftbuf[1 .. 1 + nSC/2]; | |
sc[nSC / 2 .. nSC] = fftbuf[$ - nSC/2 .. $]; | |
} | |
return subcarriers; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment