1 // =====================================================================
2 //
3 // TOD_clock.cxx
4 //
5 // interface to tcpip application fdserver.tcl
6 // fdserver is a multiple client tcpip server
7 //
8 // Copyright (C) 2016
9 // Dave Freese, W1HKJ
10 //
11 // This file is part of fldigi.
12 //
13 // Fldigi is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // Fldigi is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with fldigi. If not, see <http://www.gnu.org/licenses/>.
25 // =====================================================================
26
27 #include <iostream>
28 #include <cmath>
29 #include <cstring>
30 #include <vector>
31 #include <list>
32 #include <stdlib.h>
33
34 #include <FL/Fl_Text_Display.H>
35 #include <FL/Fl_Text_Buffer.H>
36
37 #include "fl_digi.h"
38 #include "rigsupport.h"
39 #include "modem.h"
40 #include "trx.h"
41 #include "configuration.h"
42 #include "main.h"
43 #include "waterfall.h"
44 #include "macros.h"
45 #include "qrunner.h"
46 #include "debug.h"
47 #include "status.h"
48 #include "icons.h"
49
50 #include "logsupport.h"
51 #include "fd_logger.h"
52 #include "fd_view.h"
53
54 #include "confdialog.h"
55
56 #include "timeops.h"
57 #include "nanoIO.h"
58
59 LOG_FILE_SOURCE(debug::LOG_FD);
60
61 using namespace std;
62
63 static pthread_t TOD_thread;
64 static pthread_mutex_t TX_mutex = PTHREAD_MUTEX_INITIALIZER;
65 static pthread_mutex_t time_mutex = PTHREAD_MUTEX_INITIALIZER;
66
67 static char ztbuf[20] = "20120602 123000";
68 static char ltbuf[20] = "20120602 123000";
69
70 static struct timeval tx_start_val;
71 static struct timeval tx_last_val;
72 static struct timeval now_val;
73
74 extern void xmtrcv_cb(Fl_Widget *, void *);
75
76 static int tx_timeout = 0;
77
78 static int macro_time = -1;
79
kill_tx(void *)80 void kill_tx(void *)
81 {
82 wf->xmtrcv->value(0);
83 xmtrcv_cb(wf->xmtrcv, 0);
84 fl_alert2("TX timeout expired!\nAre you awake?");
85 }
86
service_deadman()87 void service_deadman()
88 {
89 guard_lock txlock(&TX_mutex);
90 if (!tx_timeout) return;
91 if (--tx_timeout == 0) {
92 Fl::awake(kill_tx);
93 }
94 }
95
start_deadman()96 void start_deadman()
97 {
98 guard_lock txlock(&TX_mutex);
99 tx_timeout = 60 * progdefaults.tx_timeout;
100 }
101
stop_deadman()102 void stop_deadman()
103 {
104 guard_lock txlock(&TX_mutex);
105 tx_timeout = 0;
106 }
107
start_macro_time()108 void start_macro_time()
109 {
110 macro_time = 0;
111 }
112
stop_macro_time()113 int stop_macro_time()
114 {
115 return macro_time;
116 }
117
tmval(void)118 const timeval tmval(void)
119 {
120 struct timeval t1;
121 {
122 guard_lock lk(&time_mutex);
123 gettimeofday(&t1, NULL);
124 }
125 return t1;
126 }
127
zusec(void)128 const double zusec(void)
129 {
130 struct timeval t1;
131 {
132 guard_lock lk(&time_mutex);
133 gettimeofday(&t1, NULL);
134 }
135 double usecs = t1.tv_sec * 1000000L;
136 usecs += t1.tv_usec;
137 return usecs;
138 }
139
zmsec(void)140 const unsigned long zmsec(void)
141 {
142 struct timeval t1;
143 {
144 guard_lock lk(&time_mutex);
145 gettimeofday(&t1, NULL);
146 }
147 unsigned long msecs = t1.tv_sec * 1000000L;
148 msecs += t1.tv_usec;
149 msecs /= 1000L;
150 return msecs;
151 }
152
zdate(void)153 const char* zdate(void)
154 {
155 return ztbuf;
156 }
157
ztime(void)158 const char* ztime(void)
159 {
160 return ztbuf + 9;
161 }
162
ldate(void)163 const char* ldate(void)
164 {
165 return ltbuf;
166 }
167
ltime(void)168 const char *ltime(void)
169 {
170 return ltbuf + 9;
171 }
172
zshowtime(void)173 const char* zshowtime(void) {
174 static char s[5];
175 strncpy(s, &ztbuf[9], 4);
176 s[4] = 0;
177 return (const char *)s;
178 }
179
180 static char tx_time[20];
181
182 static bool TOD_exit = false;
183 static bool TOD_enabled = false;
184
185 static bool tx_timer_active = false;
186
show_tx_timer()187 void show_tx_timer()
188 {
189 if (!tx_timer) return;
190 if (progdefaults.show_tx_timer && tx_timer_active) {
191 snprintf(tx_time, sizeof(tx_time),"%02d:%02d",
192 (int)((now_val.tv_sec - tx_start_val.tv_sec)/60),
193 (int)((now_val.tv_sec - tx_start_val.tv_sec) % 60 ));
194 tx_timer->color(FL_DARK_RED);
195 tx_timer->labelcolor(FL_YELLOW);
196 tx_timer->label(tx_time);
197 tx_timer->redraw_label();
198 tx_timer->redraw();
199 } else {
200 tx_timer->color(FL_BACKGROUND_COLOR);
201 tx_timer->labelcolor(FL_BACKGROUND_COLOR);
202 tx_timer->redraw_label();
203 tx_timer->redraw();
204 }
205 }
206
start_tx_timer()207 void start_tx_timer()
208 {
209 tx_last_val = tx_start_val = now_val;
210 tx_timer_active = true;
211 REQ(show_tx_timer);
212 }
213
stop_tx_timer()214 void stop_tx_timer()
215 {
216 if (!tx_timer) return;
217 tx_timer_active = false;
218 }
219
update_tx_timer()220 void update_tx_timer()
221 {
222 if (tx_last_val.tv_sec == now_val.tv_sec) return;
223 tx_last_val = now_val;
224 show_tx_timer();
225 service_deadman();
226 macro_time++;
227 }
228
229 //void ztimer(void *)
show_ztimer()230 static void show_ztimer()
231 {
232 if (!inpTimeOff1) return;
233
234 update_tx_timer();
235
236 inpTimeOff1->value(zshowtime());
237 inpTimeOff2->value(zshowtime());
238 inpTimeOff3->value(zshowtime());
239 inpTimeOff1->redraw();
240 inpTimeOff2->redraw();
241 inpTimeOff3->redraw();
242
243 }
244
ztimer()245 static void ztimer()
246 {
247 struct tm ztm, ltm;
248 time_t t_temp;
249
250 t_temp=(time_t)now_val.tv_sec;
251 gmtime_r(&t_temp, &ztm);
252 if (!strftime(ztbuf, sizeof(ztbuf), "%Y%m%d %H%M%S", &ztm))
253 memset(ztbuf, 0, sizeof(ztbuf));
254 else
255 ztbuf[8] = '\0';
256
257 localtime_r(&t_temp, <m);
258 if (!strftime(ltbuf, sizeof(ltbuf), "%Y%m%d %H%M%S", <m))
259 memset(ltbuf, 0, sizeof(ltbuf));
260 else
261 ltbuf[8] = '\0';
262
263 REQ(show_ztimer);
264 }
265
266 //======================================================================
267 // TOD Thread loop
268 //======================================================================
TOD_loop(void * args)269 void *TOD_loop(void *args)
270 {
271 SET_THREAD_ID(TOD_TID);
272 #define LOOP 250
273 int cnt = 0;
274 while(1) {
275
276 if (TOD_exit) break;
277
278 if (++cnt == 4) {
279 guard_lock tmlock(&time_mutex);
280 gettimeofday(&now_val, NULL);
281 ztimer();
282 cnt = 0;
283 }
284 REQ(nanoIO_read_pot);
285 MilliSleep(LOOP);
286 }
287
288 // exit the TOD thread
289 SET_THREAD_CANCEL();
290 return NULL;
291 }
292
293 //======================================================================
294 //
295 //======================================================================
TOD_init(void)296 void TOD_init(void)
297 {
298 TOD_exit = false;
299
300 if (pthread_create(&TOD_thread, NULL, TOD_loop, NULL) < 0) {
301 LOG_ERROR("%s", "pthread_create failed");
302 return;
303 }
304
305 LOG_INFO("%s", "Time Of Day thread started");
306
307 TOD_enabled = true;
308 }
309
310 //======================================================================
311 //
312 //======================================================================
TOD_close(void)313 void TOD_close(void)
314 {
315 if (!TOD_enabled) return;
316
317 TOD_exit = true;
318 pthread_join(TOD_thread, NULL);
319 TOD_enabled = false;
320
321 LOG_INFO("%s", "Time Of Day thread terminated. ");
322
323 }
324
325