1 /*
2 * Copyright 2018 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "bs_types.h"
7 #include "bs_tracing.h"
8 #include "bs_oswrap.h"
9 #include "bs_utils.h"
10 #include "bs_rand_main.h"
11 #include "bs_pc_2G4.h"
12 #include "bs_pc_2G4_utils.h"
13 #include "modem_if.h"
14 #include "p2G4_pending_tx_rx_list.h"
15 #include "modem_BLE_simple.h"
16 #include "modem_BLE_simple_args.h"
17 #include <math.h>
18
19 #define FreqRes 200e3
20
21 //Rx filters "_power_ gain" (gain in natural units ^2) (the gain for the desired modulation should be 0dB)
22 static const double channel_filter_BLE[41] = {
23 1.0000e-06, 1.2589e-06, 1.5849e-06, 1.9953e-06, 2.5119e-06,
24 3.1623e-06, 5.0119e-06, 1.0000e-05, 3.1623e-05, 1.0000e-04,
25 3.1623e-04, 1.0000e-03, 3.1623e-03, 1.0000e-02, 3.9811e-02,
26 1.1398e-01, 2.6304e-01, 6.7212e-01, 7.9446e-01, 9.8531e-01,
27 1.1791e+00, 9.8531e-01, 7.9446e-01, 6.7212e-01, 2.6304e-01,
28 1.1398e-01, 3.9811e-02, 1.0000e-02, 3.1623e-03, 1.0000e-03,
29 3.1623e-04, 1.0000e-04, 3.1623e-05, 1.0000e-05, 5.0119e-06,
30 3.1623e-06, 2.5119e-06, 1.9953e-06, 1.5849e-06, 1.2589e-06,
31 1.0000e-06
32 };
33 static const uint channel_filter_BW_BLE = 20; //How many samples from the center frequency
34
35 static const double channel_filter_Prop2[81] = {
36 1.0000e-06, 1.5849e-06, 2.5119e-06, 3.9811e-06, 6.3096e-06,
37 7.9433e-06, 1.0000e-05, 1.2589e-05, 1.5849e-05, 1.9953e-05,
38 2.5119e-05, 3.1623e-05, 3.9811e-05, 5.0119e-05, 6.3096e-05,
39 7.9433e-05, 1.0000e-04, 1.2589e-04, 1.5849e-04, 1.9953e-04,
40 2.5119e-04, 3.1623e-04, 3.9811e-04, 5.0119e-04, 6.3096e-04,
41 1.0000e-03, 1.5849e-03, 3.1623e-03, 6.3096e-03, 3.1565e-02,
42 5.2087e-02, 6.4973e-02, 1.3748e-01, 2.0369e-01, 4.3440e-01,
43 8.5992e-01, 1.0097e+00, 1.0097e+00, 1.0097e+00, 1.0097e+00,
44 1.0097e+00, 1.0097e+00, 1.0097e+00, 1.0097e+00, 1.0097e+00,
45 8.5992e-01, 4.3440e-01, 2.0369e-01, 1.3748e-01, 6.4973e-02,
46 5.2087e-02, 3.1565e-02, 6.3096e-03, 3.1623e-03, 1.5849e-03,
47 1.0000e-03, 6.3096e-04, 5.0119e-04, 3.9811e-04, 3.1623e-04,
48 2.5119e-04, 1.9953e-04, 1.5849e-04, 1.2589e-04, 1.0000e-04,
49 7.9433e-05, 6.3096e-05, 5.0119e-05, 3.9811e-05, 3.1623e-05,
50 2.5119e-05, 1.9953e-05, 1.5849e-05, 1.2589e-05, 1.0000e-05,
51 7.9433e-06, 6.3096e-06, 3.9811e-06, 2.5119e-06, 1.5849e-06,
52 1.0000e-06
53 };
54 static const uint channel_filter_BW_Prop2 = 40; //How many samples from the center frequency
55
56 //_Power_ spectral density of each modulation (in natural units, power (sum must be 1.0))
57 static const double TxSpectrum_BLE[13] = {
58 4.1980e-05, 2.8516e-04, 4.8379e-04, 1.2872e-02, 9.1159e-02,
59 2.4433e-01, 3.0165e-01, 2.4433e-01, 9.1159e-02, 1.2872e-02,
60 4.8379e-04, 2.8516e-04, 4.1980e-05};
61 static const uint TxSpecBW_BLE = 6;
62
63 static const double TxSpectrum_Prop2[25] =
64 { 1.4055e-05, 5.6012e-05, 1.5134e-04, 2.1890e-04, 1.2972e-04,
65 3.2762e-04, 3.3251e-03, 1.4459e-02, 4.1335e-02, 8.0105e-02,
66 1.1656e-01, 1.5506e-01, 1.7652e-01, 1.5506e-01, 1.1656e-01,
67 8.0105e-02, 4.1335e-02, 1.4459e-02, 3.3251e-03, 3.2762e-04,
68 1.2972e-04, 2.1890e-04, 1.5134e-04, 5.6012e-05, 1.4055e-05};
69 static const uint TxSpecBW_Prop2 = 12;
70
71 static const double TxSpectrum_WLAN[123] = {
72 1.511874e-006 ,3.797656e-006 ,9.539280e-006 ,1.511874e-005 ,2.396159e-005 ,
73 3.797656e-005 ,6.753293e-005 ,9.539280e-005 ,1.347459e-004 ,1.903337e-004 ,
74 2.688534e-004 ,3.797656e-004 ,4.565786e-004 ,3.016585e-004 ,3.585218e-004 ,
75 5.617144e-004 ,7.071566e-004 ,8.501892e-004 ,7.577319e-004 ,1.200924e-003 ,
76 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
77 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
78 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
79 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
80 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
81 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
82 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
83 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
84 1.200924e-002 ,2.396159e-003 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
85 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
86 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
87 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
88 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
89 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
90 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
91 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,
92 1.200924e-002 ,1.200924e-002 ,1.200924e-002 ,1.200924e-003 ,7.577319e-004 ,
93 8.501892e-004 ,7.071566e-004 ,5.617144e-004 ,3.585218e-004 ,3.016585e-004 ,
94 4.565786e-004 ,3.797656e-004 ,2.688534e-004 ,1.903337e-004 ,1.347459e-004 ,
95 9.539280e-005 ,6.753293e-005 ,3.797656e-005 ,2.396159e-005 ,1.511874e-005 ,
96 9.539280e-006 ,3.797656e-006 ,1.511874e-006
97 };
98 static const uint TxSpecBW_WLAN = 61;
99
100 static const double TxSpectrum_CW[1] = {1};
101 static const uint TxSpecBW_CW = 0;
102 static const double TxSpectrum_WN1MHz[5] = {
103 1.0/5 , 1.0/5.0, 1.0/5.0, 1.0/5.0, 1.0/5
104 };
105 static const uint TxSpecBW_WN1MHz = 2;
106 static const double TxSpectrum_WN2MHz[11] = {
107 1.0/20.0, 1.0/10.0, 1.0/10.0, 1.0/10.0, 1.0/10.0,
108 1.0/10.0, 1.0/10.0, 1.0/10.0, 1.0/10.0, 1.0/10.0,
109 1.0/20.0
110 };
111 static const uint TxSpecBW_WN2MHz = 5;
112 static const double TxSpectrum_WN4MHz[21] = {
113 1.0/40.0, 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0,
114 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0,
115 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0,
116 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0, 1.0/20.0,
117 1.0/40.0
118 };
119 static const uint TxSpecBW_WN4MHz = 10;
120
121 static const double TxSpectrum_WN8MHz[41] = {
122 1.0/80.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0,
123 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0,
124 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0,
125 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0, 1.0/40.0,
126 1.0/80.0
127 };
128
129 static const uint TxSpecBW_WN8MHz = 20;
130
131 static const double TxSpectrum_WN16MHz[81] = {
132 1.0/160.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
133 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
134 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
135 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
136 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
137 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
138 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
139 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0, 1.0/80.0,
140 1.0/160.0
141 };
142 static const uint TxSpecBW_WN16MHz = 40;
143
144 static const double TxSpectrum_WN20MHz[101] = {
145 1.0/200.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //1
146 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //2
147 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //3
148 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //4
149 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //5
150 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //6
151 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //7
152 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //8
153 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //9
154 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, 1.0/100.0, //10
155 1.0/200.0
156 };
157
158 static const uint TxSpecBW_WN20MHz = 50;
159
160 static const double TxSpectrum_WN40MHz[201] = {
161 1.0/400.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //1
162 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //2
163 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //3
164 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //4
165 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //5
166 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //6
167 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //7
168 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //8
169 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //9
170 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //10
171 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //11
172 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //12
173 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //13
174 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //14
175 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //15
176 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //16
177 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //17
178 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //18
179 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //19
180 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, 1.0/200.0, //20
181 1.0/400.0
182 };
183 static const uint TxSpecBW_WN40MHz = 100;
184
185 static const double TxSpectrum_WN80MHz[401] = {
186 1.0/800.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //1
187 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //2
188 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //3
189 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //4
190 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //5
191 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //6
192 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //7
193 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //8
194 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //9
195 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //10
196 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //11
197 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //12
198 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //13
199 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //14
200 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //15
201 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //16
202 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //17
203 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //18
204 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //19
205 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //20
206 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //21
207 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //22
208 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //23
209 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //24
210 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //25
211 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //26
212 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //27
213 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //28
214 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //29
215 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //30
216 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //31
217 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //32
218 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //33
219 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //34
220 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //35
221 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //36
222 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //37
223 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //38
224 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //39
225 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, 1.0/400.0, //40
226 1.0/800.0
227 };
228 static const uint TxSpecBW_WN80MHz = 200;
229
230 /**
231 * Return the Rx filter equivalent noise BW for a given Rx modulation configuration
232 *
233 * Note that these values do not need to necessarily match the real Rx filter noise BW.
234 * As they really are just a factor in the thermal noise calculation they may
235 * just include any other effect which would affect the resulting thermal noise component
236 * in the demodulator input for that given modulation.
237 */
noiseBW_from_modulation(uint modulation_type)238 static double noiseBW_from_modulation(uint modulation_type) {
239 switch (modulation_type) {
240 case P2G4_MOD_BLE:
241 case P2G4_MOD_BLE_CODED:
242 case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
243 return 1.1e6;
244 break;
245 case P2G4_MOD_BLE2M:
246 case P2G4_MOD_PROP2M:
247 return 2.5e6;
248 break;
249 default:
250 bs_trace_error_line("modem BLE Simple does not support receiving "
251 "configured with this modulation type (%i)\n",
252 modulation_type);
253 break;
254 }
255 return 0;
256 }
257
RxFilter_from_modulation(uint modulation_type,const double ** filter_attenuation,uint * filter_half_BW)258 static void RxFilter_from_modulation(uint modulation_type, const double ** filter_attenuation,
259 uint *filter_half_BW) {
260
261 switch (modulation_type) {
262 case P2G4_MOD_BLE:
263 case P2G4_MOD_BLE_CODED:
264 case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
265 *filter_attenuation = channel_filter_BLE;
266 *filter_half_BW = channel_filter_BW_BLE;
267 break;
268 case P2G4_MOD_BLE2M:
269 case P2G4_MOD_PROP2M:
270 *filter_attenuation = channel_filter_Prop2;
271 *filter_half_BW = channel_filter_BW_Prop2;
272 break;
273 default:
274 bs_trace_error_line("modem BLE Simple does not support receiving "
275 "configured with this modulation type (%i)\n",
276 modulation_type);
277 break;
278 }
279 }
280
spectrum_from_modulation(uint modulation_type,const double ** tx_spectrum,uint * tx_spec_halfBW)281 static void spectrum_from_modulation(uint modulation_type, const double **tx_spectrum,
282 uint *tx_spec_halfBW) {
283
284 switch (modulation_type) {
285 case P2G4_MOD_BLE :
286 case P2G4_MOD_BLE_CODED:
287 case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
288 *tx_spectrum = TxSpectrum_BLE;
289 *tx_spec_halfBW = TxSpecBW_BLE;
290 break;
291 case P2G4_MOD_BLE2M:
292 case P2G4_MOD_PROP2M:
293 *tx_spectrum = TxSpectrum_Prop2;
294 *tx_spec_halfBW = TxSpecBW_Prop2;
295 break;
296 case P2G4_MOD_PROP4M :
297 *tx_spectrum = TxSpectrum_WN4MHz;
298 *tx_spec_halfBW = TxSpecBW_WN4MHz;
299 break;
300 case P2G4_MOD_CWINTER :
301 *tx_spectrum = TxSpectrum_CW;
302 *tx_spec_halfBW = TxSpecBW_CW;
303 break;
304 case P2G4_MOD_WHITENOISE1MHz :
305 *tx_spectrum = TxSpectrum_WN1MHz;
306 *tx_spec_halfBW = TxSpecBW_WN1MHz;
307 break;
308 case P2G4_MOD_WHITENOISE2MHz :
309 *tx_spectrum = TxSpectrum_WN2MHz;
310 *tx_spec_halfBW = TxSpecBW_WN2MHz;
311 break;
312 case P2G4_MOD_WHITENOISE4MHz :
313 *tx_spectrum = TxSpectrum_WN4MHz;
314 *tx_spec_halfBW = TxSpecBW_WN4MHz;
315 break;
316 case P2G4_MOD_WHITENOISE8MHz :
317 *tx_spectrum = TxSpectrum_WN8MHz;
318 *tx_spec_halfBW = TxSpecBW_WN8MHz;
319 break;
320 case P2G4_MOD_WHITENOISE16MHz :
321 *tx_spectrum = TxSpectrum_WN16MHz;
322 *tx_spec_halfBW = TxSpecBW_WN16MHz;
323 break;
324 case P2G4_MOD_WHITENOISE20MHz :
325 *tx_spectrum = TxSpectrum_WN20MHz;
326 *tx_spec_halfBW = TxSpecBW_WN20MHz;
327 break;
328 case P2G4_MOD_WHITENOISE40MHz :
329 *tx_spectrum = TxSpectrum_WN40MHz;
330 *tx_spec_halfBW = TxSpecBW_WN40MHz;
331 break;
332 case P2G4_MOD_WHITENOISE80MHz :
333 *tx_spectrum = TxSpectrum_WN80MHz;
334 *tx_spec_halfBW = TxSpecBW_WN80MHz;
335 break;
336 case P2G4_MOD_WLANINTER :
337 *tx_spectrum = TxSpectrum_WLAN;
338 *tx_spec_halfBW = TxSpecBW_WLAN;
339 break;
340 default:
341 bs_trace_warning_line("modem BLE Simple does not support seeing this "
342 "modulation type (%i) in the air, it will be "
343 "treated as 1MHz white noise\n",modulation_type);
344 *tx_spectrum = TxSpectrum_WN1MHz;
345 *tx_spec_halfBW = TxSpecBW_WN1MHz;
346 break;
347 }
348 }
349
350 /**
351 * Q function:
352 * Q(x) = P(X > x) , where X = N(0,1)
353 * That is, Q(x) is the probability of a N(0,1) having a value > x
354 * where N(0,1) is a Normal distribution with average 0, and standard deviation 1
355 */
Q_function(double x)356 static double Q_function(double x) {
357 return 1.0/2.0*erfc(x/sqrt(2.0));
358 }
359
360 /************
361 * Modem IF *
362 ************/
363
364 /**
365 * Initialize the modem internal status
366 *
367 * The input parameters are:
368 * dev_nbr : the device number this modem library corresponds to
369 * (note that this library may be reused in between several devices)
370 * nbr_devices : the total number of devices in the simulation (gives the length of vectors later)
371 * char *argv[] : a set of arguments passed to the modem library (same convention as POSIX main() command line arguments)
372 * int argc : the number of arguments passed to the modem library
373 *
374 * It is up to the modem to define which arguments it can or shall receive to configure it
375 * The only argument all modems shall understand is :
376 * [-h] [--h] [--help] [-?] The modem shall print a list of arguments it supports with a descriptive message for each
377 *
378 * This function shall return a pointer to this modems status structure
379 * This same pointer will be passed back to consecutive function calls of the library (void *this)
380 *
381 * If the library does not require to keep any status it can just return NULL
382 */
modem_init(int argc,char * argv[],uint d,uint n_devs)383 void* modem_init(int argc, char *argv[], uint d, uint n_devs) {
384 m_simple_status_t* mo_st;
385
386 mo_st = (m_simple_status_t *)bs_calloc(1,sizeof(m_simple_status_t));
387
388 mo_st->nbr_devices = n_devs;
389
390 modem_simple_argparse(argc, argv, d, &mo_st->args);
391
392 mo_st->device_RSSI_offsetdB = bs_random_Gaus()*mo_st->args.RSSI_offsetdB_std;
393
394 return (void*)mo_st;
395 }
396
397 /**
398 * Calculate the SNR of the desired input signal at the digital modem input/analog output
399 * including all modem analog impairments
400 *
401 * inputs:
402 * this : Pointer to this modem object
403 * rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
404 * rx_powers : For each possible transmitter ([0..n_devices-1]) what is their power level at this device antenna connector in dBm
405 * txl_c : For each possible transmitter what are their Tx parameters
406 * desired_tx_nbr : which of the transmitters is the one we are trying to receive
407 *
408 * outputs:
409 * OutputSNR : SNR in the analog output / digital input of this modem (dB)
410 * Output_RSSI_power_level : RSSI level (analog, dBm) sent to the modem digital
411 */
modem_analog_rx(void * this,p2G4_radioparams_t * rx_radioparams,double * OutputSNR,double * Output_RSSI_power_level,double * rx_powers,tx_l_c_t * txl_c,uint desired_tx_nbr)412 void modem_analog_rx(void *this, p2G4_radioparams_t *rx_radioparams, double *OutputSNR,
413 double *Output_RSSI_power_level, double *rx_powers, tx_l_c_t *txl_c,
414 uint desired_tx_nbr) {
415 m_simple_status_t *mo_st = (m_simple_status_t *)this;
416 uint i;
417
418 double ThermalNoisemW = 0;
419 double TotalInterfmW = 0;
420 double TotalPhaseReciprocalMixmW = 0; //If we were more precise, we would also calculate here the phase noise mixing
421 double TotalIntermmW = 0; //Intermodulation noise. This can be very significant if there is any blocker present, but we don't include it in this model
422
423 { //Thermal noise calculation
424 double NoiseFigure = mo_st->args.NFigure_ana; //dB
425 double EquivalentBW = noiseBW_from_modulation(rx_radioparams->modulation);
426 ThermalNoisemW = EquivalentBW * pow(10, (-174.0 + NoiseFigure )/10);
427 }
428
429 { //Interference calculation (including adjacent channel)
430 const double *RxFilterAttenuation;
431 uint RxFilterHalfBW;
432
433 RxFilter_from_modulation(rx_radioparams->modulation, &RxFilterAttenuation, &RxFilterHalfBW);
434 //The "Rx filter" shall include all effects which would increase
435 //the noise/interference power at a given frequency offset
436
437 int CenterR = p2G4_freq_to_d(rx_radioparams->center_freq) / (FreqRes/1e6); //Center frequency (where 0 = 2400MHz)
438 int StartR = CenterR - RxFilterHalfBW;
439 int EndR = CenterR + RxFilterHalfBW;
440
441 for ( i = 0; i < mo_st->nbr_devices ; i++ ) {
442 if ( txl_c->used[i] && ( i != desired_tx_nbr ) ){ //For each active transmitter
443 //Calculate how much power comes thru the Rx channel/IF filtering
444
445 const double *TxSpectrum;
446 uint TxSpecHalfBW;
447
448 spectrum_from_modulation(txl_c->tx_list[i].tx_s.radio_params.modulation, &TxSpectrum, &TxSpecHalfBW);
449
450 int CenterI = p2G4_freq_to_d(txl_c->tx_list[i].tx_s.radio_params.center_freq) / (FreqRes/1e6); //Center frequency (where 0 = 2400MHz)
451 int StartI = CenterI - TxSpecHalfBW;
452 int EndI = CenterI + TxSpecHalfBW;
453
454 int StartOverlap = BS_MAX(StartR,StartI);
455 int EndOverlap = BS_MIN(EndR, EndI);
456
457 double AccRatio = 0; //Calculate the overlap of the Rx filter with the tx modulation shape
458 for (int Freq = StartOverlap; Freq <= EndOverlap ; Freq++) {
459 int IndexR = (Freq - StartR);
460 int IndexI = (Freq - StartI);
461 AccRatio = AccRatio + TxSpectrum[IndexI] * RxFilterAttenuation[IndexR];
462 }
463
464 TotalInterfmW = TotalInterfmW + AccRatio * pow(10.0, rx_powers[i]/10.0);
465
466 }
467 }
468 } //End of Interference calc.
469
470 { //Adding it all together
471 double DesiredPowerdBm;
472 double TotalNoisemW = ThermalNoisemW + TotalInterfmW + TotalPhaseReciprocalMixmW + TotalIntermmW;
473 double TotalSignalEtNoisemW;
474
475 if ( desired_tx_nbr >= mo_st->nbr_devices ){
476 DesiredPowerdBm = -1000; //-1000dB == nothing
477 } else {
478 DesiredPowerdBm = rx_powers[desired_tx_nbr];
479 }
480
481 TotalSignalEtNoisemW = TotalNoisemW + pow( 10.0, DesiredPowerdBm/10.0 );
482
483 *OutputSNR = DesiredPowerdBm - 10.0*log10( TotalNoisemW );
484 *Output_RSSI_power_level = 10*log10(TotalSignalEtNoisemW);
485 }
486 }
487
488 /**
489 * Return the bit error probability ([0.. RAND_PROB_1]) for a given SNR
490 *
491 * inputs:
492 * this : Pointer to this modem object
493 * rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
494 * SNR : SNR level at the analog output as calculated by modem_analog_rx()
495 */
modem_digital_perf_ber(void * this,p2G4_modemdigparams_t * rx_modem_params,double SNR)496 uint32_t modem_digital_perf_ber(void *this, p2G4_modemdigparams_t *rx_modem_params, double SNR) {
497 m_simple_status_t *mo_st = (m_simple_status_t *)this;
498
499 double coding_gain = 0;
500
501 if (rx_modem_params->modulation == P2G4_MOD_BLE_CODED) {
502 //By now let's just offset the curve by 4 and 9dB respectively
503 //It is not too accurate, but much better than nothing
504 if (rx_modem_params->coding_rate == 2) { //S=2
505 coding_gain = 4;
506 } else { //S=8
507 coding_gain = 9;
508 }
509 }
510
511 //Just the theoretical BER vs Eb/No | SNR
512 // BER = Q(sqrt(Eb/No)) = 1/2*erfc(sqrt(Eb/(2*No)))
513
514 /*SNR = SNR - NFigure;
515 N_u = 1./10.^((SNR)/10);
516 N_u_o = N_u + 10.^(NoiseFloor/10);
517 SNR_2 = 10*log10(1./N_u_o); */
518
519 SNR = SNR - mo_st->args.NFigure_extra + coding_gain;
520 double N_u = 1.0/pow(10.0,SNR/10.0); //equivalent noise level level relative to the signal power
521 double N_u_o = N_u + pow(10.0, mo_st->args.NFloor_dig/10); //add the noise equivalent to the noise floor (relative to the singal power also)
522
523 double SNR_nu = 1.0/N_u_o; //back to SNR (in natural units)
524 //SNR = 10.0*log10(1.0/N_u_o);
525
526 double BER = Q_function(sqrt(SNR_nu)); //BER from [0..1.0]
527 //BER = Q_function(pow(10.0,SNR/20));
528
529 return BER*RAND_PROB_1 + 0.5; //scaled to 32bits and rounded to nearest int.
530 }
531
532 /**
533 * Return the probability of the packet sync'ing ([0.. RAND_PROB_1]) for a given SNR and
534 * transmission parameters
535 *
536 * (note that this should ONLY include excess packet error probability,
537 * as over the sync word and address normal bit errors will also be calculated)
538 *
539 * inputs:
540 * this : Pointer to this modem object
541 * rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
542 * SNR : SNR level at the analog output as calculated by modem_analog_rx()
543 * tx_s : Parameters of the transmission we are receiving (in case the sync. probability depends on any of them)
544 */
modem_digital_perf_sync(void * this,p2G4_modemdigparams_t * rx_modem_params,double SNR,p2G4_txv2_t * tx_s)545 uint32_t modem_digital_perf_sync(void *this, p2G4_modemdigparams_t *rx_modem_params,
546 double SNR, p2G4_txv2_t* tx_s) {
547 m_simple_status_t *mo_st = (m_simple_status_t *)this;
548 mo_simple_args_t *args = &mo_st->args;
549
550 return args->Sync_prob;
551 }
552
553 /**
554 * Return the digital RSSI value the modem would have produced for this given
555 * RSSI_power_level in the digital input
556 *
557 * inputs:
558 * this : Pointer to this modem object
559 * rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
560 * RSSI_power_level : Analog power level as measured by modem_analog_rx()
561 *
562 * outputs:
563 * RSSI : RSSI "digital" value returned by this modem, following the p2G4_rssi_power_t format (16.16 signed value)
564 */
modem_digital_RSSI(void * this,p2G4_radioparams_t * rx_radioparams,double RSSI_power_level,p2G4_rssi_power_t * RSSI)565 void modem_digital_RSSI(void *this, p2G4_radioparams_t *rx_radioparams,
566 double RSSI_power_level, p2G4_rssi_power_t* RSSI) {
567
568 m_simple_status_t *mo_st = (m_simple_status_t *)this;
569
570 RSSI_power_level += mo_st->device_RSSI_offsetdB; //average measurement offset of this device relative to a perfect device
571 RSSI_power_level += bs_random_Gaus() * mo_st->args.RSSI_meas_noisedB_std; //measurement noise
572
573 *RSSI = p2G4_RSSI_value_from_dBm(RSSI_power_level);
574 }
575
576 /**
577 * Clean up: Free the memory the modem may have allocated
578 * close any file descriptors etc.
579 * (the simulation has ended)
580 */
modem_delete(void * this)581 void modem_delete(void *this) {
582 if (this != NULL) {
583 free(this);
584 }
585 }
586