Skip to content

Instantly share code, notes, and snippets.

@k3kaimu
Last active September 7, 2019 13:56
Show Gist options
  • Save k3kaimu/28f42c3f5aef7312f1adad47982416f2 to your computer and use it in GitHub Desktop.
Save k3kaimu/28f42c3f5aef7312f1adad47982416f2 to your computer and use it in GitHub Desktop.
QPSK-OFDM modulation and demodulation
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