grovepi/Software/CSharp/GrovePi/I2CDevices/OLEDDisplay128X64.cs
2025-03-21 16:04:17 +01:00

440 lines
15 KiB
C#

/*
* 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);
}
}
}