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_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
242 return 1.1e6;
243 break;
244 case P2G4_MOD_BLE2M:
245 case P2G4_MOD_PROP2M:
246 return 2.5e6;
247 break;
248 default:
249 bs_trace_error_line("modem BLE Simple does not support receiving "
250 "configured with this modulation type (%i)\n",
251 modulation_type);
252 break;
253 }
254 return 0;
255 }
256
RxFilter_from_modulation(uint modulation_type,const double ** filter_attenuation,uint * filter_half_BW)257 static void RxFilter_from_modulation(uint modulation_type, const double ** filter_attenuation,
258 uint *filter_half_BW) {
259
260 switch (modulation_type) {
261 case P2G4_MOD_BLE:
262 case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
263 *filter_attenuation = channel_filter_BLE;
264 *filter_half_BW = channel_filter_BW_BLE;
265 break;
266 case P2G4_MOD_BLE2M:
267 case P2G4_MOD_PROP2M:
268 *filter_attenuation = channel_filter_Prop2;
269 *filter_half_BW = channel_filter_BW_Prop2;
270 break;
271 default:
272 bs_trace_error_line("modem BLE Simple does not support receiving "
273 "configured with this modulation type (%i)\n",
274 modulation_type);
275 break;
276 }
277 }
278
spectrum_from_modulation(uint modulation_type,const double ** tx_spectrum,uint * tx_spec_halfBW)279 static void spectrum_from_modulation(uint modulation_type, const double **tx_spectrum,
280 uint *tx_spec_halfBW) {
281
282 switch (modulation_type) {
283 case P2G4_MOD_BLE :
284 case P2G4_MOD_154_250K_DSS: //Provisionally let's treat 15.4 like 1Mbps BLE
285 *tx_spectrum = TxSpectrum_BLE;
286 *tx_spec_halfBW = TxSpecBW_BLE;
287 break;
288 case P2G4_MOD_BLE2M:
289 case P2G4_MOD_PROP2M:
290 *tx_spectrum = TxSpectrum_Prop2;
291 *tx_spec_halfBW = TxSpecBW_Prop2;
292 break;
293 case P2G4_MOD_PROP4M :
294 *tx_spectrum = TxSpectrum_WN4MHz;
295 *tx_spec_halfBW = TxSpecBW_WN4MHz;
296 break;
297 case P2G4_MOD_CWINTER :
298 *tx_spectrum = TxSpectrum_CW;
299 *tx_spec_halfBW = TxSpecBW_CW;
300 break;
301 case P2G4_MOD_WHITENOISE1MHz :
302 *tx_spectrum = TxSpectrum_WN1MHz;
303 *tx_spec_halfBW = TxSpecBW_WN1MHz;
304 break;
305 case P2G4_MOD_WHITENOISE2MHz :
306 *tx_spectrum = TxSpectrum_WN2MHz;
307 *tx_spec_halfBW = TxSpecBW_WN2MHz;
308 break;
309 case P2G4_MOD_WHITENOISE4MHz :
310 *tx_spectrum = TxSpectrum_WN4MHz;
311 *tx_spec_halfBW = TxSpecBW_WN4MHz;
312 break;
313 case P2G4_MOD_WHITENOISE8MHz :
314 *tx_spectrum = TxSpectrum_WN8MHz;
315 *tx_spec_halfBW = TxSpecBW_WN8MHz;
316 break;
317 case P2G4_MOD_WHITENOISE16MHz :
318 *tx_spectrum = TxSpectrum_WN16MHz;
319 *tx_spec_halfBW = TxSpecBW_WN16MHz;
320 break;
321 case P2G4_MOD_WHITENOISE20MHz :
322 *tx_spectrum = TxSpectrum_WN20MHz;
323 *tx_spec_halfBW = TxSpecBW_WN20MHz;
324 break;
325 case P2G4_MOD_WHITENOISE40MHz :
326 *tx_spectrum = TxSpectrum_WN40MHz;
327 *tx_spec_halfBW = TxSpecBW_WN40MHz;
328 break;
329 case P2G4_MOD_WHITENOISE80MHz :
330 *tx_spectrum = TxSpectrum_WN80MHz;
331 *tx_spec_halfBW = TxSpecBW_WN80MHz;
332 break;
333 case P2G4_MOD_WLANINTER :
334 *tx_spectrum = TxSpectrum_WLAN;
335 *tx_spec_halfBW = TxSpecBW_WLAN;
336 break;
337 default:
338 bs_trace_warning_line("modem BLE Simple does not support seeing this "
339 "modulation type (%i) in the air, it will be "
340 "treated as 1MHz white noise\n",modulation_type);
341 *tx_spectrum = TxSpectrum_WN1MHz;
342 *tx_spec_halfBW = TxSpecBW_WN1MHz;
343 break;
344 }
345 }
346
347 /**
348 * Q function:
349 * Q(x) = P(X > x) , where X = N(0,1)
350 * That is, Q(x) is the probability of a N(0,1) having a value > x
351 * where N(0,1) is a Normal distribution with average 0, and standard deviation 1
352 */
Q_function(double x)353 static double Q_function(double x) {
354 return 1.0/2.0*erfc(x/sqrt(2.0));
355 }
356
357 /************
358 * Modem IF *
359 ************/
360
361 /**
362 * Initialize the modem internal status
363 *
364 * The input parameters are:
365 * dev_nbr : the device number this modem library corresponds to
366 * (note that this library may be reused in between several devices)
367 * nbr_devices : the total number of devices in the simulation (gives the length of vectors later)
368 * char *argv[] : a set of arguments passed to the modem library (same convention as POSIX main() command line arguments)
369 * int argc : the number of arguments passed to the modem library
370 *
371 * It is up to the modem to define which arguments it can or shall receive to configure it
372 * The only argument all modems shall understand is :
373 * [-h] [--h] [--help] [-?] The modem shall print a list of arguments it supports with a descriptive message for each
374 *
375 * This function shall return a pointer to this modems status structure
376 * This same pointer will be passed back to consecutive function calls of the library (void *this)
377 *
378 * If the library does not require to keep any status it can just return NULL
379 */
modem_init(int argc,char * argv[],uint d,uint n_devs)380 void* modem_init(int argc, char *argv[], uint d, uint n_devs) {
381 m_simple_status_t* mo_st;
382
383 mo_st = (m_simple_status_t *)bs_calloc(1,sizeof(m_simple_status_t));
384
385 mo_st->nbr_devices = n_devs;
386
387 modem_simple_argparse(argc, argv, d, &mo_st->args);
388
389 mo_st->device_RSSI_offsetdB = bs_random_Gaus()*mo_st->args.RSSI_offsetdB_std;
390
391 return (void*)mo_st;
392 }
393
394 /**
395 * Calculate the SNR of the desired input signal at the digital modem input/analog output
396 * including all modem analog impairments
397 *
398 * inputs:
399 * this : Pointer to this modem object
400 * rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
401 * rx_powers : For each possible transmitter ([0..n_devices-1]) what is their power level at this device antenna connector in dBm
402 * txl_c : For each possible transmitter what are their Tx parameters
403 * desired_tx_nbr : which of the transmitters is the one we are trying to receive
404 *
405 * outputs:
406 * OutputSNR : SNR in the analog output / digital input of this modem (dB)
407 * Output_RSSI_power_level : RSSI level (analog, dBm) sent to the modem digital
408 */
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)409 void modem_analog_rx(void *this, p2G4_radioparams_t *rx_radioparams, double *OutputSNR,
410 double *Output_RSSI_power_level, double *rx_powers, tx_l_c_t *txl_c,
411 uint desired_tx_nbr) {
412 m_simple_status_t *mo_st = (m_simple_status_t *)this;
413 uint i;
414
415 double ThermalNoisemW = 0;
416 double TotalInterfmW = 0;
417 double TotalPhaseReciprocalMixmW = 0; //If we were more precise, we would also calculate here the phase noise mixing
418 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
419
420 { //Thermal noise calculation
421 double NoiseFigure = mo_st->args.NFigure_ana; //dB
422 double EquivalentBW = noiseBW_from_modulation(rx_radioparams->modulation);
423 ThermalNoisemW = EquivalentBW * pow(10, (-174.0 + NoiseFigure )/10);
424 }
425
426 { //Interference calculation (including adjacent channel)
427 const double *RxFilterAttenuation;
428 uint RxFilterHalfBW;
429
430 RxFilter_from_modulation(rx_radioparams->modulation, &RxFilterAttenuation, &RxFilterHalfBW);
431 //The "Rx filter" shall include all effects which would increase
432 //the noise/interference power at a given frequency offset
433
434 int CenterR = p2G4_freq_to_d(rx_radioparams->center_freq) / (FreqRes/1e6); //Center frequency (where 0 = 2400MHz)
435 int StartR = CenterR - RxFilterHalfBW;
436 int EndR = CenterR + RxFilterHalfBW;
437
438 for ( i = 0; i < mo_st->nbr_devices ; i++ ) {
439 if ( txl_c->used[i] && ( i != desired_tx_nbr ) ){ //For each active transmitter
440 //Calculate how much power comes thru the Rx channel/IF filtering
441
442 const double *TxSpectrum;
443 uint TxSpecHalfBW;
444
445 spectrum_from_modulation(txl_c->tx_list[i].tx_s.radio_params.modulation, &TxSpectrum, &TxSpecHalfBW);
446
447 int CenterI = p2G4_freq_to_d(txl_c->tx_list[i].tx_s.radio_params.center_freq) / (FreqRes/1e6); //Center frequency (where 0 = 2400MHz)
448 int StartI = CenterI - TxSpecHalfBW;
449 int EndI = CenterI + TxSpecHalfBW;
450
451 int StartOverlap = BS_MAX(StartR,StartI);
452 int EndOverlap = BS_MIN(EndR, EndI);
453
454 double AccRatio = 0; //Calculate the overlap of the Rx filter with the tx modulation shape
455 for (int Freq = StartOverlap; Freq <= EndOverlap ; Freq++) {
456 int IndexR = (Freq - StartR);
457 int IndexI = (Freq - StartI);
458 AccRatio = AccRatio + TxSpectrum[IndexI] * RxFilterAttenuation[IndexR];
459 }
460
461 TotalInterfmW = TotalInterfmW + AccRatio * pow(10.0, rx_powers[i]/10.0);
462
463 }
464 }
465 } //End of Interference calc.
466
467 { //Adding it all together
468 double DesiredPowerdBm;
469 double TotalNoisemW = ThermalNoisemW + TotalInterfmW + TotalPhaseReciprocalMixmW + TotalIntermmW;
470 double TotalSignalEtNoisemW;
471
472 if ( desired_tx_nbr >= mo_st->nbr_devices ){
473 DesiredPowerdBm = -1000; //-1000dB == nothing
474 } else {
475 DesiredPowerdBm = rx_powers[desired_tx_nbr];
476 }
477
478 TotalSignalEtNoisemW = TotalNoisemW + pow( 10.0, DesiredPowerdBm/10.0 );
479
480 *OutputSNR = DesiredPowerdBm - 10.0*log10( TotalNoisemW );
481 *Output_RSSI_power_level = 10*log10(TotalSignalEtNoisemW);
482 }
483 }
484
485 /**
486 * Return the bit error probability ([0.. RAND_PROB_1]) for a given SNR
487 *
488 * inputs:
489 * this : Pointer to this modem object
490 * rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
491 * SNR : SNR level at the analog output as calculated by modem_analog_rx()
492 */
modem_digital_perf_ber(void * this,p2G4_radioparams_t * rx_radioparams,double SNR)493 uint32_t modem_digital_perf_ber(void *this, p2G4_radioparams_t *rx_radioparams, double SNR) {
494 m_simple_status_t *mo_st = (m_simple_status_t *)this;
495
496 //Just the theoretical BER vs Eb/No | SNR:
497 // BER = Q(sqrt(Eb/No)) = 1/2*erfc(sqrt(Eb/(2*No)))
498
499 /*SNR = SNR - NFigure;
500 N_u = 1./10.^((SNR)/10);
501 N_u_o = N_u + 10.^(NoiseFloor/10);
502 SNR_2 = 10*log10(1./N_u_o); */
503
504 SNR = SNR - mo_st->args.NFigure_extra;
505 double N_u = 1.0/pow(10.0,SNR/10.0); //equivalent noise level level relative to the signal power
506 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)
507
508 double SNR_nu = 1.0/N_u_o; //back to SNR (in natural units)
509 //SNR = 10.0*log10(1.0/N_u_o);
510
511 double BER = Q_function(sqrt(SNR_nu)); //BER from [0..1.0]
512 //BER = Q_function(pow(10.0,SNR/20));
513
514 return BER*RAND_PROB_1 + 0.5; //scaled to 32bits and rounded to nearest int.
515 }
516
517 /**
518 * Return the probability of the packet sync'ing ([0.. RAND_PROB_1]) for a given SNR and
519 * transmission parameters
520 *
521 * (note that this should ONLY include excess packet error probability,
522 * as over the sync word and address normal bit errors will also be calculated)
523 *
524 * inputs:
525 * this : Pointer to this modem object
526 * rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
527 * SNR : SNR level at the analog output as calculated by modem_analog_rx()
528 * tx_s : Parameters of the transmission we are receiving (in case the sync. probability depends on any of them)
529 */
modem_digital_perf_sync(void * this,p2G4_radioparams_t * rx_radioparams,double SNR,p2G4_txv2_t * tx_s)530 uint32_t modem_digital_perf_sync(void *this, p2G4_radioparams_t *rx_radioparams,
531 double SNR, p2G4_txv2_t* tx_s) {
532 m_simple_status_t *mo_st = (m_simple_status_t *)this;
533 mo_simple_args_t *args = &mo_st->args;
534
535 return args->Sync_prob;
536 }
537
538 /**
539 * Return the digital RSSI value the modem would have produced for this given
540 * RSSI_power_level in the digital input
541 *
542 * inputs:
543 * this : Pointer to this modem object
544 * rx_radioparams : Radio parameters/configuration of this receiver for this Rx/RSSI measurement
545 * RSSI_power_level : Analog power level as measured by modem_analog_rx()
546 *
547 * outputs:
548 * RSSI : RSSI "digital" value returned by this modem, following the p2G4_rssi_power_t format (16.16 signed value)
549 */
modem_digital_RSSI(void * this,p2G4_radioparams_t * rx_radioparams,double RSSI_power_level,p2G4_rssi_power_t * RSSI)550 void modem_digital_RSSI(void *this, p2G4_radioparams_t *rx_radioparams,
551 double RSSI_power_level, p2G4_rssi_power_t* RSSI) {
552
553 m_simple_status_t *mo_st = (m_simple_status_t *)this;
554
555 RSSI_power_level += mo_st->device_RSSI_offsetdB; //average measurement offset of this device relative to a perfect device
556 RSSI_power_level += bs_random_Gaus() * mo_st->args.RSSI_meas_noisedB_std; //measurement noise
557
558 *RSSI = p2G4_RSSI_value_from_dBm(RSSI_power_level);
559 }
560
561 /**
562 * Clean up: Free the memory the modem may have allocated
563 * close any file descriptors etc.
564 * (the simulation has ended)
565 */
modem_delete(void * this)566 void modem_delete(void *this) {
567 if (this != NULL) {
568 free(this);
569 }
570 }
571