Monday, December 16, 2013

Corvette HUD Horizontal Flip and Display Screens

Made some good progress today on the HUD.  I've added the capability to have multiple screens using individual class files.  This means I can have a screen for the track, a screen for the daily drive, a screen for GPS, a screen for music.. and so on.  Since I don't want them instantiated more than one time, each screen is a static class.  I know that I'm the only one programming this thing so I'm essentially saving myself from myself when I do that.  All the screens also inherit from a screen base class that sets some initial parameters.

I also added the ability to horizontally flip the entire display.  This is necessary because once the HUD is installed, it is going to reflect off a mirror onto the windshield.  That mirror is going to flip it, so I need to make sure it's reversed before it gets to the mirror.  That was an interesting task in itself.  I'm not sure that my approach was the best one, but I started by making a Flow Dependency Matrix for the graphics class for the display itself (which was created by Adafruit).

Please excuse the bad handwriting.

I needed to combine that with the ST7335 class that inherits the graphics class.  The circles in blue are the ST7335 class and the methods it overrides.  Once I had that mapped out, I was able to more accurately see who is calling what.  This is important because when I use drawCircle(), I am passing in an X and Y coordinate.  I need to flip the X coordinate but also make sure that I am not re-flipping it down the line.  A good example of this is the fillRoundRect() method.  fillRoundRect() draws a rectangle with beveled edges.  So one might think that you should flip the X in there, right?  Well it really calls the fillRect() method and the fillCircleHelper() method.  That means that the X will be re-flipped in fillRect() and throw everything off.  By mapping everything in the FDM I was able to trace all the methods and find out who calls what.  After taking my time and carefully placing all the flips in their right methods, I can now horizontally flip the screen using a single line of code:

tft.setHorizontalFlip(true, SCREEN_WIDTH);

tft is the class that draws directly to the screen.  setHorizontalFlip() is the method that sets a private boolean variable to whatever is passed in (which in this case is true).  SCREEN_WIDTH is, well, the display width of the screen.  This is what allows me to flip the X.  The formula to flip the screen is pretty simple:

if (shouldHorizontalFlip)
x = horizontalFlipAmount - x;

horizontalFlipAmount is the private variable that is set to SCREEN_WIDTH.  Pretty straight forward when inserted into the right spots.

So I'm at the point where I can build some screens.  I have a few concerns about the display right now.  When I rented a Camaro with a HUD a few weeks ago, I noticed that you can clearly see the edges of the display.  It looked like a screen reflected onto the windshield whereas with my car, there are no edges (because it's not an actual screen, it's more like your old alarm clock display).  I want to avoid that if at all possible.  The other concern I have is the refresh rate.  Similar issue to the Camaro in that you could almost see the lines scanning along the display.  That kind of issue will be hard to work on because I need to physically install the HUD in the car.  Installing the HUD in the car requires me to take out the entire dashpad which is a long process in it self.  I have to do that anyway so I can sniff the serial line so I need to plan a few days where I don't need to use my car so I can take it all apart and play around.  An idea I had for a possible fix is to use an OLED screen.  I found this 1.5" screen on ADAfruit that might work but it's too small.  I really need something that's at least 2" due to the width of the display area.  I'll have to look around and see if I can find a larger one.

So that's where I am right now.  I'm going to spend the week creating a tachometer display and throw some fake data in there so I can see it animate.  Hopefully I can get a good video together showing everything off :]

Until next time..