/*********************************************************************
|original code The Last Outpost Workshop code to display Aurebesh (video here The Last Outpost Workshop )
|
|Edited for Scopenator 2000 by Mordred 06-08-2024
|Random slection code by Darwinwaswrong in Wokwi discord.
i2c SH1106 modified by Rupert Hirst 12/09/21
*********************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
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
/* 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);
// 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];
//noise,
// Screen Modes
enum Modes
{
listing,
listingAlert,
target,
target2,
target3,
sector,
sector2,
aurebeshComplex
};
const int nbrModes = 8;
void setup()
{
Serial.begin(9600);
Serial.println("go");
//for (int dogs_feet=0 ; dogs_feet <nbrModes;dogs_feet++ )
// {
// pinMode(dogs_feet, INPUT_PULLUP);
// }
delay(250); // wait for the OLED to power up
if (!display.begin(i2c_Address, true))
{
Serial.println(F("Oled Failed"));
while (true)
{
/* code */
}
}
initAurebeshScreen();
display.display();
}
void loop()
{
displayRandomScreenMode();
displayCursor(currentCoordinate, random(500, 200), 200);
}
void displayRandomScreenMode()
{
int mode = getRandomMode();
resetAurebeshScreen();
switch (mode)
{
// case noise:
// displayNoisePixelated(random(10, 300), false, random(10, 2000));
// break;
case listing:
displayAurebeshString((char *)getRandomSentences());
//transitionVertical();
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case listingAlert:
resetAurebeshScreen();
displayAurebeshString((char *)getRandomSentences());
invertLine(getRandomLineNotEmptyCurrentlyShowing(), 50, 5000);
//transitionVertical();
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
/*
case sector:
displaySector(random(5000, 20000), random(4));
//transitionVertical();
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case sector2:
displaySector(random(5000, 20000), random(8));
//transitionVertical();
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case target:
resetAurebeshScreen();
displayTarget(random(3000, 10000));
//transitionVertical();
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case target2:
resetAurebeshScreen();
displayTarget(random(3000, 8000));
//transitionVertical();
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case target3:
resetAurebeshScreen();
displayTarget(random(5000, 10000));
//transitionVertical();
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
case aurebeshComplex:
resetAurebeshScreen();
complexAurebesh(random(5000, 10000), 25);
//transitionVertical();
displayNoisePixelated(random(10, 300), false, random(10, 500));
break;
*/
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);
}
// Read the Switch array and select a random from the enabled;
//Thanks @darwinwaswrong in Wokwi forum
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);
}
}
}