Jump to content

Jittery output for Altimeter data


lesthegrngo

Recommended Posts

I have tested the dropbox version for 20 minutes now without any problems

 

Yup. I just ran the drop box one in Altimeter mode with none of the problems of the other one.

Looks good to me. :thumbup:

 

And the A-10 really does NOT like flying that high. ;)

 

Gonna try pressure now.

Link to comment
Share on other sites

Gents, I'm very happy to report that it works perfectly. I had an old instance running alongside the modified version for both the Baro Alt and the Altimeter, on the 64 x 32 and 128 x 64 resolutions respectively, and while the old version continued to glitch frequently, the new version behaved beautifully.

 

A brilliant piece of work, gents, I take my hat off to you both

 

If you want the 128 x 64 version of the scrolling altimeter sketch and .h library, let me know

 

Thanks again for all your hard work on this

 

Les

Link to comment
Share on other sites

Just a note to inform you all that while you can run the scrolling OLED altimeter on the same Nano as you can for the altimeter or other gauge, my advice is don't - it makes both items very laggy, slow to respond plus when I tried it you got the very occasional glitch that we were trying to eradicate.

 

Having a separate Nano for the scrolling Altimeter is the way to go

 

Cheers

 

Les

Link to comment
Share on other sites

Now that this is working I need to my self sorted out with a way to cut down on the USB port usage - with everything connected I am getting up to nine seconds lag between the on screen change and the device change, and that includes gauges and the Altimeter OLED, despite being on dedicated Nanos.

 

Nevertheless, I consider progress has been made, despite the unpleasant thought of having to come back to trying to get RS485 working

 

It is super cool watching everything work!

 

Les

Link to comment
Share on other sites

Nice work, guys.

 

Now it seems we're at the "optimisation" stage. Or the "How much can we cut it back before it stops working properly" stage. ;)

 

Now that this is working I need to my self sorted out with a way to cut down on the USB port usage - with everything connected I am getting up to nine seconds lag between the on screen change and the device change, and that includes gauges and the Altimeter OLED, despite being on dedicated Nanos.
This might be due to daisy-chained USB hubs. Each hub adds a delay. One computer USB connection to 16 USB devices, running with 4-port hubs requires 5 hubs in 2 stages.

One 4-port hub connects to four 4-port hubs. That's a lot of handshaking delays, etc.

RS485 just hangs all 16 on one bus. It's much faster.

 

Just a note to inform you all that while you can run the scrolling OLED altimeter on the same Nano as you can for the altimeter or other gauge, my advice is don't - it makes both items very laggy, slow to respond plus when I tried it you got the very occasional glitch that we were trying to eradicate.

 

Having a separate Nano for the scrolling Altimeter is the way to go

Does it work OK with the gauge and Baro display? That shouldn't need a lot of updating.

 

In any case, I had a cunning plan late last night.

 

My "submaster" idea may still have some use.

Transmitting the data for the OLEDs is a quick job that might mean the "submaster" running DCS-BIOS can handle the rotary gauge AND sending the data for the OLEDs.

If the "slave" can run both OLEDs, from its hardware UART, it would cut the arduino count to 2, and the DCS-Bios connection count to 1.

 

To that end, I'd appreciate it if you could let me have your 128 x6 4 code, please Les.

 

It may take a few days for my 128 x 64 OLEDs to get here, though.

Link to comment
Share on other sites

Of course, the least I can do!

 

here's the sketch

 

#define DCSBIOS_IRQ_SERIAL

#include "DcsBios.h"

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "Character40X64.h"

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)

//Comment for barometric pressure
#define ALTIMETER

int updateInterval = 100; //the number of milliseconds between updates

struct scrollDigit {
 int digit; //The digit that is displayed
 int y; // The vertical position of the digit
};

struct disp {
 Adafruit_SSD1306 display;
 int width;
 int numberOfDigits;
 scrollDigit digits[5];
};

#ifdef ALTIMETER
 disp oled = {Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET), 42, 3, {{0,0},{00,0},{00,0},{0,0},{0,0}}};
#else
 disp oled = {Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET), 16, 4, {{0,0},{0,0},{0,0},{0,0},{0,0}}};
#endif

void setup() {
 if(!oled.display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
   for(;;); // Don't proceed, loop forever
 }

 DcsBios::setup();
}

void UpdateDisplay()
{
 oled.display.clearDisplay();
 for (int i = 0; i < oled.numberOfDigits; i++)
 {
   printScrollingDigit(oled.digits[i].digit, oled.width, oled.digits[i].y, i + 1, &oled);
 }
 //Clear the area below the the numbers if we are using the small font
 if (oled.width == 16)
 {
   oled.display.fillRect(0, 63, 127, 7, BLACK);
 }
 
 oled.display.display();
}

int YPos()
{
 return (oled.width + 1) * -1.5;
}

void printScrollingDigit(int digit, int width, int y, int pos, disp *oled)
{
 int x = (width * pos) - width + pos;
#ifdef ALTIMETER
   switch (digit)
   {
     case -1: oled->display.drawBitmap(x, y, c24_Empty, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_1, 40, 64, 1); break;
     case 1: oled->display.drawBitmap(x, y, c24_1, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_2, 40, 64, 1); break;
     case 2: oled->display.drawBitmap(x, y, c24_2, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_3, 40, 64, 1); break;
     case 3: oled->display.drawBitmap(x, y, c24_3, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_4, 40, 64, 1); break;
     case 4: oled->display.drawBitmap(x, y, c24_4, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_5, 40, 64, 1); break;
     case 5: oled->display.drawBitmap(x, y, c24_5, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_6, 40, 64, 1); break;
     case 6: oled->display.drawBitmap(x, y, c24_6, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_7, 40, 64, 1); break;
     case 7: oled->display.drawBitmap(x, y, c24_7, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_8, 40, 64, 1); break;
     case 8: oled->display.drawBitmap(x, y, c24_8, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_9, 40, 64, 1); break;
     case 9: oled->display.drawBitmap(x, y, c24_9, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_0, 40, 64, 1); break;
     default: oled->display.drawBitmap(x, y, c24_0, 40, 64, 1); oled->display.drawBitmap(x, y+65, c24_1, 40, 64, 1); break;
   }

#endif
}

