I am using a... NEO M6N GPS.
Are you sure? The NAV-PVT message is only available on NEO 7 and 8, according to the specs. Just curious...
If I move
FastLED.show();
into the main loop it runs even slower. And by slow I mean the display and leds are in "slow motion".
That makes sense, because you would be reloading the WS2812 string on every loop iteration. 
No matter what I try, when I am running both FastLEd and the display functions everything runs too slow.
Yes, that's (obviously) quite a load for a Nano, but there are a few things to you can do. I think the biggest problems are
1) GPS and OLED updates @ 10Hz
The display is tiny, the speed digits are tiny, the spinner is tiny... Are you sure? I would knock the GPS updates down to 1Hz and OLED updates to 4Hz for the spinner.
2) OLED and FastLED updates aren't sync'ed to the GPS updates
If you look at loop
, the GPS updates and the screen updates run independently. The best time to do things is right after a GPS update comes in. Then the serial port is quiet for a while (no interrupts). As it is, the GPS character interrupts could be occurring while you're trying to update the screen and the LEDs. FastLED will interfere with the GPS data, too.
I would suggest something like this:
void loop() {
if ( processGPS() ) {
numSV = pvt.numSV;
gSpeed = pvt.gSpeed;
hMSL = pvt.hMSL;
gpsUpdateSpinnerPos = (gpsUpdateSpinnerPos + 1) % 4;
// }
// unsigned long now = millis();
// if ( now - lastScreenUpdate > 100 ) {
updateScreen();
// lastScreenUpdate = now;
screenRefreshSpinnerPos = (screenRefreshSpinnerPos + 1) % 4; // Are you sure you need this?
}
}
This will still update the screen at 10Hz, but it will do it right after the GPS goes quiet for a while.
Also, it might help to move the FastLEDs.show
before the OLED draw:
void updateScreen()
{
//int kmh = gSpeed * 0.0036;
int mph = gSpeed * 0.002237;
if (mph < 2 ) {
sinelon();
} else if (mph < 6 && mph >= 2 ) {
juggle();
} else {
bpm();
}
FastLED.show();
//EVERY_N_MILLISECONDS( 20 ) { gHue++; }
sprintf(speedBuf, "%3d", mph);
sprintf(satsBuf, "%c %c %d", spinner[screenRefreshSpinnerPos], spinner[gpsUpdateSpinnerPos], numSV);
int feet = hMSL / 304.8;
sprintf(heightBuf, "%5d", feet);
u8g2.firstPage();
do {
draw();
} while( u8g2.nextPage() );
}
The OLED update can be interrupted by GPS characters, if they start coming in again, before updateScreen is completed. The FastLED.show cannot be interrupted, so those GPS characters would be lost.
There are several other things, but these might be enough.
Cheers,
/dev