/* * Ten Wong (wangtengoo7@gmail.com) 2017 Seeed technology inc. * Refer to: https://github.com/Seeed-Studio/OLED_Display_128X64 * MIT License */ using System; using Windows.Devices.I2c; namespace GrovePi.I2CDevices { public interface IOLEDDisplay128X64 { void init(); void setNormalDisplay(); void setInverseDisplay(); void sendCommand(byte command); void sendData(byte data); void setPageMode(); void setHorizontalMode(); void setTextXY(byte row, byte column); void clearDisplay(); void setBrightness(byte brightness); void putChar(char c); void putString(string str); int putNumber(long n); int putFloat(float floatNumber, byte deci); int putFloat(float floatNumber); void drawBitmap(byte[] bitmaparray, int bytes); void setHorizontalScrollProperties(byte direction, byte startPage, byte endPage, byte scrollSpeed); void activateScroll(); void deactivateScroll(); } internal sealed class OLEDDisplay128X64: IOLEDDisplay128X64 { private const byte SeeedOLED_Max_X = 127; //128 Pixels private const byte SeeedOLED_Max_Y = 63; //64 Pixels private const byte PAGE_MODE = 01; private const byte HORIZONTAL_MODE = 02; private const byte SeeedOLED_Address = 0x3c; private const byte SeeedOLED_Command_Mode = 0x80; private const byte SeeedOLED_Data_Mode = 0x40; private const byte SeeedOLED_Display_Off_Cmd = 0xAE; private const byte SeeedOLED_Display_On_Cmd = 0xAF; private const byte SeeedOLED_Normal_Display_Cmd = 0xA6; private const byte SeeedOLED_Inverse_Display_Cmd = 0xA7; private const byte SeeedOLED_Activate_Scroll_Cmd = 0x2F; private const byte SeeedOLED_Dectivate_Scroll_Cmd = 0x2E; private const byte SeeedOLED_Set_Brightness_Cmd = 0x81; private const byte Scroll_Left = 0x00; private const byte Scroll_Right = 0x01; private const byte Scroll_2Frames = 0x7; private const byte Scroll_3Frames = 0x4; private const byte Scroll_4Frames = 0x5; private const byte Scroll_5Frames = 0x0; private const byte Scroll_25Frames = 0x6; private const byte Scroll_64Frames = 0x1; private const byte Scroll_128Frames = 0x2; private const byte Scroll_256Frames = 0x3; // This font be freely used without any restriction(It is placed in public domain) private byte[,] BasicFont = new byte[,] { {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, {0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00}, {0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00}, {0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00}, {0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00}, {0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00}, {0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00}, {0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00}, {0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00}, {0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00}, {0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00}, {0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00}, {0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00}, {0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00}, {0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00}, {0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00}, {0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00}, {0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00}, {0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00}, {0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00}, {0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00}, {0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00}, {0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00}, {0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00}, {0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00}, {0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00}, {0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00}, {0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00}, {0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00}, {0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00}, {0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00}, {0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00}, {0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00}, {0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00}, {0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00}, {0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00}, {0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00}, {0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00}, {0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00}, {0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00}, {0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00}, {0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00}, {0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00}, {0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00}, {0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00}, {0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00}, {0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00}, {0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00}, {0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00}, {0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00}, {0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00}, {0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00}, {0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00}, {0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00}, {0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00}, {0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00}, {0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00}, {0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00}, {0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00}, {0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00}, {0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00}, {0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00}, {0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00}, {0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00}, {0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00}, {0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00}, {0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00}, {0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00}, {0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00}, {0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00}, {0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00}, {0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00}, {0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00}, {0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00}, {0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00}, {0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00}, {0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00}, {0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00}, {0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00}, {0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00}, {0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00}, {0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00}, {0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00}, {0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00}, {0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00}, {0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00}, {0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00}, {0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00}, {0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00}, {0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00}, {0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00}, {0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00}, {0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00}, {0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00}, {0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00}, {0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00} }; internal I2cDevice DirectAccess { get; } internal byte addressingMode; internal OLEDDisplay128X64(I2cDevice Device) { if (Device == null) throw new ArgumentNullException(nameof(Device)); DirectAccess = Device; } public void init() { sendCommand(SeeedOLED_Display_Off_Cmd); //display off //delay(5); sendCommand(SeeedOLED_Display_On_Cmd); //display on //delay(5); sendCommand(SeeedOLED_Normal_Display_Cmd); //Set Normal Display (default) } public void setNormalDisplay() { sendCommand(SeeedOLED_Normal_Display_Cmd); } public void setInverseDisplay() { sendCommand(SeeedOLED_Inverse_Display_Cmd); } public void sendCommand(byte command) { DirectAccess.Write(new byte[] { SeeedOLED_Command_Mode, command }); } public void sendData(byte data) { DirectAccess.Write(new byte[] { SeeedOLED_Data_Mode, data }); } public void setPageMode() { addressingMode = PAGE_MODE; sendCommand(0x20); //set addressing mode sendCommand(0x02); //set page addressing mode } public void setHorizontalMode() { addressingMode = HORIZONTAL_MODE; sendCommand(0x20); //set addressing mode sendCommand(0x00); //set horizontal addressing mode } public void setTextXY(byte row, byte column) { sendCommand((byte)(0xB0 + row)); //set page address sendCommand((byte)(0x00 + (8 * column & 0x0F))); //set column lower address sendCommand((byte)(0x10 + ((8 * column >> 4) & 0x0F))); //set column higher address } public void clearDisplay() { byte i, j; sendCommand(SeeedOLED_Display_Off_Cmd); //display off for (j = 0; j < 8; j++) { setTextXY(j, 0); { for (i = 0; i < 16; i++) //clear all columns { putChar(' '); } } } sendCommand(SeeedOLED_Display_On_Cmd); //display on setTextXY(0, 0); } public void setBrightness(byte brightness) { sendCommand(SeeedOLED_Set_Brightness_Cmd); sendCommand(brightness); } public void putChar(char c) { if (c < 32 || c > 127) //Ignore non-printable ASCII characters. This can be modified for multilingual font. { c = ' '; //Space } byte i = 0; for (i = 0; i < 8; i++) { //read bytes from code memory sendData(BasicFont[c-32, i]); //font array starts at 0, ASCII starts at 32. Hence the translation } } public void putString(string str) { foreach (var c in str) { putChar(c); } } public int putNumber(long long_num) { char[] char_buffer = new char[10]; int i = 0; int f = 0; if (long_num < 0) { f = 1; putChar('-'); long_num = -long_num; } else if (long_num == 0) { f = 1; putChar('0'); return f; } while (long_num > 0) { char_buffer[i++] = (char)(long_num % 10); long_num /= 10; } f = f + i; for (; i > 0; i--) { putChar((char)('0' + (int)(char_buffer[i - 1]))); } return f; } public int putFloat(float floatNumber, byte deci) { int temp = 0; float decy = 0.0F; float rounding = 0.5F; int f = 0; if (floatNumber < 0.0F) { putString("-"); floatNumber = -floatNumber; f += 1; } for (int i = 0; i < deci; ++i) { rounding /= 10.0F; } floatNumber += rounding; temp = (int)floatNumber; f += putNumber(temp); if (deci > 0) { putChar('.'); f += 1; } decy = floatNumber - temp;//decimal part, for (int i = 0; i < deci; i++)//4 { decy *= 10;// for the next decimal temp = (int)decy;//get the decimal putNumber(temp); decy -= temp; } f += deci; return f; } public int putFloat(float floatNumber) { int deci= 2; int temp = 0; float decy = 0.0F; float rounding = 0.5F; int f = 0; if (floatNumber < 0.0) { putString("-"); floatNumber = -floatNumber; f += 1; } for (int i = 0; i < deci; ++i) { rounding /= 10.0F; } floatNumber += rounding; temp = (int)floatNumber; f += putNumber(temp); if (deci > 0) { putChar('.'); f += 1; } decy = floatNumber - temp;//decimal part, for (int i = 0; i < deci; i++)//4 { decy *= 10;// for the next decimal temp = (int)decy;//get the decimal putNumber(temp); decy -= temp; } f += deci; return f; } public void drawBitmap(byte[] bitmaparray, int bytes) { byte localAddressMode = addressingMode; if (addressingMode != HORIZONTAL_MODE) { //Bitmap is drawn in horizontal mode setHorizontalMode(); } for (int i = 0; i < bytes; i++) { sendData(bitmaparray[i]); } if (localAddressMode == PAGE_MODE) { //If pageMode was used earlier, restore it. setPageMode(); } } public void setHorizontalScrollProperties(byte direction, byte startPage, byte endPage, byte scrollSpeed) { if (Scroll_Right == direction) { //Scroll Right sendCommand(0x26); } else { //Scroll Left sendCommand(0x27); } sendCommand(0x00); sendCommand(startPage); sendCommand(scrollSpeed); sendCommand(endPage); sendCommand(0x00); sendCommand(0xFF); } public void activateScroll() { sendCommand(SeeedOLED_Activate_Scroll_Cmd); } public void deactivateScroll() { sendCommand(SeeedOLED_Dectivate_Scroll_Cmd); } } }