#ifdef ALTIMETER
  void onAlt10000FtChange(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6553;
   unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, YPos());

   if (mappedValue == 0)
   {
     mappedValue = -1;
   }
   #ifdef TEST
     Serial.println(mappedValue);
   #endif
   oled.digits[0].digit = mappedValue;
   oled.digits[0].y = y;
 }
 
 
 void onAlt1000FtChange(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6553;
   unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, YPos());
 
   oled.digits[1].digit = mappedValue;
   oled.digits[1].y = y;
 }
 
 void onAlt100FtChange(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6553;
   unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, YPos());
 
   oled.digits[2].digit = mappedValue;
   oled.digits[2].y = y;
 }
 
 DcsBios::IntegerBuffer Alt10000FtBuffer(0x1080, 0xffff, 0, onAlt10000FtChange);
 DcsBios::IntegerBuffer Alt1000FtBuffer(0x1082, 0xffff, 0, onAlt1000FtChange);
 DcsBios::IntegerBuffer Alt100FtBuffer(0x1084, 0xffff, 0, onAlt100FtChange);
#endif


unsigned long time = 0;

void loop() {
 DcsBios::loop();

 time = millis();
 if (time % updateInterval == 50)
 {
   UpdateDisplay();
 }
}

 

 

And here's the character map, you need to rename it as Character40X64.h

 

