No1sonuk Posted May 21, 2020 Share Posted May 21, 2020 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 More sharing options...
Middlefart Posted May 21, 2020 Share Posted May 21, 2020 Glad to hear it works! Link to comment Share on other sites More sharing options...
No1sonuk Posted May 21, 2020 Share Posted May 21, 2020 Pressure is OK too. I guess it's down to Les to try with his 64-line display - I don't have one to try. I'll hold work on my other option for now, though. Link to comment Share on other sites More sharing options...
lesthegrngo Posted May 21, 2020 Author Share Posted May 21, 2020 Guys, will give it a go first thing in the morning, fingers crossed Cheers Les Link to comment Share on other sites More sharing options...
lesthegrngo Posted May 22, 2020 Author Share Posted May 22, 2020 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 More sharing options...
Middlefart Posted May 22, 2020 Share Posted May 22, 2020 Good to hear! :thumbup: The latest version of the sketch can now be found on https://github.com/Middlefart/DCS-A10 Link to comment Share on other sites More sharing options...
lesthegrngo Posted May 22, 2020 Author Share Posted May 22, 2020 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 More sharing options...
Middlefart Posted May 22, 2020 Share Posted May 22, 2020 :thumbup: Yes I agree. I would like a more beefed up version of the nano with a little more oumph! Would be nice to have a little more CPU to play with Link to comment Share on other sites More sharing options...
lesthegrngo Posted May 22, 2020 Author Share Posted May 22, 2020 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 More sharing options...
No1sonuk Posted May 22, 2020 Share Posted May 22, 2020 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 More sharing options...
lesthegrngo Posted May 22, 2020 Author Share Posted May 22, 2020 (edited) 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 May 22, 2020 by lesthegrngo Link to comment Share on other sites More sharing options...
No1sonuk Posted May 22, 2020 Share Posted May 22, 2020 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 More sharing options...
lesthegrngo Posted May 22, 2020 Author Share Posted May 22, 2020 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 More sharing options...
lesthegrngo Posted May 22, 2020 Author Share Posted May 22, 2020 Just a quick update - almost an hour and a half of flying this afternoon, no glitching of any of the OLED displays at all. Cheers Les Link to comment Share on other sites More sharing options...
No1sonuk Posted May 22, 2020 Share Posted May 22, 2020 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 More sharing options...
lesthegrngo Posted May 22, 2020 Author Share Posted May 22, 2020 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 More sharing options...
No1sonuk Posted May 23, 2020 Share Posted May 23, 2020 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 More sharing options...
lesthegrngo Posted May 24, 2020 Author Share Posted May 24, 2020 That sounds cool - but how would the two units be linked? Please don't say RS485........! Les Link to comment Share on other sites More sharing options...
No1sonuk Posted May 24, 2020 Share Posted May 24, 2020 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 More sharing options...
No1sonuk Posted May 25, 2020 Share Posted May 25, 2020 (edited) 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 May 25, 2020 by No1sonuk Link to comment Share on other sites More sharing options...
lesthegrngo Posted May 26, 2020 Author Share Posted May 26, 2020 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 More sharing options...
No1sonuk Posted May 26, 2020 Share Posted May 26, 2020 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 More sharing options...
lesthegrngo Posted May 26, 2020 Author Share Posted May 26, 2020 I think you have to make individual 'struct' parts as well - have a look at my multiple stepper motor on one mega sketch Les Link to comment Share on other sites More sharing options...
Middlefart Posted May 26, 2020 Share Posted May 26, 2020 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 More sharing options...
Middlefart Posted May 26, 2020 Share Posted May 26, 2020 Disclaimer: I'm not sure that the sketch in the previous post is 100% working but I think so :-) Link to comment Share on other sites More sharing options...
Recommended Posts