1 /*
2 * Copyright 2018 Oticon A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <string.h>
7 #include "bs_pc_2G4_utils.h"
8 #include "bs_tracing.h"
9 #include "bs_oswrap.h"
10
11 /**
12 * Return a power level as usable by libCom from a double value (dBm)
13 */
p2G4_power_from_d(double power)14 p2G4_power_t p2G4_power_from_d(double power){
15 if ( power < -128 ) {//we need to ensure we fit into p2G4_power_t (range -128dBm..127dBm)
16 power = -128;
17 } else if ( power > 127 ) {
18 power = 127;
19 }
20 return (p2G4_power_t)(power*256);
21 }
22
23 /**
24 * Convert a libCom power level (p2G4_power_t) into a double float (dBm)
25 */
p2G4_power_to_d(p2G4_power_t power)26 double p2G4_power_to_d(p2G4_power_t power){
27 return ((double)power)/256.0;
28 }
29
30 /**
31 * Convert a libCom RSSI level (p2G4_rssi_power_t) into a double float (dBm)
32 */
p2G4_RSSI_value_to_dBm(p2G4_rssi_power_t value)33 double p2G4_RSSI_value_to_dBm(p2G4_rssi_power_t value){
34 return value/65536.0;
35 }
36
37 /**
38 * Convert a power level in dBm (Represented as double) into P2G4Com RSSI level format
39 */
p2G4_RSSI_value_from_dBm(double value)40 p2G4_rssi_power_t p2G4_RSSI_value_from_dBm(double value){
41 if (value < -32768) {//staturate to the type limit
42 value = -32768;
43 } else if (value > 32767) {
44 value = 32767;
45 }
46 return (p2G4_rssi_power_t)(value*65536);
47 }
48
49 /**
50 * Return a center frequency as usable by P2G4Com from a ble channel number
51 */
p2G4_center_freq_from_ble_ch_nbr(uint ch_idx)52 p2G4_freq_t p2G4_center_freq_from_ble_ch_nbr(uint ch_idx){
53 double freq;
54 if (ch_idx < 37) {
55 freq = 2404 + ch_idx*2 + (ch_idx > 10)*2;
56 } else {
57 if (ch_idx == 37) {
58 freq = 2402;
59 } else if (ch_idx == 38) {
60 freq = 2426;
61 } else if (ch_idx == 39) {
62 freq = 2480;
63 }
64 }
65 p2G4_freq_t center_freq;
66 if ( p2G4_freq_from_d( freq, 1, ¢er_freq ) != 0 ){
67 bs_trace_error_line("Got wrong channel index (%i)\n", ch_idx);
68 }
69 return center_freq;
70 }
71
72 /**
73 * Convert a strings into a low level modulation
74 * The strings may be either straight the number (decimal or hexadecimal) (which is a inadvisable way of using it)
75 * or a human readable string (see below in the code)
76 */
p2G4_modulation_from_string(const char * name,p2G4_modulation_t * modulation,p2G4_mod_limits_t limit,int verb)77 int p2G4_modulation_from_string(const char* name, p2G4_modulation_t *modulation, p2G4_mod_limits_t limit, int verb){
78 uint i = 0;
79
80 while(1) {
81 if ( name[i] != 0 ) {
82 if ( name[i] == ' ' ) {
83 i++;
84 } else {
85 break;
86 }
87 } else {
88 bs_trace_warning_line("No modulation type found in string %s\n",name);
89 return -1;
90 }
91 }
92
93 if ( name[i] >= '0' && name[i] <='9') { //it's a number
94 bs_trace_warning_line("Converting modulation from numerical string not yet allowed %s\n",name);
95 return -1;
96 //TOLOW: handle this
97 } else { //It's a string
98 if ( strncmp(&name[i], "BLI",3)==0 ){
99 *modulation = P2G4_MOD_BLEINTER;
100 if (verb) bs_trace_raw(9,"Modulation set to BLE interferent\n");
101 } else if ( strncmp(&name[i], "BL",2)==0 ){
102 *modulation = P2G4_MOD_BLE;
103 if (verb) bs_trace_raw(9,"Modulation set to BLE\n");
104 } else if ( strncmp(&name[i], "CW",2)==0 ) {
105 *modulation = P2G4_MOD_CWINTER;
106 if (verb) bs_trace_raw(9,"Modulation set to CW\n");
107 } else if ( strncmp(&name[i], "Prop2M",6)==0 ) {
108 *modulation = P2G4_MOD_PROP2M;
109 if (verb) bs_trace_raw(9,"Modulation set to 2Mbit propietary\n");
110 } else if ( strncmp(&name[i], "Prop3M",6)==0 ) {
111 *modulation = P2G4_MOD_PROP3M;
112 if (verb) bs_trace_raw(9,"Modulation set to 3Mbit propietary\n");
113 } else if ( strncmp(&name[i], "Prop4M",6)==0 ) {
114 *modulation = P2G4_MOD_PROP4M;
115 if (verb) bs_trace_raw(9,"Modulation set to 4Mbit propietary\n");
116 } else if ( strncmp(&name[i], "WLAN",4)==0 ){
117 *modulation = P2G4_MOD_WLANINTER;
118 if (verb) bs_trace_raw(9,"Modulation set to WLAN\n");
119 } else if ( strcmp(&name[i], "WN16")==0 ){
120 *modulation = P2G4_MOD_WHITENOISE16MHz;
121 if (verb) bs_trace_raw(9,"Modulation set to 16MHz White noise\n");
122 } else if ( strcmp(&name[i], "WN1")==0 ){
123 *modulation = P2G4_MOD_WHITENOISE1MHz;
124 if (verb) bs_trace_raw(9,"Modulation set to 1MHz White noise\n");
125 } else if ( strcmp(&name[i], "WN2")==0 ){
126 *modulation = P2G4_MOD_WHITENOISE2MHz;
127 if (verb) bs_trace_raw(9,"Modulation set to 2MHz White noise\n");
128 } else if ( strcmp(&name[i], "WN4")==0 ){
129 *modulation = P2G4_MOD_WHITENOISE4MHz;
130 if (verb) bs_trace_raw(9,"Modulation set to 4MHz White noise\n");
131 } else if ( strcmp(&name[i], "WN8")==0 ){
132 *modulation = P2G4_MOD_WHITENOISE8MHz;
133 if (verb) bs_trace_raw(9,"Modulation set to 8MHz White noise\n");
134 } else if ( strcmp(&name[i], "WN20")==0 ){
135 *modulation = P2G4_MOD_WHITENOISE20MHz;
136 if (verb) bs_trace_raw(9,"Modulation set to 20MHz White noise\n");
137 } else if ( strcmp(&name[i], "WN40")==0 ){
138 *modulation = P2G4_MOD_WHITENOISE40MHz;
139 if (verb) bs_trace_raw(9,"Modulation set to 40MHz White noise\n");
140 } else if ( strcmp(&name[i], "WN80")==0 ){
141 *modulation = P2G4_MOD_WHITENOISE80MHz;
142 if (verb) bs_trace_raw(9,"Modulation set to 80MHz White noise\n");
143 } else {
144 bs_trace_warning_line("Unknown modulation type %s\n",name);
145 return -1;
146 }
147 }
148
149 return 0;
150 }
151
152 /**
153 * Convert a p2G4_freq_t frequency into a double
154 *
155 * Note that the frequency is returned in MHz, as an offset relative to 2400 MHz
156 */
p2G4_freq_to_d(p2G4_freq_t freq)157 double p2G4_freq_to_d(p2G4_freq_t freq){
158 return ((double)freq)/(1<<P2G4_freq_FRACB);
159 }
160
161 /**
162 * Convert a frequency in double float to p2G4_freq_t
163 *
164 * If prevent_OOB is set, frequencies out of the 2400..2480MHz band wont be allowed
165 */
p2G4_freq_from_d(double center_freq,int prevent_OOB,p2G4_freq_t * result)166 int p2G4_freq_from_d(double center_freq, int prevent_OOB, p2G4_freq_t *result){
167 double i_center_freq = center_freq;
168 if ( center_freq > 1e9 ){ //they provided it in Hz
169 center_freq = center_freq/1e6;
170 } else if ( center_freq > 1e6 ) { //they provided it in KHz..
171 center_freq = center_freq/1e3;
172 }
173 //We expect MHz
174
175 if ( ( center_freq >= 2400-128 ) && ( center_freq <= 2400+128 ) ) //we offset it down to 0 = 2400MHz
176 center_freq = center_freq - 2400;
177 //it could have been provided directly as an offset relative to 2400MHz and we would accept it
178
179 if ( ( center_freq >= 127 ) || ( center_freq <= -127 ) ) {
180 bs_trace_error_line("center_frequency seems to be more than 127MHz apart from 2400MHz (%e, %e+2400MHz)\n",i_center_freq, center_freq);
181 }
182
183 if ( ( prevent_OOB == 1 ) && ( ( center_freq > 80) || (center_freq < 0 ) ) ){
184 bs_trace_warning_line("center_frequency out of ISM band\n");
185 return -1;
186 }
187
188 center_freq *= (1<<P2G4_freq_FRACB);
189
190 *result = (p2G4_freq_t)(center_freq+0.5);
191 return 0;
192 }
193