static const unsigned char PROGMEM c24_0[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x00, 0x1f, 
0xff, 0xf0, 0x00, 0x00, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x7f, 0xff, 0xf8, 0x00, 0x00, 0x7f, 0xc7, 
0xfc, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x00, 0x00, 0xfc, 0x00, 0xfe, 0x00, 0x01, 0xfc, 0x00, 0x7f, 
0x00, 0x01, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0xf0, 0x00, 0x1f, 0x80, 
0x03, 0xf0, 0x00, 0x1f, 0x80, 0x03, 0xf0, 0x00, 0x1f, 0x80, 0x07, 0xe0, 0x00, 0x1f, 0x80, 0x07, 
0xe0, 0x00, 0x1f, 0x80, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 
0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 
0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 
0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 
0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 
0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 
0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 
0x1f, 0x80, 0x03, 0xe0, 0x00, 0x1f, 0x80, 0x03, 0xf0, 0x00, 0x1f, 0x80, 0x03, 0xf0, 0x00, 0x1f, 
0x80, 0x03, 0xf0, 0x00, 0x3f, 0x80, 0x03, 0xf8, 0x00, 0x3f, 0x00, 0x01, 0xf8, 0x00, 0x3f, 0x00, 
0x01, 0xfc, 0x00, 0x7f, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xff, 0x01, 0xfe, 0x00, 0x00, 
0x7f, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xf8, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x1f, 
0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM c24_1[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 
0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7e, 
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 
0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 
0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 
0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 
0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 
0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 
0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 
0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 
0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 
0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 
0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 
0x7f, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x00, 0x00, 0x7f, 
0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM c24_2[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x01, 0xff, 
0xff, 0xf0, 0x00, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 
0xfc, 0x00, 0x01, 0xfc, 0x03, 0xfe, 0x00, 0x01, 0xe0, 0x00, 0xfe, 0x00, 0x01, 0x80, 0x00, 0x7f, 
0x00, 0x01, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 
0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 
0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 
0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 
0x7e, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xfc, 
0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 
0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 
0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x01, 
0xfc, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0xf0, 
0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 
0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 
0x03, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xc0, 0x03, 
0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 
0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM c24_3[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x01, 0xff, 
0xff, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xff, 
0xfe, 0x00, 0x03, 0xfc, 0x03, 0xfe, 0x00, 0x03, 0xe0, 0x00, 0xff, 0x00, 0x03, 0x80, 0x00, 0x7f, 
0x00, 0x03, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 
0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 
0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 
0x00, 0xfe, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x3f, 
0xf0, 0x00, 0x00, 0x01, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0x80, 
0x00, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 
0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 
0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 
0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 
0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 
0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x06, 0x00, 0x00, 0x7f, 0x00, 
0x07, 0x00, 0x00, 0xff, 0x00, 0x07, 0xe0, 0x01, 0xfe, 0x00, 0x07, 0xf8, 0x07, 0xfe, 0x00, 0x07, 
0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xff, 0xff, 0xf0, 0x00, 0x03, 0xff, 
0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM c24_4[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 
0x01, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x0f, 
0xfc, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x3f, 0xfc, 
0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0xfc, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x00, 
0x00, 0x01, 0xf8, 0xfc, 0x00, 0x00, 0x03, 0xf0, 0xfc, 0x00, 0x00, 0x07, 0xf0, 0xfc, 0x00, 0x00, 
0x0f, 0xe0, 0xfc, 0x00, 0x00, 0x0f, 0xc0, 0xfc, 0x00, 0x00, 0x1f, 0x80, 0xfc, 0x00, 0x00, 0x3f, 
0x00, 0xfc, 0x00, 0x00, 0x7f, 0x00, 0xfc, 0x00, 0x00, 0xfe, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 
0xfc, 0x00, 0x01, 0xf8, 0x00, 0xfc, 0x00, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x07, 0xf0, 0x00, 0xfc, 
0x00, 0x07, 0xe0, 0x00, 0xfc, 0x00, 0x0f, 0xc0, 0x00, 0xfc, 0x00, 0x1f, 0x80, 0x00, 0xfc, 0x00, 
0x1f, 0x80, 0x00, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x1f, 
0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 
0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 
0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 
0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 
0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
static const unsigned char PROGMEM c24_5[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 
0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 
0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0x80, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 
0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 
0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 
0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xff, 
0xc0, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xfc, 
0x00, 0x00, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xc0, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 
0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 
0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 
0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 
0x1f, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 
0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x02, 0x00, 0x00, 0x7f, 0x00, 
0x03, 0x80, 0x00, 0x7f, 0x00, 0x03, 0xe0, 0x01, 0xfe, 0x00, 0x03, 0xfc, 0x07, 0xfe, 0x00, 0x03, 
0xff, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xff, 0xf8, 0x00, 0x03, 0xff, 0xff, 0xf0, 0x00, 0x01, 0xff, 
0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
static const unsigned char PROGMEM c24_6[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 
0xff, 0xfe, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xff, 
0xfe, 0x00, 0x00, 0x1f, 0xf0, 0x06, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 
0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x01, 
0xf0, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x03, 0xf0, 
0x00, 0x00, 0x00, 0x03, 0xe0, 0x3f, 0x00, 0x00, 0x07, 0xe1, 0xff, 0xe0, 0x00, 0x07, 0xe7, 0xff, 
0xf8, 0x00, 0x07, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xff, 0xff, 
0x00, 0x07, 0xff, 0x01, 0xff, 0x80, 0x07, 0xf8, 0x00, 0x7f, 0x80, 0x07, 0xe0, 0x00, 0x3f, 0xc0, 
0x07, 0xe0, 0x00, 0x1f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xe0, 0x07, 
0xe0, 0x00, 0x0f, 0xe0, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x07, 0xe0, 
0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 
0x07, 0xe0, 0x03, 0xf0, 0x00, 0x07, 0xe0, 0x03, 0xf0, 0x00, 0x0f, 0xe0, 0x03, 0xf0, 0x00, 0x0f, 
0xc0, 0x03, 0xf8, 0x00, 0x0f, 0xc0, 0x01, 0xf8, 0x00, 0x0f, 0xc0, 0x01, 0xfc, 0x00, 0x1f, 0x80, 
0x00, 0xfc, 0x00, 0x3f, 0x80, 0x00, 0xfe, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x80, 0xff, 0x00, 0x00, 
0x7f, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x0f, 
0xff, 0xf0, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM c24_7[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 
0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 
0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x0f, 
0xe0, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0x80, 
0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 
0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 
0x00, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x03, 
0xf8, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xe0, 
0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 
0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 
0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 
0xfe, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xf8, 
0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 
0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 
0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 
0x3f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x7e, 
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM c24_8[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x1f, 
0xff, 0xf8, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0xff, 0x01, 
0xfe, 0x00, 0x01, 0xfc, 0x00, 0x7f, 0x00, 0x01, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0xf8, 0x00, 0x1f, 
0x80, 0x03, 0xf0, 0x00, 0x1f, 0x80, 0x03, 0xf0, 0x00, 0x1f, 0x80, 0x03, 0xf0, 0x00, 0x1f, 0x80, 
0x03, 0xf0, 0x00, 0x0f, 0x80, 0x03, 0xf0, 0x00, 0x0f, 0x80, 0x03, 0xf0, 0x00, 0x0f, 0x80, 0x03, 
0xf0, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x00, 0x1f, 0x80, 0x01, 0xfc, 
0x00, 0x3f, 0x00, 0x01, 0xff, 0x00, 0x3f, 0x00, 0x00, 0xff, 0x80, 0x7e, 0x00, 0x00, 0x7f, 0xe0, 
0xfc, 0x00, 0x00, 0x3f, 0xf9, 0xf8, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xe0, 
0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x3f, 0x7f, 0xf8, 0x00, 0x00, 0xfe, 0x1f, 0xfc, 0x00, 
0x00, 0xfc, 0x07, 0xfe, 0x00, 0x01, 0xf8, 0x01, 0xff, 0x00, 0x03, 0xf0, 0x00, 0x7f, 0x80, 0x03, 
0xf0, 0x00, 0x3f, 0x80, 0x07, 0xe0, 0x00, 0x1f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 
0x00, 0x0f, 0xc0, 0x0f, 0xe0, 0x00, 0x0f, 0xe0, 0x0f, 0xc0, 0x00, 0x0f, 0xe0, 0x0f, 0xc0, 0x00, 
0x07, 0xe0, 0x0f, 0xc0, 0x00, 0x07, 0xe0, 0x0f, 0xe0, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x0f, 
0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xf0, 0x00, 0x0f, 0xc0, 0x07, 0xf0, 0x00, 0x1f, 0xc0, 
0x03, 0xf8, 0x00, 0x1f, 0x80, 0x03, 0xfc, 0x00, 0x3f, 0x80, 0x01, 0xfe, 0x00, 0x7f, 0x00, 0x01, 
0xff, 0x83, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xf8, 0x00, 0x00, 0x1f, 
0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM c24_9[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x1f, 
0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xcf, 
0xfc, 0x00, 0x01, 0xfe, 0x01, 0xfe, 0x00, 0x03, 0xf8, 0x00, 0xfe, 0x00, 0x03, 0xf8, 0x00, 0x7f, 
0x00, 0x07, 0xf0, 0x00, 0x3f, 0x00, 0x07, 0xe0, 0x00, 0x3f, 0x80, 0x07, 0xe0, 0x00, 0x1f, 0x80, 
0x07, 0xe0, 0x00, 0x1f, 0x80, 0x0f, 0xc0, 0x00, 0x1f, 0x80, 0x0f, 0xc0, 0x00, 0x1f, 0xc0, 0x0f, 
0xc0, 0x00, 0x0f, 0xc0, 0x0f, 0xc0, 0x00, 0x0f, 0xc0, 0x0f, 0xc0, 0x00, 0x0f, 0xc0, 0x0f, 0xc0, 
0x00, 0x0f, 0xc0, 0x0f, 0xc0, 0x00, 0x0f, 0xc0, 0x0f, 0xc0, 0x00, 0x0f, 0xc0, 0x0f, 0xe0, 0x00, 
0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xe0, 0x00, 0x0f, 0xc0, 0x07, 0xf0, 0x00, 0x0f, 
0xc0, 0x07, 0xf8, 0x00, 0x1f, 0xc0, 0x03, 0xfc, 0x00, 0x7f, 0xc0, 0x01, 0xff, 0x03, 0xff, 0xc0, 
0x01, 0xff, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xef, 0xc0, 0x00, 
0x1f, 0xff, 0x8f, 0xc0, 0x00, 0x0f, 0xfe, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 
0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 
0x1f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x7e, 
0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 
0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0xe0, 0x3f, 0xf0, 0x00, 0x00, 
0xff, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xc0, 0x00, 0x00, 0xff, 0xff, 0x80, 0x00, 0x00, 0xff, 
0xfe, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

static const unsigned char PROGMEM c24_Empty[] =
{ 0x01, 0xf8, 0x0f, 0xc0, 0xfe, 0x80, 0xfc, 0x0f, 0xe0, 0x7e, 0xc0, 0x7e, 0x07, 0xf0, 0x3f, 0xe0, 
0x3f, 0x03, 0xf8, 0x1f, 0xf0, 0x1f, 0x81, 0xfc, 0x0f, 0xf8, 0x0f, 0xc0, 0xfe, 0x07, 0xfc, 0x07, 
0xe0, 0x7f, 0x03, 0x7e, 0x03, 0xf0, 0x3f, 0x81, 0x3f, 0x01, 0xf8, 0x1f, 0xc0, 0x1f, 0x80, 0xfc, 
0x0f, 0xe0, 0x0f, 0xc0, 0x7e, 0x07, 0xf0, 0x07, 0xe0, 0x3f, 0x03, 0xf8, 0x03, 0xf0, 0x1f, 0x81, 
0xfc, 0x01, 0xf8, 0x0f, 0xc0, 0xfe, 0xc0, 0xfc, 0x07, 0xe0, 0x7f, 0xe0, 0x7e, 0x03, 0xf0, 0x3f, 
0xf0, 0x3f, 0x01, 0xf8, 0x1f, 0xf8, 0x1f, 0x80, 0xfc, 0x0f, 0xfc, 0x0f, 0xc0, 0x7e, 0x07, 0xfe, 
0x07, 0xe0, 0x3f, 0x03, 0x7f, 0x03, 0xf0, 0x1f, 0x81, 0x3f, 0x81, 0xf8, 0x0f, 0xc0, 0x1f, 0xc0, 
0xfc, 0x07, 0xe0, 0x0f, 0xe0, 0x7e, 0x03, 0xf0, 0x07, 0xf0, 0x3f, 0x01, 0xf8, 0x03, 0xf8, 0x1f, 
0x80, 0xfc, 0x81, 0xfc, 0x0f, 0xc0, 0x7e, 0xc0, 0xfe, 0x07, 0xe0, 0x3f, 0xe0, 0x7f, 0x03, 0xf0, 
0x1f, 0xf0, 0x3f, 0x81, 0xf8, 0x0f, 0xf8, 0x1f, 0xc0, 0xfc, 0x07, 0xfc, 0x0f, 0xe0, 0x7e, 0x03, 
0xfe, 0x07, 0xf0, 0x3f, 0x01, 0x3f, 0x03, 0xf8, 0x1f, 0x80, 0x1f, 0x81, 0xfc, 0x0f, 0xc0, 0x0f, 
0xc0, 0xfe, 0x07, 0xe0, 0x07, 0xe0, 0x7f, 0x03, 0xf0, 0x03, 0xf0, 0x3f, 0x81, 0xf8, 0x01, 0xf8, 
0x1f, 0xc0, 0xfc, 0x80, 0xfc, 0x0f, 0xe0, 0x7e, 0xc0, 0x7e, 0x07, 0xf0, 0x3f, 0xe0, 0x3f, 0x03, 
0xf8, 0x1f, 0xf0, 0x1f, 0x81, 0xfc, 0x0f, 0xf8, 0x0f, 0xc0, 0xfe, 0x07, 0xfc, 0x07, 0xe0, 0x7f, 
0x03, 0x7e, 0x03, 0xf0, 0x3f, 0x81, 0x3f, 0x01, 0xf8, 0x1f, 0xc0, 0x1f, 0x80, 0xfc, 0x0f, 0xe0, 
0x0f, 0xc0, 0x7e, 0x07, 0xf0, 0x07, 0xe0, 0x3f, 0x03, 0xf8, 0x03, 0xf0, 0x1f, 0x81, 0xfc, 0x01, 
0xf8, 0x0f, 0xc0, 0xfe, 0xc0, 0xfc, 0x07, 0xe0, 0x7f, 0xe0, 0x7e, 0x03, 0xf0, 0x3f, 0xf0, 0x3f, 
0x01, 0xf8, 0x1f, 0xf8, 0x1f, 0x80, 0xfc, 0x0f, 0xfc, 0x0f, 0xc0, 0x7e, 0x07, 0xfe, 0x07, 0xe0, 
0x3f, 0x03, 0x7f, 0x03, 0xf0, 0x1f, 0x81, 0x3f, 0x81, 0xf8, 0x0f, 0xc0, 0x1f, 0xc0, 0xfc, 0x07, 
0xe0, 0x0f, 0xe0, 0x7e, 0x03, 0xf0, 0x07, 0xf0, 0x3f, 0x01, 0xf8, 0x03, 0xf8, 0x1f, 0x80, 0xfc};

 

Where are you getting your 128 x 64 OLED from? If it's China, you have a long wait right now, in my experience. If you want it quickly I can send you one from here, won't take more than a week for you to get it. You can have it in exchange for the help you gave on this!

 

Cheers

 

Les


Edited by lesthegrngo
Link to comment
Share on other sites

Where are you getting your 128 x 64 OLED from? If it's China, you have a long wait right now, in my experience. If you want it quickly I can send you one from here, won't take more than a week for you to get it. You can have it in exchange for the help you gave on this!

I've been using the "fulfilled by Amazon" as an indicator for reasonable shipping. There's a large Amazon warehouse about 15 miles from here. Quoted non-Prime free delivery dates are Tuesday/Wednesday (4/5 days).

Link to comment
Share on other sites

I've been using the "fulfilled by Amazon" as an indicator for reasonable shipping. There's a large Amazon warehouse about 15 miles from here. Quoted non-Prime free delivery dates are Tuesday/Wednesday (4/5 days).

 

Of course - I forgot you were in the UK, where free shipping and delivery dates mean something. To give you an idea of the problems I have, IF you can find someone who ships to Hungary ( and many don't) it is a lottery as to when you get things. For example, I received on Tuesday of this week some 3 pin connector headers that were ordered on the 8th January.

 

UPS should be better, right? Nah. They were supposed to deliver something I managed to buy from Amazon, but when the guy went to deliver it, because there was a plaque with the owners name on it at the gate (I rent) he made the decision that it was the wrong address and didn't deliver, and all I knew about was an e-mail 2 days later saying that there was a failed attempted delivery. I got my order ten days later after numerous calls to UPS.

 

Many items never arrive at all.

 

Still, it is a very attractive city.

 

Cheers

 

Les

Link to comment
Share on other sites

Pre-COVID19, the best I've had from Amazon free delivery is 14 hours.

Ordered a pair of side cutters from Amazon about 23:30 on the Friday.

They were through my door before 14:00 the next day!

 

What stepper are you using for the needle? I've read a few things saying X27s aren't fast enough.

Link to comment
Share on other sites

I'm using exclusively X27-168 motors and have not had an issue, and would recommend pairing with A4988 drivers. The lag is definitely due to lots of USB connections, I disconnected some and was happily doing bumps and circuits this afternoon. Obviously I would welcome any suggestions, but realise that a good USB 3.0 pcie card is next on the shopping list

 

What I didn't realise was that the replays also drive the gauges and stuff, which means I have a canned way of really accurately setting up the calibration of the gauges - plus it's really neat seeing everything working on the replays!

 

Les

Link to comment
Share on other sites

Some progress...

 

I made the DCS-BIOS to software serial "sub-master" transmitter...

And it WORKS!

 

All it does is send the 7 counter numbers with some frame start and stop bytes out on a software serial port when the counter values change.

 

So far only tested with the single-display receiver I made before, but the fact the transmitter works is a big step.

 

Next step is trying to make both displays work on the same receiver Nano. The 64-line displays are due tomorrow.

 

Then if that works, it's trying to make the transmitter control the needle as well.

Link to comment
Share on other sites

My end plan is that the whole thing is self-contained - 2 Arduinos in the same gauge.

The Sub-master connects to DCS-BIOS by whatever means you'd normally use (USB definitely works so far). Then a wire goes from the serial data TX pin of the sub-master to the hardware UART RX pin of the display driver.

 

If the two arduinos share a 5V supply, only the serial data wire needs to go between them.

 

My current set setup has an Uno as sub-master and a Nano for the display. The Uno is supplying the power to the display Nano. It may need a separate 5V supply to run the whole thing, though.

 

The point of it is that the display driver doesn't get any information on its serial port except the counter positions, and it doesn't send anything back to the sub-master.

This means that if the display driver can't reliably handle both OLEDs, you could just hook up 2 independent OLED driver Nanos to the same output from the sub-master.

Link to comment
Share on other sites

Progress:

Received the 128 x 64 and successfully changed its I2C address.

Using my modified version of Middlefart's code, I can make one or the other work.

I can't figure out how to make both work independently.

 

Here's my receiver/display code

//  Code from display:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "characters.h"

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)

// Comment for barometric pressure
 #define ALTIMETER

#ifdef ALTIMETER
 #define SCREEN_HEIGHT 64 // OLED display height, in pixels
#else
 #define SCREEN_HEIGHT 32 // OLED display height, in pixels
#endif

int updateInterval = 100; //the number of milliseconds between updates

struct scrollDigit {
 int digit; //The digit that is displayed
 int y; // The vertical position of the digit
};

struct disp {
 Adafruit_SSD1306 display;
 int width;
 int numberOfDigits;
 scrollDigit digits[5];
};

#ifdef ALTIMETER
 disp oled = {Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET), 24, 3, {{0,0},{0,0},{0,0},{0,0},{0,0}}};
#else
 disp oled = {Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET), 16, 4, {{0,0},{0,0},{0,0},{0,0},{0,0}}};
#endif


//  End of code from display





unsigned int upperByte, lowerByte ;
int dataByte;
bool dataValid = false;

#define frameLength 8  // Number of data bytes in the frame, excluding the start and end bytes +1

unsigned int frameData[frameLength] = {0, 6553, 13106, 19660, 26214, 32767, 39321, 45875};  // Set up frame data array with test data

void setup() 
{
 Serial.begin(57600);
 
#ifdef ALTIMETER
   if(!oled.display.begin(SSD1306_SWITCHCAPVCC, 0x3d, false)) { // Address 0x3C for 128x32 and 0x3D for 128 x 64
   for(;;); // Don't proceed, loop forever
#else
   if(!oled.display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false)) { // Address 0x3C for 128x32 and 0x3D for 128 x 64
   for(;;); // Don't proceed, loop forever
#endif

 }

   displayOutput();

} 
unsigned long time = 0;
void loop () 
{

 checkFrameStart();

 getFrameData();

// if (dataValid == true)  //  Check if a valid frame has been received
 {displayOutput();     //  Send data to the display if it's valid
 }

 //  Ignore the data if the frame isn't valid



 time = millis();
 if (time % updateInterval == 0)
 {
   displayOutput();
 }

}

void checkFrameStart(){


// Look for the frame start
 int FstartBytes = 0;

 while (FstartBytes <4){           // number of "A"s in frame start
   while (Serial.available()>=1)
   {
     if (Serial.read()=='A')
     {
       FstartBytes++;
     }
     else {
       FstartBytes = 0;
     }
   }
 }
}   

void getFrameData(){

 int byteCount = frameLength -1;   //  
 dataValid = false;

 while (byteCount>0){                           // Get data frame
   if (Serial.available()>1)
   {
     upperByte = Serial.read();
     lowerByte = Serial.read();

     frameData[byteCount] = (upperByte << 8) + lowerByte ;  // Read data into array. Byte [0] unused
     byteCount --;
   }
 }

 if (upperByte == 'Z' && lowerByte == 'Z' )   // Check end bytes
 { dataValid = true;
 }
}

// ************************************
// *  Display stuff after this point  *
// ************************************

void displayOutput()
{
 // Data display here

 // Uses original OnChange functions to avoid breaking something that works
 
 // Transmitter needs to send in this order (top to bottom)
 #ifdef ALTIMETER
 {
   onAlt10000FtChange(frameData[7]);  // *..
   onAlt1000FtChange(frameData[6]);   // .*.
   onAlt100FtChange(frameData[5]);    // ..*
 }
 #else
 {
   onBaro3Change(frameData[4]);  // ...*
   onBaro2Change(frameData[3]);  // ..*.
   onBaro1Change(frameData[2]);  // .*..
   onBaro0Change(frameData[1]);  // *...
 }
 #endif

UpdateDisplay();
 
}


void UpdateDisplay()
{
 oled.display.clearDisplay();
 for (int i = 0; i < oled.numberOfDigits; i++)
 {
   printScrollingDigit(oled.digits[i].digit, oled.width, oled.digits[i].y, i + 1, &oled);
 }
 //Clear the area below the the numbers if we are using the small font
 if (oled.width == 16)
 {
   oled.display.fillRect(0, 25, 67, 7, BLACK);
 }
 
 oled.display.display();
}

int YPos()
{
 return (oled.width + 9) * -1;
}

void printScrollingDigit(int digit, int width, int y, int pos, disp *oled)
{

   pos = pos+2;  // Shift display 2 digits to the right

 
 int x = (width * pos) - width + pos;



#ifdef ALTIMETER
 y=y+16;             //  Centre digits in display

   switch (digit)
   {
     case -1: oled->display.drawBitmap(x, y-35, c24_9, 24, 32, 1); oled->display.drawBitmap(x, y, c24_Empty, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_1, 24, 32, 1); break;
     case 1: oled->display.drawBitmap(x, y-35, c24_0, 24, 32, 1); oled->display.drawBitmap(x, y, c24_1, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_2, 24, 32, 1); break;
     case 2: oled->display.drawBitmap(x, y-35, c24_1, 24, 32, 1); oled->display.drawBitmap(x, y, c24_2, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_3, 24, 32, 1); break;
     case 3: oled->display.drawBitmap(x, y-35, c24_2, 24, 32, 1); oled->display.drawBitmap(x, y, c24_3, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_4, 24, 32, 1); break;
     case 4: oled->display.drawBitmap(x, y-35, c24_3, 24, 32, 1); oled->display.drawBitmap(x, y, c24_4, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_5, 24, 32, 1); break;
     case 5: oled->display.drawBitmap(x, y-35, c24_4, 24, 32, 1); oled->display.drawBitmap(x, y, c24_5, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_6, 24, 32, 1); break;
     case 6: oled->display.drawBitmap(x, y-35, c24_5, 24, 32, 1); oled->display.drawBitmap(x, y, c24_6, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_7, 24, 32, 1); break;
     case 7: oled->display.drawBitmap(x, y-35, c24_6, 24, 32, 1); oled->display.drawBitmap(x, y, c24_7, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_8, 24, 32, 1); break;
     case 8: oled->display.drawBitmap(x, y-35, c24_7, 24, 32, 1); oled->display.drawBitmap(x, y, c24_8, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_9, 24, 32, 1); break;
     case 9: oled->display.drawBitmap(x, y-35, c24_8, 24, 32, 1); oled->display.drawBitmap(x, y, c24_9, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_0, 24, 32, 1); break;
     default: oled->display.drawBitmap(x, y-35, c24_9, 24, 32, 1); oled->display.drawBitmap(x, y, c24_0, 24, 32, 1); oled->display.drawBitmap(x, y+35, c24_1, 24, 32, 1); break;
   }
#else
   switch (digit)
   {
     case -1: oled->display.drawBitmap(x, y, c16_Empty, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_1, 16, 24, 1); break;
     case 1: oled->display.drawBitmap(x, y, c16_1, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_2, 16, 24, 1); break;
     case 2: oled->display.drawBitmap(x, y, c16_2, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_3, 16, 24, 1); break;
     case 3: oled->display.drawBitmap(x, y, c16_3, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_4, 16, 24, 1); break;
     case 4: oled->display.drawBitmap(x, y, c16_4, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_5, 16, 24, 1); break;
     case 5: oled->display.drawBitmap(x, y, c16_5, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_6, 16, 24, 1); break;
     case 6: oled->display.drawBitmap(x, y, c16_6, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_7, 16, 24, 1); break;
     case 7: oled->display.drawBitmap(x, y, c16_7, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_8, 16, 24, 1); break;
     case 8: oled->display.drawBitmap(x, y, c16_8, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_9, 16, 24, 1); break;
     case 9: oled->display.drawBitmap(x, y, c16_9, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_0, 16, 24, 1); break;
     default: oled->display.drawBitmap(x, y, c16_0, 16, 24, 1); oled->display.drawBitmap(x, y+25, c16_1, 16, 24, 1); break;
   }
#endif
}

#ifdef ALTIMETER
 void onAlt10000FtChange(unsigned int newValue)
 {
   if (newValue == 0)
   {
     oled.digits[0].digit = -1;
     oled.digits[0].y = 0;
   }
   else
   {
   unsigned int mappedValue = newValue / 6553;
   unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, YPos());
 
   oled.digits[0].digit = mappedValue;
   oled.digits[0].y = y;
   }
 }
 
 void onAlt1000FtChange(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6553;
   unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, YPos());
 
   oled.digits[1].digit = mappedValue;
   oled.digits[1].y = y;
 }
 
 void onAlt100FtChange(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6553;
   unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, YPos());
 
   oled.digits[2].digit = mappedValue;
   oled.digits[2].y = y;
 }
 

#else
 void onBaro0Change(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6554;
   unsigned int y = map(newValue, mappedValue * 6554, mappedValue * 6554 + 6554, 0, YPos());
 
   oled.digits[3].digit = mappedValue;
   oled.digits[3].y = y;
 }
 
 void onBaro1Change(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6554;
   unsigned int y = map(newValue, mappedValue * 6554, mappedValue * 6554 + 6554, 0, YPos());
 
   oled.digits[2].digit = mappedValue;
   oled.digits[2].y = y;
 }
 
 void onBaro2Change(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6554;
   unsigned int y = map(newValue, mappedValue * 6554, mappedValue * 6554 + 6554, 0, YPos());
 
   oled.digits[1].digit = mappedValue;
   oled.digits[1].y = y;
 }
 
 void onBaro3Change(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6554;
   unsigned int y = map(newValue, mappedValue * 6554, mappedValue * 6554 + 6554, 0, YPos());
 
   oled.digits[0].digit = mappedValue;
   oled.digits[0].y = y;
 }

#endif

It's not pretty, but it works.

 

If you run this in altimeter mode, it'll show "765" after booting, no data transmission required.

If you run it in barometric mode, it'll show "4321" after booting.


Edited by No1sonuk
Link to comment
Share on other sites

Nice

 

I think you have to assign each OLED an individual name up at the initial definitions, something like

 

oled.display.begin Oled0 (0x3d)

oled.display.begin Oled1 (0x3c)

 

then call out the OLED instance in each case

 

Here's how I did it for multiple LCD displays for the CMSC

 

#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>
#define DCSBIOS_IRQ_SERIAL

#include <DcsBios.h>

LiquidCrystal_PCF8574 lcd0(0x27);  // set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_PCF8574 lcd1(0x26);
LiquidCrystal_PCF8574 lcd2(0x25);
int show;



void onCmscTxtJmrChange(char* newValue) {
lcd0.setCursor(0, 0);
lcd0.print(newValue);
}
DcsBios::StringBuffer<8> cmscTxtJmrBuffer(0x1096, onCmscTxtJmrChange);

void onCmscTxtChaffFlareChange(char* newValue) {
lcd1.setCursor(0, 0);
lcd1.print(newValue);
}
DcsBios::StringBuffer<8> cmscTxtChaffFlareBuffer(0x108e, onCmscTxtChaffFlareChange);

void onCmscTxtMwsChange(char* newValue) {
lcd2.setCursor(0, 0);
lcd2.print(newValue);
}
DcsBios::StringBuffer<8> cmscTxtMwsBuffer(0x12b0, onCmscTxtMwsChange);

void setup() {
 lcd0.begin(16, 2);
 lcd1.begin(16, 2);
 lcd2.begin(16, 2);
 DcsBios::setup();
 
}

void loop() {
 DcsBios::loop();
lcd0.setBacklight(5);
lcd1.setBacklight(5);
lcd2.setBacklight(5);
}

 

Cheers

 

Les

Link to comment
Share on other sites

Nice

 

I think you have to assign each OLED an individual name up at the initial definitions, something like

 

oled.display.begin Oled0 (0x3d)

oled.display.begin Oled1 (0x3c)

 

then call out the OLED instance in each case

 

I tried that.

The problem is that with all the "struct" stuff and the long instructions, it's not quite as easy as copying and replacing "oled" with "oled1" for example.

 

There's something I've not tried yet, though...

Link to comment
Share on other sites

You might wanna have a look at this sketch.

This is my original one which i used in conjunction with a I2C Multiplexer to drive two displays (with the same address) from the same Arduino Nano.

 

You need to do some changes since you are not using the Multiplexer but the base functionality should be the same.

 

#define DCSBIOS_RS485_SLAVE 2
#define TXENABLE_PIN 2

#include "DcsBios.h"

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "characters.h"

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define TCAAddress 0x70
#define AltAddress 0
#define HGAddress 1

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)

struct scrollDigit {
 int digit;
 int y;
};

struct disp {
 Adafruit_SSD1306 display;
 int address;
 int width;
 int numberOfDigits;
 scrollDigit digits[5];
};


disp displays[2] = 
{
 {Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET), 0, 24, 5, {{0,0},{0,0},{0,0},{0,0},{0,0}}},
 {Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET), 1, 16, 4, {{0,0},{0,0},{0,0},{0,0},{0,0}}}
};

void TCASelect(uint8_t addr) {
 if (addr > 7) return;

 Wire.beginTransmission(TCAAddress);
 Wire.write(1 << addr);
 Wire.endTransmission();  
}

void setup() {
 
 for (int i = 0; i<2; i++)
 {
   TCASelect(displays[i].address);
   if(!displays[i].display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
     for(;;); // Don't proceed, loop forever
   }
 }

 DcsBios::setup();

}

void UpdateDisplays()
{
 for (int j = 0; j<2; j++)
 {
   TCASelect(displays[j].address);
   displays[j].display.clearDisplay();
   for (int i = 0; i < displays[j].numberOfDigits; i++)
   {
     printScrollingDigit(displays[j].digits[i].digit, displays[j].width, displays[j].digits[i].y, i + 1, &displays[j]);
   }
   if (displays[j].width == 16)
   {
     displays[j].display.fillRect(0, 25, 128, 7, BLACK);
   }
   displays[j].display.display();
 }
}

void printScrollingDigit(int digit, int width, int y, int pos, disp *display)
{
//  int width = 24;
 int x = (width * pos) - width + pos;

 if (width == 24)
 {
   switch (digit)
   {
     case -1: display->display.drawBitmap(x, y, c24_Empty, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_1, 24, 32, 1); break;
     case 1: display->display.drawBitmap(x, y, c24_1, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_2, 24, 32, 1); break;
     case 2: display->display.drawBitmap(x, y, c24_2, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_3, 24, 32, 1); break;
     case 3: display->display.drawBitmap(x, y, c24_3, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_4, 24, 32, 1); break;
     case 4: display->display.drawBitmap(x, y, c24_4, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_5, 24, 32, 1); break;
     case 5: display->display.drawBitmap(x, y, c24_5, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_6, 24, 32, 1); break;
     case 6: display->display.drawBitmap(x, y, c24_6, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_7, 24, 32, 1); break;
     case 7: display->display.drawBitmap(x, y, c24_7, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_8, 24, 32, 1); break;
     case 8: display->display.drawBitmap(x, y, c24_8, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_9, 24, 32, 1); break;
     case 9: display->display.drawBitmap(x, y, c24_9, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_0, 24, 32, 1); break;
     default: display->display.drawBitmap(x, y, c24_0, 24, 32, 1); display->display.drawBitmap(x, y+33, c24_1, 24, 32, 1); break;
   }
 }
 else
 {
   switch (digit)
   {
     case -1: display->display.drawBitmap(x, y, c16_Empty, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_1, 16, 24, 1); break;
     case 1: display->display.drawBitmap(x, y, c16_1, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_2, 16, 24, 1); break;
     case 2: display->display.drawBitmap(x, y, c16_2, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_3, 16, 24, 1); break;
     case 3: display->display.drawBitmap(x, y, c16_3, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_4, 16, 24, 1); break;
     case 4: display->display.drawBitmap(x, y, c16_4, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_5, 16, 24, 1); break;
     case 5: display->display.drawBitmap(x, y, c16_5, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_6, 16, 24, 1); break;
     case 6: display->display.drawBitmap(x, y, c16_6, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_7, 16, 24, 1); break;
     case 7: display->display.drawBitmap(x, y, c16_7, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_8, 16, 24, 1); break;
     case 8: display->display.drawBitmap(x, y, c16_8, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_9, 16, 24, 1); break;
     case 9: display->display.drawBitmap(x, y, c16_9, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_0, 16, 24, 1); break;
     default: display->display.drawBitmap(x, y, c16_0, 16, 24, 1); display->display.drawBitmap(x, y+25, c16_1, 16, 24, 1); break;
   }
 }
}

void onAlt10000FtChange(unsigned int newValue)
{
 void onAlt10000FtChange(unsigned int newValue)
 {
   unsigned int mappedValue = newValue / 6553;
   unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, YPos());

   if (mappedValue == 0)
   {
     mappedValue = -1;
   }
   oled.digits[0].digit = mappedValue;
   oled.digits[0].y = y;
 }
}

void onAlt1000FtChange(unsigned int newValue)
{
 unsigned int mappedValue = newValue / 6553;
 unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, -33);

 displays[AltAddress].digits[1].digit = mappedValue;
 displays[AltAddress].digits[1].y = y;
//  UpdateDisplays();
}

