Fiat 124 Spider Forum banner

1 - 10 of 10 Posts

·
Registered
2020 124 Spider Abarth
Joined
·
16 Posts
Discussion Starter #1
I can't explain why, but I like the idea of the compass heading being displayed in the CMU status bar. Except that I don't like that everything is 180 out of wack because my car has nav! I run the MZD-AIO 2.8.6 tweaks with Touchscreen While Moving enabled with Fix Cluster Compass checked and the Speedometer app with GPS Heading sent to the status bar. I was able to edit one of the speedometer files to fix the heading. Note this does not fix the round compass in the "Classic Analog" speedometer. It only corrects what is displayed in the status bar. This is fine with me as I used the digital speedometer. This should also work with Ameridan's AIO install tool.

Generate an AIO USB drive with the speedometer app

Use a text editor or WordPad to edit file speedometer.js in folder config\speedometer\jci\gui\apps\_speedometer\js on the USB drive.

Cut/paste to swap the two blocks of "case" directions (16 lines each) in function updateGPSHeading

Save, safely eject, and install in car.

(Note on my car with the nav SD installed the directions seem to always come from the first block of case statements, even though this is the "noNavSD" logic flow.)
 

·
Premium Member
2018 Abarth
Joined
·
104 Posts
Does this work to fix the bar speedometer heading readout or just the status bar heading? I like the speedo app but the reversed heading is driving me nuts... :(
 

·
Registered
2020 124 Spider Abarth
Joined
·
16 Posts
Discussion Starter #3
Does this work to fix the bar speedometer heading readout or just the status bar heading? I like the speedo app but the reversed heading is driving me nuts... :(
This does also fix the heading displayed in the bottom of the digital bar speedo app.
 

·
Premium Member
2018 Abarth
Joined
·
104 Posts
So I may just be pissing in the wind here, but I think I know what's going on and how to fix it. I'm not a JS guy though, but I dabble in Arduino and took C++ in high school so not too scared to dig through the code. This is a bit long, but I've had a few drinks and I'm bored, so here we go...

As pointed out, the section of interest is this:
JavaScript:
function updateGPSHeading(currentGPShead) {
    currentGPShead = $.trim(currentGPShead);
    if ($.isNumeric(currentGPShead) && currentGPShead !== lastGPSheadingValue) {
      // without NavSD
      if (noNavSD) {
        if (speedCurrent > 0) {
          $('.gpsCompassBG').css("transform", "rotate(" + (-Math.round(currentGPShead)) + "deg)");
          // Mazda Infotainment System GPS heading is S = 0/360 degrees even though docs say otherwise, YMMV
          headingSwitchValue = Math.round(currentGPShead / 22.5);
          // Close enough
          switch (headingSwitchValue) {
            case 1: direction = "NNE"; break;
            case 2: direction = "NE"; break;
            case 3: direction = "ENE"; break;
            case 4: direction = "E"; break;
            case 5: direction = "ESE"; break;
            case 6: direction = "SE"; break;
            case 7: direction = "SSE"; break;
            case 8: direction = "S"; break;
            case 9: direction = "SSW"; break;
            case 10: direction = "SW"; break;
            case 11: direction = "WSW"; break;
            case 12: direction = "W"; break;
            case 13: direction = "WNW"; break;
            case 14: direction = "NW"; break;
            case 15: direction = "NNW"; break;
            default: direction = "N";
          }
          if (language === 'DE') {
            direction = direction.replace(/E/g, "O");
          }
          if (language === 'FR') {
            direction = direction.replace(/W/g, "O");
          }
          if (language === 'TR') {
            direction = direction.replace(/N/g, "K");
            direction = direction.replace(/S/g, "G");
            direction = direction.replace(/E/g, "D");
            direction = direction.replace(/W/g, "B");
          }
          $('.gpsHeading').html(direction);
          lastGPSheadingValue = currentGPShead;
        }
        // with NavSD
      } else {
        $('.gpsCompassBG').css("transform", "rotate(" + (-Math.abs(currentGPShead) + 180) + "deg)");
        // Mazda Infotainment System GPS heading is S = 0/360 degrees even though docs say otherwise, YMMV
        headingSwitchValue = Math.round(currentGPShead / 22.5);
        // Close enough
        switch (headingSwitchValue) {
          case 1: direction = "SSW"; break;
          case 2: direction = "SW"; break;
          case 3: direction = "WSW"; break;
          case 4: direction = "W"; break;
          case 5: direction = "WNW"; break;
          case 6: direction = "NW"; break;
          case 7: direction = "NNW"; break;
          case 8: direction = "N"; break;
          case 9: direction = "NNE"; break;
          case 10: direction = "NE"; break;
          case 11: direction = "ENE"; break;
          case 12: direction = "E"; break;
          case 13: direction = "ESE"; break;
          case 14: direction = "SE"; break;
          case 15: direction = "SSE"; break;
          default: direction = "S";
        }
        if (language === 'DE') {
          direction = direction.replace(/E/g, "O");
        }
        if (language === 'FR') {
          direction = direction.replace(/W/g, "O");
        }
        if (language === 'TR') {
          direction = direction.replace(/N/g, "K");
          direction = direction.replace(/S/g, "G");
          direction = direction.replace(/E/g, "D");
          direction = direction.replace(/W/g, "B");
        }
        $('.gpsHeading').html(direction);
        lastGPSheadingValue = currentGPShead;
      }
    }
  }
I'm not sure what sets the "noNavSD" variable but the whole problem hinges on it. From just looking at the code, I'd wager a guess that there once was a bug in the CMU navigation that resulted in the directions reversing with or without a nav SD card.

To help follow along, I've omitted the code author's comment marks to avoid any confusion.

The lines
Code:
function updateGPSHeading(currentGPShead) {
    currentGPShead = $.trim(currentGPShead);
    if ($.isNumeric(currentGPShead) && currentGPShead !== lastGPSheadingValue) {
first define the start of the function of checking GPS heading. The next lines determine if the vehicle is moving and/or when to run the calculation to process the new direction. the "lastGPSheadingValue" is set at the end of the function.

After that,
Code:
if (noNavSD) {
and then
Code:
} else {
gives the functions two possible paths to take. Basically, "If" no SD card is present, do this. "Else," do this.

Here's where it gets interesting...

Let's look at the "If":
JavaScript:
if (noNavSD) {
        if (speedCurrent > 0) {
          $('.gpsCompassBG').css("transform", "rotate(" + (-Math.round(currentGPShead)) + "deg)");
          headingSwitchValue = Math.round(currentGPShead / 22.5);
          switch (headingSwitchValue) {
            case 1: direction = "NNE"; break;
            case 2: direction = "NE"; break;
            case 3: direction = "ENE"; break;
            case 4: direction = "E"; break;
            case 5: direction = "ESE"; break;
            case 6: direction = "SE"; break;
            case 7: direction = "SSE"; break;
            case 8: direction = "S"; break;
            case 9: direction = "SSW"; break;
            case 10: direction = "SW"; break;
            case 11: direction = "WSW"; break;
            case 12: direction = "W"; break;
            case 13: direction = "WNW"; break;
            case 14: direction = "NW"; break;
            case 15: direction = "NNW"; break;
            default: direction = "N";
          }
          if (language === 'DE') {
            direction = direction.replace(/E/g, "O");
          }
          if (language === 'FR') {
            direction = direction.replace(/W/g, "O");
          }
          if (language === 'TR') {
            direction = direction.replace(/N/g, "K");
            direction = direction.replace(/S/g, "G");
            direction = direction.replace(/E/g, "D");
            direction = direction.replace(/W/g, "B");
          }
          $('.gpsHeading').html(direction);
          lastGPSheadingValue = currentGPShead;
        }
      }
This part of the function starts by checking that the vehicle is moving via the vehicle speed sensor reading. If the speed of the vehicle is greater than zero, the calculation continues. Next, the line
Code:
$('.gpsCompassBG').css("transform", "rotate(" + (-Math.round(currentGPShead)) + "deg)");
seems to control the compass graphics on the classic analog speedometer. Simple enough... The calculation takes the data from the GPS heading reading and determines where to position the compass graphic. Seems legit.

Then we have the logic for the heading indication.
Code:
headingSwitchValue = Math.round(currentGPShead / 22.5);
          switch (headingSwitchValue) {
            case 1: direction = "NNE"; break;
            case 2: direction = "NE"; break;
            case 3: direction = "ENE"; break;
            case 4: direction = "E"; break;
            case 5: direction = "ESE"; break;
            case 6: direction = "SE"; break;
            case 7: direction = "SSE"; break;
            case 8: direction = "S"; break;
            case 9: direction = "SSW"; break;
            case 10: direction = "SW"; break;
            case 11: direction = "WSW"; break;
            case 12: direction = "W"; break;
            case 13: direction = "WNW"; break;
            case 14: direction = "NW"; break;
            case 15: direction = "NNW"; break;
            default: direction = "N";
          }
This is pretty clever. It takes the GPS heading in decimal and translates it to language directions by dividing the heading in degrees by 22.5 and then rounding it.

Say you're heading West.
270 / 22.5 = 12
12 matches the instruction in the above code for position "W"

Say you're heading North-North East.
22 / 22.5 = .97 or 1.0 after rounding.
1 matches the instruction in the above code for position "NNE"

So without a nav SD card installed, we can see the functions work as intended and produce the expected results.

So why does 💩 hit the fan with the card inserted? Let's look at the "Else" statement for clues.
JavaScript:
  else {
        $('.gpsCompassBG').css("transform", "rotate(" + (-Math.abs(currentGPShead) + 180) + "deg)");
         headingSwitchValue = Math.round(currentGPShead / 22.5);
         switch (headingSwitchValue) {
          case 1: direction = "SSW"; break;
          case 2: direction = "SW"; break;
          case 3: direction = "WSW"; break;
          case 4: direction = "W"; break;
          case 5: direction = "WNW"; break;
          case 6: direction = "NW"; break;
          case 7: direction = "NNW"; break;
          case 8: direction = "N"; break;
          case 9: direction = "NNE"; break;
          case 10: direction = "NE"; break;
          case 11: direction = "ENE"; break;
          case 12: direction = "E"; break;
          case 13: direction = "ESE"; break;
          case 14: direction = "SE"; break;
          case 15: direction = "SSE"; break;
          default: direction = "S";
        }
        if (language === 'DE') {
          direction = direction.replace(/E/g, "O");
        }
        if (language === 'FR') {
          direction = direction.replace(/W/g, "O");
        }
        if (language === 'TR') {
          direction = direction.replace(/N/g, "K");
          direction = direction.replace(/S/g, "G");
          direction = direction.replace(/E/g, "D");
          direction = direction.replace(/W/g, "B");
        }
        $('.gpsHeading').html(direction);
        lastGPSheadingValue = currentGPShead;
      }
The first thing I noticed in the "Else" statement is that it doesn't seem to have a code to stipulate to only run the code when the vehicle is moving like it did before. The first thing we see in this half of the function is the statement
Code:
$('.gpsCompassBG').css("transform", "rotate(" + (-Math.abs(currentGPShead) + 180) + "deg)");
This part, like before, appears to control the compass on the classic speedo's position. I noticed two key differences though.
1. It's taking and absolute reading and not rounding the heading degrees. Not sure if that is significant yet. More confusingly,
2. It adds 180 degrees to the hardware reading, essentially flipping it around.

The next oddity is the code for the heading indication...
Code:
headingSwitchValue = Math.round(currentGPShead / 22.5);
        switch (headingSwitchValue) {
          case 1: direction = "SSW"; break;
          case 2: direction = "SW"; break;
          case 3: direction = "WSW"; break;
          case 4: direction = "W"; break;
          case 5: direction = "WNW"; break;
          case 6: direction = "NW"; break;
          case 7: direction = "NNW"; break;
          case 8: direction = "N"; break;
          case 9: direction = "NNE"; break;
          case 10: direction = "NE"; break;
          case 11: direction = "ENE"; break;
          case 12: direction = "E"; break;
          case 13: direction = "ESE"; break;
          case 14: direction = "SE"; break;
          case 15: direction = "SSE"; break;
          default: direction = "S";
        }
Again, this appears to be tied in no way to the last code for the compass graphic on the classic speedo. The computation is done separately from the compass position, and like the compass position, the readings are 180 degrees backwards of what they should be.

This can only mean, in my mind, that the 180 degree flips were programmed in for a bug that no longer exists, and in itself, re-introduces the bug.

I tried refining the code a bit, but I couldn't get things to work. Tomorrow I'm going to take baby steps and try some basics.

For the code in the "Else" statement for if the card is present, I am going to remove the code to flip the on-screen compass 180 degrees, and as noted by @124geek I am going to copy the table from the "If" section heading translation into the "Else" section. I THINK the following code should work.

JavaScript:
  // --------------------------------------------------------------------------
  // update GPS Heading
  // --------------------------------------------------------------------------
  function updateGPSHeading(currentGPShead) {
    currentGPShead = $.trim(currentGPShead);
    if ($.isNumeric(currentGPShead) && currentGPShead !== lastGPSheadingValue) {
      // without NavSD
      if (noNavSD) {
        if (speedCurrent > 0) {
          $('.gpsCompassBG').css("transform", "rotate(" + (-Math.round(currentGPShead)) + "deg)");
          // Mazda Infotainment System GPS heading is S = 0/360 degrees even though docs say otherwise, YMMV
          headingSwitchValue = Math.round(currentGPShead / 22.5);
          // Close enough
          switch (headingSwitchValue) {
            case 1: direction = "NNE"; break;
            case 2: direction = "NE"; break;
            case 3: direction = "ENE"; break;
            case 4: direction = "E"; break;
            case 5: direction = "ESE"; break;
            case 6: direction = "SE"; break;
            case 7: direction = "SSE"; break;
            case 8: direction = "S"; break;
            case 9: direction = "SSW"; break;
            case 10: direction = "SW"; break;
            case 11: direction = "WSW"; break;
            case 12: direction = "W"; break;
            case 13: direction = "WNW"; break;
            case 14: direction = "NW"; break;
            case 15: direction = "NNW"; break;
            default: direction = "N";
          }
          if (language === 'DE') {
            direction = direction.replace(/E/g, "O");
          }
          if (language === 'FR') {
            direction = direction.replace(/W/g, "O");
          }
          if (language === 'TR') {
            direction = direction.replace(/N/g, "K");
            direction = direction.replace(/S/g, "G");
            direction = direction.replace(/E/g, "D");
            direction = direction.replace(/W/g, "B");
          }
          $('.gpsHeading').html(direction);
          lastGPSheadingValue = currentGPShead;
        }
        // with NavSD
      } else {
        $('.gpsCompassBG').css("transform", "rotate(" + (-Math.round(currentGPShead)) + "deg)");
        // Mazda Infotainment System GPS heading is S = 0/360 degrees even though docs say otherwise, YMMV
        headingSwitchValue = Math.round(currentGPShead / 22.5);
        // Close enough
        switch (headingSwitchValue) {
          case 1: direction = "NNE"; break;
          case 2: direction = "NE"; break;
          case 3: direction = "ENE"; break;
          case 4: direction = "E"; break;
          case 5: direction = "ESE"; break;
          case 6: direction = "SE"; break;
          case 7: direction = "SSE"; break;
          case 8: direction = "S"; break;
          case 9: direction = "SSW"; break;
          case 10: direction = "SW"; break;
          case 11: direction = "WSW"; break;
          case 12: direction = "W"; break;
          case 13: direction = "WNW"; break;
          case 14: direction = "NW"; break;
          case 15: direction = "NNW"; break;
          default: direction = "N";
        }
        if (language === 'DE') {
          direction = direction.replace(/E/g, "O");
        }
        if (language === 'FR') {
          direction = direction.replace(/W/g, "O");
        }
        if (language === 'TR') {
          direction = direction.replace(/N/g, "K");
          direction = direction.replace(/S/g, "G");
          direction = direction.replace(/E/g, "D");
          direction = direction.replace(/W/g, "B");
        }
        $('.gpsHeading').html(direction);
        lastGPSheadingValue = currentGPShead;
      }
    }
  }
If that works, I'm going to work on eliminating the If/Else statement altogether as I believe it isn't necessary any longer. I tried to do it tonight, but I wasn't able to get the intended results while exploring the JavaScript and having a few drinks. I'll hit it tomorrow with a fresh head.
 

·
Registered
2020 124 Spider Abarth
Joined
·
16 Posts
Discussion Starter #5
Nice evaluation!

Another thing you can do is change the lines

$('.gpsHeading').html(direction);

to

$('.gpsHeading').html(currentGPShead);

This will print the raw value that the function is working with instead of the text directions. I did this to verify that south is 0 and west is 90 when you have the nav. I did not look to see what the values would be without the nav. Maybe I'll check that after the remnants of Sally blow through.

The last thing I plan to look into is that the speedometer tweak to status bar doesn't go away when in CarPlay mode. This same behavior can be seen when turning off the car. The speedometer tweak info will stay on the screen long after everything else is gone. So the original CMU code knows when to stop displaying the status bar, but the tweak code does not.
 

·
Premium Member
2018 Abarth
Joined
·
104 Posts
Well, I flashed on the new .js file this morning and went for a drive.

Nothing changed.

So what it now seems like; there is still a bug that flips the heading with the nav SD card installed, and the code isn't properly detecting that the nav SD is inserted so it's not running the "Else" statement.

So I'm pretty sure I was right about the line "if (noNavSD) {" but for the wrong reasons.

Whatever is supposed to set the noNavSD variable seems to be broken. I've been looking through the code today but haven't found anything yet. I'll have time to do more digging later.

In the meantime, I think this code will work for us with nav SD cards. It would be nice to figure it out and get it patched for everyone, but since I always have the SD card in, this will likely be my permanent fix if it works. I took out the If/Else and just made the code treat the heading with the 180 degree offset.

JavaScript:
  // --------------------------------------------------------------------------
  // update GPS Heading
  // --------------------------------------------------------------------------
  function updateGPSHeading(currentGPShead) {
    currentGPShead = $.trim(currentGPShead);
    if ($.isNumeric(currentGPShead) && currentGPShead !== lastGPSheadingValue) {
      if (speedCurrent > 0) {
          $('.gpsCompassBG').css("transform", "rotate(" + (-Math.abs(currentGPShead) + 180) + "deg)");
          headingSwitchValue = Math.round(currentGPShead / 22.5);
          switch (headingSwitchValue) {
           case 1: direction = "SSW"; break;
           case 2: direction = "SW"; break;
           case 3: direction = "WSW"; break;
           case 4: direction = "W"; break;
           case 5: direction = "WNW"; break;
           case 6: direction = "NW"; break;
           case 7: direction = "NNW"; break;
           case 8: direction = "N"; break;
           case 9: direction = "NNE"; break;
           case 10: direction = "NE"; break;
           case 11: direction = "ENE"; break;
           case 12: direction = "E"; break;
           case 13: direction = "ESE"; break;
           case 14: direction = "SE"; break;
           case 15: direction = "SSE"; break;
           default: direction = "S";
          }
        if (language === 'DE') {
          direction = direction.replace(/E/g, "O");
        }
        if (language === 'FR') {
          direction = direction.replace(/W/g, "O");
        }
        if (language === 'TR') {
          direction = direction.replace(/N/g, "K");
          direction = direction.replace(/S/g, "G");
          direction = direction.replace(/E/g, "D");
          direction = direction.replace(/W/g, "B");
        }
        $('.gpsHeading').html(direction);
        lastGPSheadingValue = currentGPShead;
      }     
      
    }
  }
I'll post back the results after I get to drive again.
 

·
Registered
2020 124 Spider Abarth
Joined
·
16 Posts
Discussion Starter #7
I drove this afternoon without the SD card and it still went into the if(noNAVSD) { branch, however now the directions were flipped. This verified that without SD card North is 0, while with the SD card South is 0. I'm starting to think the noNavSD flag is not set by anything in the system, but can be manually forced in the code after doing the compile. However, I tried that a few weeks ago and ended up with no compass displayed at all in the statusbar. That could have been caused by something else, but it made me dig into the code deeper and come up with switching the directions around which worked for me.
 

·
Premium Member
2018 Abarth
Joined
·
104 Posts
Thanks Dan! Here's where I'm at as of now.

I examined some of the other files for clues. I found where the "noNavSD" variable is located. It's a variable defined in the "speedometer-startup.js" code on line 7.

var noNavSD = false;

This was interesting, because I checked every other line of code in the speedometer app files and could not find what on earth set this variable. It didn't make sense that it would be hard-coded instead of just removing all the excess code to make the If/Else statement work.

I then decided to start at the beginning, and examined the tweaks.sh shell script. Lo and behold, the answers were found on lines 1,015 through 1,020.

Bash:
# change compass rotating depending on NAV SD card inside or not
if [ ! -d /mnt/sd_nav/content/speedcam ] || [ $COMPAT_GROUP -ne 1  ]
then
  sed -i 's/var noNavSD = false;/var noNavSD = true;/g' /jci/gui/apps/_speedometer/js/speedometer-startup.js
  log_message "===    Changed compass rotating, because no NAV SD card is inside     ==="
fi
So... The script checks for a specific file/folder on the SD card. If the card is present, it's supposed to write line 7 in speedometer-startup.js as True. If absent, line 7 is False. This answers the question of whether or not the SD card needs to be inserted during the speedo installation...

That said, I'm pretty sure I tried installing the speedo with and without the SD card inserted, so I think the code in the shell script isn't working. However, I don't know enough about it to determine if the problem is with the code or with the file not being on the SD.

I think we need to get Trezdog44 to have a looksie... 👀
 
1 - 10 of 10 Posts
Top