Rev 186 | Blame | Compare with Previous | Last modification | View Log | RSS feed
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace nitdcscore {
public class Oled {
public const int LCD_WIDTH = 128;
public const int LCD_HEIGHT = 64;
public const int EXTERNALVCC = 0x01;
public const int SWITCHCAPVCC = 0x02;
public const int SETLOWCOLUMN = 0x00;
public const int SETHIGHCOLUMN = 0x10;
public const int MEMORYMODE = 0x20;
public const int COLUMNADDR = 0x21;
public const int PAGEADDR = 0x22;
public const int DEACTIVATESCROLL = 0x2E;
public const int SETSTARTLINE = 0x40;
public const int SETCONTRAST = 0x81;
public const int CHARGEPUMP = 0x8D;
public const int SEGREMAP = 0xA0;
public const int DISPLAYALLON_RESUME = 0xA4;
public const int DISPLAYALLON = 0xA5;
public const int NORMALDISPLAY = 0xA6;
public const int INVERTDISPLAY = 0xA7;
public const int SETMULTIPLEX = 0xA8;
public const int DISPLAYOFF = 0xAE;
public const int DISPLAYON = 0xAF;
public const int COMSCANINC = 0xC0;
public const int COMSCANDEC = 0xC8;
public const int SETDISPLAYOFFSET = 0xD3;
public const int SETCOMPINS = 0xDA;
public const int SETVCOMDETECT = 0xDB;
public const int SETDISPLAYCLOCKDIV = 0xD5;
public const int SETPRECHARGE = 0xD9;
public byte[] buffer = new byte[Oled.LCD_WIDTH / 8 * Oled.LCD_HEIGHT];
public int vccstate { get; set; }
public byte i2caddr { get; set; }
public i2cmaster i2c { get; set; }
public Oled(int vccstate, byte i2caddr, i2cmaster i2c) {
this.vccstate = vccstate;
this.i2caddr = i2caddr;
this.i2c = i2c;
for (int t = 0; t < (LCD_WIDTH * LCD_HEIGHT / 8); t++) {
buffer[t] = new byte();
buffer[t] = 0x00;
}
}
public void init() {
// Init sequence
oled_command(DISPLAYOFF);
oled_command(SETDISPLAYCLOCKDIV);
oled_command(0x80); // Suggested ratio
oled_command(SETMULTIPLEX);
oled_command(LCD_HEIGHT - 1);
oled_command(SETDISPLAYOFFSET);
oled_command(0x00); // No offset
oled_command(SETSTARTLINE | 0x00); // Start line 0
oled_command(CHARGEPUMP);
if (this.vccstate == EXTERNALVCC)
oled_command(0x10);
else
oled_command(0x14);
oled_command(MEMORYMODE);
oled_command(0x00);
oled_command(SEGREMAP | 0x01);
oled_command(COMSCANDEC);
// 128-64 specific
oled_command(SETCOMPINS);
oled_command(0x12);
oled_command(SETCONTRAST);
if (this.vccstate == EXTERNALVCC)
oled_command(0x9F);
else
oled_command(0xCF);
oled_command(SETPRECHARGE);
if (this.vccstate == EXTERNALVCC)
oled_command(0x22);
else
oled_command(0xF1);
oled_command(SETVCOMDETECT);
oled_command(0x40);
oled_command(DISPLAYALLON_RESUME);
oled_command(NORMALDISPLAY);
oled_command(DEACTIVATESCROLL);
oled_command(DISPLAYON);
}
public void display() {
oled_command(COLUMNADDR);
oled_command(0x00); // Column start address
oled_command(LCD_WIDTH - 1); // Column end address
oled_command(PAGEADDR);
oled_command(0x00); // Page start address
oled_command(7); // Page end address (7 for 64 pixels)
// 1024 - 388ms
// 16 - 1190ms
const int BYTES_TO_SEND = 1024;
for (int i = 0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++) {
byte[] data = new byte[BYTES_TO_SEND + 1];
data[0] = 0x40;
for (int j = 1; j < BYTES_TO_SEND + 1; j++) {
data[j] = buffer[i];
i++;
}
i--;
i2c.WriteI2cData(i2cUtils.addressToWrite(this.i2caddr), data, BYTES_TO_SEND + 1);
}
}
public int oled_command(byte c) {
byte[] data = { 0x00, c };
i2c.SetGpio(0, 1);
i2c.WriteI2cData(i2cUtils.addressToWrite(this.i2caddr), data, 2);
i2c.SetGpio(0, 0);
return 0;
}
}
public class BmpImage {
public string filename; // The image filename
public int filesize; // Total size of the
public int datastart; // Location of the start of image data
public int imagesize; // The size of actual image data
public int width; // Width of the image
public int height; // Height of the image
public int bpp; // Bits per pixel of the image
public int bytepad; // Bytes padded to align image row
public byte[] data; // The bmp image data
public BitArray[] bitdata; // Data in bitarray format
public BmpImage(string filename) {
this.filename = filename;
filesize = 0;
datastart = 0xffffff;
imagesize = 0;
width = 0;
height = 0;
bpp = 0;
bytepad = 0;
data = new byte[8192];
bitdata = new BitArray[1];
this.load();
}
public int load() {
using (BinaryReader b = new BinaryReader(File.Open(this.filename, FileMode.Open))) {
int pos = 0;
int readLen = (int)b.BaseStream.Length;
while (pos < readLen) {
// Read the image data from the file
if (pos >= this.datastart) {
// BMP format stored in 'data'
int imgptr = 0;
while (imgptr < this.imagesize) {
this.data[imgptr++] = b.ReadByte();
}
//Console.WriteLine("Read " + imgptr.ToString() + " bytes");
// Raw decoded data stored in 'bitdata'
this.bitdata = new BitArray[this.height];
int x = 0; // Cursor X position
int y = 0; // Cursor Y position
int i = 0; // Current byte position
//Console.WriteLine("W:{0} H:{1}", img.width.ToString(), img.height.ToString());
for (y = this.height - 1; y >= 0; y--) {
this.bitdata[y] = new BitArray(this.width);
x = 0;
while (x < this.width) {
if (x >= this.width)
break;
// Reverse the bit cause its stored back to front in bmp format
byte br;
br = this.data[i];
br = (byte)((br * 0x0202020202 & 0x010884422010) % 1023);
for (int bitidx = 0; bitidx < 8; bitidx++) {
int bitpos = x + bitidx;
if (bitpos >= this.width)
break;
int val = br >> bitidx & 0x01;
//Console.WriteLine("X:{0} Y:{1}", x.ToString(), y.ToString());
this.bitdata[y].Set(bitpos, Convert.ToBoolean(val));
}
x += 8;
i++;
}
i += this.bytepad; // Account for the padding
}
break;
}
// Read the header data from the file
switch (pos) {
// Magic number header ("BM")
case 0x00: {
byte t1 = b.ReadByte();
byte t2 = b.ReadByte();
pos += 2;
string text = ((char)t1).ToString();
text += ((char)t2).ToString();
}
break;
// The size of the image file
case 0x02: {
this.filesize = (int)b.ReadUInt32();
pos += 4;
if (this.filesize != b.BaseStream.Length)
Console.WriteLine("Size mismatch: " + this.filesize.ToString() + ":" + b.BaseStream.Length.ToString());
else
Console.WriteLine("Size: " + this.filesize.ToString());
}
break;
// The start of image data location
case 0x0a: {
this.datastart = (int)b.ReadUInt32();
pos += 4;
}
break;
// The DIB header file size
case 0x0e: {
//UInt32 dibhs = b.ReadUInt32();
b.ReadUInt32();
pos += 4;
}
break;
// Bitmap width in pixels
case 0x12: {
this.width = (int)b.ReadInt32();
pos += 4;
// Rows aligned to a DWORD
int bitsOver = this.width % 32;
if (bitsOver > 0) {
this.bytepad = (32 - bitsOver) / 8;
}
}
break;
// Bitmap height in pixels
case 0x16: {
this.height = (int)b.ReadInt32();
pos += 4;
}
break;
// Bitmap bytes per pixel
case 0x1c: {
this.bpp = (int)b.ReadUInt16();
pos += 2;
}
break;
// Bitmap size
case 0x22: {
this.imagesize = (int)b.ReadUInt32();
pos += 4;
}
break;
// Not an important piece of data; dump it
default:
b.ReadByte();
pos++;
break;
}
}
}
return 0;
}
}
public class BitImage {
public BitArray[] bitdata;
public int width;
public int height;
public BitImage(int width, int height) {
this.width = width;
this.height = height;
this.bitdata = new BitArray[this.height];
for (int i = 0; i < this.height; i++) {
this.bitdata[i] = new BitArray(this.width);
}
}
public BitImage(BitArray[] matrix) {
this.width = matrix[0].Length;
this.height = matrix.Length;
this.bitdata = BitImage.copy(matrix);
}
public BitImage(BmpImage bmp) {
this.width = bmp.width;
this.height = bmp.height;
this.bitdata = BitImage.copy(bmp.bitdata);
}
public BitImage(BitImage bit) {
this.width = bit.width;
this.height = bit.height;
this.bitdata = BitImage.copy(bit.bitdata);
}
public BitImage(Bitmap bmp) {
//Bitmap bmp = new Bitmap(nitdcscore.Properties.Resources.flap_bg);
//BitImage bi = new BitImage(new Bitmap(Resources.flap_needle));
this.width = bmp.Width;
this.height = bmp.Height;
this.bitdata = new BitArray[this.height];
for (int y = 0; y < this.height; y++) {
this.bitdata[y] = new BitArray(this.width);
for (int x = 0; x < this.width; x++) {
Color c = bmp.GetPixel(x, y);
if (c.GetBrightness() == 0)
this.bitdata[y].Set(x, false);
else
this.bitdata[y].Set(x, true);
}
}
}
public void fillAll(bool color) {
for (int i = 0; i < this.height; i++) {
this.bitdata[i].SetAll(color);
}
}
public void drawPixel(int x, int y, bool color) {
if (x < 0 || y < 0 || x >= this.width || y >= this.height)
return;
this.bitdata[y].Set(x, color);
}
public void drawVLine(int x, int y, int h, bool color) {
if (x < 0 || x >= this.width)
return;
if (y < 0) {
h += y;
y = 0;
}
if ((y + h) > this.height)
h = this.height - y;
if (h <= 0)
return;
for (int i = y; i < y + h; i++) {
this.bitdata[i].Set(x, color);
}
}
public void drawHLine(int x, int y, int w, bool color) {
if (y < 0 || y >= this.height)
return;
if (x < 0) {
w += x;
x = 0;
}
if ((x + w) > this.width)
w = this.width - x;
if (w <= 0)
return;
for (int i = x; i < x + height; i++) {
this.bitdata[y].Set(i, color);
}
}
public void drawLine(int x0, int y0, int x1, int y1, bool color) {
bool steep = Math.Abs(y1 - y0) > Math.Abs(x1 - x0);
if (steep) {
swap(ref x0, ref y0);
swap(ref x1, ref y1);
}
if (x0 > x1) {
swap(ref x0, ref x1);
swap(ref y0, ref y1);
}
int dx, dy;
dx = x1 - x0;
dy = Math.Abs(y1 - y0);
int err = dx / 2;
int ystep;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (; x0 <= x1; x0++) {
if (steep)
drawPixel(y0, x0, color);
else
drawPixel(x0, y0, color);
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
public void drawRect(int x, int y, int w, int h, bool color) {
drawHLine(x, y, w, color);
drawHLine(x, y + h - 1, w, color);
drawVLine(x, y, h, color);
drawVLine(x + w - 1, y, h, color);
}
public void fillRect(int x, int y, int w, int h, bool color) {
for (int i = x; i < x + w; i++) {
drawVLine(i, y, h, color);
}
}
public void drawCircle(int x0, int y0, int r, bool color) {
int f = 1 - r;
int ddF_x = 1;
int ddF_y = -2 * r;
int x = 0;
int y = r;
drawPixel(x0, y0 + r, color);
drawPixel(x0, y0 - r, color);
drawPixel(x0 + r, y0, color);
drawPixel(x0 - r, y0, color);
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
drawPixel(x0 + x, y0 + y, color);
drawPixel(x0 - x, y0 + y, color);
drawPixel(x0 + x, y0 - y, color);
drawPixel(x0 - x, y0 - y, color);
drawPixel(x0 + y, y0 + x, color);
drawPixel(x0 - y, y0 + x, color);
drawPixel(x0 + y, y0 - x, color);
drawPixel(x0 - y, y0 - x, color);
}
}
public void fillCircle(int x0, int y0, int r, bool color) {
drawVLine(x0, y0 - r, 2 * r + 1, color);
fillCircleHelper(x0, y0, r, 3, 0, color);
}
public void fillCircleHelper(int x0, int y0, int r, int corner, int delta, bool color) {
int f = 1 - r;
int ddF_x = 1;
int ddF_y = -2 * r;
int x = 0;
int y = r;
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if ((corner & 0x01) > 0) {
drawVLine(x0 + x, y0 - y, 2 * y + 1 + delta, color);
drawVLine(x0 + y, y0 - x, 2 * x + 1 + delta, color);
}
if ((corner & 0x02) > 0) {
drawVLine(x0 - x, y0 - y, 2 * y + 1 + delta, color);
drawVLine(x0 - y, y0 - x, 2 * x + 1 + delta, color);
}
}
}
public void drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2, bool color) {
drawLine(x0, y0, x1, y1, color);
drawLine(x1, y1, x2, y2, color);
drawLine(x2, y2, x0, y0, color);
}
public void drawPoly(Point[] points, bool color) {
int idx = 1;
int c = points.Length;
while (idx < c) {
drawLine(points[idx - 1].X, points[idx - 1].Y, points[idx].X, points[idx].Y, color);
idx++;
}
drawLine(points[c - 1].X, points[c - 1].Y, points[0].X, points[0].Y, color);
}
public void drawChar(int x, int y, byte c, bool color, int size) {
for (int i = 0; i < 6; i++) {
byte line;
if (i < 5)
line = Font.classic[c * 5 + i];
else
line = 0x00;
for (int j = 0; j < 8; j++, line >>= 1) {
if ((line & 0x01) > 0) {
if (size == 1)
drawPixel(x + i, y + j, color);
else
fillRect(x + (i * size), y + (j * size), size, size, color);
}
/*
} else {
if (size == 1)
drawPixel(x + i, y + j, !color);
else
fillRect(x+i*size, y+j*size, size, size, !color);
}
*/
}
}
}
public void write(string text, int x, int y, bool color, int size) {
Point cur = new Point(x, y);
foreach (byte c in text) {
if (c == '\n') {
cur.Y += size * 8;
cur.X = x;
} else if (c == '\r') {
} else if (c == ' ') {
// Quicker then calling drawChar function
cur.X += size * 6;
} else {
drawChar(cur.X, cur.Y, c, color, size);
cur.X += size * 6;
}
}
}
public static void swap(ref int i, ref int j) {
int t = i; i = j; j = t;
}
/// <summary>
/// Copies the provided image onto the objects image, at position specified
/// by the ox and oy parms. Only copies lit bits (not dark)
/// </summary>
/// <param name="bit">The bit image to paste onto this image</param>
/// <param name="ox">The X origin</param>
/// <param name="oy">The Y origin</param>
public void blit(BitImage bit, int ox, int oy) {
int x = 0;
int y = 0;
for (y = 0; y < bit.height; y++) {
for (x = 0; x < bit.width; x++) {
if (bit.bitdata[y].Get(x)) {
if (oy + y > this.height -1 || ox + x > this.width)
return;
this.bitdata[oy + y].Set(ox + x, true);
}
}
}
}
/// <summary>
/// Rotate the image by the specified degrees.
/// </summary>
/// <param name="degrees">Degrees to rotate</param>
public void rotate(int degrees) {
this.bitdata = (BitArray[])BitImage.rotateMatrix(this.bitdata, degrees).bitdata;
this.width = this.bitdata[0].Length;
this.height = this.bitdata.Length;
}
public byte[] toByteArray() {
return BitImage.toByteArray(this.bitdata);
}
public static BitArray[] copy(BitArray[] ba) {
int width = ba[0].Length;
int height = ba.Length;
BitArray[] newba = new BitArray[height];
for (int y = 0; y < height; y++) {
newba[y] = new BitArray(width);
for (int x = 0; x < width; x++) {
if (ba[y].Get(x)) {
newba[y].Set(x, true);
}
}
}
return newba;
}
public static byte[] toByteArray(BitArray[] ba) {
int width = ba[0].Length;
int height = ba.Length;
int size = width * height / 8;
byte[] buffer = new byte[size];
if (size % 8 != 0) {
Console.WriteLine("toByteArray only supports mod 8 array (size: {0}, misalinged by {1})", size, size % 8);
return null;
}
BitArray data = new BitArray(width * height);
int i = 0;
for (int y = 0; y < ba.Length; y += 8) {
for (int x = 0; x < width; x++) {
for (int j = 0; j < 8; j++) {
data.Set(i, ba[y+j].Get(x));
i++;
}
}
}
data.CopyTo(buffer, 0);
return buffer;
}
/// <summary>
/// Rotates a matrix by provided degrees. Note that the size of the
/// image may change with this process
/// </summary>
/// <returns>A matrix with the rotated elements</returns>
/// <param name="matrix">The BitArray matrix to be rotated</param>
/// <param name="degrees">The degress to rotate the matrix by</param>
public static BitImage rotateMatrix(BitArray[] matrix, int degrees) {
// Widths of the matrix
int oldwidth = matrix[0].Length;
int oldheight = matrix.Length;
// If no rotation nessecary, just return a new BitImage
if (degrees == 0 || degrees == 360) {
BitImage bit = new BitImage(oldwidth, oldheight);
bit.bitdata = (BitArray[])matrix;
return bit;
}
// Calc the new image meta data
double rads = degrees * Math.PI / 180;
double tcos = Math.Cos(rads);
double tsin = Math.Sin(rads);
Point p1 = new Point((int)(-oldheight * tsin), (int)(oldheight * tcos));
Point p2 = new Point((int)(oldwidth * tcos - oldheight * tsin),
(int)(oldheight * tcos + oldwidth * tsin));
Point p3 = new Point((int)(oldwidth * tcos), (int)(oldwidth * tsin));
Point min = new Point(Math.Min(0, Math.Min(p1.X, Math.Min(p2.X, p3.X))),
Math.Min(0, Math.Min(p1.Y, Math.Min(p2.Y, p3.Y))));
Point max = new Point(Math.Max(p1.X, Math.Max(p2.X, p3.X)),
Math.Max(p1.Y, Math.Max(p2.Y, p3.Y)));
Point size = new Point(max.X - min.X, max.Y - min.Y);
// Prepopulate the bitarray
BitArray[] bitmatrix = new BitArray[size.Y];
for (int y = 0; y < size.Y; y++) {
bitmatrix[y] = new BitArray(size.X);
}
// Transform pixel by pixel
for (int y = 0; y < size.Y - 1; y++) {
for (int x = 0; x < size.X - 1; x++) {
int sourcex = (int)((x + min.X) * tcos + (y + min.Y) * tsin);
int sourcey = (int)((y + min.Y) * tcos - (x + min.X) * tsin);
if (sourcex < 0 || sourcex > oldwidth - 1 || sourcey < 0 || sourcey > oldheight - 1)
continue;
if (x < 0 || x > size.X - 1 || y < 0 || y > size.Y - 1)
continue;
bitmatrix[y].Set(x, matrix[sourcey].Get(sourcex));
}
}
BitImage bi = new BitImage(bitmatrix[0].Length, bitmatrix.Length);
bi.bitdata = (BitArray[])bitmatrix;
return bi;
}
}
public struct Point {
private int x;
private int y;
public int X {
get {
return this.x;
}
set {
this.x = value;
}
}
public int Y {
get {
return this.y;
}
set {
this.y = value;
}
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Font {
public Font() {
}
public static byte[] classic = new byte[] {
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
0x18, 0x3C, 0x7E, 0x3C, 0x18,
0x1C, 0x57, 0x7D, 0x57, 0x1C,
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
0x00, 0x18, 0x3C, 0x18, 0x00,
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
0x00, 0x18, 0x24, 0x18, 0x00,
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
0x30, 0x48, 0x3A, 0x06, 0x0E,
0x26, 0x29, 0x79, 0x29, 0x26,
0x40, 0x7F, 0x05, 0x05, 0x07,
0x40, 0x7F, 0x05, 0x25, 0x3F,
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
0x14, 0x22, 0x7F, 0x22, 0x14,
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
0x06, 0x09, 0x7F, 0x01, 0x7F,
0x00, 0x66, 0x89, 0x95, 0x6A,
0x60, 0x60, 0x60, 0x60, 0x60,
0x94, 0xA2, 0xFF, 0xA2, 0x94,
0x08, 0x04, 0x7E, 0x04, 0x08,
0x10, 0x20, 0x7E, 0x20, 0x10,
0x08, 0x08, 0x2A, 0x1C, 0x08,
0x08, 0x1C, 0x2A, 0x08, 0x08,
0x1E, 0x10, 0x10, 0x10, 0x10,
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
0x30, 0x38, 0x3E, 0x38, 0x30,
0x06, 0x0E, 0x3E, 0x0E, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x51, 0x49, 0x45, 0x3E,
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C,
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F,
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32,
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78,
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C,
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44,
0x00, 0x08, 0x36, 0x41, 0x00,
0x00, 0x00, 0x77, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00,
0x02, 0x01, 0x02, 0x04, 0x02,
0x3C, 0x26, 0x23, 0x26, 0x3C,
0x1E, 0xA1, 0xA1, 0x61, 0x12,
0x3A, 0x40, 0x40, 0x20, 0x7A,
0x38, 0x54, 0x54, 0x55, 0x59,
0x21, 0x55, 0x55, 0x79, 0x41,
0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
0x21, 0x55, 0x54, 0x78, 0x40,
0x20, 0x54, 0x55, 0x79, 0x40,
0x0C, 0x1E, 0x52, 0x72, 0x12,
0x39, 0x55, 0x55, 0x55, 0x59,
0x39, 0x54, 0x54, 0x54, 0x59,
0x39, 0x55, 0x54, 0x54, 0x58,
0x00, 0x00, 0x45, 0x7C, 0x41,
0x00, 0x02, 0x45, 0x7D, 0x42,
0x00, 0x01, 0x45, 0x7C, 0x40,
0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
0xF0, 0x28, 0x25, 0x28, 0xF0,
0x7C, 0x54, 0x55, 0x45, 0x00,
0x20, 0x54, 0x54, 0x7C, 0x54,
0x7C, 0x0A, 0x09, 0x7F, 0x49,
0x32, 0x49, 0x49, 0x49, 0x32,
0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
0x32, 0x4A, 0x48, 0x48, 0x30,
0x3A, 0x41, 0x41, 0x21, 0x7A,
0x3A, 0x42, 0x40, 0x20, 0x78,
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
0x3D, 0x40, 0x40, 0x40, 0x3D,
0x3C, 0x24, 0xFF, 0x24, 0x24,
0x48, 0x7E, 0x49, 0x43, 0x66,
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
0xFF, 0x09, 0x29, 0xF6, 0x20,
0xC0, 0x88, 0x7E, 0x09, 0x03,
0x20, 0x54, 0x54, 0x79, 0x41,
0x00, 0x00, 0x44, 0x7D, 0x41,
0x30, 0x48, 0x48, 0x4A, 0x32,
0x38, 0x40, 0x40, 0x22, 0x7A,
0x00, 0x7A, 0x0A, 0x0A, 0x72,
0x7D, 0x0D, 0x19, 0x31, 0x7D,
0x26, 0x29, 0x29, 0x2F, 0x28,
0x26, 0x29, 0x29, 0x29, 0x26,
0x30, 0x48, 0x4D, 0x40, 0x20,
0x38, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x38,
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
0x2F, 0x10, 0x28, 0x34, 0xFA,
0x00, 0x00, 0x7B, 0x00, 0x00,
0x08, 0x14, 0x2A, 0x14, 0x22,
0x22, 0x14, 0x2A, 0x14, 0x08,
0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
0x00, 0x00, 0x00, 0xFF, 0x00,
0x10, 0x10, 0x10, 0xFF, 0x00,
0x14, 0x14, 0x14, 0xFF, 0x00,
0x10, 0x10, 0xFF, 0x00, 0xFF,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x14, 0x14, 0x14, 0xFC, 0x00,
0x14, 0x14, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x14, 0x14, 0xF4, 0x04, 0xFC,
0x14, 0x14, 0x17, 0x10, 0x1F,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0x1F, 0x00,
0x10, 0x10, 0x10, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x10,
0x10, 0x10, 0x10, 0x1F, 0x10,
0x10, 0x10, 0x10, 0xF0, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0xFF, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x14,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x1F, 0x10, 0x17,
0x00, 0x00, 0xFC, 0x04, 0xF4,
0x14, 0x14, 0x17, 0x10, 0x17,
0x14, 0x14, 0xF4, 0x04, 0xF4,
0x00, 0x00, 0xFF, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0xF7, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x17, 0x14,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0xF4, 0x14,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x00, 0x00, 0x1F, 0x10, 0x1F,
0x00, 0x00, 0x00, 0x1F, 0x14,
0x00, 0x00, 0x00, 0xFC, 0x14,
0x00, 0x00, 0xF0, 0x10, 0xF0,
0x10, 0x10, 0xFF, 0x10, 0xFF,
0x14, 0x14, 0x14, 0xFF, 0x14,
0x10, 0x10, 0x10, 0x1F, 0x00,
0x00, 0x00, 0x00, 0xF0, 0x10,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x38, 0x44, 0x44, 0x38, 0x44,
0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
0x7E, 0x02, 0x02, 0x06, 0x06,
0x02, 0x7E, 0x02, 0x7E, 0x02,
0x63, 0x55, 0x49, 0x41, 0x63,
0x38, 0x44, 0x44, 0x3C, 0x04,
0x40, 0x7E, 0x20, 0x1E, 0x20,
0x06, 0x02, 0x7E, 0x02, 0x02,
0x99, 0xA5, 0xE7, 0xA5, 0x99,
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
0x4C, 0x72, 0x01, 0x72, 0x4C,
0x30, 0x4A, 0x4D, 0x4D, 0x30,
0x30, 0x48, 0x78, 0x48, 0x30,
0xBC, 0x62, 0x5A, 0x46, 0x3D,
0x3E, 0x49, 0x49, 0x49, 0x00,
0x7E, 0x01, 0x01, 0x01, 0x7E,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x44, 0x44, 0x5F, 0x44, 0x44,
0x40, 0x51, 0x4A, 0x44, 0x40,
0x40, 0x44, 0x4A, 0x51, 0x40,
0x00, 0x00, 0xFF, 0x01, 0x03,
0xE0, 0x80, 0xFF, 0x00, 0x00,
0x08, 0x08, 0x6B, 0x6B, 0x08,
0x36, 0x12, 0x36, 0x24, 0x36,
0x06, 0x0F, 0x09, 0x0F, 0x06,
0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x10, 0x10, 0x00,
0x30, 0x40, 0xFF, 0x01, 0x01,
0x00, 0x1F, 0x01, 0x01, 0x1E,
0x00, 0x19, 0x1D, 0x17, 0x12,
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
};
}
}