void onAlt100FtChange(unsigned int newValue)
{
 unsigned int mappedValue = newValue / 6553;
 unsigned int y = map(newValue, mappedValue * 6553, mappedValue * 6553 + 6553, 0, -33);

 displays[AltAddress].digits[2].digit = mappedValue;
 displays[AltAddress].digits[2].y = y;
 //UpdateDisplays();
}

void onBaro0Change(unsigned int newValue)
{
 unsigned int mappedValue = newValue / 6554;
 unsigned int y = map(newValue, mappedValue * 6554, mappedValue * 6554 + 6554, 0, -25);

 displays[HGAddress].digits[3].digit = mappedValue;
 displays[HGAddress].digits[3].y = y;
 //UpdateDisplays();
}

void onBaro1Change(unsigned int newValue)
{
 unsigned int mappedValue = newValue / 6554;
 unsigned int y = map(newValue, mappedValue * 6554, mappedValue * 6554 + 6554, 0, -25);

 displays[HGAddress].digits[2].digit = mappedValue;
 displays[HGAddress].digits[2].y = y;
//  UpdateDisplays();
}

void onBaro2Change(unsigned int newValue)
{
 unsigned int mappedValue = newValue / 6554;
 unsigned int y = map(newValue, mappedValue * 6554, mappedValue * 6554 + 6554, 0, -25);

 displays[HGAddress].digits[1].digit = mappedValue;
 displays[HGAddress].digits[1].y = y;
//  UpdateDisplays();
}

