📄 gps source code.txt
字号:
setup_timer_3(T3_INTERNAL | T3_DIV_BY_1);
setup_ccp2 (CCP_CAPTURE_RE | CCP_USE_TIMER3);
}
/**
* Verify the GPS engine is sending GGA and RMC messages. If not,
* configure the GPS engine to send the proper data.
*
* @return TRUE if GPS engine operation; otherwise FALSE
*/
boolean gpsSetup()
{
uint8_t startTime;
// We wait 3 seconds for a GPS update to give the engine time to start.
startTime = timeGetTicks();
while (timeGetTicks() - startTime < 30) {
// Read the serial FIFO and process the GPS messages.
gpsUpdate();
// If the GPS state changed, then the GPS is running.
if (gpsState != GPS_WAIT_MSG) {
timeSetDutyCycle (TIME_DUTYCYCLE_10);
return true;
}
} // END while
// Set the baud rate for the Motorola binary mode.
set_uart_speed(9600);
// Wait for the UART buffer to empty.
delay_ms(10);
// Put the GPS engine in NMEA mode.
puts ("@@Ci\001\053\015\012");
// Wait for the GPS to switch modes.
delay_ms(500);
// Set the baud rate for NMEA-0183 messages.
set_uart_speed(4800);
// Send a couple <CR><LF> to clear the GPS engine buffer.
delay_ms(100);
puts ("\015\012");
delay_ms(100);
puts ("\015\012");
delay_ms(100);
// Tell the GPS to send GGA and RMC NMEA messages.
puts ("$PMOTG,GGA,0001\015\012");
delay_ms(100);
puts ("$PMOTG,RMC,0001\015\012");
delay_ms(100);
return false;
}
/**
* Parse the altitude in tens of feet from the NMEA-0183 $GPGGA message.
*
* @return altitude in tens of feet; otherwise 0 if invalid message
*/
int16_t gpsParseAltitude()
{
uint8_t i, count;
int32_t altitude;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 9)
if (gpsBuffer[i++] == ',')
++count;
if (count != 9)
return 0;
// Convert meters to tens of feet. ft = (10000 * meters) / 30480
altitude = atoi32(gpsBuffer + i) * 10000l;
altitude /= 30480l;
return altitude;
}
/**
* Parse the DOP in tenths from the NMEA-0183 $GPGGA message.
*
* @return DOP; otherwise 0 if invalid message
*/
uint16_t gpsParseDOP()
{
uint8_t i, count, dop;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 8)
if (gpsBuffer[i++] == ',')
++count;
if (count != 8)
return 0;
// Parse the DOP value x.x or xx.x. Return 0 if the field is NULL.
dop = 0;
while (gpsBuffer[i] != 0 && gpsBuffer[i] != ',') {
if (gpsBuffer[i] >= '0' && gpsBuffer[i] <= '9')
dop = (dop * 10) + (gpsBuffer[i] - '0');
++i;
} // END while
return dop;
}
uint16_t gpsParseHeading()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 8)
if (gpsBuffer[i++] == ',')
++count;
// Convert knots to MPH
return atol(gpsBuffer + i);
}
/**
* Determine if NMEA-0183 $GPGGA navigation fix is valid.
*
* @return true for valid fix; otherwise false
*/
boolean gpsParseIsGGAValid()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 6)
if (gpsBuffer[i++] == ',')
++count;
// Indicate the solution is bad if the parse failed or the fix valid is set to '0'.
if (count != 6 || gpsBuffer[i] != '1')
return false;
return true;
}
/**
* Determine if NMEA-0183 $GPRMC navigation fix is valid.
*
* @return true for valid fix; otherwise false
*/
boolean gpsParseIsRMCValid()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 2)
if (gpsBuffer[i++] == ',')
++count;
// Indicate the solution is bad if the parse failed or the fix valid is set to 'V'.
if (count != 2 || gpsBuffer[i] != 'A')
return false;
return true;
}
/**
* Parse the altitude in tens of feet from the NMEA-0183 $GPGGA message.
*
* @return altitude in tens of feet; otherwise 0 if invalid message
*/
char *gpsParseLatitude()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 2)
if (gpsBuffer[i++] == ',')
++count;
return gpsBuffer + i;
}
char gpsParseLatitudeOrdinal()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 3)
if (gpsBuffer[i++] == ',')
++count;
return gpsBuffer[i];
}
/**
* Parse the altitude in tens of feet from the NMEA-0183 $GPGGA message.
*
* @return altitude in tens of feet; otherwise 0 if invalid message
*/
char *gpsParseLongitude()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 4)
if (gpsBuffer[i++] == ',')
++count;
return gpsBuffer + i;
}
char gpsParseLongitudeOrdinal()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 5)
if (gpsBuffer[i++] == ',')
++count;
return gpsBuffer[i];
}
/**
* Parse the tracking satelite count from the NMEA-0183 $GPGGA message.
*
* @return sat count; otherwise 0 if invalid message
*/
uint8_t gpsParseSatCount()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 7)
if (gpsBuffer[i++] == ',')
++count;
if (count != 7)
return 0;
// Parse the sat count field.
return ((gpsBuffer[i] - '0') * 10) + (gpsBuffer[i + 1] - '0');
}
/**
* Parse the seconds from the UTC time in the NMEA-0183 $GPGGA or $GPRMC message.
*
* @return GPS seconds; otherwise 0xff if invalid message
*/
uint8_t gpsParseSeconds()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 1)
if (gpsBuffer[i++] == ',')
++count;
if (count != 1)
return 0xff;
// Make sure our time stamp field contains all digits.
while (gpsBuffer[i] != 0 && isdigit(gpsBuffer[i]) && i < 13)
++i;
if (i != 13)
return 0xff;
return ((gpsBuffer[11] - '0') * 10) + (gpsBuffer[12] - '0');
}
/**
* Parse the minutes from the UTC time in the NMEA-0183 $GPGGA or $GPRMC message.
*
* @return GPS minutes; otherwise 0xff if invalid message
*/
uint8_t gpsParseMinutes()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 1)
if (gpsBuffer[i++] == ',')
++count;
if (count != 1)
return 0xff;
// Make sure our time stamp field contains all digits.
while (gpsBuffer[i] != 0 && isdigit(gpsBuffer[i]) && i < 13)
++i;
if (i != 13)
return 0xff;
return ((gpsBuffer[9] - '0') * 10) + (gpsBuffer[10] - '0');
}
/**
* Parse the hours from the UTC time in the NMEA-0183 $GPGGA or $GPRMC message.
*
* @return GPS minutes; otherwise 0xff if invalid message
*/
uint8_t gpsParseHours()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 1)
if (gpsBuffer[i++] == ',')
++count;
if (count != 1)
return 0xff;
// Make sure our time stamp field contains all digits.
while (gpsBuffer[i] != 0 && isdigit(gpsBuffer[i]) && i < 13)
++i;
if (i != 13)
return 0xff;
return ((gpsBuffer[7] - '0') * 10) + (gpsBuffer[8] - '0');
}
uint16_t gpsParseSpeed()
{
uint8_t i, count;
// Count the number of field delimiters until we find the desired one.
i = 0;
count = 0;
while (gpsBuffer[i] != 0 && count != 7)
if (gpsBuffer[i++] == ',')
++count;
// Convert knots to MPH
return (atol (gpsBuffer + i) * 23l) / 20l;
}
/**
* Read the serial FIFO and process complete GPS messages.
*/
void gpsUpdate()
{
uint8_t value;
// Only update the buffer if we are waiting for a message.
if (gpsState != GPS_WAIT_MSG)
return;
// Continue to process until the FIFO is empty.
while (serialHasData()) {
// Get the character value.
value = serialRead();
// Save each character to the telemetry buffer to transmit later.
gpsBuffer[gpsIndex] = value;
// If we filled the buffer, then something is wrong and we need to reset.
if (gpsIndex == GPS_BUFFER_SIZE - 1)
gpsIndex = 0;
// At the EOL determine and set the GPS state.
if (value == 10) {
if (gpsIndex > 15) {
// NULL terminate the buffer.
gpsBuffer[gpsIndex] = 0;
// Reset the index pointer for the next message.
gpsIndex = 0;
// Set a flag for the desired message, otherwise we'll wait for the next one.
if (strncmp(gpsBuffer, GPS_GGA_TEXT, 6) == 0) {
gpsState = GPS_GGA_MSG;
return;
} // END if
if (strncmp(gpsBuffer, GPS_RMC_TEXT, 6) == 0) {
gpsState = GPS_RMC_MSG;
return;
} // END if
}
// This wasn't a valid message, so just start over.
gpsIndex = 0;
} else
++gpsIndex;
} // END while
}
/**
* Wait up to 2.0 seconds for the GPS message of <b>messageType</b>.
*
* @param messageType desired GPS message type <i>GPS_GGA_MSG</i> or <i>GPS_RMC_MSG</i>
*
* @return TRUE if successful; otherwise false
*/
boolean gpsWaitMessage(uint8_t messageType)
{
uint8_t startTime;
// We already have the one we are looking for.
if (gpsState == messageType)
return true;
// Clear the message type and wait for the new one.
gpsState = GPS_WAIT_MSG;
// Record the current time so we can time out.
startTime = timeGetTicks();
while (timeGetTicks() - startTime < 20) {
gpsUpdate();
// If we have the correct one, we are done.
if (gpsState == messageType)
return true;
gpsState = GPS_WAIT_MSG;
} // END while
return false;
}
// ****************************************************************************
// PSK 31 modulator
//
const uint16_t PSK31_VARICODE[] =
{
0xAAC0, // ASCII = 0 1010101011
0xB6C0, // ASCII = 1 1011011011
0xBB40, // ASCII = 2 1011101101
0xDDC0, // ASCII = 3 1101110111
0xBAC0, // ASCII = 4 1011101011
0xD7C0, // ASCII = 5 1101011111
0xBBC0, // ASCII = 6 1011101111
0xBF40, // ASCII = 7 1011111101
0xBFC0, // ASCII = 8 1011111111
0xEF00, // ASCII = 9 11101111
0xE800, // ASCII = 10 11101
0xDBC0, // ASCII = 11 1101101111
0xB740, // ASCII = 12 1011011101
0xF800, // ASCII = 13 11111
0xDD40, // ASCII = 14 1101110101
0xEAC0, // ASCII = 15 1110101011
0xBDC0, // ASCII = 16 1011110111
0xBD40, // ASCII = 17 1011110101
0xEB40, // ASCII = 18 1110101101
0xEBC0, // ASCII = 19 1110101111
0xD6C0, // ASCII = 20 1101011011
0xDAC0, // ASCII = 21 1101101011
0xDB40, // ASCII = 22 1101101101
0xD5C0, // ASCII = 23 1101010111
0xDEC0, // ASCII = 24 1101111011
0xDF40, // ASCII = 25 1101111101
0xEDC0, // ASCII = 26 1110110111
0xD540, // ASCII = 27 1101010101
0xD740, // ASCII = 28 1101011101
0xEEC0, // ASCII = 29 1110111011
0xBEC0, // ASCII = 30 1011111011
0xDFC0, // ASCII = 31 1101111111
0x8000, // ASCII = ' ' 1
0xFF80, // ASCII = '!' 111111111
0xAF80, // ASCII = '"' 101011111
0xFA80, // ASCII = '#' 111110101
0xED80, // ASCII = '$' 111011011
0xB540, // ASCII = '%' 1011010101
0xAEC0, // ASCII = '&' 1010111011
0xBF80, // ASCII = ''' 101111111
0xFB00, // ASCII = '(' 11111011
0xF700, // ASCII = ')' 11110111
0xB780, // ASCII = '*' 101101111
0xEF80, // ASCII = '+' 111011111
0xEA00, // ASCII = ',' 1110101
0xD400, // ASCII = '-' 110101
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -