Show the file size of the files in the tmp_dir on the LCD.
[ruwai.git] / software / c++ / ruwaicom / src / root.cpp
bloba171aaf83436a88ed1f95a1ed8e75283c45d9fa0
1 /*--------------------------------------------------------------------------*/
2 // LICENSE
3 //
4 // This file is part of ruwai.
5 //
6 // If you use ruwai_parser in any program or publication, please inform and
7 // acknowledge its author Stefan Mertl (stefan@mertl-research.at).
8 //
9 // ruwai is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 /*--------------------------------------------------------------------------*/
23 #include "root.h"
24 #include "log_temperature.h"
26 Root::Root(std::string config_file)
28 boost::property_tree::ptree pt;
29 double c1_gain, c2_gain, c3_gain, c4_gain;
30 int sps_raw;
32 display = new LCDDisplay(66, 67, 45, 23, 47, 27);
33 display->init();
34 display->clear();
35 display->home();
36 display->print("Hello, Ruwai", "is speaking.");
38 try {
39 boost::property_tree::ini_parser::read_ini(config_file, pt);
41 // ---------------------------------------------------------
42 // Parse the arduino stack section.
43 dev_name = pt.get<std::string>("arduino_stack.serial_port");
44 n_channels = pt.get<unsigned int>("arduino_stack.n_channels");
46 channel1_active = pt.get<bool>("arduino_stack.channel1_active");
47 channel2_active = pt.get<bool>("arduino_stack.channel2_active");
48 channel3_active = pt.get<bool>("arduino_stack.channel3_active");
49 channel4_active = pt.get<bool>("arduino_stack.channel4_active");
51 if (channel1_active)
53 record_channels.push_back(1);
56 if (channel2_active)
58 record_channels.push_back(2);
61 if (channel3_active)
63 record_channels.push_back(3);
66 if (channel4_active)
68 record_channels.push_back(4);
71 c1_gain = pt.get<double>("arduino_stack.channel1_pga");
72 channel1_gain = translate_pga_gain(c1_gain);
73 if (channel1_gain == PGA_GAIN_UNKNOWN)
75 syslog(LOG_ERR, "[ERROR][root] Unknown gain setting for channel 1: %f.", c1_gain);
76 std::exit(EXIT_FAILURE);
79 c2_gain = pt.get<double>("arduino_stack.channel2_pga");
80 channel2_gain = translate_pga_gain(c2_gain);
81 if (channel2_gain == PGA_GAIN_UNKNOWN)
83 syslog(LOG_ERR, "[ERROR][root] Unknown gain setting for channel 4: %f.", c2_gain);
84 std::exit(EXIT_FAILURE);
87 c3_gain = pt.get<double>("arduino_stack.channel3_pga");
88 channel3_gain = translate_pga_gain(c3_gain);
89 if (channel3_gain == PGA_GAIN_UNKNOWN)
91 syslog(LOG_ERR, "[ERROR][root] Unknown gain setting for channel 4: %f.", c3_gain);
92 std::exit(EXIT_FAILURE);
95 c4_gain = pt.get<double>("arduino_stack.channel4_pga");
96 channel4_gain = translate_pga_gain(c4_gain);
97 if (channel4_gain == PGA_GAIN_UNKNOWN)
99 syslog(LOG_ERR, "[ERROR][root] Unknown gain setting for channel 4: %f.", c4_gain);
100 std::exit(EXIT_FAILURE);
103 sps_raw = pt.get<uint16_t>("arduino_stack.sps");
104 sps = translate_adc_sps(sps_raw);
105 if (sps == ADC_SPS_UNKNOWN)
107 syslog(LOG_ERR, "[ERROR][root] Not supported sps setting: %d.", sps_raw);
108 std::exit(EXIT_FAILURE);
112 // ------------------------------------------------------------------------
113 // Parse the record section.
114 storage_mode = pt.get<std::string>("record.storage_mode");
115 tmp_dir = pt.get<std::string>("record.tmp_dir");
116 ruwai_serial_file = pt.get<std::string>("record.ruwai_serial_file");
117 file_length = pt.get<unsigned int>("record.file_length");
118 //record_channels = to_array<unsigned int>(pt.get<std::string>("record.record_channels"));
120 // ------------------------------------------------------------------------
121 // Depending on the selected storage mode, parse the sd or hdd section.
122 if (storage_mode == "sd")
124 sd_dev_label = pt.get<std::string>("sd.dev_label");
125 sd_dev_1 = pt.get<std::string>("sd.dev_1");
126 sd_dev_2 = pt.get<std::string>("sd.dev_2");
127 sd_mnt_point = pt.get<std::string>("sd.mnt_point");
128 } else if (storage_mode == "hdd")
130 hdd_mseed_dir = pt.get<std::string>("hdd.mseed_dir");
133 // ------------------------------------------------------------------------
134 rts_start_server = pt.get<bool>("rt_server.start_server");
135 rts_port = pt.get<unsigned int>("rt_server.port");
136 rts_max_clients = pt.get<unsigned int>("rt_server.max_clients");
138 catch (const boost::property_tree::ptree_bad_path& e) {
139 syslog(LOG_ERR, "[ERROR][root] Couldn't read the config file %s. Error message: %s.", config_file.c_str(), e.what());
140 throw;
144 try {
145 //const std::string serial_filename = "/etc/ruwai_serial";
146 std::string line;
147 std::ifstream myfile(ruwai_serial_file);
148 if (myfile.is_open())
150 std::getline(myfile, line);
151 boost::trim_left(line);
152 boost::trim_right(line);
153 serial_number = line;
154 syslog(LOG_NOTICE, "[root] Ruwai serial number: %s.", serial_number.c_str());
155 myfile.close();
157 else
159 syslog(LOG_ERR, "[ERROR][root] Unable to open the file %s to read the serial number.", ruwai_serial_file.c_str());
160 std::exit(EXIT_FAILURE);
163 catch (...) {
164 syslog(LOG_ERR, "[ERROR][root] Couldn't read the serial number from %s. Unknown error.", ruwai_serial_file.c_str());
165 throw;
169 std::string rec_channels_string = "";
170 for (unsigned int k = 0; k < record_channels.size(); k++)
172 rec_channels_string += std::to_string(record_channels[k]);
174 if (k < record_channels.size() - 1)
176 rec_channels_string += ",";
180 syslog(LOG_NOTICE, "------- read configuration --------");
181 syslog(LOG_NOTICE, "arduino_stack");
182 syslog(LOG_NOTICE, "serial_port: %s", dev_name.c_str());
183 syslog(LOG_NOTICE, "n_channels: %d", n_channels);
184 syslog(LOG_NOTICE, "channel1_active: %d", channel1_active);
185 syslog(LOG_NOTICE, "channel2_active: %d", channel2_active);
186 syslog(LOG_NOTICE, "channel3_active: %d", channel3_active);
187 syslog(LOG_NOTICE, "channel4_active: %d", channel4_active);
188 syslog(LOG_NOTICE, "channel1_gain: %.3f (%d)", c1_gain, channel1_gain);
189 syslog(LOG_NOTICE, "channel2_gain: %.3f (%d)", c2_gain, channel2_gain);
190 syslog(LOG_NOTICE, "channel3_gain: %.3f (%d)", c3_gain, channel3_gain);
191 syslog(LOG_NOTICE, "channel4_gain: %.3f (%d)", c4_gain, channel4_gain);
192 syslog(LOG_NOTICE, "sps: %d (%d)", sps_raw, sps);
193 syslog(LOG_NOTICE, "record");
194 syslog(LOG_NOTICE, "storage_mode: %s", storage_mode.c_str());
195 syslog(LOG_NOTICE, "tmp_dir: %s", tmp_dir.c_str());
196 syslog(LOG_NOTICE, "record_channels: %s", rec_channels_string.c_str());
197 syslog(LOG_NOTICE, "file_length: %d", file_length);
198 if (storage_mode == "sd")
200 syslog(LOG_NOTICE, "sd");
201 syslog(LOG_NOTICE, "dev_label: %s", sd_dev_label.c_str());
202 syslog(LOG_NOTICE, "dev_1: %s", sd_dev_1.c_str());
203 syslog(LOG_NOTICE, "dev_2: %s", sd_dev_2.c_str());
204 syslog(LOG_NOTICE, "mnt_point: %s", sd_mnt_point.c_str());
205 } else if (storage_mode == "hdd")
207 syslog(LOG_NOTICE, "hdd");
208 syslog(LOG_NOTICE, "mseed_dir: %s", hdd_mseed_dir.c_str());
210 syslog(LOG_NOTICE, "rt_server");
211 syslog(LOG_NOTICE, "start_server: %d", rts_start_server);
212 syslog(LOG_NOTICE, "port: %d", rts_port);
213 syslog(LOG_NOTICE, "max_clients: %d", rts_max_clients);
214 syslog(LOG_NOTICE, "-----------------------------------");
216 // Create the temporary data directory.
217 if (!boost::filesystem::exists(tmp_dir))
219 if (!boost::filesystem::create_directory(tmp_dir))
221 syslog(LOG_ERR, "[ERROR][root] Can't create the tmp_dir: %s. This is mandatory. Exiting.", tmp_dir.c_str());
222 std::exit(EXIT_FAILURE);
226 std::string mseed_dir;
227 if (storage_mode == "sd")
228 mseed_dir = sd_mnt_point;
229 else if (storage_mode == "hdd")
230 mseed_dir = hdd_mseed_dir;
231 recorder = new Recorder(serial_number, n_channels, record_channels, sps, mseed_dir, tmp_dir, file_length);
232 rt_server = new RealTimeServer(rts_port, rts_max_clients);
236 bool
237 Root::ready(void)
239 bool is_ready = true;
241 // Check the output directory structure. If it doesn't exist, it's created.
242 if(!recorder->check_output_dir_structure())
244 syslog(LOG_ERR, "[ERROR][root] The output directory structure couldn't be created. Can't start the recorder.");
245 is_ready = false;
248 if (storage_mode == "sd" && !is_sd_mounted())
250 is_ready = false;
253 return is_ready;
256 bool
257 Root::is_sd_dev_available(void)
259 bool dev_available = false;
260 struct stat sb;
262 if (stat(sd_dev_label.c_str(), &sb) != -1)
264 switch (sb.st_mode & S_IFMT) {
265 case S_IFBLK:
266 syslog(LOG_NOTICE, "[root] SD card block device found at %s.", sd_dev_label.c_str());
267 dev_available = true;
268 break;
269 default:
270 syslog(LOG_ERR, "[ERROR][root] SD card device file %s is not a block device.", sd_dev_label.c_str());
271 break;
274 else
276 syslog(LOG_WARNING, "[WARNING][root] SD card block device file %s not found.", sd_dev_label.c_str());
279 return dev_available;
282 bool
283 Root::is_sd_mounted(void)
285 FILE *mtab = NULL;
286 struct mntent *part = NULL;
287 bool is_mounted = false;
289 if ((mtab = setmntent("/etc/mtab", "r")) != NULL)
291 while ((part = getmntent(mtab)) != NULL)
293 if((part->mnt_fsname != NULL) && ((strcmp(part->mnt_fsname, sd_dev_1.c_str())) == 0 || (strcmp(part->mnt_fsname, sd_dev_2.c_str())) == 0) && (strcmp(part->mnt_dir, sd_mnt_point.c_str()) == 0) )
295 is_mounted = true;
299 endmntent(mtab);
300 if (is_mounted)
302 syslog(LOG_NOTICE, "[root] The SD card is correctly mounted at %s.", sd_mnt_point.c_str());
304 else
306 syslog(LOG_WARNING, "[WARNING][root] The SD card is NOT mounted. Couldn't find an entry for %s or %s mounted at %s in /etc/mtab.", sd_dev_1.c_str(), sd_dev_2.c_str(), sd_mnt_point.c_str());
308 return is_mounted;
312 bool
313 Root::mount_sd(void)
315 bool mount_success = false;
316 int ret_val = -1;
318 // TODO: Use the mount function instead of calling mount using the system
319 // command. Using the mount function didn't work because of missing
320 // permissions when running as a normal user. Also the mtab entry is not
321 // written automatically. I think I would have to add an entry to mtab.
322 //ret_val = mount(sd_dev_label.c_str(), sd_mnt_point.c_str(), "ext4", MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL);
324 std::string cmd = "mount " + sd_mnt_point;
325 ret_val = system(cmd.c_str());
327 if (ret_val == 0)
329 syslog(LOG_NOTICE, "[root] Successfully mounted the sd card on %s.", sd_mnt_point.c_str());
330 mount_success = true;
332 else
334 syslog(LOG_ERR, "[ERROR][root] Troubles when mounting the SD card: %s.", strerror(errno));
336 return mount_success;
340 void
341 Root::run(void)
343 bool port_open = false;
344 bool config_confirmed = false;
345 int max_try = 10;
347 display->print("Starting...", "");
349 // Start the temperature logging thread.
350 syslog(LOG_NOTICE, "[root] Starting the temperature logging thread.");
351 std::thread t_temp_log(log_temperature);
352 t_temp_log.detach();
354 // Check the output directory structure. If it doesn't exist, it's created.
355 if(!recorder->check_output_dir_structure())
357 syslog(LOG_ERR, "[ERROR][root] The output directory structure couldn't be created. Can't start the recorder.");
359 else
361 port_open = open_port();
363 if (port_open)
365 bool success;
366 // Test the chrono measurement.
368 syslog(LOG_DEBUG, "Testing the chrono measurement with usleep(1000).");
369 auto start = std::chrono::high_resolution_clock::now();
370 usleep(1000);
371 auto end = std::chrono::high_resolution_clock::now();
372 auto diff = end - start;
373 syslog(LOG_DEBUG, "Measured time: %d nanoseconds", (int)std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count());
376 // Start the real time server if activated.
377 if (rts_start_server)
379 syslog(LOG_NOTICE, "[root] Starting the realtime server thread.");
380 std::thread t_rts([&] (RealTimeServer* rt_server) {rt_server->start_listen();}, rt_server);
381 t_rts.detach();
384 configure_port();
385 parser = new SerialParser(serial_port, recorder);
386 std::thread t_read_and_parse([&] (SerialParser* parser) {parser->read_and_parse();}, parser);
388 // Wait for handshaking.
389 display->print("Handshaking...", "");
390 syslog(LOG_NOTICE, "[root] Handshaking with Arduino stack....");
391 max_try = 10;
392 for (int k = 0; k < max_try; k++)
394 syslog(LOG_NOTICE, "[root] Waiting for handshake with Arduino stack...");
395 parser->start_handshake();
396 usleep(1000000);
397 if (parser->is_synced())
399 break;
402 if (!parser->is_synced())
404 syslog(LOG_ERR, "[ERROR][root] ...tried handshake for %d times. Got no answer. Giving up.", max_try);
405 std::exit(EXIT_FAILURE);
407 else
409 syslog(LOG_NOTICE, "[root] ...handshake was successful.");
413 display->print("Configuring...", "");
414 syslog(LOG_NOTICE, "[root] Setting the Arduino stack to control mode.");
415 success = parser->set_control_mode();
416 if (success)
418 syslog(LOG_NOTICE, "[root] Confirmed control mode configuration by the Arduino stack.");
420 else
422 syslog(LOG_ERR, "[ERROR][root] No confirmation of the control mode configuration.");
425 // Configure the Arduino stack.
426 // TODO: Restart the configuration if no confirmation was received.
427 syslog(LOG_NOTICE, "[root] Configuring the Arduino stack....");
428 max_try = 10;
429 for (int k = 0; k < max_try; k++)
431 config_confirmed = true;
432 syslog(LOG_NOTICE, "[root] Setting the sps to %d.", sps);
433 success = parser->set_sps((uint16_t)sps);
434 if (success)
436 syslog(LOG_NOTICE, "[root] Confirmed sps configuration by the Arduino stack.");
438 else
440 syslog(LOG_ERR, "[ERROR][root] No confirmation of the sps configuration. Start again.");
441 config_confirmed = false;
442 continue;
445 success = parser->set_channels(channel1_active, channel2_active, channel3_active, channel4_active, channel1_gain, channel2_gain, channel3_gain, channel4_gain);
446 if (success)
448 syslog(LOG_NOTICE, "[root] Confirmed channel configuration by the Arduino stack.");
450 else
452 syslog(LOG_ERR, "[ERROR][root] No confirmation of the channel configuration. Start again.");
453 config_confirmed = false;
454 continue;
457 if (config_confirmed)
459 break;
463 if (!config_confirmed)
465 syslog(LOG_ERR, "[ERROR][root] Couldn't configure the Arduino Stack. Tried it %d times.", max_try);
466 std::exit(EXIT_FAILURE);
469 syslog(LOG_NOTICE, "[root] Stack configured successfully.");
471 syslog(LOG_NOTICE, "[root] Set to record mode.");
472 success = parser->set_record_mode();
473 if (success)
475 syslog(LOG_NOTICE, "[root] Confirmed record mode configuration by the Arduino stack.");
476 display->print("Recording...", "");
478 else
480 syslog(LOG_ERR, "[ERROR][root] No confirmation of the record mode configuration.");
483 //std::thread t_lcd_status([&] (Root* this) {this->lcd_status();}, this);
484 std::thread t_lcd_status(&Root::lcd_status, this);
486 t_read_and_parse.join();
488 // Close the serial port.
489 close_port();
495 bool
496 Root::open_port(void)
498 serial_port = open(dev_name.c_str(), O_RDWR | O_NOCTTY );
499 if(serial_port == -1)
501 // Couldn't open the serial port.
502 syslog(LOG_ERR, "[ERROR][root] Unable to open the Arduino stack serial port %s", dev_name.c_str());
503 return false;
505 else
507 //fcntl(serial_port, F_SETFL, 0);
508 syslog(LOG_NOTICE, "[root] Serial port %s to Arduino stack opened.", dev_name.c_str());
509 return true;
513 void
514 Root::close_port(void)
516 close(serial_port);
520 void
521 Root::configure_port(void)
523 struct termios port_options; // struct to hold the port settings
525 // Fetch the current port settings
526 tcgetattr(serial_port, &port_options);
528 // Flush the port's buffers (in and out) before we start using it
529 tcflush(serial_port, TCIOFLUSH);
531 // Input flags - Turn off input processing
533 // convert break to null byte, no CR to NL translation,
534 // no NL to CR translation, don't mark parity errors or breaks
535 // no input parity check, don't strip high bit off,
536 // no XON/XOFF software flow control
538 // port_options.c_iflag &= ~(IGNBRK | BRKINT | ICRNL |
539 // INLCR | PARMRK | INPCK | ISTRIP | IXON);
540 port_options.c_iflag = 0;
542 // Output flags - Turn off output processing
544 // no CR to NL translation, no NL to CR-NL translation,
545 // no NL to CR translation, no column 0 CR suppression,
546 // no Ctrl-D suppression, no fill characters, no case mapping,
547 // no local output processing
549 // port_options.c_oflag &= ~(OCRNL | ONLCR | ONLRET |
550 // ONOCR | ONOEOT| OFILL | OLCUC | OPOST);
551 port_options.c_oflag = 0;
553 // Turn off line processing
555 // echo off, echo newline off, canonical mode on,
556 // extended input processing off, signal chars off
557 // port_options.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
559 // In non-blocking mode, the infinite loop in the serial parser causes a
560 // large CPU load which significantly increases the power consumption of
561 // the BBB.
562 port_options.c_lflag = 0;
563 port_options.c_lflag &= ~ICANON; // Set to non-canonical (blocking) mode.
564 port_options.c_cc[VMIN] = 0; // Minimum number of bytes read.
565 port_options.c_cc[VTIME] = 10; // timeout in deci-seconds
567 // Set the input and output baud rates
568 cfsetispeed(&port_options, B1000000);
569 cfsetospeed(&port_options, B1000000);
570 //cfsetispeed(&port_options, B500000);
571 //cfsetospeed(&port_options, B500000);
572 //cfsetispeed(&port_options, B1152000);
573 //cfsetospeed(&port_options, B1152000);
575 // c_cflag contains a few important things- CLOCAL and CREAD, to prevent
576 // this program from "owning" the port and to enable receipt of data.
577 // Also, it holds the settings for number of data bits, parity, stop bits,
578 // and hardware flow control.
579 port_options.c_cflag |= CLOCAL;
580 port_options.c_cflag |= CREAD;
581 // Set up the frame information.
582 port_options.c_cflag &= ~CSIZE; // clear frame size info
583 port_options.c_cflag |= CS8; // 8 bit frames
584 port_options.c_cflag &= ~PARENB;// no parity
585 port_options.c_cflag &= ~CSTOPB;// one stop bit
587 // Now that we've populated our options structure, let's push it back to the
588 // system.
589 tcsetattr(serial_port, TCSANOW, &port_options);
591 syslog(LOG_DEBUG, "Configured the serial port:");
592 syslog(LOG_DEBUG, "port_options.c_cflag: %d - %s", port_options.c_cflag, std::bitset<16>(port_options.c_cflag).to_string().c_str());
593 syslog(LOG_DEBUG, "port_options.c_iflag: %d - %s", port_options.c_iflag, std::bitset<16>(port_options.c_iflag).to_string().c_str());
594 syslog(LOG_DEBUG, "port_options.c_oflag: %d - %s", port_options.c_oflag, std::bitset<16>(port_options.c_oflag).to_string().c_str());
595 syslog(LOG_DEBUG, "port_options.c_lflag: %d - %s", port_options.c_lflag, std::bitset<16>(port_options.c_lflag).to_string().c_str());
597 // Flush the buffer one more time.
598 tcflush(serial_port, TCIOFLUSH);
600 //fcntl(serial_port, F_SETFL, 0);
604 void
605 Root::clear_tmp_dir(void)
607 // Check for forgotten files in the tmp directory.
608 syslog(LOG_NOTICE, "[root] Cleaning the tmp directory.");
610 std::vector<std::string> file_list;
611 boost::filesystem::path search_dir(tmp_dir);
612 boost::filesystem::directory_iterator end_itr;
614 if (boost::filesystem::exists(search_dir) && boost::filesystem::is_directory(search_dir))
616 for (boost::filesystem::directory_iterator dir_itr(search_dir); dir_itr != end_itr; dir_itr++)
618 //syslog(LOG_NOTICE, "Moving file %s from tmp directory to mseed_dir.", dir_itr->path().filename().string().c_str());
619 file_list.push_back(dir_itr->path().filename().string());
623 if (file_list.size() == 0)
625 syslog(LOG_NOTICE, "[root] No data files found in the tmp directory: %s.", search_dir.c_str());
627 else
629 recorder->copy_files(file_list);
635 pga_gain_t
636 Root::translate_pga_gain(double gain)
638 pga_gain_t ret = PGA_GAIN_UNKNOWN;
639 if (gain == 0.125 || gain == 0.172 || gain == 0.25 || gain == 0.344 || \
640 gain == 0.5 || gain == 0.688 || gain == 1 || gain == 1.375 || \
641 gain == 2 || gain == 2.75 || gain == 4 || gain == 5.5 || gain == 8 || \
642 gain == 11 || gain == 16 || gain == 22 || gain == 32 || gain == 44 || \
643 gain == 64 || gain == 88 || gain == 128 || gain == 176)
645 ret = (pga_gain_t) gain;
647 return ret;
652 pga_gain_t
653 Root::translate_pga_gain(double gain)
655 pga_gain_t ret = PGA_GAIN_UNKNOWN;
656 if (gain == 0.125)
657 ret = PGA_GAIN_0_125;
658 else if (gain == 0.172)
659 ret = PGA_GAIN_0_172;
660 else if (gain == 0.25)
661 ret = PGA_GAIN_0_25;
662 else if (gain == 0.344)
663 ret = PGA_GAIN_0_344;
664 else if (gain == 0.5)
665 ret = PGA_GAIN_0_5;
666 else if (gain == 0.688)
667 ret = PGA_GAIN_0_688;
668 else if (gain == 1)
669 ret = PGA_GAIN_1;
670 else if (gain == 1.375)
671 ret = PGA_GAIN_1_375;
672 else if (gain == 2)
673 ret = PGA_GAIN_2;
674 else if (gain == 2.75)
675 ret = PGA_GAIN_2_75;
676 else if (gain == 4)
677 ret = PGA_GAIN_4;
678 else if (gain == 5.5)
679 ret = PGA_GAIN_5_5;
680 else if (gain == 8)
681 ret = PGA_GAIN_8;
682 else if (gain == 11)
683 ret = PGA_GAIN_11;
684 else if (gain == 16)
685 ret = PGA_GAIN_16;
686 else if (gain == 22)
687 ret = PGA_GAIN_22;
688 else if (gain == 32)
689 ret = PGA_GAIN_32;
690 else if (gain == 44)
691 ret = PGA_GAIN_44;
692 else if (gain == 64)
693 ret = PGA_GAIN_64;
694 else if (gain == 88)
695 ret = PGA_GAIN_88;
696 else if (gain == 128)
697 ret = PGA_GAIN_128;
698 else if (gain == 176)
699 ret = PGA_GAIN_176;
701 return ret;
706 adc_sps_t
707 Root::translate_adc_sps(uint16_t sps)
709 adc_sps_t ret = ADC_SPS_UNKNOWN;
710 if (sps == 100 || sps == 200 || sps == 400 || sps == 500 || \
711 sps == 800 )
713 ret = (adc_sps_t) sps;
715 return ret;
719 void
720 Root::lcd_status(void)
722 char c_time_string[27];
723 std::string time_string;
724 timestamp_t last_timestamp;
726 while (true)
728 std::stringstream stream;
729 std::string msg1;
730 std::string msg2;
732 last_timestamp = recorder->get_last_timestamp();
733 ms_hptime2isotimestr(last_timestamp.time, c_time_string, true);
734 time_string = std::string(c_time_string);
735 display->print(time_string.substr(0, 10), time_string.substr(11));
736 std::this_thread::sleep_for(std::chrono::seconds(3));
739 stream << "GPS F:" << last_timestamp.gps_fix << " OK:" << last_timestamp.gps_fix_ok;
740 msg1 = stream.str();
741 stream.str("");
742 stream << "SLTS:" << last_timestamp.sec_slts;
743 msg2 = stream.str();
744 display->print(msg1, msg2);
745 std::this_thread::sleep_for(std::chrono::seconds(3));
748 std::string tmp_dir = recorder->get_tmp_dir();
749 std::vector<std::string> rec_files = get_file_list(tmp_dir);
750 std::sort(rec_files.begin(), rec_files.end());
751 stream.str("");
752 stream << rec_files.size() << " files";
753 msg1 = stream.str();
755 stream.str("");
756 for (std::vector<std::string>::iterator it = rec_files.begin(); it != rec_files.end(); it++)
758 std::string file_path = tmp_dir + "/" + *it;
759 stream << boost::filesystem::file_size(file_path) / 1024 << "; ";
761 msg2 = stream.str();
762 stream.str("");
764 std::this_thread::sleep_for(std::chrono::seconds(10));
768 std::vector<std::string>
769 Root::get_file_list(const std::string path)
771 std::vector<std::string> m_file_list;
772 if (!path.empty())
774 boost::filesystem::path apk_path(path);
776 for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(apk_path), {}))
778 m_file_list.push_back(entry.path().string());
781 return m_file_list;