void onBaro3Change(unsigned int newValue)
{
 unsigned int mappedValue = newValue / 6554;
 unsigned int y = map(newValue, mappedValue * 6554, mappedValue * 6554 + 6554, 0, -25);

 displays[HGAddress].digits[0].digit = mappedValue;
 displays[HGAddress].digits[0].y = y;
//  UpdateDisplays();
}

DcsBios::IntegerBuffer Alt10000FtBuffer(0x1080, 0xffff, 0, onAlt10000FtChange);
DcsBios::IntegerBuffer Alt1000FtBuffer(0x1082, 0xffff, 0, onAlt1000FtChange);
DcsBios::IntegerBuffer Alt100FtBuffer(0x1084, 0xffff, 0, onAlt100FtChange);
DcsBios::IntegerBuffer Baro0Buffer(0x1086, 0xffff, 0, onBaro0Change);
DcsBios::IntegerBuffer Baro1Buffer(0x1088, 0xffff, 0, onBaro1Change);
DcsBios::IntegerBuffer Baro2Buffer(0x108a, 0xffff, 0, onBaro2Change);
DcsBios::IntegerBuffer Baro3Buffer(0x108c, 0xffff, 0, onBaro3Change);

int count = 0;
void loop() {

 DcsBios::loop();
 count++;
 if (count % 100 == 0)
 {
   UpdateDisplays();
 }


}

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...