/*********************************************************************
This is an example for our Monochrome OLEDs based on SH110X drivers
This example is for a 128x64 size display using I2C to communicate
3 pins are required to interface (2 I2C and one reset)
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
i2c SH1106 modified by Rupert Hirst 12/09/21
*********************************************************************/
const uint8_t Aurebesh8pt7bBitmaps[] PROGMEM = {
0x00, 0x5B, 0xDA, 0xC3, 0xE3, 0x33, 0x1B, 0x0F, 0x00, 0x00, 0x0D, 0x80,
0x0D, 0x80, 0x7F, 0xFF, 0xFF, 0xFC, 0x0D, 0x9C, 0x0D, 0xB8, 0x00, 0x70,
0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00,
0xED, 0xB6, 0x80, 0x33, 0x33, 0xFF, 0x33, 0x33, 0xCC, 0xCC, 0xFF, 0xCC,
0xCC, 0x00, 0x00, 0xFF, 0xC0, 0xFF, 0xF0, 0xDE, 0xF7, 0xBD, 0x80, 0x33,
0x33, 0x3C, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x01,
0xE0, 0x0F, 0x00, 0x78, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0x37, 0xB3, 0x33,
0x33, 0x33, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0x00, 0x3F, 0xFF, 0xFF, 0xFF,
0x00, 0x18, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xC0, 0x06,
0x00, 0x37, 0xFF, 0xFF, 0xFC, 0x00, 0x60, 0x03, 0xFF, 0xFF, 0xFF, 0xC0,
0x00, 0x60, 0xE3, 0x0E, 0x00, 0x60, 0x07, 0xFF, 0xFF, 0xFC, 0x01, 0x80,
0x0C, 0x00, 0x60, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0x80, 0x0F,
0xFF, 0xFF, 0xFC, 0x00, 0x60, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF,
0xFF, 0xF0, 0x01, 0x80, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0x78, 0x03, 0xFF,
0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFE, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x70,
0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80,
0x3F, 0xFF, 0xFF, 0xFF, 0x00, 0x78, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF,
0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3F, 0xFF, 0xFF, 0xFC, 0x00, 0x60, 0x03,
0xFF, 0xFF, 0xFF, 0xC0, 0x84, 0x30, 0xC3, 0x7F, 0xE0, 0xFF, 0xFF, 0xF0,
0x00, 0x00, 0x00, 0xE7, 0xB7, 0xBD, 0x8C, 0x63, 0x33, 0x00, 0x00, 0xC0,
0x0F, 0xE0, 0x1E, 0x3F, 0xFC, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03,
0xFF, 0x01, 0xFF, 0xE0, 0xC0, 0x3C, 0x60, 0x07, 0xC0, 0x3F, 0xF8, 0x3F,
0xFC, 0x60, 0x06, 0x80, 0x01, 0x07, 0xE0, 0x07, 0xE0, 0x00, 0x00, 0xE0,
0x07, 0x3F, 0xFC, 0x3F, 0xFC, 0xC0, 0x30, 0x0C, 0x03, 0x33, 0xCC, 0xF3,
0x3C, 0xCC, 0x03, 0x00, 0xC0, 0x30, 0x7F, 0xFF, 0xFE, 0x00, 0xC0, 0x18,
0x3F, 0x07, 0xF0, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xC0, 0x7E, 0xC0,
0xFD, 0x83, 0xB1, 0x86, 0x63, 0x1C, 0xC3, 0x31, 0x86, 0x63, 0x07, 0x86,
0x0F, 0x0C, 0x0C, 0x18, 0x03, 0x02, 0x06, 0x3C, 0x0F, 0xE7, 0xFF, 0x0F,
0xF0, 0x18, 0x60, 0x30, 0xC0, 0x61, 0x80, 0xFF, 0xFF, 0xFF, 0xFC, 0xCF,
0xFF, 0x9F, 0xFB, 0x00, 0x66, 0x00, 0xCC, 0x03, 0x18, 0x0E, 0x30, 0x18,
0x60, 0x60, 0xFF, 0xC1, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0x3B, 0xF7, 0xB1, 0x8C, 0x63, 0x18, 0xC0, 0x00, 0x0E, 0x00,
0x38, 0x01, 0xE0, 0x1F, 0xCF, 0xFB, 0x1F, 0x86, 0x00, 0x18, 0x00, 0x30,
0xFF, 0xC1, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x18, 0x00, 0x30,
0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x01,
0x80, 0xC0, 0x60, 0x3C, 0x1F, 0x0D, 0xE6, 0x3B, 0x0F, 0x81, 0xC0, 0x07,
0x86, 0xC3, 0x03, 0x01, 0x81, 0x80, 0xC0, 0xC0, 0x7F, 0xFF, 0x80, 0x31,
0xC0, 0xC3, 0x83, 0x8F, 0x86, 0x1B, 0x0C, 0x73, 0x18, 0xC6, 0x33, 0x86,
0x76, 0x0C, 0x7C, 0x0C, 0x70, 0x1C, 0x0F, 0xE0, 0x3F, 0xE0, 0x60, 0xC1,
0xC1, 0xC3, 0x01, 0x8E, 0x03, 0x98, 0x03, 0x70, 0x07, 0xFF, 0xFE, 0xFF,
0xF8, 0x38, 0xDE, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x83, 0x7F,
0xCF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x00, 0x60, 0x03,
0x00, 0x18, 0x00, 0xFF, 0x87, 0xF8, 0x00, 0x7F, 0xFF, 0xFE, 0x00, 0xC0,
0x18, 0x03, 0x00, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0x1C, 0x0C,
0x38, 0x30, 0x70, 0xC0, 0xC3, 0x01, 0x8E, 0x03, 0x3F, 0x0E, 0xDF, 0x1F,
0x0F, 0x3C, 0x0C, 0x70, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03,
0x03, 0x8C, 0x77, 0x33, 0x8E, 0xDC, 0x1F, 0xE0, 0x3F, 0x00, 0xC1, 0xFF,
0x07, 0xFC, 0x30, 0xF1, 0x83, 0xC8, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03,
0xFF, 0xFF, 0xFF, 0xF0, 0xE1, 0xDC, 0xE3, 0x30, 0x78, 0x0C, 0x03, 0x00,
0xC0, 0x30, 0x0C, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x1E, 0x00,
0x3C, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xFF, 0xFF, 0xFF, 0xFC,
0x07, 0x00, 0x78, 0x03, 0x60, 0x33, 0x81, 0x8C, 0x18, 0x71, 0xC1, 0x8C,
0x06, 0xFF, 0xF3, 0xFF, 0xC0, 0xFC, 0x1F, 0xE1, 0xDB, 0x8C, 0xCC, 0xE3,
0x06, 0x18, 0x30, 0x63, 0x03, 0x18, 0x0D, 0x80, 0x7C, 0x00, 0x00, 0x18,
0x00, 0xC3, 0xFE, 0x3F, 0xF3, 0x81, 0xB8, 0x0C, 0x00, 0x60, 0x03, 0xFF,
0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0xE0,
0x1E, 0x3F, 0xFC, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x01,
0xFF, 0xE0, 0xC0, 0x3C, 0x60, 0x07, 0xC0, 0x3F, 0xF8, 0x3F, 0xFC, 0x60,
0x06, 0x80, 0x01, 0x07, 0xE0, 0x07, 0xE0, 0x00, 0x00, 0xE0, 0x07, 0x3F,
0xFC, 0x3F, 0xFC, 0xC0, 0x30, 0x0C, 0x03, 0x33, 0xCC, 0xF3, 0x3C, 0xCC,
0x03, 0x00, 0xC0, 0x30, 0x7F, 0xFF, 0xFE, 0x00, 0xC0, 0x18, 0x3F, 0x07,
0xF0, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xC0, 0x7E, 0xC0, 0xFD, 0x83,
0xB1, 0x86, 0x63, 0x1C, 0xC3, 0x31, 0x86, 0x63, 0x07, 0x86, 0x0F, 0x0C,
0x0C, 0x18, 0x03, 0x02, 0x06, 0x3C, 0x0F, 0xE7, 0xFF, 0x0F, 0xF0, 0x18,
0x60, 0x30, 0xC0, 0x61, 0x80, 0xFF, 0xFF, 0xFF, 0xFC, 0xCF, 0xFF, 0x9F,
0xFB, 0x00, 0x66, 0x00, 0xCC, 0x03, 0x18, 0x0E, 0x30, 0x18, 0x60, 0x60,
0xFF, 0xC1, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x1F, 0xF8, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x3B, 0xF7, 0xB1, 0x8C, 0x63, 0x18, 0xC0, 0x00, 0x0E, 0x00, 0x38, 0x01,
0xE0, 0x1F, 0xCF, 0xFB, 0x1F, 0x86, 0x00, 0x18, 0x00, 0x30, 0xFF, 0xC1,
0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60,
0x00, 0xC0, 0x01, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x01, 0x80, 0xC0,
0x60, 0x3C, 0x1F, 0x0D, 0xE6, 0x3B, 0x0F, 0x81, 0xC0, 0x07, 0x86, 0xC3,
0x03, 0x01, 0x81, 0x80, 0xC0, 0xC0, 0x7F, 0xFF, 0x80, 0x31, 0xC0, 0xC3,
0x83, 0x8F, 0x86, 0x1B, 0x0C, 0x73, 0x18, 0xC6, 0x33, 0x86, 0x76, 0x0C,
0x7C, 0x0C, 0x70, 0x1C, 0x0F, 0xE0, 0x3F, 0xE0, 0x60, 0xC1, 0xC1, 0xC3,
0x01, 0x8E, 0x03, 0x98, 0x03, 0x70, 0x07, 0xFF, 0xFE, 0xFF, 0xF8, 0x38,
0xDE, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x83, 0x7F, 0xCF, 0xF0,
0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x00, 0x60, 0x03, 0x00, 0x18,
0x00, 0xFF, 0x87, 0xF8, 0x00, 0x7F, 0xFF, 0xFE, 0x00, 0xC0, 0x18, 0x03,
0x00, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0x1C, 0x0C, 0x38, 0x30,
0x70, 0xC0, 0xC3, 0x01, 0x8E, 0x03, 0x3F, 0x0E, 0xDF, 0x1F, 0x0F, 0x3C,
0x0C, 0x70, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x03, 0x8C,
0x77, 0x33, 0x8E, 0xDC, 0x1F, 0xE0, 0x3F, 0x00, 0xC1, 0xFF, 0x07, 0xFC,
0x30, 0xF1, 0x83, 0xC8, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xFF, 0xFF,
0xFF, 0xF0, 0xE1, 0xDC, 0xE3, 0x30, 0x78, 0x0C, 0x03, 0x00, 0xC0, 0x30,
0x0C, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x1E, 0x00, 0x3C, 0x00,
0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x07, 0x00,
0x78, 0x03, 0x60, 0x33, 0x81, 0x8C, 0x18, 0x71, 0xC1, 0x8C, 0x06, 0xFF,
0xF3, 0xFF, 0xC0, 0xFC, 0x1F, 0xE1, 0xDB, 0x8C, 0xCC, 0xE3, 0x06, 0x18,
0x30, 0x63, 0x03, 0x18, 0x0D, 0x80, 0x7C, 0x00, 0x00, 0x18, 0x00, 0xC3,
0xFE, 0x3F, 0xF3, 0x81, 0xB8, 0x0C, 0x00, 0x60, 0x03, 0xFF, 0xFF, 0xFF,
0xC0, 0x00, 0x00, 0x00, 0x00 };
const GFXglyph Aurebesh8pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 8, 0, 0 }, // 0x20 ' '
{ 1, 2, 8, 5, 0, -8 }, // 0x21 '!'
{ 3, 9, 5, 9, 0, -10 }, // 0x22 '"'
{ 9, 1, 1, 8, 0, 0 }, // 0x23 '#'
{ 10, 16, 12, 16, 0, -11 }, // 0x24 '$'
{ 34, 1, 1, 8, 0, 0 }, // 0x25 '%'
{ 35, 1, 1, 8, 0, 0 }, // 0x26 '&'
{ 36, 3, 6, 5, 0, -10 }, // 0x27 '''
{ 39, 4, 10, 6, 0, -9 }, // 0x28 '('
{ 44, 4, 10, 6, 0, -9 }, // 0x29 ')'
{ 49, 1, 1, 8, 0, 0 }, // 0x2A '*'
{ 50, 1, 1, 8, 0, 0 }, // 0x2B '+'
{ 51, 2, 5, 4, 0, -4 }, // 0x2C ','
{ 53, 6, 2, 8, 0, -9 }, // 0x2D '-'
{ 55, 5, 5, 7, 0, -4 }, // 0x2E '.'
{ 59, 4, 10, 6, 0, -9 }, // 0x2F '/'
{ 64, 13, 10, 15, 0, -9 }, // 0x30 '0'
{ 81, 4, 10, 5, 0, -9 }, // 0x31 '1'
{ 86, 13, 10, 15, 0, -9 }, // 0x32 '2'
{ 103, 13, 10, 15, 0, -9 }, // 0x33 '3'
{ 120, 13, 10, 15, 0, -9 }, // 0x34 '4'
{ 137, 13, 10, 15, 0, -9 }, // 0x35 '5'
{ 154, 13, 10, 15, 0, -9 }, // 0x36 '6'
{ 171, 12, 10, 14, 0, -9 }, // 0x37 '7'
{ 186, 13, 10, 15, 0, -9 }, // 0x38 '8'
{ 203, 13, 10, 15, 0, -9 }, // 0x39 '9'
{ 220, 5, 7, 7, 0, -6 }, // 0x3A ':'
{ 225, 2, 10, 4, 0, -9 }, // 0x3B ';'
{ 228, 1, 1, 8, 0, 0 }, // 0x3C '<'
{ 229, 1, 1, 8, 0, 0 }, // 0x3D '='
{ 230, 1, 1, 8, 0, 0 }, // 0x3E '>'
{ 231, 5, 10, 7, 0, -9 }, // 0x3F '?'
{ 238, 1, 1, 8, 0, 0 }, // 0x40 '@'
{ 239, 17, 10, 17, 0, -9 }, // 0x41 'A'
{ 261, 16, 10, 17, 0, -9 }, // 0x42 'B'
{ 281, 10, 10, 12, 0, -9 }, // 0x43 'C'
{ 294, 12, 10, 12, 0, -9 }, // 0x44 'D'
{ 309, 15, 10, 16, 0, -9 }, // 0x45 'E'
{ 328, 15, 10, 16, 0, -9 }, // 0x46 'F'
{ 347, 15, 10, 15, 0, -9 }, // 0x47 'G'
{ 366, 16, 10, 17, 0, -9 }, // 0x48 'H'
{ 386, 5, 10, 7, 0, -9 }, // 0x49 'I'
{ 393, 15, 10, 15, 0, -9 }, // 0x4A 'J'
{ 412, 15, 10, 17, 0, -9 }, // 0x4B 'K'
{ 431, 9, 10, 11, 0, -9 }, // 0x4C 'L'
{ 443, 9, 10, 10, 0, -9 }, // 0x4D 'M'
{ 455, 15, 10, 15, 0, -9 }, // 0x4E 'N'
{ 474, 15, 10, 16, 0, -9 }, // 0x4F 'O'
{ 493, 10, 10, 12, 0, -9 }, // 0x50 'P'
{ 506, 13, 10, 14, 0, -9 }, // 0x51 'Q'
{ 523, 12, 10, 12, 0, -9 }, // 0x52 'R'
{ 538, 14, 10, 16, 0, -9 }, // 0x53 'S'
{ 556, 14, 10, 15, 0, -9 }, // 0x54 'T'
{ 574, 14, 10, 16, 0, -9 }, // 0x55 'U'
{ 592, 10, 10, 12, 0, -9 }, // 0x56 'V'
{ 605, 15, 10, 17, 0, -9 }, // 0x57 'W'
{ 624, 13, 10, 13, 0, -9 }, // 0x58 'X'
{ 641, 13, 10, 14, 0, -9 }, // 0x59 'Y'
{ 658, 13, 10, 15, 0, -9 }, // 0x5A 'Z'
{ 675, 1, 1, 8, 0, 0 }, // 0x5B '['
{ 676, 1, 1, 8, 0, 0 }, // 0x5C '\'
{ 677, 1, 1, 8, 0, 0 }, // 0x5D ']'
{ 678, 1, 1, 8, 0, 0 }, // 0x5E '^'
{ 679, 1, 1, 8, 0, 0 }, // 0x5F '_'
{ 680, 1, 1, 8, 0, 0 }, // 0x60 '`'
{ 681, 17, 10, 17, 0, -9 }, // 0x61 'a'
{ 703, 16, 10, 17, 0, -9 }, // 0x62 'b'
{ 723, 10, 10, 12, 0, -9 }, // 0x63 'c'
{ 736, 12, 10, 12, 0, -9 }, // 0x64 'd'
{ 751, 15, 10, 16, 0, -9 }, // 0x65 'e'
{ 770, 15, 10, 16, 0, -9 }, // 0x66 'f'
{ 789, 15, 10, 15, 0, -9 }, // 0x67 'g'
{ 808, 16, 10, 17, 0, -9 }, // 0x68 'h'
{ 828, 5, 10, 7, 0, -9 }, // 0x69 'i'
{ 835, 15, 10, 15, 0, -9 }, // 0x6A 'j'
{ 854, 15, 10, 17, 0, -9 }, // 0x6B 'k'
{ 873, 9, 10, 11, 0, -9 }, // 0x6C 'l'
{ 885, 9, 10, 11, 0, -9 }, // 0x6D 'm'
{ 897, 15, 10, 15, 0, -9 }, // 0x6E 'n'
{ 916, 15, 10, 16, 0, -9 }, // 0x6F 'o'
{ 935, 10, 10, 12, 0, -9 }, // 0x70 'p'
{ 948, 13, 10, 14, 0, -9 }, // 0x71 'q'
{ 965, 12, 10, 12, 0, -9 }, // 0x72 'r'
{ 980, 14, 10, 16, 0, -9 }, // 0x73 's'
{ 998, 14, 10, 15, 0, -9 }, // 0x74 't'
{ 1016, 14, 10, 16, 0, -9 }, // 0x75 'u'
{ 1034, 10, 10, 11, 0, -9 }, // 0x76 'v'
{ 1047, 15, 10, 17, 0, -9 }, // 0x77 'w'
{ 1066, 13, 10, 13, 0, -9 }, // 0x78 'x'
{ 1083, 13, 10, 14, 0, -9 }, // 0x79 'y'
{ 1100, 13, 10, 15, 0, -9 }, // 0x7A 'z'
{ 1117, 1, 1, 8, 0, 0 }, // 0x7B '{'
{ 1118, 1, 1, 8, 0, 0 }, // 0x7C '|'
{ 1119, 1, 1, 8, 0, 0 }, // 0x7D '}'
{ 1120, 1, 1, 8, 0, 0 } }; // 0x7E '~'
const GFXfont Aurebesh8pt7b PROGMEM = {
(uint8_t *)Aurebesh8pt7bBitmaps,
(GFXglyph *)Aurebesh8pt7bGlyphs,
0x20, 0x7E, 12 };
// Approx. 1793 bytes
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
//#include <Adafruit_SH110X.h>
//#include <U8g2lib.h>
/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
#define i2c_Address 0x3C // initialize with the I2C addr 0x3C Typically eBay OLED's
//#define i2c_Address 0x3d //initialize with the I2C addr 0x3D Typically Adafruit OLED's
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SCREEN_CENTER_X 64
#define SCREEN_CENTER_y 32
#define OLED_RESET -1 // QT-PY / XIAO
//Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
U8G2_SH1107_128X128_1_HW_I2C display(U8G2_R0);
// IIC connection of the OLED display and Arduino UNO
// +5V > +5V
// GND > GND
// SCL (serial clock) > A5 or SCL
// SDA (serial data) > A4 or SDA
// Screen parameters with Aurebesh
const int AUREBESH_WIDTH = 18;
const int AUREBESH_HEIGHT = 15;
const int aurebeshScreenLines = 4; // SCREEN_HEIGHT / AUREBESH_HEIGHT;
const int aurebeshScreenColumns = 7; // SCREEN_WIDTH / AUREBESH_WIDTH;
typedef struct
{
int line;
int column;
} AurebeshScreenCoordinate;
typedef struct
{
int16_t x;
int16_t y;
} PixelCoordinate;
typedef struct
{
unsigned long time_start;
unsigned long durationMs;
} Timer;
typedef struct
{
uint16_t lx;
uint16_t ly;
uint16_t rx;
uint16_t ry;
} resultPos;
static AurebeshScreenCoordinate currentCoordinate;
static const int cursorSpeed = 50;
static char currentlyShowing[aurebeshScreenLines][aurebeshScreenColumns + 1];
// Screen Modes
enum Modes
{
mode01,
mode02,
mode03,
mode04,
mode05,
mode06,
mode07,
mode08,
};
const int nbrModes = 8;
void setup()
{
Serial.begin(9600);
display.begin(); // begin the u8g2 library
display.setContrast(255);
//delay(250); // wait for the OLED to power up
// if (!display.begin(i2c_Address, true))
// {
// Serial.println(F("Oled Failed"));
// while (true)
// {
// /* code */Serial.println("go");
// }
// }
initAurebeshScreen();
display.display();
}
void loop()
{
displayRandomScreenMode();
displayCursor(currentCoordinate, random(500, 5000), 200);
}
void displayRandomScreenMode()
{
int mode = getRandomMode();
resetAurebeshScreen();
switch (mode)
{
case mode01:
displayNoisePixelated(random(10, 300), false, random(10, 2000));
break;
case mode02:
Serial.println("mode02");
displayAurebeshString((char *)getRandomSentences());
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case mode03:
Serial.println("mode03");
resetAurebeshScreen();
displayAurebeshString((char *)getRandomSentences());
invertLine(getRandomLineNotEmptyCurrentlyShowing(), 50, 5000);
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case mode04:
Serial.println("mode04");
displaySector(random(5000, 20000), random(4));
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case mode05:
Serial.println("mode05");
resetAurebeshScreen();
displayTarget(random(3000, 10000));
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case mode06:
Serial.println("mode06");
resetAurebeshScreen();
displayTarget(random(3000, 8000));
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case mode07:
Serial.println("mode07");
resetAurebeshScreen();
displayTarget(random(5000, 10000));
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case mode08:
Serial.println("mode08");
resetAurebeshScreen();
complexAurebesh(random(5000, 10000), 25);
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
default:
Serial.println("Default");
break;
}
display.clearDisplay();
}
void transitionVertical(void)
{
int x1 = SCREEN_CENTER_X;
int x2 = SCREEN_CENTER_X;
while (x1 > 0)
{
display.drawFastVLine(x1, 0, SCREEN_HEIGHT, SH110X_WHITE);
display.drawFastVLine(x2, 0, SCREEN_HEIGHT, SH110X_WHITE);
display.display();
delay(5);
display.drawFastVLine(x1, 0, SCREEN_HEIGHT, SH110X_BLACK);
display.drawFastVLine(x2, 0, SCREEN_HEIGHT, SH110X_BLACK);
display.display();
delay(5);
x1--;
x2++;
}
}
void complexAurebesh(int durationsMS, int speedMS)
{
AurebeshScreenCoordinate coord;
char aurebeshChar;
char displayed[aurebeshScreenLines][aurebeshScreenColumns];
memset(displayed, -1, sizeof(displayed[0][0]) * aurebeshScreenLines * aurebeshScreenColumns);
Timer time = initTimer(durationsMS);
while (duration(time))
{
coord.line = random(aurebeshScreenLines);
coord.column = random(aurebeshScreenColumns);
aurebeshChar = random(32, 128);
if (displayed[coord.line][coord.column] != -1)
{
display.setTextColor(SH110X_BLACK);
displayAurebeshCharAtCoordinate(displayed[coord.line][coord.column], coord);
}
display.setTextColor(SH110X_WHITE);
displayAurebeshCharAtCoordinate(aurebeshChar, coord);
// Serial.println(displayed[coord.line][coord.column],DEC);
displayed[coord.line][coord.column] = aurebeshChar;
display.display();
delay(speedMS);
}
}
void displaySector(int durationMS, int quadrant)
{
displayCircleCentered(6, SH110X_WHITE);
displayCircleCentered(15, SH110X_WHITE);
displayCircleCentered(24, SH110X_WHITE);
displayLineVerticalCentered(SCREEN_HEIGHT, SH110X_WHITE);
displayLineHorizontalCentered(SCREEN_WIDTH, SH110X_WHITE);
display.fillTriangle(SCREEN_CENTER_X, SCREEN_CENTER_y, SCREEN_CENTER_X + 20, SCREEN_CENTER_y + 32, SCREEN_CENTER_X + 60, SCREEN_CENTER_y + 32, SH110X_BLACK);
// display.drawLine(SCREEN_CENTER_X + 6, SCREEN_CENTER_y + 11, SCREEN_CENTER_X + 15, SCREEN_CENTER_y + 28, SH110X_WHITE);
// display.drawLine(SCREEN_CENTER_X + 14, SCREEN_CENTER_y + 5, SCREEN_CENTER_X + 31, SCREEN_CENTER_y + 23, SH110X_WHITE);
display.display();
int x, y;
switch (quadrant)
{
case 1:
x = (SCREEN_WIDTH / 3);
y = -(SCREEN_HEIGHT / 4);
break;
case 2:
x = (SCREEN_WIDTH / 3);
y = (SCREEN_HEIGHT / 4);
break;
case 3:
x = -(SCREEN_WIDTH / 3);
y = (SCREEN_HEIGHT / 4);
break;
default:
x = -(SCREEN_WIDTH / 3);
y = -(SCREEN_HEIGHT / 4);
break;
}
Timer time = initTimer(durationMS);
int r = 2;
while (duration(time))
{
display.drawCircle(SCREEN_CENTER_X + x, SCREEN_CENTER_y + y, r, SH110X_WHITE);
display.display();
delay(25);
display.drawCircle(SCREEN_CENTER_X + x, SCREEN_CENTER_y + y, r, SH110X_BLACK);
r++;
if (r > 6)
{
r = 2;
}
delay(25);
}
r = 2;
time = initTimer(durationMS);
while (duration(time))
{
display.fillCircle(SCREEN_CENTER_X + x, SCREEN_CENTER_y + y, r, SH110X_WHITE);
display.display();
delay(125);
display.fillCircle(SCREEN_CENTER_X + x, SCREEN_CENTER_y + y, r, SH110X_BLACK);
display.display();
delay(125);
}
display.display();
}
void displayTarget(int durationMS)
{
resultPos pos, pos1;
display.clearDisplay();
pos1 = displayRectCentered(32, 42);
display.drawLine(pos1.lx, pos1.ly, pos1.rx, pos1.ly, SH110X_BLACK);
displayRoundRectCentered(SCREEN_WIDTH, SCREEN_HEIGHT);
pos = displayRectCentered(20, 30);
display.drawLine(40, 0, pos.lx, pos.ly, SH110X_WHITE);
display.drawLine(20, 0, pos.lx, pos.ly + 5, SH110X_WHITE);
display.drawLine(0, 15, pos.lx, pos.ly + 10, SH110X_WHITE);
display.drawLine(0, 49, pos.lx, pos.ly + 15, SH110X_WHITE);
display.drawLine(20, 64, pos.lx, pos.ly + 20, SH110X_WHITE);
display.drawLine(40, 64, pos.lx, pos.ly + 27, SH110X_WHITE);
display.drawLine(88, 0, pos.rx, pos.ly, SH110X_WHITE);
display.drawLine(108, 0, pos.rx, pos.ly + 5, SH110X_WHITE);
display.drawLine(128, 15, pos.rx, pos.ly + 10, SH110X_WHITE);
display.drawLine(128, 49, pos.rx, pos.ly + 15, SH110X_WHITE);
display.drawLine(108, 64, pos.rx, pos.ly + 20, SH110X_WHITE);
display.drawLine(88, 64, pos.rx, pos.ly + 27, SH110X_WHITE);
Timer time = initTimer(durationMS);
uint16_t color = SH110X_WHITE;
while (duration(time))
{
displayCircleCentered(6, color);
displayLineHorizontalCentered(pos.rx - pos.lx - 2, color);
displayLineVerticalCentered(pos.ry - pos.ly - 2, color);
display.display();
delay(200);
if (color == SH110X_WHITE)
{
color = SH110X_BLACK;
}
else
{
color = SH110X_WHITE;
}
}
}
resultPos displayRectCentered(int16_t w, int16_t h)
{
resultPos pos;
pos.lx = SCREEN_CENTER_X - (w / 2);
pos.ly = SCREEN_CENTER_y - (h / 2);
pos.rx = pos.lx + w;
pos.ry = pos.ly + h;
display.drawRect(SCREEN_CENTER_X - (w / 2), SCREEN_CENTER_y - (h / 2), w, h, SH110X_WHITE);
return pos;
}
void displayLineHorizontalCentered(int16_t length, uint16_t color)
{
display.drawLine(SCREEN_CENTER_X - (length / 2), SCREEN_CENTER_y, SCREEN_CENTER_X + (length / 2), SCREEN_CENTER_y, color);
}
void displayLineVerticalCentered(int16_t length, uint16_t color)
{
display.drawLine(SCREEN_CENTER_X, SCREEN_CENTER_y - (length / 2), SCREEN_CENTER_X, SCREEN_CENTER_y + (length / 2), color);
}
void displayCircleCentered(int16_t r, uint16_t color)
{
display.drawCircle(SCREEN_CENTER_X, SCREEN_CENTER_y, r, color);
}
void displayRoundRectCentered(int16_t w, int16_t h)
{
display.drawRoundRect(SCREEN_CENTER_X - (w / 2), SCREEN_CENTER_y - (h / 2), w, h, 10, SH110X_WHITE);
}
int getRandomMode()
{
//original
return random(nbrModes);
}
const char *getRandomSentences()
{
// Sentences
static const char *Sentences[] = {"Silence on all comms", "Empire is looking for a Denari",
"Scanning sector AB4", "Tie is needed ASAP",
"Rebels located in sector HG-7"};
int nbrOfSentences = sizeof(Sentences) / sizeof(Sentences[0]);
int rnd = random(nbrOfSentences);
return Sentences[rnd];
}
void scrollCurrentlyShowing(void)
{
for (int i = 0; i < aurebeshScreenLines - 1; i++)
{
strcpy(currentlyShowing[i], currentlyShowing[i + 1]);
}
strcpy(currentlyShowing[aurebeshScreenLines - 1], "");
}
bool isOutOfScreen(AurebeshScreenCoordinate coord)
{
if (coord.line > (aurebeshScreenLines - 1) || coord.column > (aurebeshScreenColumns - 1))
{
// line or columns out of range
Serial.println(F("Coord OFR: "));
Serial.print(F("l="));
Serial.print(coord.line);
Serial.print(F("C="));
Serial.println(coord.column);
return true;
}
return false;
}
PixelCoordinate aurebeshCoordinateToPixel(AurebeshScreenCoordinate coord)
{
int16_t x = coord.column * AUREBESH_WIDTH;
int16_t y = (coord.line + 1) * AUREBESH_HEIGHT;
return {x, y};
}
void displayAurebeshString(char *s)
{
for (int i = 0; i < strlen(s); i++)
{
displayAurebeshChar(s[i]);
delay(cursorSpeed);
}
}
void displayAurebeshChar(char c)
{
displayAurebeshCharAtCoordinate(c, currentCoordinate);
display.display();
currentlyShowing[currentCoordinate.line][currentCoordinate.column] = c;
currentlyShowing[currentCoordinate.line][currentCoordinate.column + 1] = 0;
currentCoordinate.column++;
if (currentCoordinate.column == aurebeshScreenColumns)
{
scrollCurrentlyShowing();
redrawCurrentlyShowing();
resetCoordinates();
}
}
void displayAurebeshCharAtCoordinate(char c, AurebeshScreenCoordinate coord)
{
if (!isOutOfScreen(coord))
{
PixelCoordinate pixCoord = aurebeshCoordinateToPixel(coord);
display.setCursor(pixCoord.x, pixCoord.y); // as per Adafruit convention custom fonts draw up from line so move cursor
display.print(c);
}
}
void initAurebeshScreen(void)
{
display.clearDisplay();
display.display();
display.setFont(&Aurebesh8pt7b);
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.setTextWrap(false);
resetAurebeshScreen();
}
void resetAurebeshScreen()
{
resetCurrentlyShowing();
resetCoordinates();
display.clearDisplay();
display.display();
}
void resetCoordinates(void)
{
currentCoordinate = {aurebeshScreenLines - 1, 0};
}
void resetCurrentlyShowing(void)
{
for (int i = 0; i < aurebeshScreenLines; i++)
{
currentlyShowing[i][0] = 0;
}
}
int getRandomLineNotEmptyCurrentlyShowing(void)
{
int lines[aurebeshScreenLines];
int nbrOfNotEmptyLines;
nbrOfNotEmptyLines = 0;
for (int i = 0; i < aurebeshScreenLines; i++)
{
if (currentlyShowing[i][0] != 0)
{
lines[nbrOfNotEmptyLines] = i;
nbrOfNotEmptyLines++;
}
}
return lines[random(aurebeshScreenLines)];
}
void redrawCurrentlyShowing(void)
{
display.clearDisplay();
for (int i = 0; i < aurebeshScreenLines - 1; i++)
{
for (int j = 0; j < aurebeshScreenColumns; j++)
{
if (currentlyShowing[i][j] == 0)
{
break;
}
displayAurebeshCharAtCoordinate(currentlyShowing[i][j], {i, j});
}
display.display();
}
}
void displayNoisePixelated(int density, bool accumulate, int durationMS)
{
int rnd_x;
int rnd_y;
Timer time = initTimer(durationMS);
while (duration(time))
{
for (int i = 0; i < density; i++)
{
rnd_x = random(display.width());
rnd_y = random(display.height());
display.drawPixel(rnd_x, rnd_y, SH110X_WHITE);
}
display.display();
delay(1);
if (!accumulate)
{
display.clearDisplay();
}
}
display.display();
}
Timer initTimer(unsigned long durationMS)
{
return {millis(), durationMS};
}
boolean duration(Timer time)
{
return millis() - time.time_start < time.durationMs;
}
void invertLine(int lineNumber, int speedMS, int durationMS)
{
Timer time = initTimer(durationMS);
while (duration(time))
{
invertLineNumber(lineNumber);
display.display();
delay(speedMS);
invertLineNumber(lineNumber);
display.display();
delay(speedMS);
}
}
void invertLineNumber(int lineNumber)
{
AurebeshScreenCoordinate coord = {lineNumber, 0};
if (!isOutOfScreen(coord))
{
PixelCoordinate pixCoord;
pixCoord = aurebeshCoordinateToPixel(coord);
invertPixels(pixCoord.x, pixCoord.y - AUREBESH_HEIGHT + 3, SCREEN_WIDTH + AUREBESH_WIDTH, AUREBESH_HEIGHT);
}
}
void invertPixels(int16_t x, int16_t y, int16_t w, int16_t h)
{
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
if (display.getPixel(x + i, y + j))
{
display.drawPixel(x + i, y + j, SH110X_BLACK);
}
else
{
display.drawPixel(x + i, y + j, SH110X_WHITE);
}
}
}
}
void displayCursor(AurebeshScreenCoordinate coord, int durationMS, int speedMS)
{
if (!isOutOfScreen(coord))
{
Timer time = initTimer(durationMS);
PixelCoordinate pixCoord = aurebeshCoordinateToPixel(coord);
while (duration(time))
{
display.fillRect(pixCoord.x, pixCoord.y - AUREBESH_HEIGHT + 5, AUREBESH_WIDTH - 4, AUREBESH_HEIGHT - 4, SH110X_WHITE);
display.display();
delay(speedMS);
display.fillRect(pixCoord.x, pixCoord.y - AUREBESH_HEIGHT + 5, AUREBESH_WIDTH - 4, AUREBESH_HEIGHT - 4, SH110X_BLACK);
display.display();
delay(speedMS);
}
}
}