/* Simple GPS Odometer v2 David Johnson-Davies - www.technoblogy.com - 9th July 2018 ATtiny2313 @ 8 MHz (external crystal; BOD disabled) CC BY 4.0 Licensed under a Creative Commons Attribution 4.0 International license: http://creativecommons.org/licenses/by/4.0/ */ // Seven-segment definitions const int charArrayLen = 12; uint8_t charArray[] = { // ABCDEFG Segments 0b1111110, // 0 0b0110000, // 1 0b1101101, // 2 0b1111001, // 3 0b0110011, // 4 0b1011011, // 5 0b1011111, // 6 0b1110000, // 7 0b1111111, // 8 0b1111011, // 9 0b0000001, // 10 '-' 0b0000000 // 11 Space }; const int Dash = 10; const int Space = 11; uint8_t Buffer[] = { Dash, Dash, Dash, Dash}; uint8_t dp = -1; // Decimal point position 0 to 3 uint8_t digit = 0; uint8_t Digits[] = {14, 17, 15, 16}; // Segments must all go to port B; this specifies how they're wired up: // g f e d c b a dp uint8_t Segments[] = {2, 4, 5, 3, 1, 6, 7, 0}; void ReorderBits() { uint8_t segs, newsegs; for (int i=0; i> 1; } charArray[i]=newsegs; } } void DisplayNextDigit() { pinMode(Digits[digit], INPUT); digit = (digit+1) % 4; uint8_t segs = charArray[Buffer[digit]]; // Display decimal point? if (digit == dp) segs = segs | (1<9999) { j=10000; dp=2; } else { j=1000; dp=1; } for (int d=0; d<4 ; d++) { int i = (number/j) % 10; if (!i && !dig && j>100) Buffer[d]=Space; else { Buffer[d]=i; dig = true; } j=j/10; } } // ParseGPS // Example: $GPRMC,194509.000,A,4042.6142,N,07400.4168,W,2.03,221.11,160412,,,A*77 const char fmt[] PROGMEM = "$GPRMC,dddtdd.ddm,A,????.????,?,?????.????,?,djdk,???.??,??????,,,?*??"; int state = 0; unsigned int temp; // GPS variables volatile unsigned int Time, Msecs, Knots; volatile boolean Fix; void ParseGPS (char c) { if (c == '$') { state = 0; temp = 0; } uint8_t mode = pgm_read_byte_near(fmt + state++); // If received character matches format string, or format is '?' - return if ((mode == c) || (mode == '?')) return; // d=decimal digit uint8_t d = c - '0'; if (mode == 'd') temp = temp*10 + d; // t=Time - hhmm else if (mode == 't') { Time = temp*10 + d; temp = 0; } // m=Millisecs else if (mode == 'm') { Msecs = temp*10 + d; temp = 0; } // j/k=Speed - in knots*100 else if (mode == 'j') { if (c != '.') { temp = temp*10 + d; state--; } } else if (mode == 'k') { Knots = temp*10 + d; Fix = 1; } else state = 0; } // Timer interrupt - multiplexes display ISR (TIMER1_COMPA_vect) { DisplayNextDigit(); } // USART interrupt - receives data from GPS module ISR (USART_RX_vect) { uint8_t c = UDR; ParseGPS(c); } void setup() { ReorderBits(); // Set up Timer1 to multiplex the display TCCR1A = 0< Stationary) Distance = Distance + temp; Display(Distance*19/59438); Fix = 0; }