-
Notifications
You must be signed in to change notification settings - Fork 1
/
Modem.cpp
110 lines (90 loc) · 2.99 KB
/
Modem.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "Modem/Modem.hpp"
/**
* @brief Construct a new Modem:: Modem object
*
* @param freqc carrier frequency
* @param freqs sampling frequency
* @param Timeb secs of each symbol
* @param t type of Modem, choose from MODEM_BPSK, default to be MODEM_BPSK
*/
Modem::Modem(int freqc, int freqs, double Timeb, int t) {
fc = freqc;
fs = freqs;
Tb = Timeb;
type = t;
L = Tb * fs;
}
Modem::~Modem() {}
/**
* @brief https://github.com/DenisMedeiros/BPSKModDemod
*
* @param c : encoded code word
* @return Eigen::RowVectorXd
*/
Eigen::RowVectorXd Modem::modulate(const Eigen::RowVectorXi &c) {
// turn 0 1 sequence into -1 1 sequence
Eigen::RowVectorXi c_symbol =
c.unaryExpr([](const int x) { return 2 * x - 1; });
int length = L * c.size();
Eigen::RowVectorXd ret;
switch (type) {
case MODEM_BPSK:
// Generate the square wave where each Tb lasts L samples
Eigen::RowVectorXd wave = repeat(c_symbol, L).cast<double>();
// Generate the carrier
Eigen::RowVectorXd t =
Eigen::RowVectorXd::LinSpaced(length, 0, length);
Eigen::RowVectorXd carrier = cos(2 * M_PI * fc * t);
ret = multiplyd(carrier, wave);
break;
}
return ret;
}
Eigen::RowVectorXd Modem::demodulate(const Eigen::RowVectorXd &x) {
Eigen::RowVectorXd ret;
switch (type) {
case MODEM_BPSK:
// // Generate the square wave where each Tb lasts L samples
// Eigen::RowVectorXd wave = repeat(c_symbol, L).cast<double>();
// Generate the carrier
Eigen::RowVectorXd t =
Eigen::RowVectorXd::LinSpaced(x.size(), 0, x.size());
Eigen::RowVectorXd carrier = cos(2 * M_PI * fc * t);
Eigen::RowVectorXd signald = multiplyd(carrier, x);
signald = convolve(signald, Eigen::RowVectorXd::Ones(L));
signald = signald.block(0, L - 1, 1, signald.size() - L);
// Eigen::RowVectorXi signali = signald.unaryExpr(
// [](const double x) { return x > 0 ? 1 : -1; });
// take one in every L values
Eigen::RowVectorXd tmpRet((int)ceil(signald.size() / (double)L));
for (size_t i = 0; i < signald.size(); i += L) {
tmpRet(i / L) = signald(i);
}
ret = tmpRet;
break;
}
return ret;
}
int Modem::getL() {
return L;
}
/**
* @brief Compare two sequence, one is 0,1 sequence, latter one is -1,1 sequence
*
* @param X 0, 1 sequence
* @param Y -1, 1 sequence
* @return int : return 0 if passed, 1 if failed
*/
int Compare(const Eigen::RowVectorXi &X, const Eigen::RowVectorXi &Y) {
assert(X.size() == Y.size());
int diffCount = 0;
for (size_t i = 0; i < X.size(); i++) {
int Xi = X(i), Yi = Y(i);
assert(Xi == 0 || Xi == 1);
assert(Yi == -1 || Yi == 1);
if (2 * Xi - 1 != Yi) {
diffCount++;
}
}
return diffCount;
}