Browse Source

recoding

display_support
Andreas Peters 2 years ago
parent
commit
72e6cab12e
6 changed files with 1212 additions and 271 deletions
  1. 9
    0
      README.md
  2. 2
    2
      lib/LibAPRS/AFSK.cpp
  3. 503
    0
      lib/TinyGPS++/TinyGPS++.cpp
  4. 273
    0
      lib/TinyGPS++/TinyGPS++.h
  5. 83
    269
      src/main.cpp
  6. 342
    0
      src/main.cpp.bak

+ 9
- 0
README.md View File

@@ -1 +1,10 @@
1 1
 # Arduino-APRS-Tracker
2
+
3
+## Configuration
4
+
5
+Before you start to use it, change the callsign in the main.cpp please. 
6
+
7
+```
8
+char callSign[] = "CALLSING";
9
+char comment[] = "CALLSIGN APRS Tracker";
10
+```

+ 2
- 2
lib/LibAPRS/AFSK.cpp View File

@@ -53,8 +53,8 @@ void AFSK_hw_init(void) {
53 53
                 _BV(ADPS2);
54 54
 
55 55
     AFSK_DAC_INIT();
56
-    LED_TX_INIT();
57
-    LED_RX_INIT();
56
+    //LED_TX_INIT();
57
+    //LED_RX_INIT();
58 58
 }
59 59
 
