I got somewhere eventually, using a Frequency Locked Loop.
For me, the key was to reduce the I/Q into the -3 to +3 range (just by left shifting, then use the following lookup table to convert to an angle (scaled to 0-255)
unsigned char angle_lookup[64] =
{ // i = -4 -3 -2 -1 0 1 2 3
0, 0, 0, 0, 0, 0, 0, 0, // q = -4
0,160,168,178,192,206,216,224, // -3
0,152,160,173,192,211,224,232, // -2
0,142,147,160,192,224,237,242, // -1
0,128,128,128, 0, 0, 0, 0, // -0
0,114,109, 96, 64, 32, 19, 14, // 1
0,104, 96, 83, 64, 45, 32, 24, // 2
0, 96, 88, 78, 64, 50, 40, 32}; // 3
I'm still trying to get the Costas filter tracking to eliminate the approx 2Hz drift, but I can at least strip out the NAV messages.