1 // =====================================================================
2 //
3 // time_table.cxx
4 //
5 // Author(s):
6 // Robert Stiles, KK5VD, Copyright (C) 2013, 2014
7 //
8 // This file is part of FLAMP and FLMSG.
9 //
10 // This is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // This software is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 //
23 // =====================================================================
24
25
26 // Doxygen
27 /** ********************************************************
28 \page page_modem_timing_table Modem Timing Table Structure
29
30 A table and functions to calculate the number of seconds or
31 minutes needed to transmit a string of data.
32
33 \par char *modem_name
34 The string ID of the modem.<br>
35 Example:<br>
36 8PSK125, 8PSK250, etc. <br>
37
38 \par float scale
39 A value used to scale the resulting toble in an attemp to adjust for
40 errors. However, because of the differential errors for each charater
41 and overhead time, it's not recommended for use.
42
43 \par float overhead
44 Each modem contains a leading and trailing pre/postamble. The time for
45 both a accumulated and stored in this variable.
46
47 \par table[256]
48 Floating point representation of the amount of time it takes to
49 transmit the character in seconds. Character value range 0 to 255.
50
51 \verbatim
52 typedef struct {
53 char *mode_name;
54 float scale;
55 float overhead;
56 float table[256];
57 } MODE_TIME_TABLE;
58
59 static MODE_TIME_TABLE mode_time_table[] = {
60 {
61 (char *) "8PSK125", 1.0, 2.973000,
62 {
63 0.058500, 0.058875, 0.058500, 0.058500, 0.058875, 0.058500, 0.058500, 0.058875,
64 0.042500, 0.058500, 0.058875, 0.058500, 0.058500, 0.042875, 0.058500, 0.058500,
65 0.058875, 0.058500, 0.058500, 0.058875, 0.058500, 0.058500, 0.058875, 0.058500,
66 0.058500, 0.058875, 0.058500, 0.058500, 0.058875, 0.058500, 0.063625, 0.064312,
67 0.016000, 0.047625, 0.048313, 0.053437, 0.053062, 0.053437, 0.053437, 0.047625,
68 ...
69 },...
70 },...
71 };
72
73 \endverbatim
74
75 ***********************************************************/
76
77 #include <math.h>
78
79 #include "debug.h"
80 #include "time_table.h"
81 #include "time_table_dat.cxx"
82
83 #include "status.h"
84
85 static float time_length(MODE_TIME_TABLE *mTable, const char *string, int length);
86 static int str_cnt(char * str, int count_limit);
87
88 /** ********************************************************
89 * \brief Determine the length of the string with a count
90 * limitation.
91 * \return signed integer. The number of characters in the
92 * array not to excede count limit.
93 ***********************************************************/
str_cnt(char * str,int count_limit)94 static int str_cnt(char * str, int count_limit)
95 {
96 if(!str || (count_limit < 1))
97 return 0;
98
99 int value = 0;
100
101 for(int index = 0; index < count_limit; index++) {
102 if(str[index] == 0) break;
103 value++;
104 }
105
106 return value;
107 }
108
109 /** ********************************************************
110 * \brief Calulate the time it take to transmit the given
111 * text with the selected modem.
112 ***********************************************************/
time_length(MODE_TIME_TABLE * mTable,const char * string,int length)113 static float time_length(MODE_TIME_TABLE *mTable, const char *string, int length)
114 {
115 unsigned int character = 0;
116 float accum = 0.0;
117
118 while (length > 0) {
119 character = (unsigned int) *string++;
120 character &= 0xFF;
121 accum += mTable->table[character];
122 length--;
123 }
124
125 return (accum * mTable->scale);
126 }
127
128 /** ********************************************************
129 * \brief Returns the time it take to transmit the given
130 * text with the selected modem. 'C' interface.
131 * \return float Duration in seconds.
132 ***********************************************************/
seconds_from_c_string(const char * mode,const char * string,int length,float * overhead)133 float seconds_from_c_string(const char *mode, const char *string, int length, float *overhead)
134 {
135 int mode_index = 0;
136 int max_mode_name = 16;
137 int mode_count = sizeof(mode_time_table) / sizeof(MODE_TIME_TABLE);
138 static int last_mode = 0;
139
140 if(!mode || !string || length < 1) return 0.0;
141
142 if(strncmp(mode, mode_time_table[last_mode].mode_name, max_mode_name) == 0) {
143 if(overhead) {
144 *overhead = mode_time_table[last_mode].overhead;
145 }
146 return time_length(&mode_time_table[last_mode], string, length);
147 } else {
148 for(mode_index = 0; mode_index < mode_count; mode_index++) {
149 if(strncmp((char *) mode, (char *) mode_time_table[mode_index].mode_name, max_mode_name) == 0) {
150 last_mode = mode_index;
151 if(overhead) {
152 *overhead = mode_time_table[last_mode].overhead;
153 }
154 return time_length(&mode_time_table[mode_index], string, length);
155 }
156 }
157 }
158 return 0.0;
159 }
160
161 /** ********************************************************
162 * \brief Returns the time it take to transmit the given
163 * text with the selected modem. 'C' interface.
164 * \return float Duration in minutes.
165 ***********************************************************/
minutes_from_c_string(const char * mode,const char * string,int length,float * overhead)166 float minutes_from_c_string(const char *mode, const char *string, int length, float *overhead)
167 {
168 float time = 0.0;
169
170 time = seconds_from_c_string(mode, string, length, overhead) / 60.0;
171 if(overhead)
172 *overhead /= 60.0;
173 return time;
174 }
175
176 /** ********************************************************
177 * \brief Returns the time it take to transmit the given
178 * text with the selected modem. 'C++' std::string interface.
179 * \return float Duration in seconds.
180 ***********************************************************/
seconds_from_string(std::string mode,std::string & str,float * overhead)181 float seconds_from_string(std::string mode, std::string& str, float *overhead)
182 {
183 try {
184 return seconds_from_c_string(mode.c_str(), str.c_str(), str.length(), overhead);
185 } catch ( ... ) {
186 LOG_ERROR("%s", "String Ref Error");
187 return 0.0;
188 }
189 }
190
191 /** ********************************************************
192 * \brief Returns the time it take to transmit the given
193 * text with the selected modem. 'C++' std::string interface.
194 * \return float Duration in minutes.
195 ***********************************************************/
minutes_from_string(std::string mode,std::string & str,float * overhead)196 float minutes_from_string(std::string mode, std::string& str, float *overhead)
197 {
198 float time = 0.0;
199 try {
200 time = seconds_from_c_string(mode.c_str(), str.c_str(), str.length(), overhead) / 60.0;
201 if(overhead)
202 *overhead /= 60.0;
203 } catch ( ... ) {
204 LOG_ERROR("%s", "String Ref Error");
205 return 0.0;
206 }
207
208 return time;
209 }
210
211 /** ********************************************************
212 * \brief Search the modem table for a modem string match.
213 * 'C++' std::string interface.
214 * \return bool Match found = true.
215 ***********************************************************/
modem_available(std::string modem)216 bool modem_available(std::string modem)
217 {
218 if(modem.empty())
219 return false;
220 return modem_available((char *) modem.c_str(), (int) modem.size());
221 }
222
223
224 /** ********************************************************
225 * \brief Search the modem table for a modem string match.
226 * 'C' interface.
227 * \return bool Match found = true.
228 ***********************************************************/
modem_available(char * modem,int search_limit)229 bool modem_available(char *modem, int search_limit)
230 {
231 if(!modem || (search_limit < 1))
232 return false;
233
234 int mode_count = (int) sizeof(mode_time_table) / sizeof(MODE_TIME_TABLE);
235 int index = 0;
236 int results = 0;
237 bool found = false;
238
239 for(index = 0; index < mode_count; index++) {
240 results = strncmp(modem, mode_time_table[index].mode_name, search_limit);
241 if(results == 0) {
242 results = str_cnt(mode_time_table[index].mode_name, 16);
243 if(results == search_limit) {
244 found = true;
245 break;
246 }
247 }
248 }
249
250 return found;
251 }
252
253 /** ********************************************************
254 * \brief Return the number of table entires.
255 * \return integer
256 ***********************************************************/
mode_table_count(void)257 int mode_table_count(void)
258 {
259 return (int) sizeof(mode_time_table) / sizeof(MODE_TIME_TABLE);
260 }
261
262 /** ********************************************************
263 * \brief Return modem ID string at position 'x' in the
264 * Table.
265 * \return char *.
266 ***********************************************************/
modem_at_index(int index)267 char * modem_at_index(int index)
268 {
269 static char modem_name[] = "Bad Index";
270
271 int index_limit = mode_table_count();
272
273 if(index < 0 || index >= index_limit)
274 return (char *) &modem_name[0];
275
276 return (char *) mode_time_table[index].mode_name;
277 }
278
279 /** ********************************************************
280 * \brief Return duration of mode TxID in seconds
281 * 0 if mode not in table
282 * TxID is either 25 or 50 symbols in duration
283 ***********************************************************/
rsid_duration(std::string modem)284 float rsid_duration(std::string modem)
285 {
286 size_t mode_count = sizeof(mode_time_table) / sizeof(*mode_time_table);
287
288 for( size_t index = 0; index < mode_count; index++) {
289 if (modem == mode_time_table[index].mode_name)
290 return round(mode_time_table[index].rsid_symbols * 25 * 0.09288);
291 }
292 return 0;
293 }
294
295