60 60
 void AFSK_init(Afsk *afsk) {

+ 503
- 0
lib/TinyGPS++/TinyGPS++.cpp View File

@@ -0,0 +1,503 @@
1
+/*
2
+TinyGPS++ - a small GPS library for Arduino providing universal NMEA parsing
3
+Based on work by and "distanceBetween" and "courseTo" courtesy of Maarten Lamers.
4
+Suggestion to add satellites, courseTo(), and cardinal() by Matt Monson.
5
+Location precision improvements suggested by Wayne Holder.
6
+Copyright (C) 2008-2013 Mikal Hart
7
+All rights reserved.
8
+
9
+This library is free software; you can redistribute it and/or
10
+modify it under the terms of the GNU Lesser General Public
11
+License as published by the Free Software Foundation; either
12
+version 2.1 of the License, or (at your option) any later version.
13
+
14
+This library 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 GNU
17
+Lesser General Public License for more details.
18
+
19
+You should have received a copy of the GNU Lesser General Public
20
+License along with this library; if not, write to the Free Software
21
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22
+*/
23
+
24
+#include "TinyGPS++.h"
25
+
26
+#include <string.h>
27
+#include <ctype.h>
28
+#include <stdlib.h>
29
+
30
+#define _GPRMCterm   "GPRMC"
31
+#define _GNRMCterm   "GNRMC"
32
+#define _GPGGAterm   "GPGGA"
33
+#define _GNGGAterm   "GNGGA"
34
+
35
+TinyGPSPlus::TinyGPSPlus()
36
+  :  parity(0)
37
+  ,  isChecksumTerm(false)
38
+  ,  curSentenceType(GPS_SENTENCE_OTHER)
39
+  ,  curTermNumber(0)
40
+  ,  curTermOffset(0)
41
+  ,  sentenceHasFix(false)
42
+  ,  customElts(0)
43
+  ,  customCandidates(0)
44
+  ,  encodedCharCount(0)
45
+  ,  sentencesWithFixCount(0)
46
+  ,  failedChecksumCount(0)
47
+  ,  passedChecksumCount(0)
48
+{
49
+  term[0] = '\0';
50
+}
51
+
52
+//
53
+// public methods
54
+//
55
+
56
+bool TinyGPSPlus::encode(char c)
57
+{
58
+  ++encodedCharCount;
59
+
60
+  switch(c)
61
+  {
62
+  case ',': // term terminators
63
+    parity ^= (uint8_t)c;
64
+  case '\r':
65
+  case '\n':
66
+  case '*':
67
+    {
68
+      bool isValidSentence = false;
69
+      if (curTermOffset < sizeof(term))
70
+      {
71
+        term[curTermOffset] = 0;
72
+        isValidSentence = endOfTermHandler();
73
+      }
74
+      ++curTermNumber;
75
+      curTermOffset = 0;
76
+      isChecksumTerm = c == '*';
77
+      return isValidSentence;
78
+    }
79
+    break;
80
+
81
+  case '$': // sentence begin
82
+    curTermNumber = curTermOffset = 0;
83
+    parity = 0;
84
+    curSentenceType = GPS_SENTENCE_OTHER;
85
+    isChecksumTerm = false;
86
+    sentenceHasFix = false;
87
+    return false;
88
+
89
+  default: // ordinary characters
90
+    if (curTermOffset < sizeof(term) - 1)
91
+      term[curTermOffset++] = c;
92
+    if (!isChecksumTerm)
93
+      parity ^= c;
94
+    return false;
95
+  }
96
+
97
+  return false;
98
+}
99
+
100
+//
101
+// internal utilities
102
+//
103
+int TinyGPSPlus::fromHex(char a)
104
+{
105
+  if (a >= 'A' && a <= 'F')
106
+    return a - 'A' + 10;
107
+  else if (a >= 'a' && a <= 'f')
108
+    return a - 'a' + 10;
109
+  else
110
+    return a - '0';
111
+}
112
+
113
+// static
114
+// Parse a (potentially negative) number with up to 2 decimal digits -xxxx.yy
115
+int32_t TinyGPSPlus::parseDecimal(const char *term)
116
+{
117
+  bool negative = *term == '-';
118
+  if (negative) ++term;
119
+  int32_t ret = 100 * (int32_t)atol(term);
120
+  while (isdigit(*term)) ++term;
121
+  if (*term == '.' && isdigit(term[1]))
122
+  {
123
+    ret += 10 * (term[1] - '0');
124
+    if (isdigit(term[2]))
125
+      ret += term[2] - '0';
126
+  }
127
+  return negative ? -ret : ret;
128
+}
129
+
130
+// static
131
+// Parse degrees in that funny NMEA format DDMM.MMMM
132
+void TinyGPSPlus::parseDegrees(const char *term, RawDegrees &deg)
133
+{
134
+  uint32_t leftOfDecimal = (uint32_t)atol(term);
135
+  uint16_t minutes = (uint16_t)(leftOfDecimal % 100);
136
+  uint32_t multiplier = 10000000UL;
137
+  uint32_t tenMillionthsOfMinutes = minutes * multiplier;
138
+
139
+  deg.deg = (int16_t)(leftOfDecimal / 100);
140
+
141
+  while (isdigit(*term))
142
+    ++term;
143
+
144
+  if (*term == '.')
145
+    while (isdigit(*++term))
146
+    {
147
+      multiplier /= 10;
148
+      tenMillionthsOfMinutes += (*term - '0') * multiplier;
149
+    }
150
+
151
+  deg.billionths = (5 * tenMillionthsOfMinutes + 1) / 3;
152
+  deg.negative = false;
153
+}
154
+
155
+#define COMBINE(sentence_type, term_number) (((unsigned)(sentence_type) << 5) | term_number)
156
+
157
+// Processes a just-completed term
158
+// Returns true if new sentence has just passed checksum test and is validated
159
+bool TinyGPSPlus::endOfTermHandler()
160
+{
161
+  // If it's the checksum term, and the checksum checks out, commit
162
+  if (isChecksumTerm)
163
+  {
164
+    byte checksum = 16 * fromHex(term[0]) + fromHex(term[1]);
165
+    if (checksum == parity)
166
+    {
167
+      passedChecksumCount++;
168
+      if (sentenceHasFix)
169
+        ++sentencesWithFixCount;
170
+
171
+      switch(curSentenceType)
172
+      {
173
+      case GPS_SENTENCE_GPRMC:
174
+        date.commit();
175
+        time.commit();
176
+        if (sentenceHasFix)
177
+        {
178
+           location.commit();
179
+           speed.commit();
180
+           course.commit();
181
+        }
182
+        break;
183
+      case GPS_SENTENCE_GPGGA:
184
+        time.commit();
185
+        if (sentenceHasFix)
186
+        {
187
+          location.commit();
188
+          altitude.commit();
189
+        }
190
+        satellites.commit();
191
+        hdop.commit();
192
+        break;
193
+      }
194
+
195
+      // Commit all custom listeners of this sentence type
196
+      for (TinyGPSCustom *p = customCandidates; p != NULL && strcmp(p->sentenceName, customCandidates->sentenceName) == 0; p = p->next)
197
+         p->commit();
198
+      return true;
199
+    }
200
+
201
+    else
202
+    {
203
+      ++failedChecksumCount;
204
+    }
205
+
206
+    return false;
207
+  }
208
+
209
+  // the first term determines the sentence type
210
+  if (curTermNumber == 0)
211
+  {
212
+    if (!strcmp(term, _GPRMCterm) || !strcmp(term, _GNRMCterm))
213
+      curSentenceType = GPS_SENTENCE_GPRMC;
214
+    else if (!strcmp(term, _GPGGAterm) || !strcmp(term, _GNGGAterm))
215
+      curSentenceType = GPS_SENTENCE_GPGGA;
216
+    else
217
+      curSentenceType = GPS_SENTENCE_OTHER;
218
+
219
+    // Any custom candidates of this sentence type?
220
+    for (customCandidates = customElts; customCandidates != NULL && strcmp(customCandidates->sentenceName, term) < 0; customCandidates = customCandidates->next);
221
+    if (customCandidates != NULL && strcmp(customCandidates->sentenceName, term) > 0)
222
+       customCandidates = NULL;
223
+
224
+    return false;
225
+  }
226
+
227
+  if (curSentenceType != GPS_SENTENCE_OTHER && term[0])
228
+    switch(COMBINE(curSentenceType, curTermNumber))
229
+  {
230
+    case COMBINE(GPS_SENTENCE_GPRMC, 1): // Time in both sentences
231
+    case COMBINE(GPS_SENTENCE_GPGGA, 1):
232
+      time.setTime(term);
233
+      break;
234
+    case COMBINE(GPS_SENTENCE_GPRMC, 2): // GPRMC validity
235
+      sentenceHasFix = term[0] == 'A';
236
+      break;
237
+    case COMBINE(GPS_SENTENCE_GPRMC, 3): // Latitude
238
+    case COMBINE(GPS_SENTENCE_GPGGA, 2):
239
+      location.setLatitude(term);
240
+      break;
241
+    case COMBINE(GPS_SENTENCE_GPRMC, 4): // N/S
242
+    case COMBINE(GPS_SENTENCE_GPGGA, 3):
243
+      location.rawNewLatData.negative = term[0] == 'S';
244
+      break;
245
+    case COMBINE(GPS_SENTENCE_GPRMC, 5): // Longitude
246
+    case COMBINE(GPS_SENTENCE_GPGGA, 4):
247
+      location.setLongitude(term);
248
+      break;
249
+    case COMBINE(GPS_SENTENCE_GPRMC, 6): // E/W
250
+    case COMBINE(GPS_SENTENCE_GPGGA, 5):
251
+      location.rawNewLngData.negative = term[0] == 'W';
252
+      break;
253
+    case COMBINE(GPS_SENTENCE_GPRMC, 7): // Speed (GPRMC)
254
+      speed.set(term);
255
+      break;
256
+    case COMBINE(GPS_SENTENCE_GPRMC, 8): // Course (GPRMC)
257
+      course.set(term);
258
+      break;
259
+    case COMBINE(GPS_SENTENCE_GPRMC, 9): // Date (GPRMC)
260
+      date.setDate(term);
261
+      break;
262
+    case COMBINE(GPS_SENTENCE_GPGGA, 6): // Fix data (GPGGA)
263
+      sentenceHasFix = term[0] > '0';
264
+      break;
265
+    case COMBINE(GPS_SENTENCE_GPGGA, 7): // Satellites used (GPGGA)
266
+      satellites.set(term);
267
+      break;
268
+    case COMBINE(GPS_SENTENCE_GPGGA, 8): // HDOP
269
+      hdop.set(term);
270
+      break;
271
+    case COMBINE(GPS_SENTENCE_GPGGA, 9): // Altitude (GPGGA)
272
+      altitude.set(term);
273
+      break;
274
+  }
275
+
276
+  // Set custom values as needed
277
+  for (TinyGPSCustom *p = customCandidates; p != NULL && strcmp(p->sentenceName, customCandidates->sentenceName) == 0 && p->termNumber <= curTermNumber; p = p->next)
278
+    if (p->termNumber == curTermNumber)
279
+         p->set(term);
280
+
281
+  return false;
282
+}
283
+
284
+/* static */
285
+double TinyGPSPlus::distanceBetween(double lat1, double long1, double lat2, double long2)
286
+{
287
+  // returns distance in meters between two positions, both specified
288
+  // as signed decimal-degrees latitude and longitude. Uses great-circle
289
+  // distance computation for hypothetical sphere of radius 6372795 meters.
290
+  // Because Earth is no exact sphere, rounding errors may be up to 0.5%.
291
+  // Courtesy of Maarten Lamers
292
+  double delta = radians(long1-long2);
293
+  double sdlong = sin(delta);
294
+  double cdlong = cos(delta);
295
+  lat1 = radians(lat1);
296
+  lat2 = radians(lat2);
297
+  double slat1 = sin(lat1);
298
+  double clat1 = cos(lat1);
299
+  double slat2 = sin(lat2);
300
+  double clat2 = cos(lat2);
301
+  delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
302
+  delta = sq(delta);
303
+  delta += sq(clat2 * sdlong);
304
+  delta = sqrt(delta);
305
+  double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
306
+  delta = atan2(delta, denom);
307
+  return delta * 6372795;
308
+}
309
+
310
+double TinyGPSPlus::courseTo(double lat1, double long1, double lat2, double long2)
311
+{
312
+  // returns course in degrees (North=0, West=270) from position 1 to position 2,
313
+  // both specified as signed decimal-degrees latitude and longitude.
314
+  // Because Earth is no exact sphere, calculated course may be off by a tiny fraction.
315
+  // Courtesy of Maarten Lamers
316
+  double dlon = radians(long2-long1);
317
+  lat1 = radians(lat1);
318
+  lat2 = radians(lat2);
319
+  double a1 = sin(dlon) * cos(lat2);
320
+  double a2 = sin(lat1) * cos(lat2) * cos(dlon);
321
+  a2 = cos(lat1) * sin(lat2) - a2;
322
+  a2 = atan2(a1, a2);
323
+  if (a2 < 0.0)
324
+  {
325
+    a2 += TWO_PI;
326
+  }
327
+  return degrees(a2);
328
+}
329
+
330
+const char *TinyGPSPlus::cardinal(double course)
331
+{
332
+  static const char* directions[] = {"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};
333
+  int direction = (int)((course + 11.25f) / 22.5f);
334
+  return directions[direction % 16];
335
+}
336
+
337
+void TinyGPSLocation::commit()
338
+{
339
+   rawLatData = rawNewLatData;
340
+   rawLngData = rawNewLngData;
341
+   lastCommitTime = millis();
342
+   valid = updated = true;
343
+}
344
+
345
+void TinyGPSLocation::setLatitude(const char *term)
346
+{
347
+   TinyGPSPlus::parseDegrees(term, rawNewLatData);
348
+}
349
+
350
+void TinyGPSLocation::setLongitude(const char *term)
351
+{
352
+   TinyGPSPlus::parseDegrees(term, rawNewLngData);
353
+}
354
+
355
+double TinyGPSLocation::lat()
356
+{
357
+   updated = false;
358
+   double ret = rawLatData.deg + rawLatData.billionths / 1000000000.0;
359
+   return rawLatData.negative ? -ret : ret;
360
+}
361
+
362
+double TinyGPSLocation::lng()
363
+{
364
+   updated = false;
365
+   double ret = rawLngData.deg + rawLngData.billionths / 1000000000.0;
366
+   return rawLngData.negative ? -ret : ret;
367
+}
368
+
369
+void TinyGPSDate::commit()
370
+{
371
+   date = newDate;
372
+   lastCommitTime = millis();
373
+   valid = updated = true;
374
+}
375
+
376
+void TinyGPSTime::commit()
377
+{
378
+   time = newTime;
379
+   lastCommitTime = millis();
380
+   valid = updated = true;
381
+}
382
+
383
+void TinyGPSTime::setTime(const char *term)
384
+{
385
+   newTime = (uint32_t)TinyGPSPlus::parseDecimal(term);
386
+}
387
+
388
+void TinyGPSDate::setDate(const char *term)
389
+{
390
+   newDate = atol(term);
391
+}
392
+
393
+uint16_t TinyGPSDate::year()
394
+{
395
+   updated = false;
396
+   uint16_t year = date % 100;
397
+   return year + 2000;
398
+}
399
+
400
+uint8_t TinyGPSDate::month()
401
+{
402
+   updated = false;
403
+   return (date / 100) % 100;
404
+}
405
+
406
+uint8_t TinyGPSDate::day()
407
+{
408
+   updated = false;
409
+   return date / 10000;
410
+}
411
+
412
+uint8_t TinyGPSTime::hour()
413
+{
414
+   updated = false;
415
+   return time / 1000000;
416
+}
417
+
418
+uint8_t TinyGPSTime::minute()
419
+{
420
+   updated = false;
421
+   return (time / 10000) % 100;
422
+}
423
+
424
+uint8_t TinyGPSTime::second()
425
+{
426
+   updated = false;
427
+   return (time / 100) % 100;
428
+}
429
+
430
+uint8_t TinyGPSTime::centisecond()
431
+{
432
+   updated = false;
433
+   return time % 100;
434
+}
435
+
436
+void TinyGPSDecimal::commit()
437
+{
438
+   val = newval;
439
+   lastCommitTime = millis();
440
+   valid = updated = true;
441
+}
442
+
443
+void TinyGPSDecimal::set(const char *term)
444
+{
445
+   newval = TinyGPSPlus::parseDecimal(term);
446
+}
447
+
448
+void TinyGPSInteger::commit()
449
+{
450
+   val = newval;
451
+   lastCommitTime = millis();
452
+   valid = updated = true;
453
+}
454
+
455
+void TinyGPSInteger::set(const char *term)
456
+{
457
+   newval = atol(term);
458
+}
459
+
460
+TinyGPSCustom::TinyGPSCustom(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber)
461
+{
462
+   begin(gps, _sentenceName, _termNumber);
463
+}
464
+
465
+void TinyGPSCustom::begin(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber)
466
+{
467
+   lastCommitTime = 0;
468
+   updated = valid = false;
469
+   sentenceName = _sentenceName;
470
+   termNumber = _termNumber;
471
+   memset(stagingBuffer, '\0', sizeof(stagingBuffer));
472
+   memset(buffer, '\0', sizeof(buffer));
473
+
474
+   // Insert this item into the GPS tree
475
+   gps.insertCustom(this, _sentenceName, _termNumber);
476
+}
477
+
478
+void TinyGPSCustom::commit()
479
+{
480
+   strcpy(this->buffer, this->stagingBuffer);
481
+   lastCommitTime = millis();
482
+   valid = updated = true;
483
+}
484
+
485
+void TinyGPSCustom::set(const char *term)
486
+{
487
+   strncpy(this->stagingBuffer, term, sizeof(this->stagingBuffer));
488
+}
489
+
490
+void TinyGPSPlus::insertCustom(TinyGPSCustom *pElt, const char *sentenceName, int termNumber)
491
+{
492
+   TinyGPSCustom **ppelt;
493
+
494
+   for (ppelt = &this->customElts; *ppelt != NULL; ppelt = &(*ppelt)->next)
495
+   {
496
+      int cmp = strcmp(sentenceName, (*ppelt)->sentenceName);
497
+      if (cmp < 0 || (cmp == 0 && termNumber < (*ppelt)->termNumber))
498
+         break;
499
+   }
500
+
501
+   pElt->next = *ppelt;
502
+   *ppelt = pElt;
503
+}

+ 273
- 0
lib/TinyGPS++/TinyGPS++.h View File

@@ -0,0 +1,273 @@
1
+/*
2
+TinyGPS++ - a small GPS library for Arduino providing universal NMEA parsing
3
+Based on work by and "distanceBetween" and "courseTo" courtesy of Maarten Lamers.
4
+Suggestion to add satellites, courseTo(), and cardinal() by Matt Monson.
5
+Location precision improvements suggested by Wayne Holder.
6
+Copyright (C) 2008-2013 Mikal Hart
7
+All rights reserved.
8
+
9
+This library is free software; you can redistribute it and/or
10
+modify it under the terms of the GNU Lesser General Public
11
+License as published by the Free Software Foundation; either
12
+version 2.1 of the License, or (at your option) any later version.
13
+
14
+This library 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 GNU
17
+Lesser General Public License for more details.
18
+
19
+You should have received a copy of the GNU Lesser General Public
20
+License along with this library; if not, write to the Free Software
21
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22
+*/
23
+
24
+#ifndef __TinyGPSPlus_h
25
+#define __TinyGPSPlus_h
26
+
27
+#if defined(ARDUINO) && ARDUINO >= 100
28
+#include "Arduino.h"
29
+#else
30
+#include "WProgram.h"
31
+#endif
32
+#include <limits.h>
33
+
34
+#define _GPS_VERSION "0.95" // software version of this library
35
+#define _GPS_MPH_PER_KNOT 1.15077945
36
+#define _GPS_MPS_PER_KNOT 0.51444444
37
+#define _GPS_KMPH_PER_KNOT 1.852
38
+#define _GPS_MILES_PER_METER 0.00062137112
39
+#define _GPS_KM_PER_METER 0.001
40
+#define _GPS_FEET_PER_METER 3.2808399
41
+#define _GPS_MAX_FIELD_SIZE 15
42
+
43
+struct RawDegrees
44
+{
45
+   uint16_t deg;
46
+   uint32_t billionths;
47
+   bool negative;
48
+public:
49
+   RawDegrees() : deg(0), billionths(0), negative(false)
50
+   {}
51
+};
52
+
53
+struct TinyGPSLocation
54
+{
55
+   friend class TinyGPSPlus;
56
+public:
57
+   bool isValid() const    { return valid; }
58
+   bool isUpdated() const  { return updated; }
59
+   uint32_t age() const    { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
60
+   const RawDegrees &rawLat()     { updated = false; return rawLatData; }
61
+   const RawDegrees &rawLng()     { updated = false; return rawLngData; }
62
+   double lat();
63
+   double lng();
64
+
65
+   TinyGPSLocation() : valid(false), updated(false)
66
+   {}
67
+
68
+private:
69
+   bool valid, updated;
70
+   RawDegrees rawLatData, rawLngData, rawNewLatData, rawNewLngData;
71
+   uint32_t lastCommitTime;
72
+   void commit();
73
+   void setLatitude(const char *term);
74
+   void setLongitude(const char *term);
75
+};
76
+
77
+struct TinyGPSDate
78
+{
79
+   friend class TinyGPSPlus;
80
+public:
81
+   bool isValid() const       { return valid; }
82
+   bool isUpdated() const     { return updated; }
83
+   uint32_t age() const       { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
84
+
85
+   uint32_t value()           { updated = false; return date; }
86
+   uint16_t year();
87
+   uint8_t month();
88
+   uint8_t day();
89
+
90
+   TinyGPSDate() : valid(false), updated(false), date(0)
91
+   {}
92
+
93
+private:
94
+   bool valid, updated;
95
+   uint32_t date, newDate;
96
+   uint32_t lastCommitTime;
97
+   void commit();
98
+   void setDate(const char *term);
99
+};
100
+
101
+struct TinyGPSTime
102
+{
103
+   friend class TinyGPSPlus;
104
+public:
105
+   bool isValid() const       { return valid; }
106
+   bool isUpdated() const     { return updated; }
107
+   uint32_t age() const       { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
108
+
109
+   uint32_t value()           { updated = false; return time; }
110
+   uint8_t hour();
111
+   uint8_t minute();
112
+   uint8_t second();
113
+   uint8_t centisecond();
114
+
115
+   TinyGPSTime() : valid(false), updated(false), time(0)
116
+   {}
117
+
118
+private:
119
+   bool valid, updated;
120
+   uint32_t time, newTime;
121
+   uint32_t lastCommitTime;
122
+   void commit();
123
+   void setTime(const char *term);
124
+};
125
+
126
+struct TinyGPSDecimal
127
+{
128
+   friend class TinyGPSPlus;
129
+public:
130
+   bool isValid() const    { return valid; }
131
+   bool isUpdated() const  { return updated; }
132
+   uint32_t age() const    { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
133
+   int32_t value()         { updated = false; return val; }
134
+
135
+   TinyGPSDecimal() : valid(false), updated(false), val(0)
136
+   {}
137
+
138
+private:
139
+   bool valid, updated;
140
+   uint32_t lastCommitTime;
141
+   int32_t val, newval;
142
+   void commit();
143
+   void set(const char *term);
144
+};
145
+
146
+struct TinyGPSInteger
147
+{
148
+   friend class TinyGPSPlus;
149
+public:
150
+   bool isValid() const    { return valid; }
151
+   bool isUpdated() const  { return updated; }
152
+   uint32_t age() const    { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
153
+   uint32_t value()        { updated = false; return val; }
154
+
155
+   TinyGPSInteger() : valid(false), updated(false), val(0)
156
+   {}
157
+
158
+private:
159
+   bool valid, updated;
160
+   uint32_t lastCommitTime;
161
+   uint32_t val, newval;
162
+   void commit();
163
+   void set(const char *term);
164
+};
165
+
166
+struct TinyGPSSpeed : TinyGPSDecimal
167
+{
168
+   double knots()    { return value() / 100.0; }
169
+   double mph()      { return _GPS_MPH_PER_KNOT * value() / 100.0; }
170
+   double mps()      { return _GPS_MPS_PER_KNOT * value() / 100.0; }
171
+   double kmph()     { return _GPS_KMPH_PER_KNOT * value() / 100.0; }
172
+};
173
+
174
+struct TinyGPSCourse : public TinyGPSDecimal
175
+{
176
+   double deg()      { return value() / 100.0; }
177
+};
178
+
179
+struct TinyGPSAltitude : TinyGPSDecimal
180
+{
181
+   double meters()       { return value() / 100.0; }
182
+   double miles()        { return _GPS_MILES_PER_METER * value() / 100.0; }
183
+   double kilometers()   { return _GPS_KM_PER_METER * value() / 100.0; }
184
+   double feet()         { return _GPS_FEET_PER_METER * value() / 100.0; }
185
+};
186
+
187
+class TinyGPSPlus;
188
+class TinyGPSCustom
189
+{
190
+public:
191
+   TinyGPSCustom() {};
192
+   TinyGPSCustom(TinyGPSPlus &gps, const char *sentenceName, int termNumber);
193
+   void begin(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber);
194
+
195
+   bool isUpdated() const  { return updated; }
196
+   bool isValid() const    { return valid; }
197
+   uint32_t age() const    { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }
198
+   const char *value()     { updated = false; return buffer; }
199
+
200
+private:
201
+   void commit();
202
+   void set(const char *term);
203
+
204
+   char stagingBuffer[_GPS_MAX_FIELD_SIZE + 1];
205
+   char buffer[_GPS_MAX_FIELD_SIZE + 1];
206
+   unsigned long lastCommitTime;
207
+   bool valid, updated;
208
+   const char *sentenceName;
209
+   int termNumber;
210
+   friend class TinyGPSPlus;
211
+   TinyGPSCustom *next;
212
+};
213
+
214
+class TinyGPSPlus
215
+{
216
+public:
217
+  TinyGPSPlus();
218
+  bool encode(char c); // process one character received from GPS
219
+  TinyGPSPlus &operator << (char c) {encode(c); return *this;}
220
+
221
+  TinyGPSLocation location;
222
+  TinyGPSDate date;
223
+  TinyGPSTime time;
224
+  TinyGPSSpeed speed;
225
+  TinyGPSCourse course;
226
+  TinyGPSAltitude altitude;
227
+  TinyGPSInteger satellites;
228
+  TinyGPSDecimal hdop;
229
+
230
+  static const char *libraryVersion() { return _GPS_VERSION; }
231
+
232
+  static double distanceBetween(double lat1, double long1, double lat2, double long2);
233
+  static double courseTo(double lat1, double long1, double lat2, double long2);
234
+  static const char *cardinal(double course);
235
+
236
+  static int32_t parseDecimal(const char *term);
237
+  static void parseDegrees(const char *term, RawDegrees &deg);
238
+
239
+  uint32_t charsProcessed()   const { return encodedCharCount; }
240
+  uint32_t sentencesWithFix() const { return sentencesWithFixCount; }
241
+  uint32_t failedChecksum()   const { return failedChecksumCount; }
242
+  uint32_t passedChecksum()   const { return passedChecksumCount; }
243
+
244
+private:
245
+  enum {GPS_SENTENCE_GPGGA, GPS_SENTENCE_GPRMC, GPS_SENTENCE_OTHER};
246
+
247
+  // parsing state variables
248
+  uint8_t parity;
249
+  bool isChecksumTerm;
250
+  char term[_GPS_MAX_FIELD_SIZE];
251
+  uint8_t curSentenceType;
252
+  uint8_t curTermNumber;
253
+  uint8_t curTermOffset;
254
+  bool sentenceHasFix;
255
+
256
+  // custom element support
257
+  friend class TinyGPSCustom;
258
+  TinyGPSCustom *customElts;
259
+  TinyGPSCustom *customCandidates;
260
+  void insertCustom(TinyGPSCustom *pElt, const char *sentenceName, int index);
261
+
262
+  // statistics
263
+  uint32_t encodedCharCount;
264
+  uint32_t sentencesWithFixCount;
265
+  uint32_t failedChecksumCount;
266
+  uint32_t passedChecksumCount;
267
+
268
+  // internal utilities
269
+  int fromHex(char a);
270
+  bool endOfTermHandler();
271
+};
272
+
273
+#endif // def(__TinyGPSPlus_h)

+ 83
- 269
src/main.cpp View File

@@ -1,310 +1,124 @@
1 1
 #include "Arduino.h"
2 2
 #include <SoftwareSerial.h>
3
-#include "TinyGPS.h"
3
+#include "TinyGPS++.h"
4 4
 #include "LibAPRS.h"
5 5
 
6 6
 //UBLOX-TX sends data to the Arduino-RX
7 7
 //UBLOX-RX receives data from the Arduino-TX
8 8
 
9
-static const int RXPin = 4, TXPin = 3;
9
+static const int RXPin = 10, TXPin = 8;
10 10
 static const uint32_t SerialBaud = 9600;
11 11
 static const uint32_t GPSBaud = 9600;
12 12
 
13
-// basic setup for the APRS radio section.
14
-#define ADC_REFERENCE REF_5V
15
-#define OPEN_SQUELCH false
13
+char callSign[] = "DC6AP";
14
+char comment[] = "DC6AP APRS Tracker";
16 15
 
17 16
 boolean gotPacket = false;
18 17
 AX25Msg incomingPacket;
19 18
 uint8_t *packetData;
20
-TinyGPS gps;
21 19
 
22
-// set up a couple variables for when we last transmitted.
23
-// aprs spec is around 10 minutes or so (faster if your speed is faster)
24
-// but probably not more than once per minute.
25
-long lastUpdate=0;
26
-int Updatedelay=600; //delay between packets in seconds.
20
+#define ADC_REFERENCE REF_5V
21
+#define OPEN_SQUELCH false
22
+
23
+// The TinyGPS++ object
24
+TinyGPSPlus gps;
27 25
 
28 26
 // The serial connection to the GPS device
29 27
 SoftwareSerial ss(RXPin, TXPin);
30 28
 
31
-static void smartdelay(unsigned long ms);
32
-static void print_float(float val, float invalid, int len, int prec);
33
-static void print_int(unsigned long val, unsigned long invalid, int len);
34
-static void print_date(TinyGPS &gps);
35
-char *ftoa(char *a, double f, int precision);
36
-void processPacket();
37
-void locationUpdate(float flat,float flon);
29
+// GPS Test Data
30
+const char *gpsStream =
31
+  "$GPRMC,045103.000,A,3014.1984,N,09749.2872,W,0.67,161.46,030913,,,A*7C\r\n"
32
+  "$GPGGA,045104.000,3014.1985,N,09749.2873,W,1,09,1.2,211.6,M,-22.5,M,,0000*62\r\n"
33
+  "$GPRMC,045200.000,A,3014.3820,N,09748.9514,W,36.88,65.02,030913,,,A*77\r\n"
34
+  "$GPGGA,045201.000,3014.3864,N,09748.9411,W,1,10,1.2,200.8,M,-22.5,M,,0000*6C\r\n"
35
+  "$GPRMC,045251.000,A,3014.4275,N,09749.0626,W,0.51,217.94,030913,,,A*7D\r\n"
36
+  "$GPGGA,045252.000,3014.4273,N,09749.0628,W,1,09,1.3,206.9,M,-22.5,M,,0000*6F\r\n";
38 37
 
38
+static void smartDelay(unsigned long ms);
39
+static void displayInfo();
39 40
 
40 41
 void setup() {
41
-  // initialize serial output.
42
-  // 9600 is mandatory.   the aprs stuff can't hack a faster rate
43
-  // even though it doesn't directly use this.
44
-  Serial.begin(SerialBaud);
45
-  Serial.println(F("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    "));
46
-  Serial.println(F("          (deg)     (deg)      Age                      Age  (m)    "));
47
-  Serial.println(F("--------------------------------------------------------------------"));
48
-
49
-  // initialize serial to talk with the GPS.  
50
-  // 9600 is mandatory.
51
-  ss.begin(GPSBaud);
52
-   
53
-  // Initialise APRS library - This starts the mode
54
-  APRS_init(ADC_REFERENCE, OPEN_SQUELCH);
55
-  
56
-  // You must at a minimum configure your callsign and SSID
57
-  // you may also not use this software without a valid license
58
-  APRS_setCallsign("DC6AP", 1);
59
- 
60
-  APRS_printSettings();
61
-  Serial.print(F("Free RAM:     ")); Serial.println(freeMemory());  
62
-}
63
-
64
-
65
-void loop() {
66
-
67
-  float fLat, fLon;
68
-  unsigned long age, date = 0;
69
-
70
-  gps.f_get_position(&fLat, &fLon, &age);
42
+    Serial.begin(SerialBaud);
43
+    while(!Serial);
71 44
 
72
-  print_float(fLat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
73
-  print_float(fLon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
74
-  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);  
75
-  print_date(gps);
76
-
77
-  if ((fLat != TinyGPS::GPS_INVALID_F_ANGLE ) && ( fLon != TinyGPS::GPS_INVALID_F_ANGLE )){
78
-    // check for any new packets.
79
-    smartdelay(250);
80
-    processPacket();
81
-    smartdelay(250);
82
-    locationUpdate(fLat,fLon);
83
-  }
45
+    ss.begin(GPSBaud);
46
+    delay(1000);
47
+    
48
+    Serial.println("Setup Complete!");  
84 49
 
85
-  smartdelay(1000);
86
-  
87
-  // check for packets.
88
-  processPacket();
89
-  
90
-}
50
+    APRS_init(ADC_REFERENCE, OPEN_SQUELCH);
51
+    
52
+    APRS_setCallsign(callSign, 1);
53
+    APRS_setSymbol('n');
54
+    
55
+    APRS_printSettings();
56
+    Serial.print(F("Free RAM:     ")); Serial.println(freeMemory());    
91 57
 
92
-// TODO: have to rewrite
93
-static void print_int(unsigned long val, unsigned long invalid, int len) {
94
-  char sz[32];
95
-  if (val == invalid)
96
-    strcpy(sz, "*******");
97
-  else
98
-    sprintf(sz, "%ld", val);
99
-  sz[len] = 0;
100
-  for (int i=strlen(sz); i<len; ++i)
101
-    sz[i] = ' ';
102
-  if (len > 0) 
103
-    sz[len-1] = ' ';
104
-  Serial.print(sz);
105
-  smartdelay(0);
58
+    Serial.println(F("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    "));
59
+    Serial.println(F("          (deg)     (deg)      Age                      Age  (m)    "));
60
+    Serial.println(F("--------------------------------------------------------------------"));
61
+    
106 62
 }
107 63
 
108
-static void print_date(TinyGPS &gps) {
109
-  int year;
110
-  byte month, day, hour, minute, second, hundredths;
111
-  unsigned long age;
112
-  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
113
-  if (age == TinyGPS::GPS_INVALID_AGE)
114
-    Serial.print(F("********** ******** "));
115
-  else
116
-  {
117
-    char sz[32];
118
-    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
119
-        month, day, year, hour, minute, second);
120
-    Serial.print(sz);
64
+void displayInfo() {
65
+  Serial.print(F("Location: ")); 
66
+  if (gps.location.isValid()) {
67
+    Serial.print(gps.location.lat(), 6);
68
+    Serial.print(F(","));
69
+    Serial.print(gps.location.lng(), 6);
70
+  } else {
71
+    Serial.print(F("INVALID"));
121 72
   }
122
-  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
123
-  smartdelay(0);
124
-}
125
-
126
-
127
-//basically delay without stopping the processor.  
128
-// the library still needs to be able to decode incoming packets.
129
-static void smartdelay(unsigned long ms) {
130
-  unsigned long start = millis();
131
-  do {
132
-    while (ss.available())
133
-      gps.encode(ss.read());
134
-  } while (millis() - start < ms);
135
-}
136
-
137
-void locationUpdate(float flat,float flon) {
138
-  // Let's first set our latitude and longtitude.
139
-  // These should be in NMEA format!
140
-
141 73
 
142
-// flat, negative == Southern hemisphere
143
-// flon, negative == western hemisphere
144
-//  for instance...  43.646808, -116.286437  
145
-//nmea then is:
146
-//  43 .. (.646808*60),N
147
-// 116 .. (.286437*60),W  (w since it was negative)
148
-// APRS chokes when you send a ,N though... 
149
-// it also chokes when you send more than 2 decimal places.
150
-
151
-  int temp;
152
-  char y[13];
153
-  char z[13];
154
-
155
-// CONVERT to NMEA.  
156
-  if (flat<0){
157
-     temp=-(int)flat;
158
-     flat=temp*100 - (flat+temp)*60;
159
-     ftoa((char*)&y,flat,3);   
160
-     //z[10]=',';
161
-     if (flat > 10000) {
162
-       y[8]='S';
163
-       y[9]=0;
164
-     } else {
165
-       y[7]='S';
166
-       y[8]=0;
167
-     }
74
+  Serial.print(F("  Date/Time: "));
75
+  if (gps.date.isValid()) {
76
+    Serial.print(gps.date.month());
77
+    Serial.print(F("/"));
78
+    Serial.print(gps.date.day());
79
+    Serial.print(F("/"));
80
+    Serial.print(gps.date.year());
168 81
   } else {
169
-     temp=(int)flat;
170
-     flat=temp*100 + (flat-temp)*60;
171
-     ftoa((char*)&y,flat,3);      
172
-     //z[10]=',';
173
-     if (flat > 10000) {
174
-       y[8]='N';
175
-       y[9]=0;
176
-     } else {
177
-       y[7]='N';
178
-       y[8]=0;
179
-     }  
180
-   }
181
-     
182
-   APRS_setLat(y);
183
-   
184
-  Serial.println();
185
-  Serial.println(F("Location Update:"));
186
-  Serial.print(F("Lat: "));
187
-  Serial.println(y);
188
-  
189
-  if (flon<0){
190
-    temp=-(int)flon;
191
-    flon=temp*100 - (flon+temp)*60;
192
-    ftoa((char*)&z,flon,3);   
193
-     //z[10]=',';
194
-     if (flon > 10000){
195
-       z[8]='W';
196
-       z[9]=0;
197
-     } else {
198
-      z[7]='W';
199
-      z[8]=0; 
200
-     }
82
+    Serial.print(F("INVALID"));
83
+  }
84
+
85
+  Serial.print(F(" "));
86
+  if (gps.time.isValid()) {
87
+    if (gps.time.hour() < 10) Serial.print(F("0"));
88
+    Serial.print(gps.time.hour());
89
+    Serial.print(F(":"));
90
+    if (gps.time.minute() < 10) Serial.print(F("0"));
91
+    Serial.print(gps.time.minute());
92
+    Serial.print(F(":"));
93
+    if (gps.time.second() < 10) Serial.print(F("0"));
94
+    Serial.print(gps.time.second());
95
+    Serial.print(F("."));
96
+    if (gps.time.centisecond() < 10) Serial.print(F("0"));
97
+    Serial.print(gps.time.centisecond());
201 98
   } else {
202
-    temp=(int)flon;
203
-    flon=temp*100 + (flon-temp)*60;
204
-    ftoa((char*)&z,flon,3);   
205
-     //z[10]=',';
206
-     if (flon > 10000){
207
-       z[8]='E';
208
-       z[9]=0;
209
-     } else {
210
-      z[7]='E';
211
-      z[8]=0; 
212
-     }
213
-     
214
-}
215
-    APRS_setLon(z);
216
- 
217
- // done converting to NMEA.
99
+    Serial.print(F("INVALID"));
100
+  }
218 101
 
219
-  Serial.print(F("Lon:"));
220
-  Serial.println(z);
221
-    
222
-  // We can optionally set power/height/gain/directivity
223
-  // information. These functions accept ranges
224
-  // from 0 to 10, directivity 0 to 9.
225
-  // See this site for a calculator:
226
-  // http://www.aprsfl.net/phgr.php
227
-  // LibAPRS will only add PHG info if all four variables
228
-  // are defined!
229
-  //APRS_setPower(2);
230
-  //APRS_setHeight(4);
231
-  //APRS_setGain(7);
232
-  //APRS_setDirectivity(0);
233
-  
234
-  // We'll define a comment string
235
-  char *comment = " JWAprsTrkr";
236
-    
237
-  // And send the update
238
-  APRS_sendLoc(comment, strlen(comment));
239
-  
102
+  Serial.println();
240 103
 }
241 104
 
242
-// Here's a function to process incoming packets
243
-// Remember to call this function often, so you
244
-// won't miss any packets due to one already
245
-// waiting to be processed
246
-void processPacket() {
247
-  if (gotPacket) {
248
-    gotPacket = false;
249
-    
250
-    Serial.print(F("Rcvd APRS packet. SRC: "));
251
-    Serial.print(incomingPacket.src.call);
252
-    Serial.print(F("-"));
253
-    Serial.print(incomingPacket.src.ssid);
254
-    Serial.print(F(". DST: "));
255
-    Serial.print(incomingPacket.dst.call);
256
-    Serial.print(F("-"));
257
-    Serial.print(incomingPacket.dst.ssid);
258
-    Serial.print(F(". Data: "));
259
-
260
-    for (int i = 0; i < incomingPacket.len; i++) {
261
-      Serial.write(incomingPacket.info[i]);
262
-    }
263
-    Serial.println(F(""));
264
-
265
-    // Remeber to free memory for our buffer!
266
-    free(packetData);
267
-
268
-    // You can print out the amount of free
269
-    // RAM to check you don't have any memory
270
-    // leaks
271
-     Serial.print(F("Free RAM: ")); Serial.println(freeMemory());
272
-  }
105
+void loop() {
106
+    smartDelay(2500);
107
+    displayInfo();
273 108
 }
274 109
 
275
-// converts float to char*
276
-char *ftoa(char *a, double f, int precision){
277
-  long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
278
- 
279
-  char *ret = a;
280
-  long heiltal = (long)f;
281
-  itoa(heiltal, a, 10);
282
-  while (*a != '\0') a++;
283
-  *a++ = '.';
284
-  long desimal = abs((long)((f - heiltal) * p[precision]));
285
-  itoa(desimal, a, 10);
286
-  return ret;
110
+// basically delay without stopping the processor.  
111
+static void smartDelay(unsigned long ms) {    
112
+    unsigned long start = millis();
113
+    do {        
114
+        while (ss.available()) {        
115
+            char c = ss.read();
116
+            gps.encode(c);
117
+            //Serial.write(c);
118
+        }
119
+    } while (millis() - start < ms);
287 120
 }
288 121
 
289
-static void print_float(float val, float invalid, int len, int prec)
290
-{
291
-  if (val == invalid)
292
-  {
293
-    while (len-- > 1)
294
-      Serial.print(F("*"));
295
-    Serial.print(F(" "));
296
-  }
297
-  else
298
-  {
299
-    Serial.print(val, prec);
300
-    int vi = abs((int)val);
301
-    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
302
-    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
303
-    for (int i=flen; i<len; ++i)
304
-      Serial.print(F(" "));
305
-  }
306
-  smartdelay(0);
307
-}
308 122
 
309 123
 void aprs_msg_callback(struct AX25Msg *msg) {
310 124
   // If we already have a packet waiting to be

+ 342
- 0
src/main.cpp.bak View File

@@ -0,0 +1,342 @@
1
+#include "Arduino.h"
2
+#include <SoftwareSerial.h>
3
+#include "TinyGPS.h"
4
+#include "LibAPRS.h"
5
+
6
+//UBLOX-TX sends data to the Arduino-RX
7
+//UBLOX-RX receives data from the Arduino-TX
8
+
9
+static const int RXPin = 4, TXPin = 3;
10
+static const uint32_t SerialBaud = 9600;
11
+static const uint32_t GPSBaud = 9600;
12
+char callSign[] = "DC6AP";
13
+char comment[] = "DC6AP APRS Tracker";
14
+
15
+// basic setup for the APRS radio section.
16
+#define ADC_REFERENCE REF_5V
17
+#define OPEN_SQUELCH false
18
+
19
+boolean gotPacket = false;
20
+AX25Msg incomingPacket;
21
+uint8_t *packetData;
22
+TinyGPS gps;
23
+
24
+// set up a couple variables for when we last transmitted.
25
+// aprs spec is around 10 minutes or so (faster if your speed is faster)
26
+// but probably not more than once per minute.
27
+long lastUpdate=0;
28
+int Updatedelay=600; //delay between packets in seconds.
29
+
30
+// The serial connection to the GPS device
31
+SoftwareSerial ss(RXPin, TXPin);
32
+
33
+static void smartDelay(unsigned long ms);
34
+static void print_float(float val, float invalid, int len, int prec);
35
+static void print_int(unsigned long val, unsigned long invalid, int len);
36
+static void print_date(TinyGPS &gps);
37
+char *ftoa(char *a, double f, int precision);
38
+void processPacket();
39
+void locationUpdate(float flat,float flon);
40
+void cardinalPointSN(float latitude, char *coord);
41
+
42
+
43
+void setup() {
44
+  // initialize serial output.
45
+  // 9600 is mandatory.   the aprs stuff can't hack a faster rate
46
+  Serial.begin(SerialBaud);
47
+  Serial.println(F("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    "));
48
+  Serial.println(F("          (deg)     (deg)      Age                      Age  (m)    "));
49
+  Serial.println(F("--------------------------------------------------------------------"));
50
+
51
+  // initialize serial to talk with the GPS.  
52
+  // 9600 is mandatory.
53
+  ss.begin(GPSBaud);
54
+   
55
+  // Initialise APRS library - This starts the mode
56
+  APRS_init(ADC_REFERENCE, OPEN_SQUELCH);
57
+  
58
+  // You must at a minimum configure your callsign and SSID
59
+  // you may also not use this software without a valid license
60
+
61
+  APRS_setCallsign(callSign, 1);
62
+ 
63
+  APRS_printSettings();
64
+  Serial.print(F("Free RAM:     ")); Serial.println(freeMemory());  
65
+}
66
+
67
+
68
+void loop() {
69
+  float fLat, fLon;
70
+  unsigned long age = 0;
71
+  while (ss.available()) {    
72
+    Serial.write(ss.read());
73
+    //gps.encode(ss.read());
74
+    //displayInfo();
75
+  }  
76
+  
77
+  gps.f_get_position(&fLat, &fLon, &age);
78
+
79
+  print_float(fLat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
80
+  print_float(fLon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
81
+  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);  
82
+  print_date(gps);
83
+
84
+  if ((fLat != TinyGPS::GPS_INVALID_F_ANGLE ) && ( fLon != TinyGPS::GPS_INVALID_F_ANGLE )){
85
+    // check for any new packets.
86
+    smartDelay(250);
87
+    processPacket();
88
+    smartDelay(250);
89
+    locationUpdate(fLat,fLon);
90
+  }
91
+
92
+  smartDelay(1000);
93
+  
94
+  // check for packets.
95
+  processPacket();
96
+  
97
+}
98
+
99
+// TODO: have to rewrite
100
+static void print_int(unsigned long val, unsigned long invalid, int len) {
101
+  char sz[32];
102
+  if (val == invalid)
103
+    strcpy(sz, "*******");
104
+  else
105
+    sprintf(sz, "%ld", val);
106
+  sz[len] = 0;
107
+  for (int i=strlen(sz); i<len; ++i)
108
+    sz[i] = ' ';
109
+  if (len > 0) 
110
+    sz[len-1] = ' ';
111
+  Serial.print(sz);
112
+  smartDelay(0);
113
+}
114
+
115
+// TODO: have to rewrite
116
+static void print_date(TinyGPS &gps) {
117
+  int year;
118
+  byte month, day, hour, minute, second, hundredths;
119
+  unsigned long age;
120
+  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
121
+  if (age == TinyGPS::GPS_INVALID_AGE)
122
+    Serial.print(F("********** ******** "));
123
+  else
124
+  {
125
+    char sz[32];
126
+    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
127
+        month, day, year, hour, minute, second);
128
+    Serial.print(sz);
129
+  }
130
+  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
131
+  smartDelay(0);
132
+}
133
+
134
+
135
+// basically delay without stopping the processor.  
136
+static void smartDelay(unsigned long ms) {
137
+  unsigned long start = millis();
138
+  do {
139
+    while (ss.available())
140
+      gps.encode(ss.read());
141
+  } while (millis() - start < ms);
142
+}
143
+
144
+void cardinalPoint(int temp, float latlong, char* coord, char compa) {
145
+  latlong =temp * 100 - (latlong + temp)*60;
146
+  ftoa((char*)&coord, latlong, 3);   
147
+  
148
+  if (latlong > 10000) {
149
+    coord[8]=compa;
150
+    coord[9]=0;
151
+  } else {
152
+    coord[7]=compa;
153
+    coord[8]=0;
154
+  }  
155
+}
156
+
157
+void locationUpdate(float latitude,float longitude) {
158
+  int temp;
159
+  char y[13];
160
+  char z[13];
161
+
162
+  // CONVERT to NMEA.  
163
+  if (latitude<0){
164
+    //cardinalPoint(-(int)latitute, latitude, &y, 'S');
165
+    temp=-(int)latitude;
166
+    latitude=temp*100 - (latitude+temp)*60;
167
+    ftoa((char*)&y,latitude,3);   
168
+    //z[10]=',';
169
+    if (latitude > 10000) {
170
+      y[8]='S';
171
+      y[9]=0;
172
+    } else {
173
+      y[7]='S';
174
+      y[8]=0;
175
+    }
176
+  } else {
177
+    //cardinalPoint(-(int)latitute, latitude, &y, 'N');
178
+    temp=(int)latitude;
179
+    latitude=temp*100 + (latitude-temp)*60;
180
+    ftoa((char*)&y,latitude,3);      
181
+    //z[10]=',';
182
+    if (latitude > 10000) {
183
+      y[8]='N';
184
+      y[9]=0;
185
+    } else {
186
+      y[7]='N';
187
+      y[8]=0;
188
+    }  
189
+  }
190
+     
191
+  APRS_setLat(y);
192
+   
193
+  Serial.println();
194
+  Serial.println(F("Location Update:"));
195
+  Serial.print(F("Lat: "));
196
+  Serial.println(y);
197
+  
198
+  if (longitude<0){
199
+    //cardinalPoint(-(int)longitude, latitude, &z, 'W');
200
+    temp=-(int)longitude;
201
+    longitude=temp*100 - (longitude+temp)*60;
202
+    ftoa((char*)&z,longitude,3);   
203
+     //z[10]=',';
204
+     if (longitude > 10000){
205
+       z[8]='W';
206
+       z[9]=0;
207
+     } else {
208
+      z[7]='W';
209
+      z[8]=0; 
210
+     }
211
+  } else {
212
+    //cardinalPoint((int)longitude, latitude, &z, 'E');
213
+    temp=(int)longitude;
214
+    longitude=temp*100 + (longitude-temp)*60;
215
+    ftoa((char*)&z,longitude,3);   
216
+     //z[10]=',';
217
+     if (longitude > 10000){
218
+       z[8]='E';
219
+       z[9]=0;
220
+     } else {
221
+      z[7]='E';
222
+      z[8]=0; 
223
+     }
224
+     
225
+  }
226
+   APRS_setLon(z);
227
+ 
228
+  // done converting to NMEA.
229
+
230
+  Serial.print(F("Lon:"));
231
+  Serial.println(z);
232
+    
233
+  // We can optionally set power/height/gain/directivity
234
+  // information. These functions accept ranges
235
+  // from 0 to 10, directivity 0 to 9.
236
+  // See this site for a calculator:
237
+  // http://www.aprsfl.net/phgr.php
238
+  // LibAPRS will only add PHG info if all four variables
239
+  // are defined!
240
+  //APRS_setPower(2);
241
+  //APRS_setHeight(4);
242
+  //APRS_setGain(7);
243
+  //APRS_setDirectivity(0);
244
+    
245
+  // And send the update
246
+  APRS_sendLoc(comment, strlen(comment));  
247
+}
248
+
249
+// Here's a function to process incoming packets
250
+// Remember to call this function often, so you
251
+// won't miss any packets due to one already
252
+// waiting to be processed
253
+void processPacket() {
254
+  if (gotPacket) {
255
+    gotPacket = false;
256
+    
257
+    Serial.print(F("Rcvd APRS packet. SRC: "));
258
+    Serial.print(incomingPacket.src.call);
259
+    Serial.print(F("-"));
260
+    Serial.print(incomingPacket.src.ssid);
261
+    Serial.print(F(". DST: "));
262
+    Serial.print(incomingPacket.dst.call);
263
+    Serial.print(F("-"));
264
+    Serial.print(incomingPacket.dst.ssid);
265
+    Serial.print(F(". Data: "));
266
+
267
+    for (int i = 0; i < (int) incomingPacket.len; i++) {
268
+      Serial.write(incomingPacket.info[i]);
269
+    }
270
+    Serial.println(F(""));
271
+
272
+    // Remeber to free memory for our buffer!
273
+    free(packetData);
274
+
275
+    // You can print out the amount of free
276
+    // RAM to check you don't have any memory
277
+    // leaks
278
+    Serial.print(F("Free RAM: ")); Serial.println(freeMemory());
279
+  }
280
+}
281
+
282
+// converts float to char*
283
+char *ftoa(char *a, double f, int precision) {
284
+  long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
285
+ 
286
+  char *ret = a;
287
+  long heiltal = (long)f;
288
+  itoa(heiltal, a, 10);
289
+  while (*a != '\0') a++;
290
+  *a++ = '.';
291
+  long desimal = abs((long)((f - heiltal) * p[precision]));
292
+  itoa(desimal, a, 10);
293
+  return ret;
294
+}
295
+
296
+// TODO: have to rewrite
297
+static void print_float(float val, float invalid, int len, int prec)
298
+{
299
+  if (val == invalid)
300
+  {
301
+    while (len-- > 1)
302
+      Serial.print(F("*"));
303
+    Serial.print(F(" "));
304
+  }
305
+  else
306
+  {
307
+    Serial.print(val, prec);
308
+    int vi = abs((int)val);
309
+    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
310
+    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
311
+    for (int i=flen; i<len; ++i)
312
+      Serial.print(F(" "));
313
+  }
314
+  smartDelay(0);
315
+}
316
+
317
+void aprs_msg_callback(struct AX25Msg *msg) {
318
+  // If we already have a packet waiting to be
319
+  // processed, we must drop the new one.
320
+  if (!gotPacket) {
321
+    // Set flag to indicate we got a packet
322
+    gotPacket = true;
323
+
324
+    // The memory referenced as *msg is volatile
325
+    // and we need to copy all the data to a
326
+    // local variable for later processing.
327
+    memcpy(&incomingPacket, msg, sizeof(AX25Msg));
328
+
329
+    // We need to allocate a new buffer for the
330
+    // data payload of the packet. First we check
331
+    // if there is enough free RAM.
332
+    if (freeMemory() > (int) msg->len) {
333
+      packetData = (uint8_t*)malloc(msg->len);
334
+      memcpy(packetData, msg->info, msg->len);
335
+      incomingPacket.info = packetData;
336
+    } else {
337
+      // We did not have enough free RAM to receive
338
+      // this packet, so we drop it.
339
+      gotPacket = false;
340
+    }
341
+  }
342
+}

Loading…
Cancel
Save