syslog.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #ifdef PC_BUILD
  2. #include "../gps-test-tool/main.h"
  3. #else
  4. #include "main.h"
  5. #endif
  6. #ifndef FW_VERSION
  7. #define FW_VERSION "unknown"
  8. #endif
  9. __flash const char reject_reason_kalman[] = "kalman";
  10. __flash const char reject_reason_distdiff[] = "distdiff";
  11. __flash const char reject_reason_mindist[] = "mindist";
  12. __flash const char reject_reason_altdiff[] = "altdiff";
  13. __flash const char reject_reason_quality[] = "quality";
  14. __flash const char *reject_reason_names[] = {
  15. [REJECT_REASON_KALMAN] = reject_reason_kalman,
  16. [REJECT_REASON_DISTDIFF] = reject_reason_distdiff,
  17. [REJECT_REASON_MINDIST] = reject_reason_mindist,
  18. [REJECT_REASON_ALTDIFF] = reject_reason_altdiff,
  19. [REJECT_REASON_QUALITY] = reject_reason_quality,
  20. };
  21. __flash const char status_no_power[] = "no power";
  22. __flash const char status_no_disk[] = "no card";
  23. __flash const char status_no_gps[] = "waiting for GPS";
  24. __flash const char status_ok[] = "ok";
  25. __flash const char status_disk_error[] = "card mount failed";
  26. __flash const char status_file_write_error[] = "write failed";
  27. __flash const char status_file_sync_error[] = "sync failed";
  28. __flash const char status_file_close_error[] = "close failed";
  29. __flash const char status_file_open_error[] = "open failed";
  30. __flash const char status_unknown[] = "unknown";
  31. __flash const char *status_names[] = {
  32. status_no_power,
  33. status_no_disk,
  34. status_no_gps,
  35. status_ok,
  36. status_disk_error,
  37. status_file_write_error,
  38. status_file_sync_error,
  39. status_file_close_error,
  40. status_file_open_error,
  41. };
  42. static struct {
  43. unsigned char reason;
  44. unsigned char count;
  45. unsigned int hdop_x100;
  46. unsigned char sats;
  47. unsigned char fix_type;
  48. } reject_coalesce;
  49. static unsigned char fix_had_first;
  50. static unsigned long int gps_on_uptime;
  51. void log_prefix(void) {
  52. if (utc)
  53. xprintf(PSTR("%s up=%lu "), get_iso_time(utc, 0), get_uptime_ms());
  54. else
  55. xprintf(PSTR("NOTIME up=%lu "), get_uptime_ms());
  56. }
  57. void log_config(void) {
  58. log_prefix();
  59. xputs_P(PSTR("CFG filt="));
  60. xputs_P(get_flag(CONFFLAG_DISABLE_FILTERS) ? PSTR("off") : PSTR("on"));
  61. xprintf(PSTR(" skip=%u gate_sats=%u pause_t=%us pause_d=%um pause_v=%ukmh sbas_search="),
  62. (unsigned int)System.conf.skip_points, (unsigned int)System.conf.min_sats,
  63. (unsigned int)System.conf.auto_pause_time, (unsigned int)System.conf.auto_pause_dist,
  64. (unsigned int)System.conf.auto_pause_speed);
  65. xputs_P(get_flag(CONFFLAG_ENABLE_SBAS) ? PSTR("on") : PSTR("off"));
  66. xputs_P(PSTR(" auto_pause="));
  67. xputs_P(get_flag(CONFFLAG_AUTO_PAUSE) ? PSTR("on") : PSTR("off"));
  68. xputs_P(PSTR(" gnss="));
  69. xputs_P(gnss_names[System.conf.gnss_mode]);
  70. xputs_P(PSTR(" uart_log="));
  71. xputs_P(uart_log_mode_names[System.conf.uart_log_mode]);
  72. xputs_P(PSTR(" verbose="));
  73. xputs_P(get_flag(CONFFLAG_VERBOSE_LOG) ? PSTR("on") : PSTR("off"));
  74. xputs_P(PSTR(" reset_new_file="));
  75. xputs_P(get_flag(CONFFLAG_RESET_ON_NEW_FILE) ? PSTR("on") : PSTR("off"));
  76. xputs_P(PSTR("\r\n"));
  77. }
  78. void log_boot_record(void) {
  79. log_prefix();
  80. xputs_P(PSTR("BOOT fw="));
  81. xputs_P(PSTR(FW_VERSION));
  82. xputs_P(PSTR(" reset="));
  83. if (reset_cause & _BV(WDRF))
  84. xputs_P(PSTR("WDT"));
  85. else if (reset_cause & _BV(BORF))
  86. xputs_P(PSTR("BOR"));
  87. else if (reset_cause & _BV(EXTRF))
  88. xputs_P(PSTR("EXT"));
  89. else if (reset_cause & _BV(PORF))
  90. xputs_P(PSTR("POR"));
  91. else
  92. xputs_P(PSTR("UNKNOWN"));
  93. xputs_P(PSTR(" rx="));
  94. xputs_P(gnss_names[System.conf.gnss_mode]);
  95. xputs_P(PSTR("\r\n"));
  96. log_config();
  97. }
  98. void log_loop_status(unsigned char status) {
  99. log_prefix();
  100. xprintf(PSTR("LOOP err=%u ("), (unsigned int)status);
  101. if (status < sizeof(status_names)/sizeof(status_names[0]))
  102. xputs_P(status_names[status]);
  103. else
  104. xputs_P(status_unknown);
  105. xputs_P(PSTR(")\r\n"));
  106. }
  107. void gps_powered_on(void) {
  108. gps_on_uptime = get_uptime_ms();
  109. fix_had_first = 0;
  110. }
  111. void log_fix_event(void) {
  112. log_prefix();
  113. xprintf(PSTR("FIX %uD"), (unsigned int)System.fix_type);
  114. xputs_P(System.dgps ? PSTR("/D") : PSTR(""));
  115. if (!fix_had_first) {
  116. unsigned long int ttff = get_uptime_ms() - gps_on_uptime;
  117. xprintf(PSTR(" ttff=%lu.%01lus"), ttff/1000, (ttff%1000)/100);
  118. fix_had_first = 1;
  119. } else {
  120. xputs_P(PSTR(" regained"));
  121. }
  122. xprintf(PSTR(" sats=%u hdop=%.2f\r\n"), (unsigned int)System.satellites_used, (double)System.hdop_x100/100.0);
  123. }
  124. void log_fix_lost(void) {
  125. log_prefix();
  126. xprintf(PSTR("FIX LOST sats=%u\r\n"), (unsigned int)System.satellites_used);
  127. }
  128. void log_dgps_transition(void) {
  129. log_prefix();
  130. xputs_P(PSTR("DGPS "));
  131. xputs_P(System.dgps ? PSTR("on") : PSTR("off"));
  132. xputs_P(PSTR("\r\n"));
  133. }
  134. void log_pause_event(unsigned char started) {
  135. log_prefix();
  136. xputs_P(started ? PSTR("PAUSE\r\n") : PSTR("RESUME\r\n"));
  137. }
  138. void log_reject_flush(void) {
  139. if (!reject_coalesce.count)
  140. return;
  141. log_prefix();
  142. xputs_P(PSTR("REJ reason="));
  143. xputs_P(reject_reason_names[reject_coalesce.reason]);
  144. xprintf(PSTR(" hdop=%.2f sats=%u fix=%uD"), (double)reject_coalesce.hdop_x100/100.0,
  145. (unsigned int)reject_coalesce.sats, (unsigned int)reject_coalesce.fix_type);
  146. if (reject_coalesce.count > 1)
  147. xprintf(PSTR(" x%u"), (unsigned int)reject_coalesce.count);
  148. xputs_P(PSTR("\r\n"));
  149. reject_coalesce.count = 0;
  150. }
  151. void log_reject(unsigned char reason) {
  152. System.rejected_count++;
  153. if (reject_coalesce.count && reject_coalesce.reason == reason && reject_coalesce.count < 255) {
  154. reject_coalesce.count++;
  155. reject_coalesce.hdop_x100 = System.hdop_x100;
  156. reject_coalesce.sats = System.satellites_used;
  157. reject_coalesce.fix_type = System.fix_type;
  158. return;
  159. }
  160. log_reject_flush();
  161. reject_coalesce.reason = reason;
  162. reject_coalesce.count = 1;
  163. reject_coalesce.hdop_x100 = System.hdop_x100;
  164. reject_coalesce.sats = System.satellites_used;
  165. reject_coalesce.fix_type = System.fix_type;
  166. }
  167. void log_jump(unsigned char is_alt, float meters) {
  168. log_prefix();
  169. xputs_P(PSTR("JUMP "));
  170. xputs_P(is_alt ? PSTR("alt=") : PSTR("pos="));
  171. xprintf(PSTR("%.1fm\r\n"), (double)meters);
  172. }
  173. /* Voltage->percent breakpoints for a rough Li-ion/LiPo discharge curve,
  174. * anchored so VI_LVL (the level that forces an immediate shutdown, see
  175. * main.h) reads 0% - not just happens to clamp there. Precision isn't the
  176. * goal (a straight line between points is a rough approximation), only
  177. * getting the empty end right, since that's exactly when this number matters
  178. * most. Voltages are millivolts to keep the table integer. */
  179. __flash const unsigned int batt_lut_mv[] = { 3100, 3400, 3550, 3700, 3850, 4000, 4100, 4200 };
  180. __flash const unsigned char batt_lut_pct[] = { 0, 10, 25, 45, 65, 80, 90, 100 };
  181. #define BATT_LUT_LEN (sizeof(batt_lut_mv)/sizeof(batt_lut_mv[0]))
  182. static unsigned char battery_percent(float bat_volt) {
  183. unsigned int mv = (unsigned int)(bat_volt*1000.0 + 0.5);
  184. unsigned char i;
  185. if (mv <= batt_lut_mv[0])
  186. return batt_lut_pct[0];
  187. if (mv >= batt_lut_mv[BATT_LUT_LEN-1])
  188. return batt_lut_pct[BATT_LUT_LEN-1];
  189. for (i = 1; i < BATT_LUT_LEN; i++) {
  190. if (mv <= batt_lut_mv[i]) {
  191. unsigned int span_mv = batt_lut_mv[i] - batt_lut_mv[i-1];
  192. unsigned char span_pct = batt_lut_pct[i] - batt_lut_pct[i-1];
  193. return batt_lut_pct[i-1] + (unsigned char)((unsigned long int)(mv - batt_lut_mv[i-1]) * span_pct / span_mv);
  194. }
  195. }
  196. return batt_lut_pct[BATT_LUT_LEN-1]; /* unreachable */
  197. }
  198. void log_status_line(void) {
  199. unsigned char batpct = battery_percent(System.bat_volt);
  200. log_reject_flush();
  201. log_prefix();
  202. xprintf(PSTR("ST v=%.3f bat%%=%d"), (double)System.bat_volt, batpct);
  203. if (System.temperature_ok)
  204. xprintf(PSTR(" t=%.1f"), (double)System.temperature);
  205. xprintf(PSTR(" sats=%u hdop=%.2f fix=%u"), (unsigned int)System.satellites_used,
  206. (double)System.hdop_x100/100.0, (unsigned int)System.fix_type);
  207. xputs_P(System.dgps ? PSTR("D") : PSTR(""));
  208. xprintf(PSTR(" dist=%.2f gain=%.1f/raw%.1f loss=%.1f/raw%.1f wr=%lu rej=%lu"),
  209. (double)System.distance/100.0, (double)System.elevation_gain/10.0, (double)System.elevation_gain_raw/10.0,
  210. (double)System.elevation_loss/10.0, (double)System.elevation_loss_raw/10.0,
  211. System.points_written, System.rejected_count);
  212. xprintf(PSTR(" iomax=%ums stack=%u"), io_get_and_reset_max(), get_stack_free_bytes());
  213. if (utc)
  214. xprintf(PSTR(" loc=%s"), get_iso_time(utc, 1));
  215. xputs_P(PSTR("\r\n"));
  216. }
  217. void log_session_summary(unsigned char final) {
  218. unsigned int moving = get_logging_time();
  219. unsigned long int stopped = get_pause_time();
  220. unsigned int h, m;
  221. log_reject_flush();
  222. log_prefix();
  223. xputs_P(final ? PSTR("SUMMARY final ") : PSTR("SUMMARY "));
  224. xprintf(PSTR("dist=%.2f gain=%.1f loss=%.1f moving="), (double)System.distance/100.0,
  225. (double)System.elevation_gain/10.0, (double)System.elevation_loss/10.0);
  226. h = moving/3600; m = (moving/60)%60;
  227. xprintf(PSTR("%uh%02um stopped="), h, m);
  228. h = stopped/3600; m = (stopped/60)%60;
  229. xprintf(PSTR("%uh%02um altmax=%.1f vmin=%.3f rej=%lu"), h, m,
  230. (double)System.alt_max/10.0, (double)System.bat_volt_min, System.rejected_count);
  231. /* Both averages should track each other; a growing gap is worth noticing. */
  232. xprintf(PSTR(" avg_speed=%.2f avg_dist=%.2f"),
  233. (double)get_avg_speed_x100()/100.0, (double)get_dist_avg_speed_x100()/100.0);
  234. /* points_accepted is pre-averaging: with filters enabled (AVG_COUNT
  235. * samples per written trkpt), points_accepted - points_written*AVG_COUNT
  236. * is however many accepted points are sitting in the averaging window,
  237. * not yet flushed to a trkpt - "averaged out" here, since it never will
  238. * be on its own (the group only flushes once it reaches AVG_COUNT). */
  239. xprintf(PSTR(" paused=%lu skipped=%lu accepted=%lu wr=%lu\r\n"),
  240. System.points_paused, System.points_skipped, System.points_accepted, System.points_written);
  241. }