Let's have a look. This is accessing the registers of the microcontroller directly.
Using some code in a header file and linker script, making them appear as variables. Apart from that magic, I'll focus on the interrupt routine. This is called for every received character. This is a pretty limited parser which only looks for the GGA sentence. And in my opinion, it's rather awkward. Not a good reference to learn to understand.
When the interrupt is called, one character is received. This is read from the register and put in a local variable.
received_char = U0RBR;
If the received character is a '$', this is the character that indicated the beginning of an NMEA sentence.
if( received_char == '$' )
{
GGA_Index = 0;
CommaCounter = 0;
IsItGGAString = false;
}
Then have a look at the end. I will explain a bit out of order, but I need to explain this part first to understand what is going on.
CGA is filled up from the end, and moved forwards.
So initially, it contains "\0\0\0"
The string the GNSS module transmits is "$GPGGA". The '$' was already eaten.
So for each character we get
"\0\0G"
"\0GP"
"GPG"
"PGG"
"GGA"
This looks rather awkward. Why would anyone write this? Okay, they're ignoring the "GP" part... I get that, but why do it like this. This is code running on an ARM processor. No need to save 2 bytes of memory. If this code were running on something with an amount of RAM measured in bytes, such as a 8051 based MCU. This code is to run on a fairly old ARM chip, but still that chip got 32 kB of RAM, so there is no need to do such awkward code.
else /* Store received character */
{
GGA[0] = GGA[1];
GGA[1] = GGA[2];
GGA[2] = received_char;
}
Anyhow. After receiving this, we have "GGA" in GGA, then we look at where we were. If we have this "GGA" in GGA, a condition variable IsItGGAString is set, and GGA is nulled.
else if( ( GGA[0] == 'G' ) && ( GGA[1] == 'G' ) && ( GGA[2] == 'A' ) ) /* If GGA string received */
{
IsItGGAString = true;
GGA[0] = GGA[1] = GGA[2] = 0;
}
Now IsItGGAString is set, we enter this part of the code.
This puts the data part of the string in GGA_String, and stored the location of the commas in GGA_Comma_Pointers
else if( IsItGGAString == true ) /* If $GPGGA string */
{
if ( received_char == ',' )
{
GGA_Comma_Pointers[CommaCounter++] = GGA_Index; /* Store locations of commas in the string in a buffer */
}
GGA_String[GGA_Index++] = received_char; /* Store the $GPGGA string in a buffer */
}
The rest of the parsing is done elsewhere in the code.