Marcel Visser
/
DisplayBRW
brw1
Revision 0:a115ff47d1c1, committed 2015-11-30
- Comitter:
- reiniermarcel
- Date:
- Mon Nov 30 11:13:18 2015 +0000
- Commit message:
- ok
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/Arial12x12.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,111 @@ +#ifndef ARIAL12X12_H +#define ARIAL12X12_H + +//GLCD FontName : Arial12x12 +//GLCD FontSize : 12 x 12 + +/** Arial Font with 12*12 matrix to use with SPI_TFT lib */ +//__align(2) + +const unsigned char Arial12x12[] = { + 25,12,12,2, // Bytes/char, horz, vert, byte/vert + //width, pixel stream .... + 0x07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char + 0x02, 0X00, 0X00, 0x7F, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ! + 0x03, 0x07, 0X00, 0X00, 0X00, 0x07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char " + 0x07, 0x24, 0X00, 0xA4, 0x01, 0x7C, 0X00, 0xA7, 0x01, 0x7C, 0X00, 0x27, 0X00, 0x24, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char # + 0x06, 0X00, 0X00, 0xCE, 0X00, 0x11, 0x01, 0xFF, 0x03, 0x11, 0x01, 0xE2, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char $ + 0x0A, 0X00, 0X00, 0x0E, 0X00, 0x11, 0X00, 0x11, 0x01, 0xCE, 0X00, 0x38, 0X00, 0xE6, 0X00, 0x11, 0x01, 0x10, 0x01, 0xE0, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char % + 0x08, 0X00, 0X00, 0xE0, 0X00, 0x1E, 0x01, 0x11, 0x01, 0x29, 0x01, 0xC6, 0X00, 0xA0, 0X00, 0X00, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char & + 0x02, 0X00, 0X00, 0x07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ' + 0x04, 0X00, 0X00, 0xF8, 0X00, 0x06, 0x03, 0x01, 0x04, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ( + 0x03, 0x01, 0x04, 0x06, 0x03, 0xF8, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ) + 0x05, 0x02, 0X00, 0x0A, 0X00, 0x07, 0X00, 0x0A, 0X00, 0x02, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char * + 0x06, 0X00, 0X00, 0x10, 0X00, 0x10, 0X00, 0x7C, 0X00, 0x10, 0X00, 0x10, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char + + 0x02, 0X00, 0X00, 0X00, 0x07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char , + 0x03, 0x20, 0X00, 0x20, 0X00, 0x20, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char - + 0x02, 0X00, 0X00, 0X00, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char . + 0x03, 0x80, 0x01, 0x7C, 0X00, 0x03, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char / + 0x06, 0X00, 0X00, 0xFE, 0X00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFE, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 0 + 0x06, 0X00, 0X00, 0x04, 0X00, 0x02, 0X00, 0xFF, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 1 + 0x06, 0X00, 0X00, 0x02, 0x01, 0x81, 0x01, 0x41, 0x01, 0x31, 0x01, 0x0E, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 2 + 0x06, 0X00, 0X00, 0x82, 0X00, 0x01, 0x01, 0x11, 0x01, 0x11, 0x01, 0xEE, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 3 + 0x06, 0X00, 0X00, 0x60, 0X00, 0x58, 0X00, 0x46, 0X00, 0xFF, 0x01, 0x40, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 4 + 0x06, 0X00, 0X00, 0x9C, 0X00, 0x0B, 0x01, 0x09, 0x01, 0x09, 0x01, 0xF1, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 5 + 0x06, 0X00, 0X00, 0xFE, 0X00, 0x11, 0x01, 0x09, 0x01, 0x09, 0x01, 0xF2, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 6 + 0x06, 0X00, 0X00, 0x01, 0X00, 0xC1, 0x01, 0x39, 0X00, 0x07, 0X00, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 7 + 0x06, 0X00, 0X00, 0xEE, 0X00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0xEE, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 8 + 0x06, 0X00, 0X00, 0x9E, 0X00, 0x21, 0x01, 0x21, 0x01, 0x11, 0x01, 0xFE, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char 9 + 0x02, 0X00, 0X00, 0x04, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char : + 0x02, 0X00, 0X00, 0x40, 0x07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ; + 0x06, 0X00, 0X00, 0x10, 0X00, 0x28, 0X00, 0x28, 0X00, 0x44, 0X00, 0x44, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char < + 0x06, 0x48, 0X00, 0x48, 0X00, 0x48, 0X00, 0x48, 0X00, 0x48, 0X00, 0x48, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char = + 0x06, 0X00, 0X00, 0x44, 0X00, 0x44, 0X00, 0x28, 0X00, 0x28, 0X00, 0x10, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char > + 0x06, 0X00, 0X00, 0x06, 0X00, 0x01, 0X00, 0x61, 0x01, 0x11, 0X00, 0x0E, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ? + 0x0C, 0X00, 0X00, 0xF0, 0x01, 0x0C, 0x02, 0xE2, 0x04, 0x12, 0x09, 0x09, 0x09, 0x09, 0x09, 0xF1, 0x09, 0x19, 0x09, 0x02, 0x05, 0x86, 0x04, 0x78, 0x02, // Code for char @ + 0x07, 0x80, 0x01, 0x70, 0X00, 0x2E, 0X00, 0x21, 0X00, 0x2E, 0X00, 0x70, 0X00, 0x80, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char A + 0x07, 0X00, 0X00, 0xFF, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0xFE, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char B + 0x08, 0X00, 0X00, 0x7C, 0X00, 0x82, 0X00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0X00, 0x44, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char C + 0x08, 0X00, 0X00, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0X00, 0x7C, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char D + 0x07, 0X00, 0X00, 0xFF, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char E + 0x06, 0X00, 0X00, 0xFF, 0x01, 0x11, 0X00, 0x11, 0X00, 0x11, 0X00, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char F + 0x08, 0X00, 0X00, 0x7C, 0X00, 0x82, 0X00, 0x01, 0x01, 0x01, 0x01, 0x11, 0x01, 0x92, 0X00, 0x74, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char G + 0x08, 0X00, 0X00, 0xFF, 0x01, 0x10, 0X00, 0x10, 0X00, 0x10, 0X00, 0x10, 0X00, 0x10, 0X00, 0xFF, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char H + 0x03, 0X00, 0X00, 0xFF, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char I + 0x05, 0xC0, 0X00, 0X00, 0x01, 0X00, 0x01, 0X00, 0x01, 0xFF, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char J + 0x08, 0X00, 0X00, 0xFF, 0x01, 0x20, 0X00, 0x10, 0X00, 0x28, 0X00, 0x44, 0X00, 0x82, 0X00, 0x01, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char K + 0x07, 0X00, 0X00, 0xFF, 0x01, 0X00, 0x01, 0X00, 0x01, 0X00, 0x01, 0X00, 0x01, 0X00, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char L + 0x08, 0X00, 0X00, 0xFF, 0x01, 0x06, 0X00, 0x78, 0X00, 0x80, 0x01, 0x78, 0X00, 0x06, 0X00, 0xFF, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char M + 0x08, 0X00, 0X00, 0xFF, 0x01, 0x02, 0X00, 0x0C, 0X00, 0x10, 0X00, 0x60, 0X00, 0x80, 0X00, 0xFF, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char N + 0x08, 0X00, 0X00, 0x7C, 0X00, 0x82, 0X00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0X00, 0x7C, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char O + 0x07, 0X00, 0X00, 0xFF, 0x01, 0x11, 0X00, 0x11, 0X00, 0x11, 0X00, 0x11, 0X00, 0x0E, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char P + 0x08, 0X00, 0X00, 0x7C, 0X00, 0x82, 0X00, 0x01, 0x01, 0x41, 0x01, 0x41, 0x01, 0x82, 0X00, 0x7C, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char Q + 0x08, 0X00, 0X00, 0xFF, 0x01, 0x11, 0X00, 0x11, 0X00, 0x11, 0X00, 0x31, 0X00, 0xD1, 0X00, 0x0E, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char R + 0x07, 0X00, 0X00, 0xCE, 0X00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0xE6, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char S + 0x07, 0x01, 0X00, 0x01, 0X00, 0x01, 0X00, 0xFF, 0x01, 0x01, 0X00, 0x01, 0X00, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char T + 0x08, 0X00, 0X00, 0x7F, 0X00, 0x80, 0X00, 0X00, 0x01, 0X00, 0x01, 0X00, 0x01, 0x80, 0X00, 0x7F, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char U + 0x07, 0x03, 0X00, 0x1C, 0X00, 0x60, 0X00, 0x80, 0x01, 0x60, 0X00, 0x1C, 0X00, 0x03, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char V + 0x0B, 0x07, 0X00, 0x78, 0X00, 0x80, 0x01, 0x70, 0X00, 0x0E, 0X00, 0x01, 0X00, 0x0E, 0X00, 0x70, 0X00, 0x80, 0x01, 0x7C, 0X00, 0x03, 0X00, 0X00, 0X00, // Code for char W + 0x07, 0x01, 0x01, 0xC6, 0X00, 0x28, 0X00, 0x10, 0X00, 0x28, 0X00, 0xC6, 0X00, 0x01, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char X + 0x07, 0x01, 0X00, 0x06, 0X00, 0x08, 0X00, 0xF0, 0x01, 0x08, 0X00, 0x06, 0X00, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char Y + 0x07, 0X00, 0x01, 0x81, 0x01, 0x61, 0x01, 0x11, 0x01, 0x0D, 0x01, 0x03, 0x01, 0x01, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char Z + 0x03, 0X00, 0X00, 0xFF, 0x07, 0x01, 0x04, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char [ + 0x03, 0x03, 0X00, 0x7C, 0X00, 0x80, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char BackSlash + 0x02, 0x01, 0x04, 0xFF, 0x07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ] + 0x05, 0x18, 0X00, 0x06, 0X00, 0x01, 0X00, 0x06, 0X00, 0x18, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ^ + 0x07, 0X00, 0x04, 0X00, 0x04, 0X00, 0x04, 0X00, 0x04, 0X00, 0x04, 0X00, 0x04, 0X00, 0x04, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char _ + 0x03, 0X00, 0X00, 0x01, 0X00, 0x02, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ` + 0x06, 0X00, 0X00, 0xC8, 0X00, 0x24, 0x01, 0x24, 0x01, 0xA4, 0X00, 0xF8, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char a + 0x06, 0X00, 0X00, 0xFF, 0x01, 0x88, 0X00, 0x04, 0x01, 0x04, 0x01, 0xF8, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char b + 0x05, 0X00, 0X00, 0xF8, 0X00, 0x04, 0x01, 0x04, 0x01, 0x88, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char c + 0x06, 0X00, 0X00, 0xF8, 0X00, 0x04, 0x01, 0x04, 0x01, 0x08, 0x01, 0xFF, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char d + 0x06, 0X00, 0X00, 0xF8, 0X00, 0x24, 0x01, 0x24, 0x01, 0x24, 0x01, 0xB8, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char e + 0x04, 0x04, 0X00, 0xFE, 0x01, 0x05, 0X00, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char f + 0x06, 0X00, 0X00, 0xF8, 0x04, 0x04, 0x05, 0x04, 0x05, 0x88, 0x04, 0xFC, 0x03, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char g + 0x06, 0X00, 0X00, 0xFF, 0x01, 0x08, 0X00, 0x04, 0X00, 0x04, 0X00, 0xF8, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char h + 0x02, 0X00, 0X00, 0xFD, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char i + 0x02, 0X00, 0x04, 0xFD, 0x03, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char j + 0x06, 0X00, 0X00, 0xFF, 0x01, 0x20, 0X00, 0x30, 0X00, 0xC8, 0X00, 0x04, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char k + 0x02, 0X00, 0X00, 0xFF, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char l + 0x0A, 0X00, 0X00, 0xFC, 0x01, 0x08, 0X00, 0x04, 0X00, 0x04, 0X00, 0xF8, 0x01, 0x08, 0X00, 0x04, 0X00, 0x04, 0X00, 0xF8, 0x01, 0X00, 0X00, 0X00, 0X00, // Code for char m + 0x06, 0X00, 0X00, 0xFC, 0x01, 0x08, 0X00, 0x04, 0X00, 0x04, 0X00, 0xF8, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char n + 0x06, 0X00, 0X00, 0xF8, 0X00, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0xF8, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char o + 0x06, 0X00, 0X00, 0xFC, 0x07, 0x88, 0X00, 0x04, 0x01, 0x04, 0x01, 0xF8, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char p + 0x06, 0X00, 0X00, 0xF8, 0X00, 0x04, 0x01, 0x04, 0x01, 0x88, 0X00, 0xFC, 0x07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char q + 0x04, 0X00, 0X00, 0xFC, 0x01, 0x08, 0X00, 0x04, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char r + 0x06, 0X00, 0X00, 0x98, 0X00, 0x24, 0x01, 0x24, 0x01, 0x24, 0x01, 0xC8, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char s + 0x03, 0x04, 0X00, 0xFF, 0x01, 0x04, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char t + 0x06, 0X00, 0X00, 0xFC, 0X00, 0X00, 0x01, 0X00, 0x01, 0X00, 0x01, 0xFC, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char u + 0x05, 0x0C, 0X00, 0x70, 0X00, 0x80, 0x01, 0x70, 0X00, 0x0C, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char v + 0x09, 0x0C, 0X00, 0x70, 0X00, 0x80, 0x01, 0x70, 0X00, 0x0C, 0X00, 0x70, 0X00, 0x80, 0x01, 0x70, 0X00, 0x0C, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char w + 0x05, 0x04, 0x01, 0xD8, 0X00, 0x20, 0X00, 0xD8, 0X00, 0x04, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char x + 0x05, 0x0C, 0X00, 0x70, 0x04, 0x80, 0x03, 0x70, 0X00, 0x0C, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char y + 0x05, 0x04, 0x01, 0xC4, 0x01, 0x24, 0x01, 0x1C, 0x01, 0x04, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char z + 0x03, 0x20, 0X00, 0xDE, 0x03, 0x01, 0x04, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char { + 0x02, 0X00, 0X00, 0xFF, 0x07, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char | + 0x04, 0X00, 0X00, 0x01, 0x04, 0xDE, 0x03, 0x20, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char } + 0x07, 0X00, 0X00, 0x20, 0X00, 0x10, 0X00, 0x10, 0X00, 0x20, 0X00, 0x20, 0X00, 0x10, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // Code for char ~ + 0x08, 0X00, 0X00, 0xFE, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0xFE, 0x01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 // Code for char <del> +}; + +#endif // ARIAL12X12_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/Bitmap.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,102 @@ +// +// Windows BMP file definitions. +// +// Adapted from code written by Michael Sweet from Paul Bourke's +// web site: http://paulbourke.net/dataformats/bmp/ +// + +#ifndef _BITMAP_H_ +#define _BITMAP_H_ + +#include <mbed.h> + +// BITMAPFILEHEADER +// BITMAPINFOHEADER +// Optional Palette +// Raw Data + +// +// Bitmap file data structures +// +// must align to 2-byte boundaries so it doesn't alter the memory image when +// bytes are read from the file system into this footprint. +#pragma push +#pragma pack(2) + +typedef struct /**** BMP file header structure ****/ + { + uint16_t bfType; /* Magic number for file */ + uint32_t bfSize; /* Size of file */ + uint16_t bfReserved1; /* Reserved */ + uint16_t bfReserved2; /* ... */ + uint32_t bfOffBits; /* Offset to bitmap data */ + } BITMAPFILEHEADER; + +typedef struct /**** BMP file info structure ****/ + { + uint32_t biSize; /* Size of info header */ + uint32_t biWidth; /* Width of image */ + uint32_t biHeight; /* Height of image */ + uint16_t biPlanes; /* Number of color planes */ + uint16_t biBitCount; /* Number of bits per pixel */ + uint32_t biCompression; /* Type of compression to use */ + uint32_t biSizeImage; /* Size of image data */ + int32_t biXPelsPerMeter; /* X pixels per meter */ + int32_t biYPelsPerMeter; /* Y pixels per meter */ + uint32_t biClrUsed; /* Number of colors used */ + uint32_t biClrImportant; /* Number of important colors */ + } BITMAPINFOHEADER; +#pragma pop + +#define BF_TYPE 0x4D42 /* "MB" */ + +/* + * Constants for the biCompression field... + */ + +# define BI_RGB 0 /* No compression - straight BGR data */ +# define BI_RLE8 1 /* 8-bit run-length compression */ +# define BI_RLE4 2 /* 4-bit run-length compression */ +# define BI_BITFIELDS 3 /* RGB bitmap with RGB masks */ + +typedef struct /**** Colormap entry structure ****/ + { + uint8_t rgbBlue; /* Blue value */ + uint8_t rgbGreen; /* Green value */ + uint8_t rgbRed; /* Red value */ + uint8_t rgbReserved; /* Reserved */ + } RGBQUAD; + +//typedef struct /**** Bitmap information structure ****/ +// { +// BITMAPINFOHEADER bmiHeader; /* Image header */ +// RGBQUAD bmiColors[256]; /* Image colormap */ +// } BITMAPINFO; + + +#pragma push +#pragma pack(2) + +typedef struct /**** ICO file header structure ****/ + { + uint16_t Reserved_zero; // Always zero + uint16_t icType; // 1 for .ico, 2 for .cur + uint16_t icImageCount; // number of images in the file + } ICOFILEHEADER; + +typedef struct /**** ICO file Directory Entry structure (1 or more) ****/ + { + uint8_t biWidth; /* Width of image */ + uint8_t biHeight; /* Height of image */ + uint8_t biClrUsed; /* Number of colors used */ + uint8_t Reserved_zero; + uint16_t biPlanes; /* Number of color planes (ICO should be 0 or 1, CUR horz hotspot */ + uint16_t biBitCount; /* Number of bits per pixel (ICO bits per pixel, CUR vert hotspot */ + uint32_t biSizeImage; /* Size of image data */ + uint32_t bfOffBits; /* Offset into file for the bitmap data */ + } ICODIRENTRY; +#pragma pop + +#define IC_TYPE 0x0001 /* 1 = ICO (icon), 2 = CUR (cursor) */ + +#endif // _BITMAP_H_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/DisplayDefs.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,74 @@ +#ifndef DISPLAYDEFS_H +#define DISPLAYDEFS_H + +#define RGB(r,g,b) ( ((r<<8)&0xF800) | ((g<<3)&0x07E0) | (b>>3) ) + +typedef uint16_t color_t; + +/// return values from functions. Use this number, or use the +/// lookup function to get a text string. @see GetErrorMessage. +/// +typedef enum +{ + noerror, ///< no errors, command completed successfully + bad_parameter, ///< one or more parameters are invalid + file_not_found, ///< specified file could not be found + not_bmp_format, ///< file is not a .bmp file + not_ico_format, ///< file is not a .ico file + not_supported_format, ///< file format is not yet supported + image_too_big, ///< image is too large for the screen + not_enough_ram, ///< could not allocate ram for scanline + LastErrCode, // Private marker. +} RetCode_t; + +/// type that manages locations, which is typically an x or y pixel location, +/// which can range from -N to +N (even if the screen is 0 to +n). @see textloc_t. +typedef int16_t loc_t; + +/// type that manages text locations, which are row or column values in +/// units of character, not pixel. @see loc_t. +typedef uint16_t textloc_t; + +/// type that manages dimensions of width or height, which range from 0 to N. +typedef uint16_t dim_t; + +/// type that manages x,y pairs +typedef struct +{ + loc_t x; ///< x value in the point + loc_t y; ///< y value in the point +} point_t; + +/// type that manages rectangles, which are pairs of points. It is recommended +/// that p1 contains the top-left point and p2 contains the bottom-right point, +/// even though eventually this should not matter. +typedef struct +{ + point_t p1; ///< p1 defines one point on the rectangle + point_t p2; ///< p2 defines the opposite point on the rectangle +} rect_t; + +typedef struct +{ + int32_t An, Bn, Cn, Dn, En, Fn, Divider; +} tpMatrix_t; + +/// color type definition to let the compiler help keep us honest. +/// +/// colors can be defined with the RGB(r,g,b) macro, and there +/// are a number of predefined colors: +/// - Black, Blue, Green, Cyan, +/// - Red, Magenta, Brown, Gray, +/// - Charcoal, BrightBlue, BrightGreen, BrightCyan, +/// - Orange, Pink, Yellow, White +/// +typedef uint16_t color_t; + +/// background fill info for drawing Text, Rectangles, RoundedRectanges, Circles, Ellipses and Triangles. +typedef enum +{ + NOFILL, ///< do not fill the object with the background color + FILL ///< fill the object space with the background color +} fill_t; + +#endif // DISPLAYDEFS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/GraphicsDisplay.cpp Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,563 @@ +/* mbed GraphicsDisplay Display Library Base Class + * Copyright (c) 2007-2009 sford + * Released under the MIT License: http://mbed.org/license/mit + * + * Derivative work by D.Smart 2014 + */ + +#include "GraphicsDisplay.h" +#include "Bitmap.h" +#include "string.h" + +//#define DEBUG "GD" +// ... +// INFO("Stuff to show %d", var); // new-line is automatically appended +// +#if (defined(DEBUG) && !defined(TARGET_LPC11U24)) +#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +static void HexDump(char * title, uint8_t * p, int count) +{ + int i; + char buf[100] = "0000: "; + + if (*title) + INFO("%s", title); + for (i=0; i<count; ) { + sprintf(buf + strlen(buf), "%02X ", *(p+i)); + if ((++i & 0x0F) == 0x00) { + INFO("%s", buf); + if (i < count) + sprintf(buf, "%04X: ", i); + else + buf[0] = '\0'; + } + } + if (strlen(buf)) + INFO("%s", buf); +} +#else +#define INFO(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) +#define HexDump(a, b, c) +#endif + +#ifdef LOCALFONT +const unsigned char FONT8x8[97][8] = { + 0x08, 0x08, 0x08, 0X00, 0X00, 0X00, 0X00, 0X00, // columns, rows, num_bytes_per_char + 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // space 0x20 + 0x30, 0x78, 0x78, 0x30, 0x30, 0X00, 0x30, 0X00, // ! + 0x6C, 0x6C, 0x6C, 0X00, 0X00, 0X00, 0X00, 0X00, // " + 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0X00, // # + 0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0X00, // $ + 0X00, 0x63, 0x66, 0x0C, 0x18, 0x33, 0x63, 0X00, // % + 0x1C, 0x36, 0x1C, 0x3B, 0x6E, 0x66, 0x3B, 0X00, // & + 0x30, 0x30, 0x60, 0X00, 0X00, 0X00, 0X00, 0X00, // ' + 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0X00, // ( + 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0X00, // ) + 0X00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0X00, 0X00, // * + 0X00, 0x30, 0x30, 0xFC, 0x30, 0x30, 0X00, 0X00, // + + 0X00, 0X00, 0X00, 0X00, 0X00, 0x18, 0x18, 0x30, // , + 0X00, 0X00, 0X00, 0x7E, 0X00, 0X00, 0X00, 0X00, // - + 0X00, 0X00, 0X00, 0X00, 0X00, 0x18, 0x18, 0X00, // . + 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0X00, // / (forward slash) + 0x3E, 0x63, 0x63, 0x6B, 0x63, 0x63, 0x3E, 0X00, // 0 0x30 + 0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x7E, 0X00, // 1 + 0x3C, 0x66, 0x06, 0x1C, 0x30, 0x66, 0x7E, 0X00, // 2 + 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0X00, // 3 + 0x0E, 0x1E, 0x36, 0x66, 0x7F, 0x06, 0x0F, 0X00, // 4 + 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0X00, // 5 + 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0X00, // 6 + 0x7E, 0x66, 0x06, 0x0C, 0x18, 0x18, 0x18, 0X00, // 7 + 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0X00, // 8 + 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0X00, // 9 + 0X00, 0x18, 0x18, 0X00, 0X00, 0x18, 0x18, 0X00, // : + 0X00, 0x18, 0x18, 0X00, 0X00, 0x18, 0x18, 0x30, // ; + 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0X00, // < + 0X00, 0X00, 0x7E, 0X00, 0X00, 0x7E, 0X00, 0X00, // = + 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0X00, // > + 0x3C, 0x66, 0x06, 0x0C, 0x18, 0X00, 0x18, 0X00, // ? + 0x3E, 0x63, 0x6F, 0x69, 0x6F, 0x60, 0x3E, 0X00, // @ 0x40 + 0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0X00, // A + 0x7E, 0x33, 0x33, 0x3E, 0x33, 0x33, 0x7E, 0X00, // B + 0x1E, 0x33, 0x60, 0x60, 0x60, 0x33, 0x1E, 0X00, // C + 0x7C, 0x36, 0x33, 0x33, 0x33, 0x36, 0x7C, 0X00, // D + 0x7F, 0x31, 0x34, 0x3C, 0x34, 0x31, 0x7F, 0X00, // E + 0x7F, 0x31, 0x34, 0x3C, 0x34, 0x30, 0x78, 0X00, // F + 0x1E, 0x33, 0x60, 0x60, 0x67, 0x33, 0x1F, 0X00, // G + 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0X00, // H + 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // I + 0x0F, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0X00, // J + 0x73, 0x33, 0x36, 0x3C, 0x36, 0x33, 0x73, 0X00, // K + 0x78, 0x30, 0x30, 0x30, 0x31, 0x33, 0x7F, 0X00, // L + 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0X00, // M + 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x63, 0X00, // N + 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0X00, // O + 0x7E, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x78, 0X00, // P 0x50 + 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x3C, 0x0E, 0X00, // Q + 0x7E, 0x33, 0x33, 0x3E, 0x36, 0x33, 0x73, 0X00, // R + 0x3C, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x3C, 0X00, // S + 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // T + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7E, 0X00, // U + 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0X00, // V + 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0X00, // W + 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0X00, // X + 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0X00, // Y + 0x7F, 0x63, 0x46, 0x0C, 0x19, 0x33, 0x7F, 0X00, // Z + 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0X00, // [ + 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0X00, // \ (back slash) + 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0X00, // ] + 0x08, 0x1C, 0x36, 0x63, 0X00, 0X00, 0X00, 0X00, // ^ + 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0xFF, // _ + 0x18, 0x18, 0x0C, 0X00, 0X00, 0X00, 0X00, 0X00, // ` 0x60 + 0X00, 0X00, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0X00, // a + 0x70, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0X00, // b + 0X00, 0X00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0X00, // c + 0x0E, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3B, 0X00, // d + 0X00, 0X00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0X00, // e + 0x1C, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0X00, // f + 0X00, 0X00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x7C, // g + 0x70, 0x30, 0x36, 0x3B, 0x33, 0x33, 0x73, 0X00, // h + 0x18, 0X00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0X00, // i + 0x06, 0X00, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, // j + 0x70, 0x30, 0x33, 0x36, 0x3C, 0x36, 0x73, 0X00, // k + 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // l + 0X00, 0X00, 0x66, 0x7F, 0x7F, 0x6B, 0x63, 0X00, // m + 0X00, 0X00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0X00, // n + 0X00, 0X00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0X00, // o + 0X00, 0X00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78, // p + 0X00, 0X00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F, // q + 0X00, 0X00, 0x6E, 0x3B, 0x33, 0x30, 0x78, 0X00, // r + 0X00, 0X00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0X00, // s + 0x08, 0x18, 0x3E, 0x18, 0x18, 0x1A, 0x0C, 0X00, // t + 0X00, 0X00, 0x66, 0x66, 0x66, 0x66, 0x3B, 0X00, // u + 0X00, 0X00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0X00, // v + 0X00, 0X00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0X00, // w + 0X00, 0X00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0X00, // x + 0X00, 0X00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x7C, // y + 0X00, 0X00, 0x7E, 0x4C, 0x18, 0x32, 0x7E, 0X00, // z + 0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0X00, // { + 0x0C, 0x0C, 0x0C, 0X00, 0x0C, 0x0C, 0x0C, 0X00, // | + 0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0X00, // } + 0x3B, 0x6E, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // ~ + 0x1C, 0x36, 0x36, 0x1C, 0X00, 0X00, 0X00, 0X00 // DEL +}; +#endif // LOCALFONT + +char mytolower(char a) { + if (a >= 'A' && a <= 'Z') + return (a - 'A' + 'a'); + else + return a; +} +/// mystrnicmp exists because not all compiler libraries have this function. +/// +/// Some have strnicmp, others _strnicmp, and others have C++ methods, which +/// is outside the scope of this C-portable set of functions. +/// +/// @param l is a pointer to the string on the left +/// @param r is a pointer to the string on the right +/// @param n is the number of characters to compare +/// @returns -1 if l < r +/// @returns 0 if l == r +/// @returns +1 if l > r +/// +int mystrnicmp(const char *l, const char *r, size_t n) { + int result = 0; + + if (n != 0) { + do { + result = mytolower(*l++) - mytolower(*r++); + } while ((result == 0) && (*l != '\0') && (--n > 0)); + } + if (result < -1) + result = -1; + else if (result > 1) + result = 1; + return result; +} + + +GraphicsDisplay::GraphicsDisplay(const char *name) + : TextDisplay(name) +{ + font = NULL; +} + +RetCode_t GraphicsDisplay::set_font(const unsigned char * _font) +{ + font = _font; // trusting them, but it might be good to put some checks in here... + return noerror; +} + +#ifdef LOCALFONT +int GraphicsDisplay::character(int x, int y, int value) +{ + if (value <= 0x1F && value >= 7F) + return 0; + + return blitbit(x, y, FONT8X8[0][0], FONT8X8[0][1], + (char *)&(FONT8x8[value - 0x1F][0])); +} +#else +int GraphicsDisplay::character(int x, int y, int c) +{ + unsigned int offset; + const unsigned char * charRecord; + + if (c <= 0x1F || c >= 0x7F) + return 0; + offset = font[0]; // bytes / char + charRecord = &font[((c - ' ') * offset) + 4]; // start of char bitmap + return fontblit(x, y, font, charRecord); +} +#endif + +RetCode_t GraphicsDisplay::window(loc_t x, loc_t y, dim_t w, dim_t h) +{ + // current pixel location + _x = x; + _y = y; + // window settings + _x1 = x; + _x2 = x + w - 1; + _y1 = y; + _y2 = y + h - 1; + return noerror; +} + +RetCode_t GraphicsDisplay::WindowMax(void) +{ + return window(0,0, width(),height()); +} + +RetCode_t GraphicsDisplay::_putp(color_t color) +{ + pixel(_x, _y, color); + // update pixel location based on window settings + _x++; + if(_x > _x2) { + _x = _x1; + _y++; + if(_y > _y2) { + _y = _y1; + } + } + return noerror; +} + +RetCode_t GraphicsDisplay::fill(int x, int y, int w, int h, color_t color) +{ + return fillrect(x,y, x+w, y+h, color); +} + +RetCode_t GraphicsDisplay::cls(uint16_t layers) +{ + return fill(0, 0, width(), height(), _background); +} + +RetCode_t GraphicsDisplay::blit(int x, int y, int w, int h, const int * color) +{ + window(x, y, w, h); + _StartGraphicsStream(); + for (int i=0; i<w*h; i++) { + _putp(color[i]); + } + _EndGraphicsStream(); + return WindowMax(); +} + +#ifdef LOCALFONT +int GraphicsDisplay::blitbit(int x, int y, int w, int h, const char * color) +{ + _foreground = 0xFFFF; + INFO("blitbit(%d,%d, %d,%d, %02X) [%04X,%04X]", x,y, w,h, *color, _foreground, _background); + INFO("%lu %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + color, + color[0], color[1], color[2], color[3], color[4], color[5], color[6], color[7], + color[8], color[9], color[10], color[11], color[12], color[13], color[14], color[15]); + window(x, y, w, h); + _StartGraphicsStream(); + for (int i = 0; i < w*h; i++) { + char byte = color[i >> 3]; + int offset = i & 0x7; + if (offset == 0) + INFO(" %2d = %02X", i>>3, byte); + int c = ((byte << offset) & 0x80) ? _foreground : _background; + _putp(c); + } + _EndGraphicsStream(); + WindowMax(); + return w; +} +#endif + + +int GraphicsDisplay::fontblit(int x, int y, const unsigned char * fontTable, const unsigned char * fontChar) +{ + //int fontWidth = font[1]; // get hor size of font + int fontHeight = font[2]; // get vert size of font + int bytesPerLine = font[3]; // bytes per line + int charWidth = fontChar[0]; // width of this character + int px, py; + + //INFO("(%d,%d) %lu, %lu %X/%X", x,y, fontTable, fontChar, _foreground, _background); + //INFO("char size (%d,%d)", charWidth, fontHeight); + //HexDump("char", (uint8_t *)fontChar, 32); + //INFO("(f,b) = (%04X,%04X)", _foreground, _background) + window(x, y, charWidth, fontHeight); + _StartGraphicsStream(); + //INFO("(f,b) = (%04X,%04X)", _foreground, _background) + for (py = 0; py < fontHeight; py++) { + int bitmask = 1 << (py & 7); + + for (px = 0; px < charWidth; px++) { + int offset = (py / 8) + px * bytesPerLine; + unsigned char byte = fontChar[offset + 1]; // skip the char's # bits wide value + color_t c = (byte & bitmask) ? _foreground : _background; + //INFO("(%2d,%2d) %02X & %02X => %04X [%04X,%04X]", px, py, byte, bitmask, c, _foreground, _background); + //pixel(x+px, y+py, c); + _putp(c); + } + } + _EndGraphicsStream(); + WindowMax(); + return charWidth; +} + +// BMP Color Palette is BGRx +// BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000 +// RGB16 is +// RRRR RGGG GGGB BBBB +// swap to little endian +// GGGB BBBB RRRR RGGG +color_t GraphicsDisplay::RGBQuadToRGB16(RGBQUAD * colorPalette, uint16_t i) +{ + color_t c; + + c = ((colorPalette[i].rgbBlue >> 3) << 0); + c |= ((colorPalette[i].rgbGreen >> 2) << 5); + c |= ((colorPalette[i].rgbRed >> 3) << 11); + return c; +} + +/// RRRR RGGG GGGB BBBB +RGBQUAD GraphicsDisplay::RGB16ToRGBQuad(color_t c) +{ + RGBQUAD q; + + memset(&q, 0, sizeof(q)); + q.rgbBlue = ((c & 0x001F) << 3) | (c & 0x07); /* Blue value */ + q.rgbGreen = ((c & 0x07E0) >> 3) | ((c >> 7) & 0x03); /* Green value */ + q.rgbRed = ((c & 0xF800) >> 8) | ((c >> 11) & 0x07); /* Red value */ + q.rgbReserved = 0; + return q; +} + +RetCode_t GraphicsDisplay::_RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image) +{ + BITMAPINFOHEADER BMP_Info; + RGBQUAD * colorPalette = NULL; + int colorCount; + uint8_t * lineBuffer = NULL; + color_t * pixelBuffer = NULL; + uint16_t BPP_t; + uint32_t PixelWidth, PixelHeight; + unsigned int i, offset; + int padd,j; + #ifdef DEBUG + uint32_t start_data; + #endif + + // Now, Read the bitmap info header + fread(&BMP_Info, 1, sizeof(BMP_Info), Image); + HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); + BPP_t = BMP_Info.biBitCount; + INFO("biBitCount %04X", BPP_t); + if (BPP_t != 4 && BPP_t != 8 && BPP_t != 16 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel + fclose(Image); + return(not_supported_format); + } + + PixelHeight = BMP_Info.biHeight; + PixelWidth = BMP_Info.biWidth; + INFO("(%d,%d) (%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight, width(), height()); + if (PixelHeight > height() + y || PixelWidth > width() + x) { + fclose(Image); + return(image_too_big); + } + if (BMP_Info.biBitCount <= 8) { + int paletteSize; + // Read the color palette + colorCount = 1 << BMP_Info.biBitCount; + paletteSize = sizeof(RGBQUAD) * colorCount; + colorPalette = (RGBQUAD *)malloc(paletteSize); + if (colorPalette == NULL) { + fclose(Image); + return(not_enough_ram); + } + fread(colorPalette, 1, paletteSize, Image); + HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize); + } + + int lineBufSize = ((BPP_t * PixelWidth + 7)/8); + INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize); + lineBuffer = (uint8_t *)malloc(lineBufSize); + if (lineBuffer == NULL) { + free(colorPalette); + fclose(Image); + return(not_enough_ram); + } + pixelBuffer = (color_t *)malloc(PixelWidth * sizeof(color_t)); + if (pixelBuffer == NULL) { + free(lineBuffer); + if (colorPalette) + free(colorPalette); + fclose(Image); + return(not_enough_ram); + } + + // the Raw Data records are padded to a multiple of 4 bytes + int recordSize = 2; + if (BPP_t == 4) { + recordSize = 1; + } else if (BPP_t == 8) { + recordSize = 1; + } else if (BPP_t == 16) { + recordSize = 2; + } else if (BPP_t == 24) { + recordSize = 3; + } + padd = -1; + do { + padd++; + } while ((PixelWidth * recordSize + padd) % 4 != 0); + + // Define window for top to bottom and left to right so writing auto-wraps + window(x,y, PixelWidth,PixelHeight); + SetGraphicsCursor(x, y); + _StartGraphicsStream(); + + //start_data = BMP_Header.bfOffBits; + HexDump("Raw Data", (uint8_t *)&start_data, 32); + INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd); + for (j = PixelHeight - 1; j >= 0; j--) { //Lines bottom up + offset = fileOffset + j * (lineBufSize + padd); // start of line + fseek(Image, offset, SEEK_SET); + fread(lineBuffer, 1, lineBufSize, Image); // read a line - slow ! + //INFO("offset: %6X", offset); + for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT + if (BPP_t == 4) { + uint8_t dPix = lineBuffer[i/2]; + if ((i & 1) == 0) + dPix >>= 4; + dPix &= 0x0F; + pixelBuffer[i] = RGBQuadToRGB16(colorPalette, dPix); + } else if (BPP_t == 8) { + pixelBuffer[i] = RGBQuadToRGB16(colorPalette, lineBuffer[i]); + } else if (BPP_t == 16) { + pixelBuffer[i] = lineBuffer[i]; + } else if (BPP_t == 24) { + color_t color; + color = RGB(lineBuffer[i*3+2], lineBuffer[i*3+1], lineBuffer[i*3+0]); + pixelBuffer[i] = color; + } + } + pixelStream(pixelBuffer, PixelWidth, x, y++); + } + _EndGraphicsStream(); + WindowMax(); + free(pixelBuffer); // don't leak memory + free(lineBuffer); + if (colorPalette) + free(colorPalette); + return (noerror); +} + + +RetCode_t GraphicsDisplay::RenderImageFile(loc_t x, loc_t y, const char *FileName) +{ + if (mystrnicmp(FileName + strlen(FileName) - 4, ".bmp", 4) == 0) { + return RenderBitmapFile(x,y,FileName); + } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".ico", 4) == 0) { + return RenderIconFile(x,y,FileName); + } else { + return not_supported_format; + } +} + +RetCode_t GraphicsDisplay::RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP) +{ + BITMAPFILEHEADER BMP_Header; + + INFO("Opening {%s}", Name_BMP); + FILE *Image = fopen(Name_BMP, "rb"); + if (!Image) { + return(file_not_found); + } + + fread(&BMP_Header, 1, sizeof(BMP_Header), Image); // get the BMP Header + INFO("bfType %04X", BMP_Header.bfType); + HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); + if (BMP_Header.bfType != BF_TYPE) { + fclose(Image); + return(not_bmp_format); + } + RetCode_t rt = _RenderBitmap(x, y, BMP_Header.bfOffBits, Image); + if (rt != noerror) { + return rt; + } else { + fclose(Image); + return (noerror); + } +} + +RetCode_t GraphicsDisplay::RenderIconFile(loc_t x, loc_t y, const char *Name_ICO) +{ + ICOFILEHEADER ICO_Header; + ICODIRENTRY ICO_DirEntry; + + INFO("Opening {%s}", Name_ICO); + FILE *Image = fopen(Name_ICO, "rb"); + if (!Image) { + return(file_not_found); + } + + fread(&ICO_Header, 1, sizeof(ICO_Header), Image); // get the BMP Header + HexDump("ICO_Header", (uint8_t *)&ICO_Header, sizeof(ICO_Header)); + if (ICO_Header.Reserved_zero != 0 + || ICO_Header.icType != IC_TYPE + || ICO_Header.icImageCount == 0) { + fclose(Image); + return(not_ico_format); + } + + // Read ONLY the first of n possible directory entries. + fread(&ICO_DirEntry, 1, sizeof(ICO_DirEntry), Image); + HexDump("ICO_DirEntry", (uint8_t *)&ICO_DirEntry, sizeof(ICO_DirEntry)); + INFO("biBitCount %04X", ICO_DirEntry.biBitCount); + if (ICO_DirEntry.biBitCount != 0) { // Expecting this to be zero for ico + fclose(Image); + return(not_supported_format); + } + + RetCode_t rt = _RenderBitmap(x, y, ICO_DirEntry.bfOffBits, Image); + if (rt == noerror) { + fclose(Image); + return (noerror); + } else { + return rt; + } +} + +int GraphicsDisplay::columns() +{ + return width() / 8; +} + +int GraphicsDisplay::rows() +{ + return height() / 8; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/GraphicsDisplay.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,428 @@ +/* mbed GraphicsDisplay Display Library Base Class + * Copyright (c) 2007-2009 sford + * Released under the MIT License: http://mbed.org/license/mit + * + * A library for providing a common base class for Graphics displays + * To port a new display, derive from this class and implement + * the constructor (setup the display), pixel (put a pixel + * at a location), width and height functions. Everything else + * (locate, printf, putc, cls, window, putp, fill, blit, blitbit) + * will come for free. You can also provide a specialised implementation + * of window and putp to speed up the results + */ + +#ifndef MBED_GRAPHICSDISPLAY_H +#define MBED_GRAPHICSDISPLAY_H +#include "Bitmap.h" +#include "TextDisplay.h" + +// GraphicsDisplay has one "soft font" which is in a different format +// then the primary font rendering api - see set_font(...). This is +// therefore deprecated, but preserved for a time for backward +// compatibility. +// #define LOCALFONT + + +/// The GraphicsDisplay class +/// +/// This graphics display class supports both graphics and text operations. +/// Typically, a subclass is derived from this which has localizations to +/// adapt to a specific hardware platform (e.g. a display controller chip), +/// that overrides methods in here to either add more capability or perhaps +/// to improve performance, by leveraging specific hardware capabilities. +/// +class GraphicsDisplay : public TextDisplay +{ +public: + /// The constructor + GraphicsDisplay(const char* name); + + /// Draw a pixel in the specified color. + /// + /// @note this method must be supported in the derived class. + /// + /// @param[in] x is the horizontal offset to this pixel. + /// @param[in] y is the vertical offset to this pixel. + /// @param[in] color defines the color for the pixel. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t pixel(loc_t x, loc_t y, color_t color) = 0; + + /// Write a stream of pixels to the display. + /// + /// @note this method must be supported in the derived class. + /// + /// @param[in] p is a pointer to a color_t array to write. + /// @param[in] count is the number of pixels to write. + /// @param[in] x is the horizontal position on the display. + /// @param[in] y is the vertical position on the display. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t pixelStream(color_t * p, uint32_t count, loc_t x, loc_t y) = 0; + + /// Get a pixel from the display. + /// + /// @note this method must be supported in the derived class. + /// + /// @param[in] x is the horizontal offset to this pixel. + /// @param[in] y is the vertical offset to this pixel. + /// @returns the pixel. see @color_t + /// + virtual color_t getPixel(loc_t x, loc_t y) = 0; + + /// Get a stream of pixels from the display. + /// + /// @note this method must be supported in the derived class. + /// + /// @param[out] p is a pointer to a color_t array to accept the stream. + /// @param[in] count is the number of pixels to read. + /// @param[in] x is the horizontal offset to this pixel. + /// @param[in] y is the vertical offset to this pixel. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t getPixelStream(color_t * p, uint32_t count, loc_t x, loc_t y) = 0; + + /// get the screen width in pixels + /// + /// @note this method must be supported in the derived class. + /// + /// @returns screen width in pixels. + /// + virtual uint16_t width() = 0; + + /// get the screen height in pixels + /// + /// @note this method must be supported in the derived class. + /// + /// @returns screen height in pixels. + /// + virtual uint16_t height() = 0; + + /// Prepare the controller to write binary data to the screen by positioning + /// the memory cursor. + /// + /// @note this method must be supported in the derived class. + /// + /// @param[in] x is the horizontal position in pixels (from the left edge) + /// @param[in] y is the vertical position in pixels (from the top edge) + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t SetGraphicsCursor(loc_t x, loc_t y) = 0; + + /// Prepare the controller to read binary data from the screen by positioning + /// the memory read cursor. + /// + /// @param[in] x is the horizontal position in pixels (from the left edge) + /// @param[in] y is the vertical position in pixels (from the top edge) + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t SetGraphicsCursorRead(loc_t x, loc_t y) = 0; + + /// Draw a filled rectangle in the specified color + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @note this method must be supported in the derived class. + /// + /// @param[in] x1 is the horizontal start of the line. + /// @param[in] y1 is the vertical start of the line. + /// @param[in] x2 is the horizontal end of the line. + /// @param[in] y2 is the vertical end of the line. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to NOFILL the rectangle. default is FILL. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t fillrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + color_t color, fill_t fillit = FILL) = 0; + + + virtual RetCode_t WriteCommand(unsigned char command, unsigned int data = 0xFFFF) = 0; + virtual RetCode_t WriteData(unsigned char data) = 0; + + /// Set the window, which controls where items are written to the screen. + /// + /// When something hits the window width, it wraps back to the left side + /// and down a row. If the initial write is outside the window, it will + /// be captured into the window when it crosses a boundary. + /// + /// @param[in] x is the left edge in pixels. + /// @param[in] y is the top edge in pixels. + /// @param[in] w is the window width in pixels. + /// @param[in] h is the window height in pixels. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t window(loc_t x, loc_t y, dim_t w, dim_t h); + + /// Clear the screen. + /// + /// The behavior is to clear the whole screen. + /// + /// @param[in] layers is ignored, but supports maintaining the same + /// API for the graphics layer. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t cls(uint16_t layers = 0); + + /// method to set the window region to the full screen. + /// + /// This restores the 'window' to the full screen, so that + /// other operations (@see cls) would clear the whole screen. + /// + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t WindowMax(void); + + /// method to put a single color pixel to the screen. + /// + /// This method may be called as many times as necessary after + /// @see _StartGraphicsStream() is called, and it should be followed + /// by _EndGraphicsStream. + /// + /// @param[in] pixel is a color value to be put on the screen. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t _putp(color_t pixel); + + /// method to fill a region. + /// + /// This method fills a region with the specified color. + /// + /// @param[in] x is the left-edge of the region. + /// @param[in] y is the top-edge of the region. + /// @param[in] w specifies the width of the region. + /// @param[in] h specifies the height of the region. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t fill(int x, int y, int w, int h, color_t color); + + + virtual RetCode_t blit(int x, int y, int w, int h, const int * color); + + /// This method transfers one character from the external font data + /// to the screen. + /// + /// @note the font data is in a special format as generate by + /// the mikroe font creator. \\ + /// See http://www.mikroe.com/glcd-font-creator/ + /// + /// @param[in] x is the horizontal pixel coordinate + /// @param[in] y is the vertical pixel coordinate + /// @param[in] fontTable is the base of the table which has the metrics + /// @param[in] fontChar is the start of that record in the table for the char (e.g. 'A' - 'Z') + /// @returns how far the cursor should advance to the right in pixels + /// + virtual int fontblit(int x, int y, const unsigned char * fontTable, const unsigned char * fontChar); + + /// This method returns the color value from a palette. + /// + /// This method accepts a pointer to a Bitmap color palette, which + /// is a table in memory composed of RGB Quad values (r, g, b, 0), + /// and an index into that table. It then extracts the color information + /// and downsamples it to a color_t value which it returns. + /// + /// @note This method probably has very little value outside of + /// the internal methods for reading BMP files. + /// + /// @param[in] colorPaletteArray is the handle to the color palette array to use. + /// @param[in] index is the index into the color palette. + /// @returns the color in color_t format. + /// + color_t RGBQuadToRGB16(RGBQUAD * colorPaletteArray, uint16_t index); + + /// This method converts a 16-bit color value into a 24-bit RGB Quad. + /// + /// @param[in] c is the 16-bit color. @see color_t. + /// @returns an RGBQUAD value. @see RGBQUAD + /// + RGBQUAD RGB16ToRGBQuad(color_t c); + + /// This method attempts to render a specified graphics image file at + /// the specified screen location. + /// + /// This supports several variants of the following file types: + /// \li Bitmap file format, + /// \li Icon file format. + /// + /// @note The specified image width and height, when adjusted for the + /// x and y origin, must fit on the screen, or the image will not + /// be shown (it does not clip the image). + /// + /// @note The file extension is tested, and if it ends in a supported + /// format, the appropriate handler is called to render that image. + /// + /// @param[in] x is the horizontal pixel coordinate + /// @param[in] y is the vertical pixel coordinate + /// @param[in] FileName refers to the fully qualified path and file on + /// a mounted file system. + /// @returns success or error code. + /// + RetCode_t RenderImageFile(loc_t x, loc_t y, const char *FileName); + + /// This method reads a disk file that is in bitmap format and + /// puts it on the screen. + /// + /// Supported formats: + /// \li 4-bit color format (16 colors) + /// \li 8-bit color format (256 colors) + /// \li 16-bit color format (65k colors) + /// \li compression: no. + /// + /// @note This is a slow operation, typically due to the use of + /// the file system, and partially because bmp files + /// are stored from the bottom up, and the memory is written + /// from the top down; as a result, it constantly 'seeks' + /// on the file system for the next row of information. + /// + /// As a performance test, a sample picture was timed. A family picture + /// was converted to Bitmap format; shrunk to 352 x 272 pixels and save + /// in 8-bit color format. The resulting file size was 94.5 KByte. + /// The SPI port interface was set to 20 MHz. + /// The original bitmap rendering software was purely in software, + /// pushing 1 pixel at a time to the write function, which did use SPI + /// hardware (not pin wiggling) to transfer commands and data to the + /// display. Then, the driver was improved to leverage the capability + /// of the derived display driver. As a final check, instead of the + /// [known slow] local file system, a randomly chosen USB stick was + /// used. The performance results are impressive (but depend on the + /// listed factors). + /// + /// \li 34 seconds, LocalFileSystem, Software Rendering + /// \li 9 seconds, LocalFileSystem, Hardware Rending for RA8875 + /// \li 3 seconds, MSCFileSystem, Hardware Rendering for RA8875 + /// + /// @param[in] x is the horizontal pixel coordinate + /// @param[in] y is the vertical pixel coordinate + /// @param[in] Name_BMP is the filename on the mounted file system. + /// @returns success or error code. + /// + RetCode_t RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP); + + + /// This method reads a disk file that is in ico format and + /// puts it on the screen. + /// + /// Reading the disk is slow, but a typical icon file is small + /// so it should be ok. + /// + /// @note An Icon file can have more than one icon in it. This + /// implementation only processes the first image in the file. + /// + /// @param[in] x is the horizontal pixel coordinate + /// @param[in] y is the vertical pixel coordinate + /// @param[in] Name_ICO is the filename on the mounted file system. + /// @returns success or error code. + /// + RetCode_t RenderIconFile(loc_t x, loc_t y, const char *Name_ICO); + + + /// prints one character at the specified coordinates. + /// + /// This will print the character at the specified pixel coordinates. + /// + /// @param[in] x is the horizontal offset in pixels. + /// @param[in] y is the vertical offset in pixels. + /// @param[in] value is the character to print. + /// @returns number of pixels to index to the right if a character was printed, 0 otherwise. + /// + virtual int character(int x, int y, int value); + + /// get the number of colums based on the currently active font + /// + /// @returns number of columns. + /// + virtual int columns(void); + + /// get the number of rows based on the currently active font + /// + /// @returns number of rows. + /// + virtual int rows(void); + + /// Select a bitmap font (provided by the user) for all subsequent text + /// rendering. + /// + /// This API permits selection of a special memory mapped font, which + /// enables the presentation of many font sizes and styles, including + /// proportional fonts. + /// + /// @note Tool to create the fonts is accessible from its creator + /// available at http://www.mikroe.com. + /// Hint: Change the data to an array of type char[]. + /// + /// This special font array has a 4-byte header, followed by + /// the data: + /// \li the number of bytes per char + /// \li the vertical size in pixels for each character + /// \li the horizontal size in pixels for each character + /// \li the number of bytes per vertical line (width of the array) + /// \li the subsequent records are the font information. + /// + /// @param[in] font is a pointer to a specially formed font array. + /// NULL, or the omission of this parameter will restore the default + /// font capability, which may use the display controllers hardware + /// font (if available), or no font. + /// @returns error code. + /// + virtual RetCode_t set_font(const unsigned char * font = NULL); + +protected: + + /// Pure virtual method indicating the start of a graphics stream. + /// + /// This is called prior to a stream of pixel data being sent. + /// This may cause register configuration changes in the derived + /// class in order to prepare the hardware to accept the streaming + /// data. + /// + /// @note this method must be supported in the derived class. + /// + /// @returns error code. + /// + virtual RetCode_t _StartGraphicsStream(void) = 0; + + /// Pure virtual method indicating the end of a graphics stream. + /// + /// This is called to conclude a stream of pixel data that was sent. + /// This may cause register configuration changes in the derived + /// class in order to stop the hardware from accept the streaming + /// data. + /// + /// @note this method must be supported in the derived class. + /// + /// @returns error code. + /// + virtual RetCode_t _EndGraphicsStream(void) = 0; + + /// Protected method to render an image given a file handle and + /// coordinates. + /// + /// @param[in] x is the horizontal pixel coordinate + /// @param[in] y is the vertical pixel coordinate + /// @param[in] w is the image width restriction, or zero to permit full image width. + /// @param[in] h is the image height restriction, or zero to permit full image height. + /// @param[in] fileOffset is the offset into the file where the image data starts + /// @param[in] Image is the filename stream already opened for the data. + /// @returns success or error code. + /// + RetCode_t _RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image); + + #ifdef LOCALFONT + virtual int blitbit(int x, int y, int w, int h, const char * color); + #endif + + const unsigned char * font; ///< reference to an external font somewhere in memory + + // pixel location + short _x; + short _y; + + // window location + short _x1; + short _x2; + short _y1; + short _y2; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/RA8875.cpp Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,2462 @@ +/// RA8875 Display Controller Library. +/// +/// This is being created for a Raio RA8875-based display from buydisplay.com, +/// which is 480 x 272 using a 4-wire SPI interface. Support is provided for +/// both a keypad and a resistive touch-screen. +/// +/// This display controller is used in other display resolutions, up to 800x600. +/// While this driver has not been tested with these variants, nothing was done +/// to prevent easily supporting them. +/// +#include "RA8875.h" + +//#define DEBUG "RAIO" +// ... +// INFO("Stuff to show %d", var); // new-line is automatically appended +// +#if (defined(DEBUG) && !defined(TARGET_LPC11U24)) +#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +static void HexDump(char * title, uint8_t * p, int count) +{ + int i; + char buf[100] = "0000: "; + + if (*title) + INFO("%s", title); + for (i=0; i<count; ) { + sprintf(buf + strlen(buf), "%02X ", *(p+i)); + if ((++i & 0x0F) == 0x00) { + INFO("%s", buf); + if (i < count) + sprintf(buf, "%04X: ", i); + else + buf[0] = '\0'; + } + } + if (strlen(buf)) + INFO("%s", buf); +} +#else +#define INFO(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) +#define HexDump(a, b, c) +#endif + + +#define RA8875_DISPLAY_WIDTH 480 +#define RA8875_DISPLAY_HEIGHT 272 +#define RA8875_COLORDEPTH_BPP 16 /* Not an API */ + +#ifdef PERF_METRICS +#define PERFORMANCE_RESET performance.reset() +#define REGISTERPERFORMANCE(a) RegisterPerformance(a) +#define COUNTIDLETIME(a) CountIdleTime(a) +static const char *metricsName[] = { + "Cls", "Pixel", "Pixel Stream", + "Read Pixel", "Read Pixel Stream", + "Line", + "Rectangle", "Rounded Rectangle", + "Triangle", "Circle", "Ellipse" +}; +#else +#define PERFORMANCE_RESET +#define REGISTERPERFORMANCE(a) +#define COUNTIDLETIME(a) +#endif + +// When it is going to poll a register for completion, how many +// uSec should it wait between each polling activity. +#define POLLWAITuSec 10 + +// Private RawKeyMap for the Keyboard interface +static const uint8_t DefaultKeyMap[22] = { + 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 255 +}; + +static const char * ErrMessages[] = { + "noerror", ///< no errors, command completed successfully + "bad_parameter", ///< one or more parameters are invalid + "file_not_found", ///< specified file could not be found + "not_bmp_format", ///< file is not a .bmp file + "not_ico_format", ///< file is not a .ico file + "not_supported_format", ///< file format is not yet supported + "image_too_big", ///< image is too large for the screen + "not_enough_ram", ///< could not allocate ram for scanline +}; + +RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char *name) + : GraphicsDisplay(name) + , spi(mosi, miso, sclk) + , cs(csel) + , res(reset) +{ +} + +//RA8875::~RA8875() +//{ +//} + +RetCode_t RA8875::init(int width, int height, int color_bpp, bool poweron, bool keypadon, bool touchscreenon) +{ + font = NULL; // no external font, use internal. + pKeyMap = DefaultKeyMap; // set default key map + _select(false); // deselect the display + frequency(RA8875_DEFAULT_SPI_FREQ); // data rate + Reset(); + WriteCommand(0x88, 0x0B); // PLLC1 - Phase Lock Loop registers + wait_ms(1); + WriteCommand(0x89, 0x02); + wait_ms(1); + + // System Config Register (SYSR) + if (color_bpp == 16) { + WriteCommand(0x10, 0x0C); // 16-bpp (65K colors) color depth, 8-bit interface + } else { // color_bpp == 8 + WriteCommand(0x10, 0x00); // 8-bpp (256 colors) + } + // Pixel Clock Setting Register (PCSR) + WriteCommand(0x04, 0x82); // PDAT on PCLK falling edge, PCLK = 4 x System Clock + wait_ms(1); + + // Horizontal Settings + WriteCommand(0x14, width/8 - 1); //HDWR//Horizontal Display Width Setting Bit[6:0] + WriteCommand(0x15, 0x02); //HNDFCR//Horizontal Non-Display Period fine tune Bit[3:0] + WriteCommand(0x16, 0x03); //HNDR//Horizontal Non-Display Period Bit[4:0] + WriteCommand(0x17, 0x01); //HSTR//HSYNC Start Position[4:0] + WriteCommand(0x18, 0x03); //HPWR//HSYNC Polarity ,The period width of HSYNC. + + // Vertical Settings + WriteCommand(0x19, (height-1)&0xFF); //VDHR0 //Vertical Display Height Bit [7:0] + WriteCommand(0x1a, (height-1)>>8); //VDHR1 //Vertical Display Height Bit [8] + WriteCommand(0x1b, 0x0F); //VNDR0 //Vertical Non-Display Period Bit [7:0] + WriteCommand(0x1c, 0x00); //VNDR1 //Vertical Non-Display Period Bit [8] + WriteCommand(0x1d, 0x0e); //VSTR0 //VSYNC Start Position[7:0] + WriteCommand(0x1e, 0x06); //VSTR1 //VSYNC Start Position[8] + WriteCommand(0x1f, 0x01); //VPWR //VSYNC Polarity ,VSYNC Pulse Width[6:0] + + if (width >= 800 && height >= 480 && color_bpp > 8) { + WriteCommand(0x20, 0x00); // DPCR - 1-layer mode when the resolution is too high + } else { + WriteCommand(0x20, 0x80); // DPCR - 2-layer mode + } + + // Set display image to Blue on Black as default + window(0,0, width, height); // Initialize to full screen + SetTextCursorControl(); + foreground(Blue); + background(Black); + cls(3); + + Power(poweron); + if (poweron) + Backlight_u8(255); + if (keypadon) + KeypadInit(); + if (touchscreenon) + TouchPanelInit(); +#ifdef PERF_METRICS + performance.start(); + ClearPerformance(); +#endif + return noerror; +} + + +RetCode_t RA8875::Reset(void) +{ + RetCode_t ret; + + ret = WriteCommand(0x01, 0x01); // Apply Display Off, Reset + wait_ms(2); // no idea if I need to wait, or how long + if (ret == noerror) { + ret = WriteCommand(0x01, 0x00); // Display off, Remove reset + wait_ms(2); // no idea if I need to wait, or how long + } + return ret; +} + + +const char * RA8875::GetErrorMessage(RetCode_t code) +{ + if (code >= LastErrCode) + code = bad_parameter; + return ErrMessages[code]; +} + + +uint16_t RA8875::GetDrawingLayer(void) +{ + return (ReadCommand(0x41) & 0x01); +} + + +RetCode_t RA8875::SelectDrawingLayer(uint16_t layer) +{ + unsigned char mwcr1 = ReadCommand(0x41) & ~0x01; // retain all but the currently selected layer + + if (width() >= 800 && height() >= 480 && color_bpp() == 8) { + return bad_parameter; + } else if (layer > 1) { + return bad_parameter; + } else { // layer == 0 ro 1 + return WriteCommand(0x41, mwcr1 | layer); + } +} + + +RetCode_t RA8875::SetLayerMode(LayerMode_T mode) +{ + unsigned char ltpr0 = ReadCommand(0x52) & ~0x7; // retain all but the display layer mode + if (mode <= (LayerMode_T)6) { + WriteCommand(0x52, ltpr0 | (mode & 0x7)); + return noerror; + } else { + return bad_parameter; + } +} + + +RetCode_t RA8875::SetLayerTransparency(uint8_t layer1, uint8_t layer2) +{ + if (layer1 > 8) + layer1 = 8; + if (layer2 > 8) + layer2 = 8; + WriteCommand(0x53, ((layer2 & 0xF) << 4) | (layer1 & 0xF)); + return noerror; +} + + +RetCode_t RA8875::SetBackgroundTransparencyColor(color_t color) +{ + WriteCommand(0x67, (color >> 11) & 0x1F); + WriteCommand(0x68, (color >> 5) & 0x3F); + WriteCommand(0x69, (color & 0x1F)); + return noerror; +} + + +color_t RA8875::GetBackgroundTransparencyColor(void) +{ + RGBQUAD q; + q.rgbRed = ReadCommand(0x67); + q.rgbGreen = ReadCommand(0x68); + q.rgbBlue = ReadCommand(0x69); + return RGBQuadToRGB16(&q, 0); +} + + +RetCode_t RA8875::KeypadInit(bool scanEnable, bool longDetect, uint8_t sampleTime, uint8_t scanFrequency, + uint8_t longTimeAdjustment, bool interruptEnable, bool wakeupEnable) +{ + uint8_t value = 0; + + if (sampleTime > 3 || scanFrequency > 7 || longTimeAdjustment > 3) + return bad_parameter; + value |= (scanEnable) ? 0x80 : 0x00; + value |= (longDetect) ? 0x40 : 0x00; + value |= (sampleTime & 0x03) << 4; + value |= (scanFrequency & 0x07); + WriteCommand(0xC0, value); // KSCR1 - Enable Key Scan (and ignore possibility of an error) + + value = 0; + value |= (wakeupEnable) ? 0x80 : 0x00; + value |= (longTimeAdjustment & 0x03) << 2; + WriteCommand(0xC1, value); // KSCR2 - (and ignore possibility of an error) + + value = ReadCommand(0xF0); // (and ignore possibility of an error) + value &= ~0x10; + value |= (interruptEnable) ? 0x10 : 0x00; + return WriteCommand(0xF0, value); // INT +} + + +RetCode_t RA8875::SetKeyMap(const uint8_t * CodeList) +{ + pKeyMap = CodeList; + return noerror; +} + + +bool RA8875::readable(void) +{ + return (ReadCommand(0xF1) & 0x10); // check KS status - true if kbhit +} + + +uint8_t RA8875::getc(void) +{ + //#define GETC_DEV // for development +#ifdef GETC_DEV + uint8_t keyCode1, keyCode2; +#endif + uint8_t keyCode3; + static uint8_t count = 0; + uint8_t col, row; + uint8_t key; + + while (!readable()) { + wait_us(POLLWAITuSec); + // COUNTIDLETIME(POLLWAITuSec); // As it is voluntary to call the getc and pend. Don't tally it. + } + // read the key press number + uint8_t keyNumReg = ReadCommand(0xC1) & 0x03; + count++; + switch (keyNumReg) { + case 0x01: // one key + keyCode3 = ReadCommand(0xC2); +#ifdef GETC_DEV + keyCode2 = 0; + keyCode1 = 0; +#endif + break; + case 0x02: // two keys + keyCode3 = ReadCommand(0xC3); +#ifdef GETC_DEV + keyCode2 = ReadCommand(0xC2); + keyCode1 = 0; +#endif + break; + case 0x03: // three keys + keyCode3 = ReadCommand(0xC4); +#ifdef GETC_DEV + keyCode2 = ReadCommand(0xC3); + keyCode1 = ReadCommand(0xC2); +#endif + break; + default: // no keys (key released) + keyCode3 = 0xFF; +#ifdef GETC_DEV + keyCode2 = 0; + keyCode1 = 0; +#endif + break; + } + if (keyCode3 == 0xFF) + key = pKeyMap[0]; // Key value 0 + else { + row = (keyCode3 >> 4) & 0x03; + col = (keyCode3 & 7); + key = row * 5 + col + 1; // Keys value 1 - 20 + if (key > 21) { + key = 21; + } + key = pKeyMap[key]; + key |= (keyCode3 & 0x80); // combine the key held flag + } +#if GETC_DEV // for Development only + SetTextCursor(0, 20); + printf(" Reg: %02x\r\n", keyNumReg); + printf(" key1: %02x\r\n", keyCode1); + printf(" key2: %02x\r\n", keyCode2); + printf(" key3: %02x\r\n", keyCode3); + printf(" count: %02X\r\n", count); + printf(" key: %02X\r\n", key); +#endif + WriteCommand(0xF1, 0x10); // Clear KS status + return key; +} + + +#ifdef PERF_METRICS +void RA8875::ClearPerformance() +{ + for (int i=0; i<METRICCOUNT; i++) + metrics[i] = 0; + idletime_usec = 0; +} + + +void RA8875::RegisterPerformance(method_e method) +{ + unsigned long elapsed = performance.read_us(); + + if (method < METRICCOUNT && elapsed > metrics[method]) + metrics[method] = elapsed; +} + + +void RA8875::CountIdleTime(uint32_t t) +{ + idletime_usec += t; +} + + +void RA8875::ReportPerformance(Serial & pc) +{ + pc.printf("\r\nPerformance Metrics\r\n"); + for (int i=0; i<METRICCOUNT; i++) { + pc.printf("%10d uS %s\r\n", metrics[i], metricsName[i]); + } + pc.printf("%10d uS Idle time polling display for ready.\r\n", idletime_usec); +} +#endif + + +RetCode_t RA8875::WriteCommandW(uint8_t command, uint16_t data) +{ +#if 1 + WriteCommand(command, data & 0xFF); + WriteCommand(command+1, data >> 8); +#else + // This should be a little faster, but doesn't work... + INFO("WriteCommandW(%02X, %04X)", command, data); + _select(true); + _spiwrite(0x80); + _spiwrite(command); + //_spiwrite(0x00); // dummy + _spiwrite(data & 0xFF); + _spiwrite(data >> 8); + _select(false); +#endif + return noerror; +} + + +RetCode_t RA8875::WriteCommand(unsigned char command, unsigned int data) +{ + _select(true); + _spiwrite(0x80); // cmd: write command + _spiwrite(command); + if (data <= 0xFF) { // only if in the valid range + _spiwrite(0x00); + _spiwrite(data); + } + _select(false); + return noerror; +} + + +RetCode_t RA8875::WriteDataW(uint16_t data) +{ + _select(true); + _spiwrite(0x00); // cmd: write data + _spiwrite(data & 0xFF); + _spiwrite(data >> 8); + _select(false); + return noerror; +} + + +RetCode_t RA8875::WriteData(unsigned char data) +{ + _select(true); + _spiwrite(0x00); + _spiwrite(data); + _select(false); + return noerror; +} + + +unsigned char RA8875::ReadCommand(unsigned char command) +{ + WriteCommand(command); + return ReadData(); +} + + +unsigned char RA8875::ReadData(void) +{ + unsigned char data; + + _select(true); + _spiwrite(0x40); + data = _spiread(); + _select(false); + return data; +} + + +uint16_t RA8875::ReadDataW(void) +{ + uint16_t data; + + _select(true); + _spiwrite(0x40); + data = _spiread(); + data |= (_spiread() << 8); + _select(false); + return data; +} + + +unsigned char RA8875::ReadStatus(void) +{ + unsigned char data; + + _select(true); + _spiwrite(0xC0); // These two bits are for the special "Status Read" [STSR] + data = _spiread(); + _select(false); + return data; +} + + +/// @todo add a timeout and return false, but how long +/// to wait since some operations can be very long. +bool RA8875::_WaitWhileBusy(uint8_t mask) +{ + int i = 20000/POLLWAITuSec; // 20 msec max + + while (i-- && ReadStatus() & mask) { + wait_us(POLLWAITuSec); + COUNTIDLETIME(POLLWAITuSec); + } + if (i) + return true; + else + return false; +} + + +/// @todo add a timeout and return false, but how long +/// to wait since some operations can be very long. +bool RA8875::_WaitWhileReg(uint8_t reg, uint8_t mask) +{ + int i = 20000/POLLWAITuSec; // 20 msec max + + while (i-- && ReadCommand(reg) & mask) { + wait_us(POLLWAITuSec); + COUNTIDLETIME(POLLWAITuSec); + } + if (i) + return true; + else + return false; +} + + +dim_t RA8875::fontwidth(void) +{ + if (font == NULL) + return (((ReadCommand(0x22) >> 2) & 0x3) + 1) * 8; + else + return font[1]; +} + + +dim_t RA8875::fontheight(void) +{ + if (font == NULL) + return (((ReadCommand(0x22) >> 0) & 0x3) + 1) * 16; + else + return font[2]; +} + + +RetCode_t RA8875::locate(textloc_t column, textloc_t row) +{ + return SetTextCursor(column * fontwidth(), row * fontheight()); +} + + +int RA8875::columns(void) +{ + return width() / fontwidth(); +} + + +int RA8875::rows(void) +{ + return height() / fontheight(); +} + + +dim_t RA8875::width(void) +{ + return (ReadCommand(0x14) + 1) * 8; +} + + +dim_t RA8875::height(void) +{ + return (ReadCommand(0x19) | (ReadCommand(0x1A) << 8)) + 1; +} + + +dim_t RA8875::color_bpp(void) +{ + if ((ReadCommand(0x10) & 0x0C) == 0x04) + return 16; + else + return 8; +} + + +RetCode_t RA8875::SetTextCursor(loc_t x, loc_t y) +{ + cursor_x = x; // set these values for non-internal fonts + cursor_y = y; + WriteCommandW(0x2A, x); + WriteCommandW(0x2C, y); + return noerror; +} + + +loc_t RA8875::GetTextCursor_Y(void) +{ + if (font == NULL) + return ReadCommand(0x2C) | (ReadCommand(0x2D) << 8); + else + return cursor_y; +} + + +loc_t RA8875::GetTextCursor_X(void) +{ + if (font == NULL) + return ReadCommand(0x2A) | (ReadCommand(0x2B) << 8); + else + return cursor_x; +} + + +RetCode_t RA8875::SetTextCursorControl(cursor_t cursor, bool blink) +{ + unsigned char mwcr0 = ReadCommand(0x40) & 0x0F; // retain direction, auto-increase + unsigned char mwcr1 = ReadCommand(0x41) & 0x01; // retain currently selected layer + unsigned char horz = 0; + unsigned char vert = 0; + + mwcr0 |= 0x80; // text mode + if (cursor != NOCURSOR) + mwcr0 |= 0x40; // visible + if (blink) + mwcr0 |= 0x20; // blink + WriteCommand(0x40, mwcr0); // configure the cursor + WriteCommand(0x41, mwcr1); // close the graphics cursor + WriteCommand(0x44, 0x1f); // The cursor flashing cycle + switch (cursor) { + case IBEAM: + horz = 0x01; + vert = 0x1F; + break; + case UNDER: + horz = 0x07; + vert = 0x01; + break; + case BLOCK: + horz = 0x07; + vert = 0x1F; + break; + case NOCURSOR: + default: + break; + } + WriteCommand(0x4e, horz); // The cursor size horz + WriteCommand(0x4f, vert); // The cursor size vert + return noerror; +} + + +RetCode_t RA8875::SetTextFont(RA8875::font_t font) +{ + if (/*font >= RA8875::ISO8859_1 && */ font <= RA8875::ISO8859_4) { + WriteCommand(0x21, (unsigned int)(font)); + return noerror; + } else { + return bad_parameter; + } +} + + +RetCode_t RA8875::SetTextFontControl(fill_t fillit, + RA8875::font_angle_t angle, + RA8875::HorizontalScale hScale, + RA8875::VerticalScale vScale, + RA8875::alignment_t alignment) +{ + if (hScale >= 1 && hScale <= 4 && + vScale >= 1 && vScale <= 4) { + unsigned char x = 0; + + if (alignment == align_full) + x |= 0x80; + if (fillit == NOFILL) + x |= 0x40; + if (angle == rotated) + x |= 0x10; + x |= ((hScale - 1) << 2); + x |= ((vScale - 1) << 0); + WriteCommand(0x22, x); + return noerror; + } else { + return bad_parameter; + } +} + + +RetCode_t RA8875::SetTextFontSize(RA8875::HorizontalScale hScale, RA8875::VerticalScale vScale) +{ + unsigned char reg = ReadCommand(0x22); + + if (vScale == -1) + vScale = hScale; + if (hScale >= 1 && hScale <= 4 && vScale >= 1 && vScale <= 4) { + reg &= 0xF0; // keep the high nibble as is. + reg |= ((hScale - 1) << 2); + reg |= ((vScale - 1) << 0); + WriteCommand(0x22, reg); + return noerror; + } else { + return bad_parameter; + } +} + + +int RA8875::_putc(int c) +{ + if (font == NULL) { + return _internal_putc(c); + } else { + return _external_putc(c); + } +} + + +int RA8875::_external_putc(int c) +{ + if (c) { + if (c == '\r') { + cursor_x = 0; + } else if (c == '\n') { + cursor_y += font[2]; + } else { + int advance = character(cursor_x, cursor_y, c); // advance tells us how many pixels we advanced + //INFO("x,y,advance %d,%d,%d", cursor_x, cursor_y, advance); + if (advance) { + cursor_x += advance; + if (cursor_x >= width()) { + cursor_x = 0; + cursor_y += font[2]; + if (cursor_y >= height()) { + cursor_y = 0; // @todo Should it scroll? + } + } + } + } + } + return c; +} + + +int RA8875::_internal_putc(int c) +{ + if (c) { + unsigned char mwcr0; + + mwcr0 = ReadCommand(0x40); + if ((mwcr0 & 0x80) == 0x00) { + WriteCommand(0x40, 0x80 | mwcr0); // Put in Text mode if not already + } + if (c == '\r') { + loc_t x; + x = ReadCommand(0x30) | (ReadCommand(0x31) << 8); // Left edge of active window + WriteCommandW(0x2A, x); + } else if (c == '\n') { + loc_t y; + y = ReadCommand(0x2C) | (ReadCommand(0x2D) << 8); // current y location + y += fontheight(); + if (y >= height()) // @TODO after bottom of active window, then scroll window? + y = 0; + WriteCommandW(0x2C, y); + } else { + WriteCommand(0x02); // RA8875 Internal Fonts + _select(true); + WriteData(c); + _WaitWhileBusy(0x80); + _select(false); + } + } + return c; +} + + +RetCode_t RA8875::_StartGraphicsStream(void) +{ + WriteCommand(0x40,0x00); // Graphics write mode + WriteCommand(0x02); // Prepare for streaming data + return noerror; +} + + +RetCode_t RA8875::_EndGraphicsStream(void) +{ + return noerror; +} + + +RetCode_t RA8875::_putp(color_t pixel) +{ + WriteDataW((pixel>>8) | (pixel<<8)); + return noerror; +} + + +void RA8875::puts(loc_t x, loc_t y, const char * string) +{ + SetTextCursor(x,y); + puts(string); +} + + +void RA8875::puts(const char * string) +{ + unsigned char mwcr0 = ReadCommand(0x40); + + if (font == NULL) { + if ((mwcr0 & 0x80) == 0x00) + WriteCommand(0x40,0x80); // Put in Text mode if not already + } else { + _StartGraphicsStream(); + } + if (*string != '\0') { +#if 1 + while (*string) { // @TODO calling individual _putc is slower... optimizations? + _putc(*string++); + } +#else + WriteCommand(0x02); + _select(true); + while (*string != '\0') { + WriteData(*string); + ++string; + _WaitWhileBusy(0x80); + } + _select(false); +#endif + } + if (font) + _EndGraphicsStream(); +} + + +RetCode_t RA8875::SetGraphicsCursor(loc_t x, loc_t y) +{ + WriteCommandW(0x46, x); + WriteCommandW(0x48, y); + return noerror; +} + + +RetCode_t RA8875::SetGraphicsCursorRead(loc_t x, loc_t y) +{ + //WriteCommand(0x40, 0); // Graphics mode + //WriteCommand(0x45, 0); // left->right, top->bottom + WriteCommandW(0x4A, x); + WriteCommandW(0x4C, y); + return noerror; +} + + +RetCode_t RA8875::window(loc_t x, loc_t y, dim_t width, dim_t height) +{ + GraphicsDisplay::window(x,y, width,height); + WriteCommandW(0x30, x); + WriteCommandW(0x32, y); + WriteCommandW(0x34, (x+width-1)); + WriteCommandW(0x36, (y+height-1)); + SetGraphicsCursor(x,y); + return noerror; +} + + +RetCode_t RA8875::cls(uint16_t layers) +{ + RetCode_t ret; + + PERFORMANCE_RESET; + if (layers == 0) { + ret = clsw(FULLWINDOW); + ret = SetTextCursor(0,0); + } else if (layers > 3) { + ret = bad_parameter; + } else { + uint16_t prevLayer = GetDrawingLayer(); + if (layers & 1) { + SelectDrawingLayer(0); + clsw(FULLWINDOW); + } + if (layers & 2) { + SelectDrawingLayer(1); + clsw(FULLWINDOW); + } + ret = SelectDrawingLayer(prevLayer); + } + REGISTERPERFORMANCE(PRF_CLS); + return ret; +} + + +RetCode_t RA8875::clsw(RA8875::Region_t region) +{ + PERFORMANCE_RESET; + WriteCommand(0x8E, (region == ACTIVEWINDOW) ? 0xC0 : 0x80); + _WaitWhileReg(0x8E, 0x80); + REGISTERPERFORMANCE(PRF_CLS); + return noerror; +} + + +RetCode_t RA8875::pixel(loc_t x, loc_t y, color_t color) +{ + RetCode_t ret; + + PERFORMANCE_RESET; +#if 1 + ret = pixelStream(&color, 1, x,y); +#else + foreground(color); + ret = pixel(x,y); +#endif + REGISTERPERFORMANCE(PRF_DRAWPIXEL); + return ret; +} + + +RetCode_t RA8875::pixel(loc_t x, loc_t y) +{ + RetCode_t ret; + + PERFORMANCE_RESET; + color_t color = GetForeColor(); +#if 1 + ret = pixelStream(&color, 1, x, y); +#else + WriteCommand(0x40,0x00); // Graphics write mode + SetGraphicsCursor(x, y); + WriteCommand(0x02); + WriteDataW(color); + ret = noerror; +#endif + REGISTERPERFORMANCE(PRF_DRAWPIXEL); + return ret; +} + + +RetCode_t RA8875::pixelStream(color_t * p, uint32_t count, loc_t x, loc_t y) +{ + PERFORMANCE_RESET; + WriteCommand(0x40,0x00); // Graphics write mode + SetGraphicsCursor(x, y); + WriteCommand(0x02); + _select(true); + _spiwrite(0x00); // Cmd: write data + while (count--) { + _spiwrite(*p >> 8); + _spiwrite(*p & 0xFF); + p++; + } + _select(false); + REGISTERPERFORMANCE(PRF_PIXELSTREAM); + return(noerror); +} + + +color_t RA8875::getPixel(loc_t x, loc_t y) +{ + color_t pixel; + + PERFORMANCE_RESET; + //WriteCommand(0x45,0x00); // read left->right, top->bottom + WriteCommand(0x40,0x00); // Graphics write mode + SetGraphicsCursorRead(x, y); + WriteCommand(0x02); + _select(true); + _spiwrite(0x40); // Cmd: read data + _spiwrite(0x00); // dummy read + pixel = _spiread(); + pixel |= (_spiread() << 8); + _select(false); + REGISTERPERFORMANCE(PRF_READPIXEL); + return pixel; +} + + +RetCode_t RA8875::getPixelStream(color_t * p, uint32_t count, loc_t x, loc_t y) +{ + color_t pixel; + + PERFORMANCE_RESET; + //WriteCommand(0x45,0x00); // read left->right, top->bottom + WriteCommand(0x40,0x00); // Graphics write mode + SetGraphicsCursorRead(x, y); + WriteCommand(0x02); + _select(true); + _spiwrite(0x40); // Cmd: read data + _spiwrite(0x00); // dummy read + while (count--) { + pixel = _spiread(); + pixel |= (_spiread() << 8); + *p++ = pixel; + } + _select(false); + REGISTERPERFORMANCE(PRF_READPIXELSTREAM); + return noerror; +} + + +RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2, color_t color) +{ + foreground(color); + return line(x1,y1,x2,y2); +} + + +RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2) +{ + PERFORMANCE_RESET; + if (x1 == x2 && y1 == y2) { + pixel(x1, y1); + } else { + WriteCommandW(0x91, x1); + WriteCommandW(0x93, y1); + WriteCommandW(0x95, x2); + WriteCommandW(0x97, y2); + unsigned char drawCmd = 0x00; // Line + WriteCommand(0x90, drawCmd); + WriteCommand(0x90, 0x80 + drawCmd); // Start drawing. + _WaitWhileReg(0x90, 0x80); + } + REGISTERPERFORMANCE(PRF_DRAWLINE); + return noerror; +} + +RetCode_t RA8875::fillrect(rect_t r, color_t color, fill_t fillit) +{ + return rect(r.p1.x, r.p1.y, r.p2.x, r.p2.y, color, fillit); +} + +RetCode_t RA8875::fillrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + color_t color, fill_t fillit) +{ + return rect(x1,y1,x2,y2,color,fillit); +} + +RetCode_t RA8875::rect(rect_t r, color_t color, fill_t fillit) +{ + return rect(r.p1.x, r.p1.y, r.p2.x, r.p2.y, color, fillit); +} + +RetCode_t RA8875::rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + color_t color, fill_t fillit) +{ + foreground(color); + return rect(x1,y1,x2,y2,fillit); +} + + +RetCode_t RA8875::rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + fill_t fillit) +{ + PERFORMANCE_RESET; + if (x1 == x2 && y1 == y2) { + pixel(x1, y1); + } else if (x1 == x2) { + line(x1, y1, x2, y2); + } else if (y1 == y2) { + line(x1, y1, x2, y2); + } else { + WriteCommandW(0x91, x1); + WriteCommandW(0x93, y1); + WriteCommandW(0x95, x2); + WriteCommandW(0x97, y2); + unsigned char drawCmd = 0x10; // Rectangle + if (fillit == FILL) + drawCmd |= 0x20; + WriteCommand(0x90, drawCmd); + WriteCommand(0x90, 0x80 + drawCmd); // Start drawing. + _WaitWhileReg(0x90, 0x80); + } + REGISTERPERFORMANCE(PRF_DRAWRECTANGLE); + return noerror; +} + + +RetCode_t RA8875::fillroundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + dim_t radius1, dim_t radius2, color_t color, fill_t fillit) +{ + foreground(color); + return roundrect(x1,y1,x2,y2,radius1,radius2,fillit); +} + + +RetCode_t RA8875::roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + dim_t radius1, dim_t radius2, color_t color, fill_t fillit) +{ + foreground(color); + return roundrect(x1,y1,x2,y2,radius1,radius2,fillit); +} + + +RetCode_t RA8875::roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + dim_t radius1, dim_t radius2, fill_t fillit) +{ + RetCode_t ret = noerror; + + PERFORMANCE_RESET; + if (x1 > x2 || y1 > y2 || (radius1 > (x2-x1)/2) || (radius2 > (y2-y1)/2) ) { + ret = bad_parameter; + } else if (x1 == x2 && y1 == y2) { + pixel(x1, y1); + } else if (x1 == x2) { + line(x1, y1, x2, y2); + } else if (y1 == y2) { + line(x1, y1, x2, y2); + } else { + WriteCommandW(0x91, x1); + WriteCommandW(0x93, y1); + WriteCommandW(0x95, x2); + WriteCommandW(0x97, y2); + WriteCommandW(0xA1, radius1); + WriteCommandW(0xA3, radius2); + // Should not need this... + WriteCommandW(0xA5, 0); + WriteCommandW(0xA7, 0); + unsigned char drawCmd = 0x20; // Rounded Rectangle + if (fillit == FILL) + drawCmd |= 0x40; + WriteCommand(0xA0, drawCmd); + WriteCommand(0xA0, 0x80 + drawCmd); // Start drawing. + _WaitWhileReg(0xA0, 0x80); + } + REGISTERPERFORMANCE(PRF_DRAWROUNDEDRECTANGLE); + return ret; +} + + +RetCode_t RA8875::triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + loc_t x3, loc_t y3, color_t color, fill_t fillit) +{ + RetCode_t ret; + + foreground(color); + ret = triangle(x1,y1,x2,y2,x3,y3,fillit); + return ret; +} + + +RetCode_t RA8875::filltriangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + loc_t x3, loc_t y3, color_t color, fill_t fillit) +{ + RetCode_t ret; + + foreground(color); + ret = triangle(x1,y1,x2,y2,x3,y3,fillit); + return ret; +} + + +RetCode_t RA8875::triangle(loc_t x1, loc_t y1 ,loc_t x2, loc_t y2, + loc_t x3, loc_t y3, fill_t fillit) +{ + RetCode_t ret = noerror; + + PERFORMANCE_RESET; + if (x1 == x2 && y1 == y2 && x1 == x3 && y1 == y3) { + pixel(x1, y1); + } else { + WriteCommandW(0x91, x1); + WriteCommandW(0x93, y1); + WriteCommandW(0x95, x2); + WriteCommandW(0x97, y2); + WriteCommandW(0xA9, x3); + WriteCommandW(0xAB, y3); + unsigned char drawCmd = 0x01; // Triangle + if (fillit == FILL) + drawCmd |= 0x20; + WriteCommand(0x90, drawCmd); + WriteCommand(0x90, 0x80 + drawCmd); // Start drawing. + _WaitWhileReg(0x90, 0x80); + } + REGISTERPERFORMANCE(PRF_DRAWTRIANGLE); + return ret; +} + +RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, + color_t color, fill_t fillit) +{ + foreground(color); + return circle(x,y,radius,fillit); +} + + +RetCode_t RA8875::fillcircle(loc_t x, loc_t y, dim_t radius, + color_t color, fill_t fillit) +{ + foreground(color); + return circle(x,y,radius,fillit); +} + + +RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius, fill_t fillit) +{ + RetCode_t ret = noerror; + + PERFORMANCE_RESET; + if (radius <= 0) { + ret = bad_parameter; + } else if (radius == 1) { + pixel(x,y); + } else { + WriteCommandW(0x99, x); + WriteCommandW(0x9B, y); + WriteCommand(0x9d, radius & 0xFF); + unsigned char drawCmd = 0x00; // Circle + if (fillit == FILL) + drawCmd |= 0x20; + WriteCommand(0x90, drawCmd); + WriteCommand(0x90, 0x40 + drawCmd); // Start drawing. + _WaitWhileReg(0x90, 0x40); + } + REGISTERPERFORMANCE(PRF_DRAWCIRCLE); + return ret; +} + + +RetCode_t RA8875::ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, color_t color, fill_t fillit) +{ + foreground(color); + return ellipse(x,y,radius1,radius2,fillit); +} + + +RetCode_t RA8875::fillellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, color_t color, fill_t fillit) +{ + foreground(color); + return ellipse(x,y,radius1,radius2,fillit); +} + + +RetCode_t RA8875::ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, fill_t fillit) +{ + RetCode_t ret = noerror; + + PERFORMANCE_RESET; + if (radius1 <= 0 || radius2 <= 0) { + ; // do nothing + } else if (radius1 == 1 && radius2 == 1) { + pixel(x, y); + } else { + WriteCommandW(0xA5, x); + WriteCommandW(0xA7, y); + WriteCommandW(0xA1, radius1); + WriteCommandW(0xA3, radius2); + unsigned char drawCmd = 0x00; // Ellipse + if (fillit == FILL) + drawCmd |= 0x40; + WriteCommand(0xA0, drawCmd); + WriteCommand(0xA0, 0x80 + drawCmd); // Start drawing. + _WaitWhileReg(0xA0, 0x80); + } + REGISTERPERFORMANCE(PRF_DRAWELLIPSE); + return ret; +} + + +RetCode_t RA8875::frequency(unsigned long Hz, unsigned long Hz2) +{ + spiwritefreq = Hz; + if (Hz2 != 0) + spireadfreq = Hz2; + else + spireadfreq = Hz/2; + _setWriteSpeed(true); + // __ ___ + // Clock ___A Rising edge latched + // ___ ____ + // Data ___X____ + spi.format(8, 3); // 8 bits and clock to data phase 0 + return noerror; +} + +void RA8875::_setWriteSpeed(bool writeSpeed) +{ + if (writeSpeed) { + spi.frequency(spiwritefreq); + spiWriteSpeed = true; + } else { + spi.frequency(spireadfreq); + spiWriteSpeed = false; + } +} + +RetCode_t RA8875::Power(bool on) +{ + WriteCommand(0x01, (on) ? 0x80 : 0x00); + return noerror; +} + + +RetCode_t RA8875::Backlight_u8(unsigned char brightness) +{ + static bool is_enabled = false; + if (brightness == 0) { + WriteCommand(0x8a); // Disable the PWM + WriteData(0x00); + is_enabled = false; + } else if (!is_enabled) { + WriteCommand(0x8a); // Enable the PWM + WriteData(0x80); + WriteCommand(0x8a); // Not sure why this is needed, but following the pattern + WriteData(0x81); // open PWM (SYS_CLK / 2 as best I can tell) + is_enabled = true; + } + WriteCommand(0x8b, brightness); // Brightness parameter 0xff-0x00 + return noerror; +} + + +RetCode_t RA8875::Backlight(float brightness) +{ + unsigned char b; + + if (brightness >= 1.0) + b = 255; + else if (brightness <= 0.0) + b = 0; + else + b = (unsigned char)(brightness * 255); + return Backlight_u8(b); +} + + +RetCode_t RA8875::set_font(const unsigned char * _font) +{ + if (font && ! _font) { + SetTextCursor(cursor_x, cursor_y); // soft-font cursor -> hw cursor + } + font = _font; + GraphicsDisplay::set_font(_font); + return noerror; // trusting them, but it might be good to put some checks in here... +} + + +RetCode_t RA8875::background(color_t color) +{ + GraphicsDisplay::background(color); + WriteCommand(0x60, (color>>11)); // BGCR0 + WriteCommand(0x61, (unsigned char)(color>>5)); // BGCR0 + WriteCommand(0x62, (unsigned char)(color)); // BGCR0 + return noerror; +} + + +RetCode_t RA8875::background(unsigned char r, unsigned char g, unsigned char b) +{ + background(RGB(r,g,b)); +// WriteCommand(0x60, r); +// WriteCommand(0x61, g); +// WriteCommand(0x62, b); + return noerror; +} + + +RetCode_t RA8875::foreground(color_t color) +{ + GraphicsDisplay::foreground(color); + WriteCommand(0x63, (unsigned char)(color>>11)); + WriteCommand(0x64, (unsigned char)(color>>5)); + WriteCommand(0x65, (unsigned char)(color)); + return noerror; +} + + +RetCode_t RA8875::foreground(unsigned char r, unsigned char g, unsigned char b) +{ + foreground(RGB(r,g,b)); +// WriteCommand(0x63, r); +// WriteCommand(0x64, g); +// WriteCommand(0x65, b); + return noerror; +} + + +color_t RA8875::GetForeColor(void) +{ + color_t color; + + color = (ReadCommand(0x63) & 0x1F) << 11; + color |= (ReadCommand(0x64) & 0x3F) << 5; + color |= (ReadCommand(0x65) & 0x1F); + return color; +} + + +color_t RA8875::DOSColor(int i) +{ + const color_t colors[16] = { + Black, Blue, Green, Cyan, + Red, Magenta, Brown, Gray, + Charcoal, BrightBlue, BrightGreen, BrightCyan, + Orange, Pink, Yellow, White + }; + if (i < 16) + return colors[i]; + else + return 0; +} + + +const char * RA8875::DOSColorNames(int i) +{ + const char * names[16] = { + "Black", "Blue", "Green", "Cyan", + "Red", "Magenta", "Brown", "Gray", + "Charcoal", "BrightBlue", "BrightGreen", "BrightCyan", + "Orange", "Pink", "Yellow", "White" + }; + if (i < 16) + return names[i]; + else + return NULL; +} + + +/////////////////////////////////////////////////////////////// +// Private functions + +unsigned char RA8875::_spiwrite(unsigned char data) +{ + unsigned char retval; + + if (!spiWriteSpeed) + _setWriteSpeed(true); + retval = spi.write(data); + return retval; +} + + +unsigned char RA8875::_spiread(void) +{ + unsigned char retval; + unsigned char data = 0; + + if (spiWriteSpeed) + _setWriteSpeed(false); + retval = spi.write(data); + return retval; +} + + +RetCode_t RA8875::_select(bool chipsel) +{ + cs = (chipsel == true) ? 0 : 1; + return noerror; +} + + +RetCode_t RA8875::PrintScreen(uint16_t layer, loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) +{ +#if 1 + (void)layer; + return PrintScreen(x, y, w, h, Name_BMP); +#else + // This is the deprecated interface and with the changes it is no longer implemented correctly. + uint16_t curLayer = GetDrawingLayer(); + RetCode_t ret = SelectDrawingLayer(layer); + if (ret == noerror) { + ret = PrintScreen(x, y, w, h, Name_BMP); + } + SelectDrawingLayer(curLayer); + return ret; +#endif +} + + +RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) +{ + BITMAPFILEHEADER BMP_Header; + BITMAPINFOHEADER BMP_Info; + + INFO("(%d,%d) - (%d,%d) %s", x,y,w,h,Name_BMP); + if (x >= 0 && x < width() + && y >= 0 && y < height() + && w > 0 && x + w <= width() + && h > 0 && y + h <= height()) { + + BMP_Header.bfType = BF_TYPE; + BMP_Header.bfSize = (w * h * sizeof(RGBQUAD)) + sizeof(BMP_Header) + sizeof(BMP_Header); + BMP_Header.bfReserved1 = 0; + BMP_Header.bfReserved2 = 0; + BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Header); + + BMP_Info.biSize = sizeof(BMP_Info); + BMP_Info.biWidth = w; + BMP_Info.biHeight = h; + BMP_Info.biPlanes = 1; + BMP_Info.biBitCount = 24; + BMP_Info.biCompression = BI_RGB; + BMP_Info.biSizeImage = 0; + BMP_Info.biXPelsPerMeter = 0; + BMP_Info.biYPelsPerMeter = 0; + BMP_Info.biClrUsed = 0; + BMP_Info.biClrImportant = 0; + + INFO("Writing {%s}", Name_BMP); + FILE *Image = fopen(Name_BMP, "wb"); + if (!Image) { + ERR("File not found"); + return(file_not_found); + } + + // Be optimistic - don't check for errors. + //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); + fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image); + //INFO("fwrite returned %d", r); + + //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); + fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image); + //INFO("fwrite returned %d", r); + + int lineBufSize = ((24 * w + 7)/8); + uint8_t * lineBuffer = (uint8_t *)malloc(lineBufSize); + if (lineBuffer == NULL) { + fclose(Image); + ERR("Not enough RAM for lineBuffer"); + return(not_enough_ram); + } + color_t * pixelBuffer = (color_t *)malloc(w * sizeof(color_t)); + color_t * pixelBuffer2 = (color_t *)malloc(w * sizeof(color_t)); + color_t transparency = GetBackgroundTransparencyColor(); + unsigned char ltpr0 = ReadCommand(0x52) & 0x7; + + if (pixelBuffer == NULL || pixelBuffer2 == NULL) { + fclose(Image); + free(lineBuffer); + ERR("Not enough RAM for pixelBuffer"); + if (pixelBuffer) + free(pixelBuffer); + return(not_enough_ram); + } + + uint16_t prevLayer = GetDrawingLayer(); + // If only one of the layers is visible, select that layer + switch(ltpr0) { + case 0: + SelectDrawingLayer(0); + break; + case 1: + SelectDrawingLayer(1); + break; + default: + break; + } + + // Read the display from the last line toward the top + // so we can write the file in one pass. + for (int j = h - 1; j >= 0; j--) { + if (ltpr0 >= 2) // Need to combine the layers... + SelectDrawingLayer(0); // so read layer 0 first + // Read one line of pixels to a local buffer + if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) { + ERR("getPixelStream error, and no recovery handler..."); + } + if (ltpr0 >= 2) { // Need to combine the layers... + SelectDrawingLayer(1); // so read layer 0 first + if (getPixelStream(pixelBuffer2, w, x,y+j) != noerror) { + ERR("getPixelStream error, and no recovery handler..."); + } + } + // Convert the local buffer to RGBQUAD format + int lb = 0; + for (int i=0; i<w; i++) { + RGBQUAD q0 = RGB16ToRGBQuad(pixelBuffer[x+i]); // Scale to 24-bits + RGBQUAD q1 = RGB16ToRGBQuad(pixelBuffer2[x+i]); // Scale to 24-bits + switch (ltpr0) { + case 0: + case 1: + case 2: // lighten-overlay (@TODO Not supported yet) + case 6: // Floating Windows (@TODO not sure how to support) + default: // Reserved... + lineBuffer[lb++] = q0.rgbBlue; + lineBuffer[lb++] = q0.rgbGreen; + lineBuffer[lb++] = q0.rgbRed; + break; + case 3: // transparent mode (@TODO Read the background color register for transparent) + case 4: // boolean or + lineBuffer[lb++] = q0.rgbBlue | q1.rgbBlue; + lineBuffer[lb++] = q0.rgbGreen | q1.rgbGreen; + lineBuffer[lb++] = q0.rgbRed | q1.rgbRed; + break; + case 5: // boolean AND + lineBuffer[lb++] = q0.rgbBlue & q1.rgbBlue; + lineBuffer[lb++] = q0.rgbGreen & q1.rgbGreen; + lineBuffer[lb++] = q0.rgbRed & q1.rgbRed; + break; + } + } + if (j == h - 1) + HexDump("Line", lineBuffer, lineBufSize); + // Write to disk + fwrite(lineBuffer, sizeof(char), lb, Image); + } + SelectDrawingLayer(prevLayer); + fclose(Image); + free(pixelBuffer2); // don't leak memory. + free(pixelBuffer); + free(lineBuffer); + INFO("Image closed"); + return noerror; + } else { + return bad_parameter; + } +} + + +// ########################################################################## +// ########################################################################## +// ########################################################################## + +#ifdef TESTENABLE + +#include "Arial12x12.h" +#include "Small_6.h" + +// ______________ ______________ ______________ _______________ +// /_____ _____/ / ___________/ / ___________/ /_____ ______/ +// / / / / / / / / +// / / / /___ / /__________ / / +// / / / ____/ /__________ / / / +// / / / / / / / / +// / / / /__________ ___________/ / / / +// /__/ /_____________/ /_____________/ /__/ +// +// Everything from here down is test code. +// +bool SuppressSlowStuff = false; + +void TextWrapTest(RA8875 & display, Serial & pc) +{ + if (!SuppressSlowStuff) + pc.printf("Text Wrap Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.Backlight_u8(255); + display.puts(0,0, "Text Wrap Test.\r\n"); + for (int i=1; i<60; i++) { + display.printf("L%2d\n", i % 17); + if (!SuppressSlowStuff) + wait_ms(100); + } + if (!SuppressSlowStuff) + wait_ms(3000); +} + + +void ShowKey(RA8875 & display, int key) +{ + loc_t col, row; + dim_t r1 = 25; + color_t color = (key & 0x80) ? Red : Green; + + key &= 0x7F; // remove the long-press flag + row = (key - 1) / 5; + col = (key - 1) % 5; + if (col > 5) col = 5; + if (row > 4) row = 4; + display.circle(450 - + (2 * r1) * col, 200 - (2 * r1) * row, r1-2, color, FILL); +} + +void HideKey(RA8875 & display, int key) +{ + loc_t col, row; + dim_t r1 = 25; + + row = (key - 1) / 5; + col = (key - 1) % 5; + if (col > 5) col = 5; + if (row > 4) row = 4; + display.background(Black); + display.circle(450 - (2 * r1) * col, 200 - (2 * r1) * row, r1-2, Black, FILL); + display.circle(450 - (2 * r1) * col, 200 - (2 * r1) * row, r1-2, Blue); +} + +void KeyPadTest(RA8875 & display, Serial & pc) +{ + const uint8_t myMap[22] = { + 0, + 'a', 'b', 'c', 'd', 'e', + 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', + 'x' + }; + + display.background(Black); + display.foreground(Blue); + display.cls(); + display.Backlight_u8(255); + display.puts(0,0, "KeyPad Test. Touch the keypad..."); + pc.printf("\r\n" + "Raw KeyPad Test. Keypad returns the key-number.\r\n" + "Press [most] any PC keyboard key to advance to next test.\r\n"); + RetCode_t ret = display.KeypadInit(true, true, 3, 7, 3); + if (ret != noerror) + pc.printf("returncode from KeypadInit is %d\r\n", ret); + int lastKey = 0; + while (!pc.readable()) { + if (display.readable()) { + int key = display.getc(); + if (key) { + if (((key & 0x7F) != lastKey) && (lastKey != 0)) + HideKey(display, lastKey); + ShowKey(display, key); + lastKey = key & 0x7F; + } else { + // erase the last one + if (lastKey) + HideKey(display, lastKey); + } + } + } + (void)pc.getc(); + pc.printf("\r\n" + "Map KeyPad Test. Keypad returns the remapped key 'a' - 't'.\r\n" + "Press [most] any PC keyboard key to advance to exit test.\r\n"); + display.SetKeyMap(myMap); + while (!pc.readable()) { + if (display.readable()) { + int key = display.getc(); + bool longPress = key & 0x80; + display.SetTextCursor(0, 120); + display.printf("Long Press: %d\r\n", longPress); + display.printf(" Remapped: %c %02X\r\n", (key) ? key & 0x7F : ' ', key); + } + } + (void)pc.getc(); + display.SetKeyMap(); + pc.printf("\r\n"); +} + +void TextCursorTest(RA8875 & display, Serial & pc) +{ + const char * iCursor = "The I-Beam cursor should be visible for this text.\r\n"; + const char * uCursor = "The Underscore cursor should be visible for this text.\r\n"; + const char * bCursor = "The Block cursor should be visible for this text.\r\n"; + const char * bbCursor = "The Blinking Block cursor should be visible for this text.\r\n"; + const char * p; + int delay = 100; + + if (!SuppressSlowStuff) + pc.printf("Text Cursor Test\r\n"); + else + delay = 0; + display.background(Black); + display.foreground(Blue); + display.cls(); + display.Backlight_u8(255); + display.puts(0,0, "Text Cursor Test."); + + // visible, non-blinking + display.SetTextCursor(0,20); + display.SetTextCursorControl(RA8875::IBEAM, false); + p = iCursor; + while (*p) { + display._putc(*p++); + wait_ms(delay); + } + + display.SetTextCursorControl(RA8875::UNDER, false); + p = uCursor; + while (*p) { + display._putc(*p++); + wait_ms(delay); + } + + display.SetTextCursorControl(RA8875::BLOCK, false); + p = bCursor; + while (*p) { + display._putc(*p++); + wait_ms(delay); + } + + display.SetTextCursorControl(RA8875::BLOCK, true); + p = bbCursor; + while (*p) { + display._putc(*p++); + wait_ms(delay); + } + wait_ms(delay * 20); + display.SetTextCursorControl(RA8875::NOCURSOR, false); +} + + +void BacklightTest(RA8875 & display, Serial & pc, float ramptime) +{ + char buf[60]; + unsigned int w = (ramptime * 1000)/ 256; + int delay = 200; + + if (!SuppressSlowStuff) + pc.printf("Backlight Test - ramp over %f sec.\r\n", ramptime); + else { + delay = 0; + w = 0; + } + display.Backlight_u8(0); + display.background(White); + display.foreground(Blue); + display.cls(); + wait_ms(delay); + display.puts(0,0, "RA8875 Backlight Test - Ramp up."); + for (int i=0; i <= 255; i++) { + sprintf(buf, "%3d, %4d", i, w); + display.puts(100,100,buf); + display.Backlight_u8(i); + wait_ms(w); + } +} + + +void BacklightTest2(RA8875 & display, Serial & pc) +{ + int delay = 20; + + if (!SuppressSlowStuff) + pc.printf("Backlight Test 2\r\n"); + else + delay = 0; + + // Dim it out at the end of the tests. + display.foreground(Blue); + display.puts(0,0, "Ramp Backlight down."); + // Ramp it off + for (int i=255; i != 0; i--) { + display.Backlight_u8(i); + wait_ms(delay); + } + display.Backlight_u8(0); +} + + +void ExternalFontTest(RA8875 & display, Serial & pc) +{ + if (!SuppressSlowStuff) + pc.printf("External Font Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.Backlight(1); + display.puts(0,0, "External Font Test."); + + display.set_font(Small_6); + display.puts(0,30, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\r\n"); + + display.set_font(Arial12x12); + display.puts("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\r\n"); + display.set_font(); // restore to internal + + display.puts("Normal font again."); + //display.window(0,0, display.width(), display.height()); +} + + +void DOSColorTest(RA8875 & display, Serial & pc) +{ + if (!SuppressSlowStuff) + pc.printf("DOS Color Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "DOS Colors - Fore"); + display.puts(280,0, "Back"); + display.background(Gray); + for (int i=0; i<16; i++) { + display.foreground(display.DOSColor(i)); + display.puts(160, i*16, display.DOSColorNames(i)); + display.background(Black); + } + display.foreground(White); + for (int i=0; i<16; i++) { + display.background(display.DOSColor(i)); + display.puts(360, i*16, display.DOSColorNames(i)); + display.foreground(White); + } +} + + +void WebColorTest(RA8875 & display, Serial & pc) +{ + if (!SuppressSlowStuff) + pc.printf("Web Color Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.window(0,0, display.width(), display.height()); + display.cls(); + display.SetTextFontSize(1,1); + display.puts(200,0, "Web Color Test"); + display.SetTextCursor(0,0); + display.puts(" "); + for (int i=0; i<16; i++) + display.printf("%X", i&0xF); + display.puts("\r\n0 "); + for (int i=0; i<sizeof(WebColors)/sizeof(WebColors[0]); i++) { + display.background(WebColors[i]); + display.puts(" "); + if (i % 16 == 15 && i < 255) { + display.printf("\r\n%X ", ((i+1)/16)); + } + } + display.SetTextFontSize(1,1); +} + + +void PixelTest(RA8875 & display, Serial & pc) +{ + int i, c, x, y; + + if (!SuppressSlowStuff) + pc.printf("Pixel Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Pixel Test"); + for (i=0; i<1000; i++) { + x = rand() % 480; + y = 16 + rand() % (272-16); + c = rand() % 16; + //pc.printf(" (%d,%d) - %d\r\n", x,y,r1); + display.pixel(x,y, display.DOSColor(c)); + } +} + + +void LineTest(RA8875 & display, Serial & pc) +{ + int i, x, y, x2, y2; + + if (!SuppressSlowStuff) + pc.printf("Line Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Line Test"); + for (i=0; i<16; i++) { + // Lines + x = rand() % 480; + y = rand() % 272; + x2 = rand() % 480; + y2 = rand() % 272; + display.line(x,y, x2,y2, display.DOSColor(i)); + } + display.foreground(BrightRed); + display.foreground(BrightGreen); + display.foreground(BrightBlue); + display.line(55,50, 79,74, BrightRed); + display.line(57,50, 81,74, BrightGreen); + display.line(59,50, 83,74, BrightBlue); + // horz + display.line(30,40, 32,40, BrightRed); + display.line(30,42, 32,42, BrightGreen); + display.line(30,44, 32,44, BrightBlue); + // vert + display.line(20,40, 20,42, BrightRed); + display.line(22,40, 22,42, BrightGreen); + display.line(24,40, 24,42, BrightBlue); + // compare point to line-point + display.pixel(20,50, BrightRed); + display.pixel(22,50, BrightGreen); + display.pixel(24,50, BrightBlue); + display.line(20,52, 20,52, BrightRed); + display.line(22,52, 22,52, BrightGreen); + display.line(24,52, 24,52, BrightBlue); + + // point + display.line(50,50, 50,50, Red); + display.line(52,52, 52,52, Green); + display.line(54,54, 54,54, Blue); + display.line(60,60, 60,60, BrightRed); + display.line(62,62, 62,62, BrightGreen); + display.line(64,64, 64,64, BrightBlue); + display.line(70,70, 70,70, DarkRed); + display.line(72,72, 72,72, DarkGreen); + display.line(74,74, 74,74, DarkBlue); +} + + +void RectangleTest(RA8875 & display, Serial & pc) +{ + int i, x1,y1, x2,y2; + + if (!SuppressSlowStuff) + pc.printf("Rectangle Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Rectangle Test"); + for (i=0; i<16; i++) { + x1 = rand() % 240; + y1 = 50 + rand() % 200; + x2 = rand() % 240; + y2 = 50 + rand() % 200; + display.rect(x1,y1, x2,y2, display.DOSColor(i)); + + x1 = 240 + rand() % 240; + y1 = 50 + rand() % 200; + x2 = 240 + rand() % 240; + y2 = 50 + rand() % 200; + display.rect(x1,y1, x2,y2, FILL); + } +} + + +void LayerTest(RA8875 & display, Serial & pc) +{ + loc_t i, x1,y1, x2,y2, r1,r2; + + if (!SuppressSlowStuff) + pc.printf("Layer Test\r\n"); + + display.SelectDrawingLayer(0); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Layer 0"); + for (i=0; i<16; i++) { + x1 = rand() % 240; + y1 = 50 + rand() % 200; + x2 = x1 + rand() % 100; + y2 = y1 + rand() % 100; + r1 = rand() % (x2 - x1)/2; + r2 = rand() % (y2 - y1)/2; + display.roundrect(x1,y1, x2,y2, r1,r2, display.DOSColor(i)); + if (!SuppressSlowStuff) + wait_ms(20); + } + if (!SuppressSlowStuff) + wait_ms(1000); + + display.SelectDrawingLayer(1); + display.background(Black); + display.foreground(Yellow); + display.cls(); + display.puts(240,0, "Layer 1"); + for (i=0; i<16; i++) { + x1 = 300 + rand() % 100; + y1 = 70 + rand() % 200; + r1 = rand() % min(y1 - 20, 100); + display.circle(x1,y1,r1, display.DOSColor(i)); + if (!SuppressSlowStuff) + wait_ms(20); + } + display.SetLayerMode(RA8875::ShowLayer1); // Show it after the build-up + if (!SuppressSlowStuff) + wait_ms(2000); + + display.SelectDrawingLayer(0); + display.SetLayerMode(RA8875::ShowLayer0); // Show Layer 0 again + if (!SuppressSlowStuff) + wait_ms(1000); + display.SetLayerMode(RA8875::TransparentMode); // Transparent mode + if (!SuppressSlowStuff) + wait_ms(1000); + for (i=0; i<=8; i++) { + display.SetLayerTransparency(i, 8-i); + if (!SuppressSlowStuff) + wait_ms(200); + } + + // Restore before we exit + display.SetLayerTransparency(0, 0); + display.SetLayerMode(RA8875::ShowLayer0); // Restore to layer 0 +} + + +void RoundRectTest(RA8875 & display, Serial & pc) +{ + loc_t i, x1,y1, x2,y2, r1,r2; + + if (!SuppressSlowStuff) + pc.printf("Round Rectangle Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Rounded Rectangle Test"); + + for (i=0; i<16; i++) { + x1 = rand() % 240; + y1 = 50 + rand() % 200; + x2 = x1 + rand() % 100; + y2 = y1 + rand() % 100; + r1 = rand() % (x2 - x1)/2; + r2 = rand() % (y2 - y1)/2; + display.roundrect(x1,y1, x2,y2, 5,8, display.DOSColor(i)); + + x1 = 240 + rand() % 240; + y1 = 50 + rand() % 200; + x2 = x1 + rand() % 100; + y2 = y1 + rand() % 100; + r1 = rand() % (x2 - x1)/2; + r2 = rand() % (y2 - y1)/2; + display.roundrect(x1,y1, x2,y2, r1,r2, FILL); + } +} + + +void TriangleTest(RA8875 & display, Serial & pc) +{ + int i, x1, y1, x2, y2, x3, y3; + + if (!SuppressSlowStuff) + pc.printf("Triangle Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Triangle Test"); + + x1 = 150; + y1 = 2; + x2 = 190; + y2 = 7; + x3 = 170; + y3 = 16; + display.triangle(x1,y1, x2,y2, x3,y3); + + x1 = 200; + y1 = 2; + x2 = 240; + y2 = 7; + x3 = 220; + y3 = 16; + display.filltriangle(x1,y1, x2,y2, x3,y3, BrightRed); + + x1 = 300; + y1 = 2; + x2 = 340; + y2 = 7; + x3 = 320; + y3 = 16; + display.triangle(x1,y1, x2,y2, x3,y3, NOFILL); + + x1 = 400; + y1 = 2; + x2 = 440; + y2 = 7; + x3 = 420; + y3 = 16; + display.triangle(x1,y1, x2,y2, x3,y3, Blue); + + for (i=0; i<16; i++) { + x1 = rand() % 240; + y1 = 50 + rand() % 200; + x2 = rand() % 240; + y2 = 50 + rand() % 200; + x3 = rand() % 240; + y3 = 50 + rand() % 200; + display.triangle(x1,y1, x2,y2, x3,y3, display.DOSColor(i)); + x1 = 240 + rand() % 240; + y1 = 50 + rand() % 200; + x2 = 240 + rand() % 240; + y2 = 50 + rand() % 200; + x3 = 240 + rand() % 240; + y3 = 50 + rand() % 200; + display.triangle(x1,y1, x2,y2, x3,y3, FILL); + } +} + + +void CircleTest(RA8875 & display, Serial & pc) +{ + int i, x, y, r1; + + if (!SuppressSlowStuff) + pc.printf("Circle Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Circle Test"); + for (i=0; i<16; i++) { + x = 100 + rand() % 100; + y = 70 + rand() % 200; + r1 = rand() % min(y - 20, 100); + //pc.printf(" (%d,%d) - %d\r\n", x,y,r1); + display.circle(x,y,r1, display.DOSColor(i)); + + x = 300 + rand() % 100; + y = 70 + rand() % 200; + r1 = rand() % min(y - 20, 100); + //pc.printf(" (%d,%d) - %d FILL\r\n", x,y,r1); + display.circle(x,y,r1, display.DOSColor(i), FILL); + } +} + + +void EllipseTest(RA8875 & display, Serial & pc) +{ + int i,x,y,r1,r2; + + if (!SuppressSlowStuff) + pc.printf("Ellipse Test\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Ellipse Test"); + for (i=0; i<16; i++) { + x = 100 + rand() % 100; + y = 70 + rand() % 200; + r1 = rand() % min(y - 20, 100); + r2 = rand() % min(y - 20, 100); + display.ellipse(x,y,r1,r2, display.DOSColor(i)); + + x = 300 + rand() % 100; + y = 70 + rand() % 200; + r1 = rand() % min(y - 20, 100); + r2 = rand() % min(y - 20, 100); + display.ellipse(x,y,r1,r2, FILL); + } +} + + +void TestGraphicsBitmap(RA8875 & display, Serial & pc) +{ + LocalFileSystem local("local"); + if (!SuppressSlowStuff) + pc.printf("Bitmap File Load\r\n"); + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Graphics Test, loading /local/TestPat.bmp"); + wait(3); + + int r = display.RenderBitmapFile(0,0, "/local/TestPat.bmp"); + if (!SuppressSlowStuff) + pc.printf(" returned %d\r\n", r); +} + + +void TouchPanelTest(RA8875 & display, Serial & pc) +{ + Timer t; + loc_t x, y; + tpMatrix_t calmatrix; + + display.background(Black); + display.foreground(Blue); + display.cls(); + display.puts(0,0, "Touch Panel Test\r\n"); + pc.printf("Touch Panel Test\r\n"); + display.TouchPanelInit(); + pc.printf(" TP: c - calibrate, r - restore, t - test\r\n"); + int c = pc.getc(); + if (c == 'c') { + point_t pTest[3] = + { { 50, 50 }, {450, 150}, {225,250} }; + point_t pSample[3]; + for (int i=0; i<3; i++) { + display.foreground(Blue); + display.printf(" (%3d,%3d) => ", pTest[i].x, pTest[i].y); + display.line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, White); + display.line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, White); + while (!display.TouchPanelA2DFiltered(&x, &y)) + wait_ms(20); + pSample[i].x = x; + pSample[i].y = y; + display.line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, Black); + display.line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, Black); + display.foreground(Blue); + display.printf(" (%4d,%4d)\r\n", x,y); + while (display.TouchPanelA2DFiltered(&x, &y)) + wait_ms(20); + wait(2); + } + display.TouchPanelComputeCalibration(pTest, pSample, &calmatrix); + display.printf(" Writing calibration to tpcal.cfg\r\n"); + FILE * fh = fopen("/local/tpcal.cfg", "wb"); + if (fh) { + fwrite(&calmatrix, sizeof(calmatrix), 1, fh); + fclose(fh); + } + display.printf(" Calibration is complete."); + } else if (c == 'r') { + display.printf(" Reading calibration from tpcal.cfg\r\n"); + FILE * fh = fopen("/local/tpcal.cfg", "rb"); + if (fh) { + fread(&calmatrix, sizeof(calmatrix), 1, fh); + fclose(fh); + } + display.printf(" Calibration is complete."); + display.TouchPanelSetMatrix(&calmatrix); + } + t.start(); + do { + point_t point = {0, 0}; + if (display.TouchPanelReadable(&point)) { + display.pixel(point.x, point.y, Red); + } + } while (t.read_ms() < 30000); + pc.printf(">"); +} + + +void SpeedTest(RA8875 & display, Serial & pc) +{ + Timer t; + SuppressSlowStuff = true; + pc.printf("\r\nSpeedTest disables delays, runs tests, reports overall time.\r\n"); + t.start(); + // do stuff fast + TextCursorTest(display, pc); + TextWrapTest(display, pc); + BacklightTest(display, pc, 0); + BacklightTest2(display, pc); + ExternalFontTest(display, pc); + DOSColorTest(display, pc); + WebColorTest(display, pc); + PixelTest(display, pc); + LineTest(display, pc); + RectangleTest(display, pc); + RoundRectTest(display, pc); + TriangleTest(display, pc); + CircleTest(display, pc); + EllipseTest(display, pc); + LayerTest(display, pc); + //TestGraphicsBitmap(display, pc); + pc.printf("SpeedTest completed in %d msec\r\n", t.read_ms()); +#ifdef PERF_METRICS + display.ReportPerformance(pc); +#endif + SuppressSlowStuff = false; +} + + +void PrintScreen(RA8875 & display, Serial & pc) +{ + if (!SuppressSlowStuff) + pc.printf("PrintScreen\r\n"); + display.PrintScreen( 0,0, 480,272, "/local/Capture.bmp"); +} + + +void RunTestSet(RA8875 & lcd, Serial & pc) +{ + int q = 0; + int automode = 0; + const unsigned char modelist[] = "BDWtGLlFROTPCEbw"; // auto-test in this order. + + while(1) { + pc.printf("\r\n" + "B - Backlight up b - backlight dim\r\n" + "D - DOS Colors W - Web Colors\r\n" + "t - text cursor G - Graphics Bitmap\r\n" + "L - Lines F - external Font\r\n" + "R - Rectangles O - rOund rectangles\r\n" + "T - Triangles P - Pixels \r\n" + "C - Circles E - Ellipses\r\n" + "A - Auto Test mode S - Speed Test\r\n" + "K - Keypad Test s - touch screen test\r\n" + "p - print screen r - reset \r\n" + "l - layer test w - wrapping text \r\n" +#ifdef PERF_METRICS + "0 - clear performance 1 - report performance\r\n" +#endif + "> "); + if (automode == -1 || pc.readable()) { + automode = -1; + q = pc.getc(); + while (pc.readable()) + pc.getc(); + } else if (automode >= 0) { + q = modelist[automode]; + } + switch(q) { +#ifdef PERF_METRICS + case '0': + lcd.ClearPerformance(); + break; + case '1': + lcd.ReportPerformance(pc); + break; +#endif + case 'A': + automode = 0; + break; + case 'B': + BacklightTest(lcd, pc, 2); + break; + case 'b': + BacklightTest2(lcd, pc); + break; + case 'D': + DOSColorTest(lcd, pc); + break; + case 'K': + KeyPadTest(lcd, pc); + break; + case 'W': + WebColorTest(lcd, pc); + break; + case 't': + TextCursorTest(lcd, pc); + break; + case 'w': + TextWrapTest(lcd, pc); + break; + case 'F': + ExternalFontTest(lcd, pc); + break; + case 'L': + LineTest(lcd, pc); + break; + case 'l': + LayerTest(lcd, pc); + break; + case 'R': + RectangleTest(lcd, pc); + break; + case 'O': + RoundRectTest(lcd, pc); + break; + case 'p': + PrintScreen(lcd, pc); + break; + case 'S': + SpeedTest(lcd, pc); + break; + case 's': + TouchPanelTest(lcd, pc); + break; + case 'T': + TriangleTest(lcd, pc); + break; + case 'P': + PixelTest(lcd, pc); + break; + case 'G': + TestGraphicsBitmap(lcd, pc); + break; + case 'C': + CircleTest(lcd, pc); + break; + case 'E': + EllipseTest(lcd, pc); + break; + case 'r': + pc.printf("Resetting ...\r\n"); + wait_ms(20); + mbed_reset(); + break; + case ' ': + break; + default: + printf("huh?\n"); + break; + } + if (automode >= 0) { + automode++; + if (automode >= sizeof(modelist)) + automode = 0; + wait_ms(2000); + } + wait_ms(200); + } +} + +#endif // TESTENABLE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/RA8875.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,1864 @@ +/// +/// @mainpage RA8875 Display Controller Driver library +/// +/// The RA8875 Display controller is a powerful interface for low cost displays. It +/// can support displays up to 800 x 600 pixels x 16-bit color. Another common +/// implementation is 480 x 272 x 16 with two layers. The two layers can be +/// exchanged, or blended in various ways (transparency, OR, AND, and more). +/// It includes graphics acceleration capabilities for drawing primitives, +/// such as line, rectangle, circles, and more. +/// +/// The controller additionally supports backlight control (via PWM), keypad scanning +/// (for a 4 x 5 matrix) and resistive touch-panel support. +/// +/// @section Display_Config Display Configuration +/// +/// This section details basics for bringing the display online. At a minimum, +/// the display is instantiated. After that any of the available commands +/// may be issued. +/// +/// During the instantiation, the display is powered on, cleared, and the backlight +/// is energized. Additionally, the keypad and touchscreen features are activated. +/// It is important to keep in mind that the keypad had the default mapping, and +/// the touchscreen does not have the calibration matrix configured, so additional +/// steps may be necessary. +/// +/// @code +/// RA8875 lcd(p5, p6, p7, p12, NC, "tft"); +/// lcd.init(); +/// lcd.foreground(Blue); +/// lcd.line(0,0, 479,271); +/// ... +/// @endcode +/// +/// @section Touch_Panel Touch Panel +/// +/// The supported touch panel interface is for a resistive panel, and is natively +/// supported by the RA8875 controller. There are a few steps to enable this interface. +/// +/// @subsection Touch_Panel_Enable Touch Panel Enable +/// +/// @see TouchPanelInit has two forms - fully automatic, and controlled. See the APIs for +/// details. +/// +/// @subsection Touch_Panel_Calibration +/// +/// The touch panel is not initially calibrated on startup. The application should +/// provide a means to activate the calibration process, and that should not require +/// the touchscreen as it may not yet be usable. Alternately, a calibration matrix +/// can be loaded from non-volatile and installed. +/// +/// @section Keypad Keypad +/// +/// The keypad has a default keypad mapping, but there is an API that permits +/// installing a custom keymap. +/// +#ifndef RA8875_H +#define RA8875_H +#include <mbed.h> + +#include "RA8875_Regs.h" +#include "GraphicsDisplay.h" + +#define RA8875_DEFAULT_SPI_FREQ 5000000 + +// Define this to enable code that monitors the performance of various +// graphics commands. +//#define PERF_METRICS + +// What better place for some test code than in here and the companion +// .cpp file. See also the bottom of this file. +//#define TESTENABLE + +/// DOS colors - slightly color enhanced +#define Black (color_t)(RGB(0,0,0)) +#define Blue (color_t)(RGB(0,0,187)) +#define Green (color_t)(RGB(0,187,0)) +#define Cyan (color_t)(RGB(0,187,187)) +#define Red (color_t)(RGB(187,0,0)) +#define Magenta (color_t)(RGB(187,0,187)) +#define Brown (color_t)(RGB(63,63,0)) +#define Gray (color_t)(RGB(187,187,187)) +#define Charcoal (color_t)(RGB(85,85,85)) +#define BrightBlue (color_t)(RGB(0,0,255)) +#define BrightGreen (color_t)(RGB(0,255,0)) +#define BrightCyan (color_t)(RGB(0,255,255)) +#define BrightRed (color_t)(RGB(255,0,0)) +#define Orange (color_t)(RGB(255,85,85)) +#define Pink (color_t)(RGB(255,85,255)) +#define Yellow (color_t)(RGB(187,187,0)) +#define White (color_t)(RGB(255,255,255)) + +#define DarkBlue (color_t)(RGB(0,0,63)) +#define DarkGreen (color_t)(RGB(0,63,0)) +#define DarkCyan (color_t)(RGB(0,63,63)) +#define DarkRed (color_t)(RGB(63,0,0)) +#define DarkMagenta (color_t)(RGB(63,0,63)) +#define DarkBrown (color_t)(RGB(63,63,0)) +#define DarkGray (color_t)(RGB(63,63,63)) + + +//namespace SW_graphics +//{ + + +/// This is a graphics library for the Raio RA8875 Display Controller chip +/// attached to a 4-wire SPI interface. +/// +/// It offers both primitive and high level APIs. +/// +/// Central to this API is a coordinate system, where the origin (0,0) is in +/// the top-left corner of the display, and the width (x) extends positive to the +/// right and the height (y) extends positive toward the bottom. +/// +/// @caution As there are both graphics and text commands, one must take care to use +/// the proper coordinate system for each. Some of the text APIs are in units +/// of column and row, which is measured in character positions (and dependent +/// on the font size), where other text APIs permit pixel level positioning. +/// +/// @code +/// #include "RA8875.h" +/// RA8875 lcd(p5, p6, p7, p12, NC, "tft"); +/// +/// int main() +/// { +/// lcd.init(); +/// lcd.printf("printing 3 x 2 = %d", 3*2); +/// lcd.circle( 400,25, 25, BrightRed); +/// lcd.fillcircle( 400,25, 15, RGB(128,255,128)); +/// lcd.ellipse( 440,75, 35,20, BrightBlue); +/// lcd.fillellipse( 440,75, 25,10, Blue); +/// lcd.triangle( 440,100, 475,110, 450,125, Magenta); +/// lcd.filltriangle( 445,105, 467,111, 452,120, Cyan); +/// lcd.rect( 400,130, 475,155, Brown); +/// lcd.fillrect( 405,135, 470,150, Pink); +/// lcd.roundrect( 410,160, 475,190, 10,8, Yellow); +/// lcd.fillroundrect(415,165, 470,185, 5,3, Orange); +/// lcd.line( 430,200, 460,230, RGB(0,255,0)); +/// for (int i=0; i<=30; i+=5) +/// lcd.pixel(435+i,200+i, White); +/// } +/// @endcode +/// +/// @todo Add Scroll support for text. +/// @todo Improve sync between internal and external font support - cursor, window, scroll. +/// @todo Add Hardware reset signal - but testing to date indicates it is not needed. +/// @todo Add high level objects - x-y graph, meter, others... but these will +/// probably be best served in another class, since they may not +/// be needed for many uses. +/// +class RA8875 : public GraphicsDisplay +{ +public: + /// cursor type to be shown as the text cursor. + typedef enum + { + NOCURSOR, ///< cursor is hidden + IBEAM, ///< | cursor + UNDER, ///< _ cursor + BLOCK ///< Block cursor + } cursor_t; + + /// font type selection. + typedef enum + { + ISO8859_1, ///< ISO8859-1 font + ISO8859_2, ///< ISO8859-2 font + ISO8859_3, ///< ISO8859-3 font + ISO8859_4 ///< ISO8859-4 font + } font_t; + + /// font rotation selection + typedef enum + { + normal, ///< normal orientation + rotated ///< rotated orientation + } font_angle_t; + + /// alignment + typedef enum + { + align_none, ///< align - none + align_full ///< align - full + } alignment_t; + + /// Scale factor - 1, 2, 3 4 + typedef int HorizontalScale; + + /// Scale factor - 1, 2, 3, 4 + typedef int VerticalScale; + + /// Clear screen region + typedef enum + { + FULLWINDOW, ///< Full screen + ACTIVEWINDOW ///< active window/region + } Region_t; + + /// Set the Layer Display Mode. @ref SetLayerMode + typedef enum + { + ShowLayer0, ///< Only layer 0 is visible, layer 1 is hidden (default) + ShowLayer1, ///< Only layer 1 is visible, layer 0 is hidden + LightenOverlay, ///< Lighten-overlay mode + TransparentMode, ///< Transparent mode + BooleanOR, ///< Boolean OR mode + BooleanAND, ///< Boolean AND mode + FloatingWindow ///< Floating Window mode + } LayerMode_T; + + /// Touch Panel modes + typedef enum + { + TP_Auto, ///< Auto touch detection mode + TP_Manual, ///< Manual touch detection mode + } tpmode_t; + + /// Constructor for a display based on the RAiO RA8875 + /// display controller. + /// + /// This configures the registers and calls the @ref init method. + /// + /// @code + /// #include "RA8875.h" + /// RA8875 lcd(p5, p6, p7, p12, NC, "tft"); + /// + /// int main() + /// { + /// lcd.init(); + /// lcd.printf("printing 3 x 2 = %d", 3*2); + /// lcd.circle(400,25, 25, BrightRed); + /// } + /// @endcode + /// + /// @param[in] mosi is the SPI master out slave in pin on the mbed. + /// @param[in] miso is the SPI master in slave out pin on the mbed. + /// @param[in] sclk is the SPI shift clock pin on the mbed. + /// @param[in] csel is the DigitalOut pin on the mbed to use as the + /// active low chip select for the display controller. + /// @param[in] reset is the DigitalOut pin on the mbed to use as the + /// active low reset input on the display controller - + /// but this is not currently used. + /// @param[in] name is a text name for this object, which will permit + /// capturing stdout to puts() and printf() directly to it. + /// + RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char * name = "lcd"); + + // Destructor doesn't have much to do as this would typically be created + // at startup, and not at runtime. + //~RA8875(); + + /// Initialize the driver. + /// + /// @param[in] width in pixels to configure the display for. This parameter is optional + /// and the default is 480. + /// @param[in] height in pixels to configure the display for. This parameter is optional + /// and the default is 272. + /// @param[in] color_bpp can be either 8 or 16, but must be consistent + /// with the width and height parameters. This parameter is optional + /// and the default is 16. + /// @param[in] power defines if the display should be left in the power-on or off state. + /// If power is true (on), the backlight is set to 100%. This parameter is optional + /// and the default is true (on). @see Power. + /// @param[in] keypadon defines if the keypad support should be enabled. This parameter is optional + /// and the default is true (enabled). @see KeypadInit. + /// @param[in] touchscreeenon defines if the keypad support should be enabled. This parameter is optional + /// and the default is true (enabled). @see TouchPanelInit. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t init(int width = 480, int height = 272, int color_bpp = 16, + bool poweron = true, bool keypadon = true, bool touchscreeenon = true); + + /// Get a pointer to the error code. + /// + /// This method returns a pointer to a text string that matches the + /// code. @see RetCode_t. + /// + /// @param[in] code is the return value from RetCode_t to look up. + /// @returns a pointer to the text message representing code. If code + /// is not a valid value, then it returns the text for bad_parameter; + const char * GetErrorMessage(RetCode_t code); + + + /// Select the drawing layer for subsequent commands. + /// + /// If the screen configuration is 480 x 272, or if it is 800 x 480 + /// and 8-bit color, the the display supports two layers, which can + /// be independently drawn on and shown. Additionally, complex + /// operations involving both layers are permitted. + /// + /// @code + /// //lcd.SetLayerMode(OnlyLayer0); // default is layer 0 + /// lcd.rect(400,130, 475,155,Brown); + /// lcd.SelectDrawingLayer(1); + /// lcd.circle(400,25, 25, BrightRed); + /// wait(1); + /// lcd.SetLayerMode(ShowLayer1); + /// @endcode + /// + /// @attention The user manual refers to Layer 1 and Layer 2, however the + /// actual register values are value 0 and 1. This API as well as + /// others that reference the layers use the values 0 and 1 for + /// cleaner iteration in the code. + /// + /// @param[in] layer is 0 or 1 to select the layer for subsequent + /// commands. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t SelectDrawingLayer(uint16_t layer); + + /// Get the currently active drawing layer. + /// + /// This returns a value, 0 or 1, based on the screen configuration + /// and the currently active drawing layer. + /// + /// @code + /// uint16_t prevLayer = lcd.GetDrawingLayer(); + /// lcd.SelectDrawingLayer(x); + /// lcd.circle(400,25, 25, BrightRed); + /// lcd.SelectDrawingLayer(prevLayer); + /// @endcode + /// + /// @attention The user manual refers to Layer 1 and Layer 2, however the + /// actual register values are value 0 and 1. This API as well as + /// others that reference the layers use the values 0 and 1 for + /// cleaner iteration in the code. + /// + /// @returns the current drawing layer; 0 or 1. + /// + uint16_t GetDrawingLayer(void); + + /// Set the Layer presentation mode. + /// + /// This sets the presentation mode for layers, and permits showing + /// a single layer, or applying a mode where the two layers + /// are combined using one of the hardware methods. + /// + /// Refer to the RA8875 data sheet for full details. + /// + /// @code + /// //lcd.SetLayerMode(OnlyLayer0); // default is layer 0 + /// lcd.rect(400,130, 475,155,Brown); + /// lcd.SelectDrawingLayer(1); + /// lcd.circle(400,25, 25, BrightRed); + /// wait(1); + /// lcd.SetLayerMode(ShowLayer1); + /// @endcode + /// + /// @param[in] mode sets the mode in the Layer Transparency Register. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t SetLayerMode(LayerMode_T mode); + + /// Set the layer transparency for each layer. + /// + /// Set the transparency, where the range of values is + /// from zero (fully visible) to eight (fully transparent). + /// The input value is automatically limited to this range. + /// + /// @code + /// // draw something on each layer, then step-fade across + /// display.SetLayerMode(RA8875::TransparentMode); + /// for (i=0; i<=8; i++) { + /// display.SetLayerTransparency(i, 8-i); + /// wait_ms(200); + /// } + /// @endcode + /// + /// @param[in] layer1 sets the layer 1 transparency. + /// @param[in] layer2 sets the layer 2 transparency. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t SetLayerTransparency(uint8_t layer1, uint8_t layer2); + + /// Set the background color register used for transparency. + /// + /// This command sets the background color registers that are used + /// in the transparent color operations involving the layers. + /// + /// @param[in] color is optional and expressed in 16-bit format. If not + /// supplied, a default of Black is used. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t SetBackgroundTransparencyColor(color_t color = RGB(0,0,0)); + + + /// Get the background color value used for transparency. + /// + /// This command reads the background color registers that define + /// the transparency color for operations involving layers. + /// + /// @returns the color. + /// + color_t GetBackgroundTransparencyColor(void); + + /// Initialize theTouch Panel controller with default values + /// + /// This activates the simplified touch panel init, which may work for + /// most uses. The alternate API is available if fine-grained control + /// is needed for the numerous settings. + /// + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t TouchPanelInit(void); + + /// Initialize the Touch Panel controller with detailed settings. + /// + /// This is the detailed touch panel init, which provides the ability + /// to set nearly every possible option. + /// + /// @param[in] bTpEnable Touch Panel enable/disable control: + /// - TP_ENABLE: enable the touch panel + /// - TP_DISABLE: disable the touch panel + /// @param[in] bTpAutoManual Touch Panel operating mode: + /// - TP_MODE_AUTO: automatic capture + /// - TP_MODE_MANUAL: manual capture + /// @param[in] bTpDebounce Debounce circuit enable for touch panel interrupt: + /// - TP_DEBOUNCE_OFF: disable the debounce circuit + /// - TP_DEBOUNCE_ON: enable the debounce circuit + /// @param[in] bTpManualMode When Manual Mode is selected, this sets the mode: + /// - TP_MANUAL_IDLE: touch panel is idle + /// - TP_MANUAL_WAIT: wait for touch panel event + /// - TP_MANUAL_LATCH_X: latch X data + /// - TP_MANUAL_LATCH_Y: latch Y data + /// @param[in] bTpAdcClkDiv Sets the ADC clock as a fraction of the System CLK: + /// - TP_ADC_CLKDIV_1: Use CLK + /// - TP_ADC_CLKDIV_2: Use CLK/2 + /// - TP_ADC_CLKDIV_4: Use CLK/4 + /// - TP_ADC_CLKDIV_8: Use CLK/8 + /// - TP_ADC_CLKDIV_16: Use CLK/16 + /// - TP_ADC_CLKDIV_32: Use CLK/32 + /// - TP_ADC_CLKDIV_64: Use CLK/64 + /// - TP_ADC_CLKDIV_128: Use CLK/128 + /// @param[in] bTpAdcSampleTime Touch Panel sample time delay before ADC data is ready: + /// - TP_ADC_SAMPLE_512_CLKS: Wait 512 system clocks + /// - TP_ADC_SAMPLE_1024_CLKS: Wait 1024 system clocks + /// - TP_ADC_SAMPLE_2048_CLKS: Wait 2048 system clocks + /// - TP_ADC_SAMPLE_4096_CLKS: Wait 4096 system clocks + /// - TP_ADC_SAMPLE_8192_CLKS: Wait 8192 system clocks + /// - TP_ADC_SAMPLE_16384_CLKS: Wait 16384 system clocks + /// - TP_ADC_SAMPLE_32768_CLKS: Wait 32768 system clocks + /// - TP_ADC_SAMPLE_65536_CLKS: Wait 65536 system clocks + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t TouchPanelInit(uint8_t bTpEnable, uint8_t bTpAutoManual, uint8_t bTpDebounce, + uint8_t bTpManualMode, uint8_t bTpAdcClkDiv, uint8_t bTpAdcSampleTime); + + /// Poll the TouchPanel and on a touch event return the a to d filtered x, y coordinates. + /// + /// This method reads the touch controller, which has a 10-bit range for each the + /// x and the y axis. + /// + /// @note The returned values are not in display (pixel) units but are in analog to + /// digital converter units. + /// + /// @note This API is usually not needed. @see TouchPanelComputeCalibration. + /// @see TouchPanelReadable. + /// + /// @param[out] x is the x scale a/d value. + /// @param[out] y is the y scale a/d value. + /// @returns true if touch was detected, in which case the x and y values were set. + /// + bool TouchPanelA2DFiltered(loc_t *x, loc_t *y); + + /// Poll the TouchPanel and on a touch event return the a to d raw x, y coordinates. + /// + /// This method reads the touch controller, which has a 10-bit range for each the + /// x and the y axis. A number of samples of the raw data are taken, filtered, + /// and the results are returned. + /// + /// @note The returned values are not in display (pixel) units but are in analog to + /// digital converter units. + /// + /// @note This API is usually not needed. @see TouchPanelComputeCalibration. + /// @see TouchPanelReadable. + /// + /// @param[out] x is the x scale a/d value. + /// @param[out] y is the y scale a/d value. + /// @returns true if touch was detected, in which case the x and y values were set. + /// + bool TouchPanelA2DRaw(loc_t *x, loc_t *y); + + /// Calibrate the touch panel. + /// + /// This method accepts two lists - one list is target points in , + /// display coordinates and the other is a lit of raw touch coordinate + /// values. It generates a calibration matrix for later use. This + /// matrix is also accessible to the calling API, which may store + /// the matrix in persistent memory and then install the calibration + /// matrix on the next power cycle. By doing so, it can avoid the + /// need to calibrate on every power cycle. + /// + /// @note The methods "TouchPanelComputeCalibration", "TouchPanelReadable", and + /// indirectly the "TouchPanelSetMatrix" methods are all derived + /// from a program by Carlos E. Vidales. See the copyright note + /// for further details. See also the article + /// http://www.embedded.com/design/system-integration/4023968/How-To-Calibrate-Touch-Screens + /// + /// @copyright Copyright (c) 2001, Carlos E. Vidales. All rights reserved. + /// This sample program was written and put in the public domain + /// by Carlos E. Vidales. The program is provided "as is" + /// without warranty of any kind, either expressed or implied. + /// If you choose to use the program within your own products + /// you do so at your own risk, and assume the responsibility + /// for servicing, repairing or correcting the program should + /// it prove defective in any manner. + /// You may copy and distribute the program's source code in any + /// medium, provided that you also include in each copy an + /// appropriate copyright notice and disclaimer of warranty. + /// You may also modify this program and distribute copies of + /// it provided that you include prominent notices stating + /// that you changed the file(s) and the date of any change, + /// and that you do not charge any royalties or licenses for + /// its use. + /// + /// @param[in] display is a pointer to a set of 3 points, which + /// are in display units of measure. These are the targets + /// the calibration was aiming for. + /// @param[in] screen is a pointer to a set of 3 points, which + /// are in touchscreen units of measure. These are the + /// registered touches. + /// @param[out] matrix is an optional parameter to hold the calibration matrix + /// as a result of the calibration. This can be saved in + /// non-volatile memory to recover the calibration after a power fail. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t TouchPanelComputeCalibration(point_t display[3], point_t screen[3], tpMatrix_t * matrix); + + + /// Perform the touch panel calibration process. + /// + /// This method provides the easy "shortcut" to calibrating the touch panel. + /// The process will automatically generate the calibration points, present + /// the targets on-screen, detect the touches, compute the calibration + /// matrix, and optionally provide the calibration matrix to the calling code + /// for persistence in non-volatile memory. + /// + /// @param[out] matrix is an optional parameter to hold the calibration matrix + /// as a result of the calibration. This can be saved in + /// non-volatile memory to recover the calibration after a power fail. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t TouchPanelCalibrate(tpMatrix_t * matrix); + + /// Perform the touch panel calibration process. + /// + /// This method provides the easy "shortcut" to calibrating the touch panel. + /// The process will automatically generate the calibration points, present + /// the targets on-screen, detect the touches, compute the calibration + /// matrix, and optionally provide the calibration matrix to the calling code + /// for persistence in non-volatile memory. + /// + /// @param[in] msg is a text message to present on the screen during the + /// calibration process. + /// @param[out] matrix is an optional parameter to hold the calibration matrix + /// as a result of the calibration. This can be saved in + /// non-volatile memory to recover the calibration after a power fail. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t TouchPanelCalibrate(const char * msg, tpMatrix_t * matrix = NULL); + + /// Get the screen calibrated point of touch. + /// + /// This method determines if there is a touch and if so it will provide + /// the screen-relative touch coordinates. This method can be used in + /// a manner similar to Serial.readable(), to determine if there was a + /// touch and indicate that - but not care about the coordinates. Alternately, + /// if a valid pointer to a point_t is provided, then if a touch is detected + /// the point_t will be populated with data. + /// + /// @code + /// Timer t; + /// t.start(); + /// do { + /// point_t point = {0, 0}; + /// if (display.TouchPanelReadable(&point)) { + /// display.pixel(point.x, point.y, Red); + /// } + /// } while (t.read_ms() < 30000); + /// @endcode + /// + /// @param[out] touch is the touch point, if a touch is registered. + /// @returns true if a touch was registered, and touch is updated. + /// @returns false if no touch was detected, or if the calibration matrix is not defined. + /// + bool TouchPanelReadable(point_t * touch = NULL); + + /// Wait for a touch panel touch and return it. + /// + /// This method is similar to Serial.getc() in that it will wait for a touch + /// and then return. In order to extract the coordinates of the touch, a + /// valid pointer to a point_t must be provided. + /// + /// @note There is no timeout on this function, so its use is not recommended. + /// + /// @code + /// Timer t; + /// t.start(); + /// do { + /// point_t point = {0, 0}; + /// display.TouchPanelGet(&point); + /// display.pixel(point.x, point.y, Red); + /// } while (t.read_ms() < 30000); + /// @endcode + /// + /// @param[out] touch is the touch point, if a touch is registered. + /// @returns true if a touch was registered, and touch is updated. + /// @returns false if no touch was detected, or if the calibration matrix is not defined. + /// + bool TouchPanelGet(point_t * touch); + + /// Set the calibration matrix for the touch panel. + /// + /// This method is used to set the calibration matrix for the touch panel. After + /// performing the calibration (@see TouchPanelComputeCalibration), the matrix can be stored. + /// On a subsequence power cycle, the matrix may be restored from non-volatile and + /// passed in to this method. It will then be held to perform the corrections when + /// reading the touch panel point. + /// + /// @code + /// FILE * fh = fopen("/local/tpmatrix.cfg", "r"); + /// if (fh) { + /// tpMatrix_t matrix; + /// if (fread(fh, &matrix, sizeof(tpMatrix_t))) { + /// lcd.TouchPanelSetMatrix(&matrix); + /// } + /// fclose(fh); + /// } + /// @endcode + /// + /// @param[in] matrix is a pointer to the touch panel calibration matrix. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t TouchPanelSetMatrix(tpMatrix_t * matrix); + +#if 0 + /// Append interrupt handler for specific RA8875 interrupt source + /// + /// @param[in] bISRType Interrupt Source, should be: + /// - RA8875_INT_KEYSCAN: KEYCAN interrupt + /// - RA8875_INT_DMA: DMA interrupt + /// - RA8875_INT_TP: Touch panel interrupt + /// - RA8875_INT_BTE: BTE process complete interrupt + /// - RA8875_INT_BTEMCU_FONTWR: Multi-purpose interrupt (see spec sheet) + /// @param[in] fptr is a callback function to handle the interrupt event. + /// @returns none + /// + void AppendISR(uint8_t bISRType, void(*fptr)(void)); + + /// Unappend interrupt handler for specific RA8875 interrupt source + /// + /// @param[in] bISRType Interrupt Source, should be: + /// - RA8875_INT_KEYSCAN: KEYCAN interrupt + /// - RA8875_INT_DMA: DMA interrupt + /// - RA8875_INT_TP: Touch panel interrupt + /// - RA8875_INT_BTE: BTE process complete interrupt + /// - RA8875_INT_BTEMCU_FONTWR: Multi-purpose interrupt (see spec sheet) + /// @return none + /// + void UnAppendISR(uint8_t bISRType); +#endif + + /// Initialize the keypad interface on the RA8875 controller. + /// + /// Enables the keypad subsystem. It will scan the 4 x 5 matrix + /// and make available key presses. + /// + /// @note See section 5-13 of RAIO RA8875 data sheet for more details. + /// @caution When using the display from buy-display.com, be sure that + /// the option for the keypad is configured on the hardware. + /// + /// All parameters are optional. + /// @param[in] scanEnable when true, enables the key scan function (default: true). + /// @param[in] longDetect when true, additionally enables the long key held detection (default: false). + /// @param[in] sampleTime setting (range: 0 - 3, default: 0). + /// @param[in] scanFrequency setting (range: 0 - 7, default: 0). + /// @param[in] longTimeAdjustment (range: 0 - 3, default: 0). + /// @param[in] interruptEnable when true, enables interrupts from keypress (default: false). + /// @param[in] wakeupEnable when true, activates the wakeup function (default: false). + /// + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t KeypadInit(bool scanEnable = true, bool longDetect = false, + uint8_t sampleTime = 0, uint8_t scanFrequency = 0, + uint8_t longTimeAdjustment = 0, + bool interruptEnable = false, bool wakeupEnable = false); + + /// Create Key Code definitions for the key matrix. + /// + /// This API provides a table of 22 key-code assignments for the matrix of keys. + /// This can be used to translate the keys 1 - 20 into some other value, as + /// well as to communicate the "no key" (zero) and "error state" (21). + /// + /// In this way, a keypad could easily emulate a piece of a keyboard, transforming + /// 0 - 20 into the values 0, '0', '1', '2', '3', '4', '5', '6', '7', '8', + /// '9', '+', '-', '*' , '/', '=', '<bs>', '<cr>', and so on... + /// + /// @code + /// // Return Value by Row, Column Example reassignment + /// // Column 0 1 2 3 4 + /// // +-------------------------+ +-------------------------+ + /// // Row 0 | 1 2 3 4 5 | | '7' '8' '9' ',' '<-' | + /// // 1 | 6 7 8 9 10 | | '4' '5' '6' '/' '-' | + /// // 2 | 11 12 13 14 15 | | '1' '2' '3' '*' '+' | + /// // 3 | 16 17 18 19 20 | | '0' '.' '(' ')' '\n' | + /// // +-------------------------+ +-------------------------+ + /// // Return value 0 = No Key pressed + /// // Return value 21 = Error + /// const uint8_t CodeList[22] = + /// {0, '7', '8', '9', ',', '\h', + /// '4', '5', '6', '/', '-', + /// '1', '2', '3', '*', '+', + /// '0', '.', '(', ')', '\n', + /// '\x1b'}; + /// lcd.SetKeyMap(CodeList); + /// @endcode + /// + /// @param[in] CodeList is a pointer to an always available byte-array + /// where the first 22 bytes are used as the transformation + /// from raw code to your reassigned value. + /// If CodeList is NULL, the original raw value key map is + /// restored. + /// @returns noerror. + /// + RetCode_t SetKeyMap(const uint8_t * CodeList = NULL); + + /// Determine if a key has been hit + /// + /// @returns true if a key has been hit + /// + bool readable(); + + /// Blocking read of the keypad. + /// + /// @caution: This is a blocking read, so it is important to first call _kbhit() + /// to avoid hanging your processes. + /// + /// A keypad connected to the RA8875 is connected in a matrix of 4 rows and 5 columns. + /// When pressed, this method will return a code in the range of 1 through 20, reserving + /// the value 0 to indicate that no key is pressed. + /// + /// Additionally, if configured to detect a "long press", bit 7 will be set to indicate + /// this. In this situation, first a "normal press" would be detected and signaled and + /// soon after that a "long press" of the same key would be detected and communicated. + /// + /// @return 8-bit where bit 7 indicates a long press. The remaining bits indicate the + /// keypress using 0 = no key pressed, 1 - 20 = the key pressed. + /// + uint8_t getc(); + + /// Write a command to the display with a word of data. + /// + /// This is a high level command, and may invoke several primitives. + /// + /// @param[in] command is the command to write. + /// @param[in] data is data to be written to the command register. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t WriteCommandW(uint8_t command, uint16_t data); + + /// Write a command to the display + /// + /// This is a high level command, and may invoke several primitives. + /// + /// @param[in] command is the command to write. + /// @param[in] data is optional data to be written to the command register + /// and only occurs if the data is in the range [0 - 0xFF]. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t WriteCommand(unsigned char command, unsigned int data = 0xFFFF); + + /// Write a data word to the display + /// + /// This is a high level command, and may invoke several primitives. + /// + /// @param[in] data is the data to write. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t WriteDataW(uint16_t data); + + /// Write a data byte to the display + /// + /// This is a high level command, and may invoke several primitives. + /// + /// @param[in] data is the data to write. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t WriteData(unsigned char data); + + /// Read a command register + /// + /// @param[in] command is the command register to read. + /// @returns the value read from the register. + /// + unsigned char ReadCommand(unsigned char command); + + /// Read a data byte from the display + /// + /// This is a high level command, and may invoke several primitives. + /// + /// @returns data that was read. + /// + unsigned char ReadData(void); + + /// Read a word from the display + /// + /// This is a high level command, and may invoke several primitives. + /// + /// @returns data that was read. + /// + uint16_t ReadDataW(void); + + /// Read the display status + /// + /// This is a high level command, and may invoke several primitives. + /// + /// @returns data that was read. + /// + unsigned char ReadStatus(void); + + /// get the width in pixels of the currently active font + /// + /// @returns font width in pixels. + /// + dim_t fontwidth(void); + + /// get the height in pixels of the currently active font + /// + /// @returns font height in pixels. + /// + dim_t fontheight(void); + + /// get the number of colums based on the currently active font + /// + /// @returns number of columns. + /// + virtual int columns(void); + + /// get the number of rows based on the currently active font + /// + /// @returns number of rows. + /// + virtual int rows(void); + + /// get the screen width in pixels + /// + /// @returns screen width in pixels. + /// + virtual dim_t width(void); + + /// get the screen height in pixels + /// + /// @returns screen height in pixels. + /// + virtual dim_t height(void); + + /// get the color depth in bits per pixel. + /// + /// @returns 8 or 16 only. + /// + virtual dim_t color_bpp(void); + + /// Set cursor position based on the current font size. + /// + /// @param[in] column is the horizontal position in character positions + /// @param[in] row is the vertical position in character positions + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t locate(textloc_t column, textloc_t row); + + /// Prepare the controller to write text to the screen by positioning + /// the cursor. + /// + /// @code + /// lcd.SetTextCursor(100, 25); + /// lcd.puts("Hello"); + /// @endcode + /// + /// @param[in] x is the horizontal position in pixels (from the left edge) + /// @param[in] y is the vertical position in pixels (from the top edge) + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t SetTextCursor(loc_t x, loc_t y); + + /// Get the current cursor position in pixels. + /// + /// @code + /// point_t point = GetTextCursor(); + /// if (point.x > 100 && point.y > 150) + /// //... + /// @endcode + /// + /// @returns cursor position. + /// + point_t GetTextCursor(void); + + /// Get the current cursor horizontal position in pixels. + /// + /// @returns cursor position horizontal offset. + /// + loc_t GetTextCursor_X(void); + + /// Get the current cursor vertical position in pixels. + /// + /// @returns cursor position vertical offset. + /// + loc_t GetTextCursor_Y(void); + + /// Configure additional Cursor Control settings. + /// + /// This API lets you modify other cursor control settings; + /// Cursor visible/hidden, Cursor blink/normal, + /// Cursor I-Beam/underscore/box. + /// + /// @param[in] cursor can be set to NOCURSOR (default), IBEAM, + /// UNDER, or BLOCK. + /// @param[in] blink can be set to true or false (default false) + /// @returns success/failure code. @see RetCode_t + /// + RetCode_t SetTextCursorControl(cursor_t cursor = NOCURSOR, bool blink = false); + + /// Select the ISO 8859-X font to use next. + /// + /// Supported fonts: ISO 8859-1, -2, -3, -4 + /// + /// @param[in] font selects the font for the subsequent text rendering. + /// + /// @note if either hScale or vScale is outside of its permitted range, + /// the command is not executed. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t SetTextFont(font_t font = ISO8859_1); + + /// Control the font behavior. + /// + /// This command lets you make several modifications to any text that + /// will be written to the screen. + /// + /// Options can be combined: + /// Default: + /// @li Full alignment disabled, + /// @li Font with Background color, + /// @li Font in normal orientiation, + /// @li Horizontal scale x 1 + /// @li Vertical scale x 1 + /// @li alignment + /// + /// @param[in] fillit defaults to FILL, but can be NOFILL + /// @param[in] angle defaults to normal, but can be rotated + /// @param[in] hScale defaults to 1, but can be 1, 2, 3, or 4, + /// and scales the font size by this amount. + /// @param[in] vScale defaults to 1, but can be 1, 2, 3, or 4, + /// and scales the font size by this amount. + /// @param[in] alignment defaults to align_none, but can be + /// align_full. + /// + /// @note if either hScale or vScale is outside of its permitted range, + /// the command is not executed. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t SetTextFontControl(fill_t fillit = FILL, + font_angle_t angle = normal, + HorizontalScale hScale = 1, + VerticalScale vScale = 1, + alignment_t alignment = align_none); + + /// Control the font size + /// + /// This command lets you set the font enlargement for both horizontal + /// and vertical, independent of the rotation, background, and + /// alignment. @see SetTextFontControl. + /// + /// @param[in] hScale defaults to 1, but can be 1, 2, 3, or 4, + /// and scales the font size by this amount. + /// @param[in] vScale is an optional parameter that defaults to the hScale value, + /// but can be 1, 2, 3, or 4, and scales the font size by this amount. + /// + /// @code + /// lcd.SetTextFontSize(2); // Set the font to 2x normal size + /// lcd.puts("Two times"); + /// lcd.SetTextFontSize(2,3); // Set the font to 2x Width and 3x Height + /// lcd.puts("2*2 3*h"); + /// lcd.SetTextFontSize(); // Restore to normal size in both dimensions + /// lcd.puts("normal"); + /// @endcode + /// + /// @note if either hScale or vScale is outside of its permitted range, + /// the command is not executed. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t SetTextFontSize(HorizontalScale hScale = 1, VerticalScale vScale = -1); + + /// put a character on the screen. + /// + /// @param[in] c is the character. + /// @returns the character, or EOF if there is an error. + /// + virtual int _putc(int c); + + /// Write string of text to the display + /// + /// @code + /// lcd.puts("Test STring"); + /// @endcode + /// + /// @param[in] string is the null terminated string to send to the display. + /// + void puts(const char * string); + + /// Write string of text to the display at the specified location. + /// + /// @code + /// lcd.puts(10,25, "Test STring"); + /// @endcode + /// + /// @param[in] x is the horizontal position in pixels (from the left edge) + /// @param[in] y is the vertical position in pixels (from the top edge) + /// @param[in] string is the null terminated string to send to the display. + /// + void puts(loc_t x, loc_t y, const char * string); + + /// Prepare the controller to write binary data to the screen by positioning + /// the memory cursor. + /// + /// @param[in] x is the horizontal position in pixels (from the left edge) + /// @param[in] y is the vertical position in pixels (from the top edge) + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t SetGraphicsCursor(loc_t x, loc_t y); + + /// Prepare the controller to read binary data from the screen by positioning + /// the memory read cursor. + /// + /// @param[in] x is the horizontal position in pixels (from the left edge) + /// @param[in] y is the vertical position in pixels (from the top edge) + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t SetGraphicsCursorRead(loc_t x, loc_t y); + + /// Set the window, which controls where items are written to the screen. + /// + /// When something hits the window width, it wraps back to the left side + /// and down a row. If the initial write is outside the window, it will + /// be captured into the window when it crosses a boundary. + /// + /// @code + /// lcd.window(10,10, 80,80); + /// lcd.puts("012345678901234567890123456789012345678901234567890"); + /// @endcode + /// + /// @param[in] x is the left edge in pixels. + /// @param[in] y is the top edge in pixels. + /// @param[in] width is the window width in pixels. + /// @param[in] height is the window height in pixels. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t window(loc_t x, loc_t y, dim_t width, dim_t height); + + /// Clear either the specified layer, or the active layer. + /// + /// The behavior is to clear the whole screen for the specified + /// layer. When not specified, the active drawing layer is cleared. + /// This command can also be used to specifically clear either, + /// or both layers. @see clsw(). + /// + /// @code + /// lcd.cls(); + /// @endcode + /// + /// @param[in] layers is optional. If not provided, the active layer + /// is cleared. If bit 0 is set, layer 0 is cleared, if bit + /// 1 is set, layer 1 is cleared. If both are set, both layers + /// are cleared. Any other value does not cause an action. + /// + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t cls(uint16_t layers = 0); + + /// Clear the screen, or clear only the active window. + /// + /// The default behavior is to clear the whole screen. With the optional + /// parameter, the action can be restricted to the active window, which + /// can be set with the @see window method. + /// + /// @code + /// lcd.window(20,20, 40,10); + /// lcd.clsw(); + /// @endcode + /// + /// @param[in] region is an optional parameter that defaults to FULLWINDOW + /// or may be set to ACTIVEWINDOW. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t clsw(RA8875::Region_t region = FULLWINDOW); + + /// Set the background color. + /// + /// @param[in] color is expressed in 16-bit format. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t background(color_t color); + + /// Set the background color. + /// + /// @param[in] r is the red element of the color. + /// @param[in] g is the green element of the color. + /// @param[in] b is the blue element of the color. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t background(unsigned char r, unsigned char g, unsigned char b); + + /// Set the foreground color. + /// + /// @param[in] color is expressed in 16-bit format. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t foreground(color_t color); + + /// Set the foreground color. + /// + /// @param[in] r is the red element of the color. + /// @param[in] g is the green element of the color. + /// @param[in] b is the blue element of the color. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t foreground(unsigned char r, unsigned char g, unsigned char b); + + /// Get the current foreground color value. + /// + /// @returns the current foreground color. + /// + color_t GetForeColor(void); + + /// Draw a pixel in the specified color. + /// + /// @note Unlike many other operations, this does not + /// set the forecolor! + /// + /// @param[in] x is the horizontal offset to this pixel. + /// @param[in] y is the vertical offset to this pixel. + /// @param[in] color defines the color for the pixel. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t pixel(loc_t x, loc_t y, color_t color); + + /// Draw a pixel in the current foreground color. + /// + /// @param[in] x is the horizontal offset to this pixel. + /// @param[in] y is the veritical offset to this pixel. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t pixel(loc_t x, loc_t y); + + /// Get a pixel from the display. + /// + /// @param[in] x is the horizontal offset to this pixel. + /// @param[in] y is the vertical offset to this pixel. + /// @returns the pixel. see @color_t + /// + virtual color_t getPixel(loc_t x, loc_t y); + + /// Write a stream of pixels to the display. + /// + /// @param[in] p is a pointer to a color_t array to write. + /// @param[in] count is the number of pixels to write. + /// @param[in] x is the horizontal position on the display. + /// @param[in] y is the vertical position on the display. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t pixelStream(color_t * p, uint32_t count, loc_t x, loc_t y); + + /// Get a stream of pixels from the display. + /// + /// @param[in] p is a pointer to a color_t array to accept the stream. + /// @param[in] count is the number of pixels to read. + /// @param[in] x is the horizontal offset to this pixel. + /// @param[in] y is the vertical offset to this pixel. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t getPixelStream(color_t * p, uint32_t count, loc_t x, loc_t y); + + /// Draw a line in the specified color + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x1 is the horizontal start of the line. + /// @param[in] y1 is the vertical start of the line. + /// @param[in] x2 is the horizontal end of the line. + /// @param[in] y2 is the vertical end of the line. + /// @param[in] color defines the foreground color. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t line(loc_t x1, loc_t y1, loc_t x2, loc_t y2, color_t color); + + /// Draw a line + /// + /// Draws a line using the foreground color setting. + /// + /// @param[in] x1 is the horizontal start of the line. + /// @param[in] y1 is the vertical start of the line. + /// @param[in] x2 is the horizontal end of the line. + /// @param[in] y2 is the vertical end of the line. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t line(loc_t x1, loc_t y1, loc_t x2, loc_t y2); + + /// Draw a rectangle in the specified color + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] rect defines the rectangle. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t rect(rect_t rect, color_t color, fill_t fillit); + + /// Draw a filled rectangle in the specified color + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] rect defines the rectangle. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t fillrect(rect_t rect, color_t color, fill_t fillit = FILL); + + /// Draw a rectangle in the specified color + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x1 is the horizontal start of the line. + /// @param[in] y1 is the vertical start of the line. + /// @param[in] x2 is the horizontal end of the line. + /// @param[in] y2 is the vertical end of the line. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to FILL the rectangle. default is FILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + color_t color, fill_t fillit = NOFILL); + + /// Draw a filled rectangle in the specified color + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x1 is the horizontal start of the line. + /// @param[in] y1 is the vertical start of the line. + /// @param[in] x2 is the horizontal end of the line. + /// @param[in] y2 is the vertical end of the line. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to NOFILL the rectangle. default is FILL. + /// @returns success/failure code. @see RetCode_t. + /// + virtual RetCode_t fillrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + color_t color, fill_t fillit = FILL); + + /// Draw a rectangle + /// + /// Draws a rectangle using the foreground color setting. + /// + /// @param[in] x1 is the horizontal start of the line. + /// @param[in] y1 is the vertical start of the line. + /// @param[in] x2 is the horizontal end of the line. + /// @param[in] y2 is the vertical end of the line. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t rect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + fill_t fillit = NOFILL); + + /// Draw a filled rectangle with rounded corners using the specified color. + /// + /// This draws a rounded rectangle. A numbers of checks are made on the values, + /// and it could reduce this to drawing a line (if either x1 == x2, or y1 == y2), + /// or a single point (x1 == x2 && y1 == y2). If the radius parameters are + /// > 1/2 the length of that side (width or height), an error value is returned. + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x1 is the horizontal start of the line and must be <= x2. + /// @param[in] y1 is the vertical start of the line and must be <= y2. + /// @param[in] x2 is the horizontal end of the line and must be >= x1. + /// @param[in] y2 is the vertical end of the line and must be >= y1. + /// @param[in] radius1 defines the horizontal radius of the curved corner. Take care + /// that this value < 1/2 the width of the rectangle, or bad_parameter + /// is returned. + /// @param[in] radius2 defines the vertical radius of the curved corner. Take care + /// that this value < 1/2 the height of the rectangle, or bad_parameter + /// is returned. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t fillroundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + dim_t radius1, dim_t radius2, color_t color, fill_t fillit = FILL); + + /// Draw a rectangle with rounded corners using the specified color. + /// + /// This draws a rounded rectangle. A numbers of checks are made on the values, + /// and it could reduce this to drawing a line (if either x1 == x2, or y1 == y2), + /// or a single point (x1 == x2 && y1 == y2). If the radius parameters are + /// > 1/2 the length of that side (width or height), an error value is returned. + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x1 is the horizontal start of the line and must be <= x2. + /// @param[in] y1 is the vertical start of the line and must be <= y2. + /// @param[in] x2 is the horizontal end of the line and must be >= x1. + /// @param[in] y2 is the vertical end of the line and must be >= y1. + /// @param[in] radius1 defines the horizontal radius of the curved corner. Take care + /// that this value < 1/2 the width of the rectangle, or bad_parameter + /// is returned. + /// @param[in] radius2 defines the vertical radius of the curved corner. Take care + /// that this value < 1/2 the height of the rectangle, or bad_parameter + /// is returned. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + dim_t radius1, dim_t radius2, color_t color, fill_t fillit = NOFILL); + + /// Draw a rectangle with rounded corners. + /// + /// This draws a rounded rectangle. A numbers of checks are made on the values, + /// and it could reduce this to drawing a line (if either x1 == x2, or y1 == y2), + /// or a single point (x1 == x2 && y1 == y2). If the radius parameters are + /// > 1/2 the length of that side (width or height), an error value is returned. + /// + /// @param[in] x1 is the horizontal start of the line and must be <= x2. + /// @param[in] y1 is the vertical start of the line and must be <= y2. + /// @param[in] x2 is the horizontal end of the line and must be >= x1. + /// @param[in] y2 is the vertical end of the line and must be >= y1. + /// @param[in] radius1 defines the horizontal radius of the curved corner. Take care + /// that this value < 1/2 the width of the rectangle, or bad_parameter + /// is returned. + /// @param[in] radius2 defines the vertical radius of the curved corner. Take care + /// that this value < 1/2 the height of the rectangle, or bad_parameter + /// is returned. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t roundrect(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + dim_t radius1, dim_t radius2, fill_t fillit = NOFILL); + + /// Draw a triangle in the specified color. + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x1 is the horizontal for point 1. + /// @param[in] y1 is the vertical for point 1. + /// @param[in] x2 is the horizontal for point 2. + /// @param[in] y2 is the vertical for point 2. + /// @param[in] x3 is the horizontal for point 3. + /// @param[in] y3 is the vertical for point 3. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + loc_t x3, loc_t y3, color_t color, fill_t fillit = NOFILL); + + /// Draw a filled triangle in the specified color. + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x1 is the horizontal for point 1. + /// @param[in] y1 is the vertical for point 1. + /// @param[in] x2 is the horizontal for point 2. + /// @param[in] y2 is the vertical for point 2. + /// @param[in] x3 is the horizontal for point 3. + /// @param[in] y3 is the vertical for point 3. + /// @param[in] color defines the foreground color. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t filltriangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + loc_t x3, loc_t y3, color_t color, fill_t fillit = FILL); + + /// Draw a triangle + /// + /// Draws a triangle using the foreground color setting. + /// + /// @param[in] x1 is the horizontal for point 1. + /// @param[in] y1 is the vertical for point 1. + /// @param[in] x2 is the horizontal for point 2. + /// @param[in] y2 is the vertical for point 2. + /// @param[in] x3 is the horizontal for point 3. + /// @param[in] y3 is the vertical for point 3. + /// @param[in] fillit is optional to FILL the rectangle. default is NOFILL. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, + loc_t x3, loc_t y3, fill_t fillit = NOFILL); + + /// Draw a circle using the specified color. + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x is the horizontal center of the circle. + /// @param[in] y is the vertical center of the circle. + /// @param[in] radius defines the size of the circle. + /// @param[in] color defines the foreground color. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t circle(loc_t x, loc_t y, dim_t radius, color_t color, fill_t fillit = NOFILL); + + /// Draw a filled circle using the specified color. + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x is the horizontal center of the circle. + /// @param[in] y is the vertical center of the circle. + /// @param[in] radius defines the size of the circle. + /// @param[in] color defines the foreground color. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t fillcircle(loc_t x, loc_t y, dim_t radius, color_t color, fill_t fillit = FILL); + + /// Draw a circle. + /// + /// Draws a circle using the foreground color setting. + /// + /// @param[in] x is the horizontal center of the circle. + /// @param[in] y is the vertical center of the circle. + /// @param[in] radius defines the size of the circle. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t circle(loc_t x, loc_t y, dim_t radius, fill_t fillit = NOFILL); + + /// Draw an Ellipse using the specified color + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x is the horizontal center of the ellipse. + /// @param[in] y is the vertical center of the ellipse. + /// @param[in] radius1 defines the horizontal radius of the ellipse. + /// @param[in] radius2 defines the vertical radius of the ellipse. + /// @param[in] color defines the foreground color. + /// @param[in] fillit defines whether the circle is filled or not. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, + color_t color, fill_t fillit = NOFILL); + + /// Draw a filled Ellipse using the specified color + /// + /// @note As a side effect, this changes the current + /// foreground color for subsequent operations. + /// + /// @param[in] x is the horizontal center of the ellipse. + /// @param[in] y is the vertical center of the ellipse. + /// @param[in] radius1 defines the horizontal radius of the ellipse. + /// @param[in] radius2 defines the vertical radius of the ellipse. + /// @param[in] color defines the foreground color. + /// @param[in] fillit defines whether the circle is filled or not. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t fillellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, + color_t color, fill_t fillit = FILL); + + /// Draw an Ellipse + /// + /// Draws it using the foreground color setting. + /// + /// @param[in] x is the horizontal center of the ellipse. + /// @param[in] y is the vertical center of the ellipse. + /// @param[in] radius1 defines the horizontal radius of the ellipse. + /// @param[in] radius2 defines the vertical radius of the ellipse. + /// @param[in] fillit defines whether the circle is filled or not. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t ellipse(loc_t x, loc_t y, dim_t radius1, dim_t radius2, fill_t fillit = NOFILL); + + /// Control display power + /// + /// @param[in] on when set to true will turn on the display, when false it is turned off. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t Power(bool on); + + /// Reset the display controller via the Software Reset interface. + /// + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t Reset(void); + + /// Set backlight brightness. + /// + /// When the built-in PWM is used to control the backlight, this + /// API can be used to set the brightness. + /// + /// @param[in] brightness ranges from 0 (off) to 255 (full on) + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t Backlight_u8(unsigned char brightness); + + /// Set backlight brightness. + /// + /// When the built-in PWM is used to control the backlight, this + /// API can be used to set the brightness. + /// + /// @param[in] brightness ranges from 0.0 (off) to 1.0 (full on) + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t Backlight(float brightness); + + /// Select a bitmap font (provided by the user) for all subsequent text. + /// + /// @note Tool to create the fonts is accessible from its creator + /// available at http://www.mikroe.com. + /// Change the data to an array of type char[]. + /// + /// @param[in] font is a pointer to a specially formed font array. + /// This special font array has a 4-byte header, followed by + /// the data: + /// - the number of bytes per char + /// - the vertical size in pixels for each character + /// - the horizontal size in pixels for each character + /// - the number of bytes per vertical line (width of the array) + /// @returns error code. + /// + virtual RetCode_t set_font(const unsigned char * font = NULL); + + /// Get the RGB value for a DOS color. + /// + /// @param[in] i is the color, in the range 0 to 15; + /// @returns the RGB color of the selected index, or 0 + /// if the index is out of bounds. + /// + color_t DOSColor(int i); + + /// Get the color name (string) for a DOS color. + /// + /// @param[in] i is the color, in the range 0 to 15; + /// @returns a pointer to a string with the color name, + /// or NULL if the index is out of bounds. + /// + const char * DOSColorNames(int i); + + /// Advanced method indicating the start of a graphics stream. + /// + /// This is called prior to a stream of pixel data being sent. + /// This may cause register configuration changes in the derived + /// class in order to prepare the hardware to accept the streaming + /// data. + /// + /// Following this command, a series of @see _putp() commands can + /// be used to send individual pixels to the screen. + /// + /// To conclude the graphics stream, @see _EndGraphicsStream should + /// be callled. + /// + /// @returns error code. + /// + virtual RetCode_t _StartGraphicsStream(void); + + /// Advanced method to put a single color pixel to the screen. + /// + /// This method may be called as many times as necessary after + /// @see _StartGraphicsStream() is called, and it should be followed + /// by _EndGraphicsStream. + /// + /// @param[in] pixel is a color value to be put on the screen. + /// @returns error code. + /// + virtual RetCode_t _putp(color_t pixel); + + /// Advanced method indicating the end of a graphics stream. + /// + /// This is called to conclude a stream of pixel data that was sent. + /// This may cause register configuration changes in the derived + /// class in order to stop the hardware from accept the streaming + /// data. + /// + /// @returns error code. + /// + virtual RetCode_t _EndGraphicsStream(void); + + /// Set the SPI port frequency (in Hz). + /// + /// This uses the mbed SPI driver, and is therefore dependent on + /// its capabilities. The RA8875 can accept writes via SPI faster + /// than a read can be performed. The frequency set by this API + /// is for the SPI writes. It will automatically reduce the SPI + /// clock rate when a read is performed, and restore it for the + /// next write. Alternately, the 2nd parameters permits setting + /// the read speed rather than letting it compute it automatically. + /// + /// @note The primary effect of this is to recover more CPU cycles + /// for your application code. Keep in mind that when more than + /// one command is sent to the display controller, that it + /// will wait for the controller to finish the prior command. + /// In this case, the performance is limited by the RA8875. + /// + /// @param[in] Hz is the frequency in Hz, tested range includes the + /// range from 1,000,000 (1MHz) to 10,000,000 (10 MHz). Values + /// outside this range will be accepted, but operation may + /// be unreliable. This depends partially on your hardware design + /// and the wires connecting the display module. + /// The default value is 5,000,000, which should work for most + /// applications as a starting point. + /// @param[in] Hz2 is an optional parameter and will set the read + /// speed independently of the write speed. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t frequency(unsigned long Hz = RA8875_DEFAULT_SPI_FREQ, unsigned long Hz2 = 0); + + /// This method captures the specified area as a 24-bit bitmap file. + /// + /// Even though this is a 16-bit display, the stored image is in + /// 24-bit format. + /// + /// This method will interrogate the current display setting and + /// create a bitmap based on those settings. For instance, if + /// only layer 1 is visible, then the bitmap is only layer 1. However, + /// if there is some other operation in effect (transparent mode). + /// + /// @param[in] x is the left edge of the region to capture + /// @param[in] y is the top edge of the region to capture + /// @param[in] w is the width of the region to capture + /// @param[in] h is the height of the region to capture. + /// @param[out] Name_BMP is the filename to write the image to. + /// @return success or error code. + /// + RetCode_t PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP); + + /// This method captures the specified area as a 24-bit bitmap file, + /// including the option of layer selection. + /// + /// @caution This method is deprecated as the alternate PrintScreen API + /// automatically examines the display layer configuration. + /// Therefore, calls to this API will ignore the layer parameter + /// and automatically execute the other method. + /// + /// Even though this is a 16-bit display, the stored image is in + /// 24-bit format. + /// + /// @param[in] layer is 0 or 1 to select the layer to extract. + /// @param[in] x is the left edge of the region to capture + /// @param[in] y is the top edge of the region to capture + /// @param[in] w is the width of the region to capture + /// @param[in] h is the height of the region to capture. + /// @param[out] Name_BMP is the filename to write the image to. + /// @return success or error code. + /// + RetCode_t PrintScreen(uint16_t layer, loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP); + + +#ifdef PERF_METRICS + /// Clear the performance metrics to zero. + void ClearPerformance(); + + /// Count idle time. + /// + /// @param[in] t is the amount of idle time to accumulate. + /// + void CountIdleTime(uint32_t t); + + /// Report the performance metrics for drawing functions using + /// the available serial channel. + /// + /// @param[in,out] pc is the serial channel to write to. + /// + void ReportPerformance(Serial & pc); +#endif + + +private: + /// Touch Panel register name definitions + #define TPCR0 0x70 + #define TPCR1 0x71 + #define TPXH 0x72 + #define TPYH 0x73 + #define TPXYL 0x74 + #define INTC1 0xF0 + #define INTC2 0xF1 + + /// Specify the default settings for the Touch Panel, where different from the chip defaults + #define TP_MODE_DEFAULT TP_MODE_AUTO + #define TP_DEBOUNCE_DEFAULT TP_DEBOUNCE_ON + #define TP_ADC_CLKDIV_DEFAULT TP_ADC_CLKDIV_8 + + #define TP_ADC_SAMPLE_DEFAULT_CLKS TP_ADC_SAMPLE_8192_CLKS + + /// Other Touch Panel params + #define TPBUFSIZE 16 // Depth of the averaging buffers for x and y data + + /// Touch Panel calibration matrix. + tpMatrix_t tpMatrix; + + /// Internal function to put a character using the built-in (internal) font engine + /// + /// @param[in] is the character to put to the screen. + /// @returns the character put. + /// + int _internal_putc(int c); + + /// Internal function to put a character using the external font engine + /// + /// @param[in] is the character to put to the screen. + /// @returns the character put. + /// + int _external_putc(int c); + + /// Select the peripheral to use it. + /// + /// @param[in] chipsel when true will select the peripheral, and when false + /// will deselect the chip. This is the logical selection, and + /// the pin selection is the invert of this. + /// @returns success/failure code. @see RetCode_t. + /// + RetCode_t _select(bool chipsel); + + /// Wait while the status register indicates the controller is busy. + /// + /// @param[in] mask is the mask of bits to monitor. + /// @returns true if a normal exit. + /// @returns false if a timeout exit. + /// + bool _WaitWhileBusy(uint8_t mask); + + /// Wait while the the register anded with the mask is true. + /// + /// @param[in] reg is the register to monitor + /// @param[in] mask is the bit mask to monitor + /// @returns true if it was a normal exit + /// @returns false if it was a timeout that caused the exit. + /// + bool _WaitWhileReg(uint8_t reg, uint8_t mask); + + /// set the spi port to either the write or the read speed. + /// + /// This is a private API used to toggle between the write + /// and the read speed for the SPI port to the RA8875, since + /// it can accept writes faster than reads. + /// + /// @param[in] writeSpeed when true selects the write frequency, + /// and when false it selects the read frequency. + /// + void _setWriteSpeed(bool writeSpeed); + + /// The most primitive - to write a data value to the SPI interface. + /// + /// @param[in] data is the value to write. + /// @returns a value read from the port, since SPI is often shift + /// in while shifting out. + /// + unsigned char _spiwrite(unsigned char data); + + /// The most primitive - to read a data value to the SPI interface. + /// + /// This is really just a specialcase of the write command, where + /// the value zero is written in order to read. + /// + /// @returns a value read from the port, since SPI is often shift + /// in while shifting out. + /// + unsigned char _spiread(); + + const uint8_t * pKeyMap; + + SPI spi; ///< spi port + bool spiWriteSpeed; ///< indicates if the current mode is write or read + unsigned long spiwritefreq; ///< saved write freq + unsigned long spireadfreq; ///< saved read freq + DigitalOut cs; ///< chip select pin, assumed active low + DigitalOut res; ///< reset pin, assumed active low + const unsigned char * font; ///< reference to an external font somewhere in memory + loc_t cursor_x, cursor_y; ///< used for external fonts only + + #ifdef PERF_METRICS + typedef enum + { + PRF_CLS, + PRF_DRAWPIXEL, + PRF_PIXELSTREAM, + PRF_READPIXEL, + PRF_READPIXELSTREAM, + PRF_DRAWLINE, + PRF_DRAWRECTANGLE, + PRF_DRAWROUNDEDRECTANGLE, + PRF_DRAWTRIANGLE, + PRF_DRAWCIRCLE, + PRF_DRAWELLIPSE, + METRICCOUNT + } method_e; + unsigned long metrics[METRICCOUNT]; + unsigned long idletime_usec; + void RegisterPerformance(method_e method); + Timer performance; + #endif +}; + +//} // namespace + +//using namespace SW_graphics; + + +#ifdef TESTENABLE +// ______________ ______________ ______________ _______________ +// /_____ _____/ / ___________/ / ___________/ /_____ ______/ +// / / / / / / / / +// / / / /___ / /__________ / / +// / / / ____/ /__________ / / / +// / / / / / / / / +// / / / /__________ ___________/ / / / +// /__/ /_____________/ /_____________/ /__/ + +#include "WebColors.h" +#include "Arial12x12.h" +#include <algorithm> + +extern "C" void mbed_reset(); + +/// This activates a small set of tests for the graphics library. +/// +/// Call this API and pass it the reference to the display class. +/// It will then run a series of tests. It accepts interaction via +/// stdin to switch from automatic test mode to manual, run a specific +/// test, or to exit the test mode. +/// +/// @param[in] lcd is a reference to the display class. +/// @param[in] pc is a reference to a serial interface, typically the USB to PC. +/// +void RunTestSet(RA8875 & lcd, Serial & pc); + + +// To enable the test code, uncomment this section, or copy the +// necessary pieces to your "main()". +// +// #include "mbed.h" +// #include "RA8875.h" +// RA8875 lcd(p5, p6, p7, p12, NC, "tft"); // MOSI, MISO, SCK, /ChipSelect, /reset, name +// Serial pc(USBTX, USBRX); +// extern "C" void mbed_reset(); +// int main() +// { +// pc.baud(460800); // I like a snappy terminal, so crank it up! +// pc.printf("\r\nRA8875 Test - Build " __DATE__ " " __TIME__ "\r\n"); +// +// pc.printf("Turning on display\r\n"); +// lcd.Reset(); +// lcd.Power(true); // display power is on, but the backlight is independent +// lcd.Backlight(0.5); +// RunTestSet(lcd, pc); +// } + +#endif // TESTENABLE + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/RA8875_Regs.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,56 @@ +// +// RA8875 Display Controller Register Definitions. +// +// +#ifndef RA8875_REGS_H +#define RA8875_REGS_H + + // Touch Panel public macros + + /* Touch Panel Enable/Disable Reg TPCR0[7] */ + #define TP_ENABLE ((uint8_t)(1<<7)) + #define TP_DISABLE ((uint8_t)(0<<7)) + + /* Touch Panel operating mode Reg TPCR1[6] */ + #define TP_MODE_AUTO ((uint8_t)(0<<6)) + #define TP_MODE_MANUAL ((uint8_t)(1<<6)) + + /* Touch Panel debounce Reg TPCR1[2] */ + #define TP_DEBOUNCE_OFF ((uint8_t)(0<<2)) + #define TP_DEBOUNCE_ON ((uint8_t)(1<<2)) + + /* Touch Panel manual modes Reg TPCR1[1:0] */ + #define TP_MANUAL_IDLE 0 + #define TP_MANUAL_WAIT 1 + #define TP_MANUAL_LATCH_X 2 + #define TP_MANUAL_LATCH_Y 3 + + /* Touch Panel ADC Clock modes Reg TPCR0[2:0] */ + #define TP_ADC_CLKDIV_1 0 + #define TP_ADC_CLKDIV_2 1 + #define TP_ADC_CLKDIV_4 2 + #define TP_ADC_CLKDIV_8 3 + #define TP_ADC_CLKDIV_16 4 + #define TP_ADC_CLKDIV_32 5 + #define TP_ADC_CLKDIV_64 6 + #define TP_ADC_CLKDIV_128 7 + + + /* Touch Panel Sample Time Reg TPCR0[6:4] */ + #define TP_ADC_SAMPLE_512_CLKS ((uint8_t)(0<<4)) + #define TP_ADC_SAMPLE_1024_CLKS ((uint8_t)(1<<4)) + #define TP_ADC_SAMPLE_2048_CLKS ((uint8_t)(2<<4)) + #define TP_ADC_SAMPLE_4096_CLKS ((uint8_t)(3<<4)) + #define TP_ADC_SAMPLE_8192_CLKS ((uint8_t)(4<<4)) + #define TP_ADC_SAMPLE_16384_CLKS ((uint8_t)(5<<4)) + #define TP_ADC_SAMPLE_32768_CLKS ((uint8_t)(6<<4)) + #define TP_ADC_SAMPLE_65536_CLKS ((uint8_t)(7<<4)) + + /* RA8875 interrupt enable/flag/clear masks */ + #define RA8875_INT_KEYSCAN ((uint8_t)(1<<4)) /**< KEYSCAN interrupts */ + #define RA8875_INT_DMA ((uint8_t)(1<<3)) /**< DMA interrupts */ + #define RA8875_INT_TP ((uint8_t)(1<<2)) /**< Touch panel interrupts */ + #define RA8875_INT_BTE ((uint8_t)(1<<1)) /**< BTE process complete interrupts */ + #define RA8875_INT_BTEMCU_FONTWR ((uint8_t)(1<<0)) /**< BTE-MCU-R/W or Font-Write interrupts */ + +#endif // RA8875_REGS_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/RA8875_Touch.cpp Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,460 @@ +/// This file contains the RA8875 Touch panel methods. +/// + +#include "RA8875.h" + +// ### Touch Panel support code additions begin here + +RetCode_t RA8875::TouchPanelInit(void) +{ + //TPCR0: Set enable bit, default sample time, wakeup, and ADC clock + WriteCommand(TPCR0, TP_ENABLE | TP_ADC_SAMPLE_DEFAULT_CLKS | TP_ADC_CLKDIV_DEFAULT); + // TPCR1: Set auto/manual, Ref voltage, debounce, manual mode params + WriteCommand(TPCR1, TP_MODE_DEFAULT | TP_DEBOUNCE_DEFAULT); + WriteCommand(INTC1, ReadCommand(INTC1) | RA8875_INT_TP); // reg INTC1: Enable Touch Panel Interrupts (D2 = 1) + WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear any TP interrupt flag + return noerror; +} + +RetCode_t RA8875::TouchPanelInit(uint8_t bTpEnable, uint8_t bTpAutoManual, uint8_t bTpDebounce, uint8_t bTpManualMode, uint8_t bTpAdcClkDiv, uint8_t bTpAdcSampleTime) +{ + // Parameter bounds check + if( \ + !(bTpEnable == TP_ENABLE || bTpEnable == TP_ENABLE) || \ + !(bTpAutoManual == TP_MODE_AUTO || bTpAutoManual == TP_MODE_MANUAL) || \ + !(bTpDebounce == TP_DEBOUNCE_OFF || bTpDebounce == TP_DEBOUNCE_ON) || \ + !(bTpManualMode <= TP_MANUAL_LATCH_Y) || \ + !(bTpAdcClkDiv <= TP_ADC_CLKDIV_128) || \ + !(bTpAdcSampleTime <= TP_ADC_SAMPLE_65536_CLKS) \ + ) return bad_parameter; + // Construct the config byte for TPCR0 and write them + WriteCommand(TPCR0, bTpEnable | bTpAdcClkDiv | bTpAdcSampleTime); // Note: Wakeup is never enabled + // Construct the config byte for TPCR1 and write them + WriteCommand(TPCR1, bTpManualMode | bTpDebounce | bTpManualMode); // Note: Always uses internal Vref. + // Set up the interrupt flag and enable bits + WriteCommand(INTC1, ReadCommand(INTC1) | RA8875_INT_TP); // reg INTC1: Enable Touch Panel Interrupts (D2 = 1) + WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear any TP interrupt flag + return noerror; +} + + // +----------------------------------------------------+ + // | | + // | 1 | + // | | + // | | + // | 2 | + // | | + // | | + // | 3 | + // | | + // +----------------------------------------------------+ + + +RetCode_t RA8875::TouchPanelCalibrate(tpMatrix_t * matrix) +{ + return TouchPanelCalibrate(NULL, matrix); +} + + +RetCode_t RA8875::TouchPanelCalibrate(const char * msg, tpMatrix_t * matrix) +{ + point_t pTest[3]; + point_t pSample[3]; + loc_t x,y; + + cls(); + if (msg) + puts(msg); + SetTextCursor(0,height()/2); + pTest[0].x = 50; pTest[0].y = 50; + pTest[1].x = width() - 50; pTest[1].y = height()/2; + pTest[2].x = width()/2; pTest[2].y = height() - 50; + for (int i=0; i<3; i++) { + foreground(Blue); + printf(" (%3d,%3d) => ", pTest[i].x, pTest[i].y); + line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, White); + line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, White); + while (!TouchPanelA2DFiltered(&x, &y)) + wait_ms(20); + pSample[i].x = x; + pSample[i].y = y; + line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, Black); + line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, Black); + foreground(Blue); + printf(" (%4d,%4d)\r\n", x,y); + while (TouchPanelA2DFiltered(&x, &y)) + wait_ms(20); + wait(2); + } + return TouchPanelComputeCalibration(pTest, pSample, matrix); +} + + +/********************************************************************** + * + * Function: getDisplayPoint() + * + * Description: Given a valid set of calibration factors and a point + * value reported by the touch screen, this function + * calculates and returns the true (or closest to true) + * display point below the spot where the touch screen + * was touched. + * + * + * + * Argument(s): displayPtr (output) - Pointer to the calculated + * (true) display point. + * screenPtr (input) - Pointer to the reported touch + * screen point. + * matrixPtr (input) - Pointer to calibration factors + * matrix previously calculated + * from a call to + * setCalibrationMatrix() + * + * + * The function simply solves for Xd and Yd by implementing the + * computations required by the translation matrix. + * + * /- -\ + * /- -\ /- -\ | | + * | | | | | Xs | + * | Xd | | A B C | | | + * | | = | | * | Ys | + * | Yd | | D E F | | | + * | | | | | 1 | + * \- -/ \- -/ | | + * \- -/ + * + * It must be kept brief to avoid consuming CPU cycles. + * + * Return: OK - the display point was correctly calculated + * and its value is in the output argument. + * NOT_OK - an error was detected and the function + * failed to return a valid point. + * + * NOTE! NOTE! NOTE! + * + * setCalibrationMatrix() and getDisplayPoint() will do fine + * for you as they are, provided that your digitizer + * resolution does not exceed 10 bits (1024 values). Higher + * resolutions may cause the integer operations to overflow + * and return incorrect values. If you wish to use these + * functions with digitizer resolutions of 12 bits (4096 + * values) you will either have to a) use 64-bit signed + * integer variables and math, or b) judiciously modify the + * operations to scale results by a factor of 2 or even 4. + * + */ +bool RA8875::TouchPanelReadable(point_t * TouchPoint) +{ + bool touched = false; + point_t screenpoint = {0, 0}; + + if (TouchPanelA2DFiltered(&screenpoint.x, &screenpoint.y)) { + touched = true; + if (tpMatrix.Divider != 0 && TouchPoint) { + /* Operation order is important since we are doing integer */ + /* math. Make sure you add all terms together before */ + /* dividing, so that the remainder is not rounded off */ + /* prematurely. */ + TouchPoint->x = ( (tpMatrix.An * screenpoint.x) + + (tpMatrix.Bn * screenpoint.y) + + tpMatrix.Cn + ) / tpMatrix.Divider ; + + TouchPoint->y = ( (tpMatrix.Dn * screenpoint.x) + + (tpMatrix.En * screenpoint.y) + + tpMatrix.Fn + ) / tpMatrix.Divider ; + } else { + touched = false; + } + } + return touched; +} + + +RetCode_t RA8875::TouchPanelSetMatrix(tpMatrix_t * matrixPtr) +{ + if (matrixPtr == NULL || matrixPtr->Divider == 0) + return bad_parameter; + memcpy(&tpMatrix, matrixPtr, sizeof(tpMatrix_t)); + return noerror; +} + + +bool RA8875::TouchPanelA2DFiltered(loc_t *x, loc_t *y) +{ + unsigned char touchready; + static int xbuf[TPBUFSIZE], ybuf[TPBUFSIZE], sample = 0; + int i, j, temp; + + if( (ReadCommand(INTC2) & RA8875_INT_TP) ) { // Test for TP Interrupt pending in register INTC2 + // Get the next data samples + ybuf[sample] = ReadCommand(TPYH) << 2 | ( (ReadCommand(TPXYL) & 0xC) >> 2 ); // D[9:2] from reg TPYH, D[1:0] from reg TPXYL[3:2] + xbuf[sample] = ReadCommand(TPXH) << 2 | ( (ReadCommand(TPXYL) & 0x3) ); // D[9:2] from reg TPXH, D[1:0] from reg TPXYL[1:0] + // Check for a complete set + if(++sample == TPBUFSIZE) { + // Buffers are full, so process them using Finn's method described in Analog Dialogue No. 44, Feb 2010 + // This requires sorting the samples in order of size, then discarding the top 25% and + // bottom 25% as noise spikes. Finally, the middle 50% of the values are averaged to + // reduce Gaussian noise. + + // Sort the Y buffer using an Insertion Sort + for(i = 1; i <= TPBUFSIZE; i++) { + temp = ybuf[i]; + j = i; + while( j && (ybuf[j-1] > temp) ) { + ybuf[j] = ybuf[j-1]; + j = j-1; + } + ybuf[j] = temp; + } // End of Y sort + // Sort the X buffer the same way + for(i = 1; i <= TPBUFSIZE; i++) { + temp = xbuf[i]; + j = i; + while( j && (xbuf[j-1] > temp) ) { + xbuf[j] = xbuf[j-1]; + j = j-1; + } + xbuf[j] = temp; + } // End of X sort + // Average the middle half of the Y values and report them + j = 0; + for(i = (TPBUFSIZE/4) - 1; i < TPBUFSIZE - TPBUFSIZE/4; i++ ) { + j += ybuf[i]; + } + *y = j * (float)2/TPBUFSIZE; // This is the average + // Average the middle half of the X values and report them + j = 0; + for(i = (TPBUFSIZE/4) - 1; i < TPBUFSIZE - TPBUFSIZE/4; i++ ) { + j += xbuf[i]; + } + *x = j * (float)2/TPBUFSIZE; // This is the average + // Tidy up and return + touchready = 1; + sample = 0; // Ready to start on the next set of data samples + } else { + // Buffer not yet full, so do not return any results yet + touchready = 0; + } + WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear that TP interrupt flag + } // End of initial if -- data has been read and processed + else + touchready = 0; // Touch Panel "Int" was not set + return touchready; +} + +bool RA8875::TouchPanelA2DRaw(loc_t *x, loc_t *y) +{ + unsigned char touchready; + + if( (ReadCommand(INTC2) & RA8875_INT_TP) ) { // Test for TP Interrupt pending in register INTC2 + *y = ReadCommand(TPYH) << 2 | ( (ReadCommand(TPXYL) & 0xC) >> 2 ); // D[9:2] from reg TPYH, D[1:0] from reg TPXYL[3:2] + *x = ReadCommand(TPXH) << 2 | ( (ReadCommand(TPXYL) & 0x3) ); // D[9:2] from reg TPXH, D[1:0] from reg TPXYL[1:0] + WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear that TP interrupt flag + touchready = 1; + } else + touchready = 0; + return touchready; +} + +/* The following section is derived from Carlos E. Vidales. + * + * Copyright (c) 2001, Carlos E. Vidales. All rights reserved. + * + * This sample program was written and put in the public domain + * by Carlos E. Vidales. The program is provided "as is" + * without warranty of any kind, either expressed or implied. + * If you choose to use the program within your own products + * you do so at your own risk, and assume the responsibility + * for servicing, repairing or correcting the program should + * it prove defective in any manner. + * You may copy and distribute the program's source code in any + * medium, provided that you also include in each copy an + * appropriate copyright notice and disclaimer of warranty. + * You may also modify this program and distribute copies of + * it provided that you include prominent notices stating + * that you changed the file(s) and the date of any change, + * and that you do not charge any royalties or licenses for + * its use. + * + * This file contains functions that implement calculations + * necessary to obtain calibration factors for a touch screen + * that suffers from multiple distortion effects: namely, + * translation, scaling and rotation. + * + * The following set of equations represent a valid display + * point given a corresponding set of touch screen points: + * + * /- -\ + * /- -\ /- -\ | | + * | | | | | Xs | + * | Xd | | A B C | | | + * | | = | | * | Ys | + * | Yd | | D E F | | | + * | | | | | 1 | + * \- -/ \- -/ | | + * \- -/ + * where: + * (Xd,Yd) represents the desired display point + * coordinates, + * (Xs,Ys) represents the available touch screen + * coordinates, and the matrix + * /- -\ + * |A,B,C| + * |D,E,F| represents the factors used to translate + * \- -/ the available touch screen point values + * into the corresponding display + * coordinates. + * Note that for practical considerations, the utilities + * within this file do not use the matrix coefficients as + * defined above, but instead use the following + * equivalents, since floating point math is not used: + * A = An/Divider + * B = Bn/Divider + * C = Cn/Divider + * D = Dn/Divider + * E = En/Divider + * F = Fn/Divider + * The functions provided within this file are: + * setCalibrationMatrix() - calculates the set of factors + * in the above equation, given + * three sets of test points. + * getDisplayPoint() - returns the actual display + * coordinates, given a set of + * touch screen coordinates. + * translateRawScreenCoordinates() - helper function to transform + * raw screen points into values + * scaled to the desired display + * resolution. + */ + +/********************************************************************** + * + * Function: setCalibrationMatrix() + * + * Description: Calling this function with valid input data + * in the display and screen input arguments + * causes the calibration factors between the + * screen and display points to be calculated, + * and the output argument - matrixPtr - to be + * populated. + * + * This function needs to be called only when new + * calibration factors are desired. + * + * + * Argument(s): displayPtr (input) - Pointer to an array of three + * sample, reference points. + * screenPtr (input) - Pointer to the array of touch + * screen points corresponding + * to the reference display points. + * matrixPtr (output) - Pointer to the calibration + * matrix computed for the set + * of points being provided. + * + * + * From the article text, recall that the matrix coefficients are + * resolved to be the following: + * + * + * Divider = (Xs0 - Xs2)*(Ys1 - Ys2) - (Xs1 - Xs2)*(Ys0 - Ys2) + * + * + * + * (Xd0 - Xd2)*(Ys1 - Ys2) - (Xd1 - Xd2)*(Ys0 - Ys2) + * A = --------------------------------------------------- + * Divider + * + * + * (Xs0 - Xs2)*(Xd1 - Xd2) - (Xd0 - Xd2)*(Xs1 - Xs2) + * B = --------------------------------------------------- + * Divider + * + * + * Ys0*(Xs2*Xd1 - Xs1*Xd2) + + * Ys1*(Xs0*Xd2 - Xs2*Xd0) + + * Ys2*(Xs1*Xd0 - Xs0*Xd1) + * C = --------------------------------------------------- + * Divider + * + * + * (Yd0 - Yd2)*(Ys1 - Ys2) - (Yd1 - Yd2)*(Ys0 - Ys2) + * D = --------------------------------------------------- + * Divider + * + * + * (Xs0 - Xs2)*(Yd1 - Yd2) - (Yd0 - Yd2)*(Xs1 - Xs2) + * E = --------------------------------------------------- + * Divider + * + * + * Ys0*(Xs2*Yd1 - Xs1*Yd2) + + * Ys1*(Xs0*Yd2 - Xs2*Yd0) + + * Ys2*(Xs1*Yd0 - Xs0*Yd1) + * F = --------------------------------------------------- + * Divider + * + * + * Return: OK - the calibration matrix was correctly + * calculated and its value is in the + * output argument. + * NOT_OK - an error was detected and the + * function failed to return a valid + * set of matrix values. + * The only time this sample code returns + * NOT_OK is when Divider == 0 + * + * + * + * NOTE! NOTE! NOTE! + * + * setCalibrationMatrix() and getDisplayPoint() will do fine + * for you as they are, provided that your digitizer + * resolution does not exceed 10 bits (1024 values). Higher + * resolutions may cause the integer operations to overflow + * and return incorrect values. If you wish to use these + * functions with digitizer resolutions of 12 bits (4096 + * values) you will either have to a) use 64-bit signed + * integer variables and math, or b) judiciously modify the + * operations to scale results by a factor of 2 or even 4. + * + */ +RetCode_t RA8875::TouchPanelComputeCalibration(point_t * displayPtr, point_t * screenPtr, tpMatrix_t * matrixPtr) +{ + RetCode_t retValue = noerror; + + tpMatrix.Divider = ((screenPtr[0].x - screenPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - + ((screenPtr[1].x - screenPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ; + + if( tpMatrix.Divider == 0 ) { + retValue = bad_parameter; + } else { + tpMatrix.An = ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - + ((displayPtr[1].x - displayPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ; + + tpMatrix.Bn = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].x - displayPtr[2].x)) - + ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].x - screenPtr[2].x)) ; + + tpMatrix.Cn = (screenPtr[2].x * displayPtr[1].x - screenPtr[1].x * displayPtr[2].x) * screenPtr[0].y + + (screenPtr[0].x * displayPtr[2].x - screenPtr[2].x * displayPtr[0].x) * screenPtr[1].y + + (screenPtr[1].x * displayPtr[0].x - screenPtr[0].x * displayPtr[1].x) * screenPtr[2].y ; + + tpMatrix.Dn = ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].y - screenPtr[2].y)) - + ((displayPtr[1].y - displayPtr[2].y) * (screenPtr[0].y - screenPtr[2].y)) ; + + tpMatrix.En = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].y - displayPtr[2].y)) - + ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].x - screenPtr[2].x)) ; + + tpMatrix.Fn = (screenPtr[2].x * displayPtr[1].y - screenPtr[1].x * displayPtr[2].y) * screenPtr[0].y + + (screenPtr[0].x * displayPtr[2].y - screenPtr[2].x * displayPtr[0].y) * screenPtr[1].y + + (screenPtr[1].x * displayPtr[0].y - screenPtr[0].x * displayPtr[1].y) * screenPtr[2].y ; + if (matrixPtr) + memcpy(matrixPtr, &tpMatrix, sizeof(tpMatrix_t)); + } + return( retValue ) ; +} + +// #### end of touch panel code additions
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/Small_6.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,105 @@ + +#ifndef SMALL_6_H +#define SMALL_6_H + +const unsigned char Small_6[] = { + 9,8,8,1, // Length,horz,vert,byte/vert + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char + 0x02, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char ! + 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, // Code for char " + 0x06, 0x00, 0x12, 0x3F, 0x12, 0x3F, 0x12, 0x00, 0x00, // Code for char # + 0x04, 0x00, 0x26, 0x7F, 0x32, 0x00, 0x00, 0x00, 0x00, // Code for char $ + 0x05, 0x00, 0x13, 0x0B, 0x34, 0x32, 0x00, 0x00, 0x00, // Code for char % + 0x05, 0x00, 0x1A, 0x25, 0x1A, 0x28, 0x00, 0x00, 0x00, // Code for char & + 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char ' + 0x03, 0x00, 0x7E, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char ( + 0x03, 0x00, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char ) + 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char * + 0x04, 0x00, 0x08, 0x1C, 0x08, 0x00, 0x00, 0x00, 0x00, // Code for char + + 0x02, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char , + 0x03, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char - + 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char . + 0x03, 0x00, 0x38, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char / + 0x05, 0x00, 0x1E, 0x21, 0x21, 0x1E, 0x00, 0x00, 0x00, // Code for char 0 + 0x05, 0x00, 0x02, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char 1 + 0x05, 0x00, 0x32, 0x29, 0x29, 0x26, 0x00, 0x00, 0x00, // Code for char 2 + 0x05, 0x00, 0x12, 0x21, 0x25, 0x1A, 0x00, 0x00, 0x00, // Code for char 3 + 0x05, 0x00, 0x18, 0x16, 0x3F, 0x10, 0x00, 0x00, 0x00, // Code for char 4 + 0x05, 0x00, 0x27, 0x25, 0x19, 0x00, 0x00, 0x00, 0x00, // Code for char 5 + 0x05, 0x00, 0x1E, 0x25, 0x25, 0x18, 0x00, 0x00, 0x00, // Code for char 6 + 0x05, 0x00, 0x01, 0x3D, 0x03, 0x00, 0x00, 0x00, 0x00, // Code for char 7 + 0x05, 0x00, 0x1A, 0x25, 0x25, 0x1A, 0x00, 0x00, 0x00, // Code for char 8 + 0x05, 0x00, 0x12, 0x25, 0x25, 0x1E, 0x00, 0x00, 0x00, // Code for char 9 + 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char : + 0x02, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char ; + 0x04, 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, // Code for char < + 0x04, 0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, // Code for char = + 0x04, 0x00, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, // Code for char > + 0x05, 0x00, 0x02, 0x29, 0x05, 0x02, 0x00, 0x00, 0x00, // Code for char ? + 0x08, 0x00, 0x1C, 0x22, 0x49, 0x55, 0x59, 0x12, 0x0C, // Code for char @ + 0x06, 0x00, 0x30, 0x0C, 0x0B, 0x0C, 0x30, 0x00, 0x00, // Code for char A + 0x06, 0x00, 0x3F, 0x25, 0x25, 0x25, 0x1A, 0x00, 0x00, // Code for char B + 0x06, 0x00, 0x1E, 0x21, 0x21, 0x21, 0x12, 0x00, 0x00, // Code for char C + 0x06, 0x00, 0x3F, 0x21, 0x21, 0x21, 0x1E, 0x00, 0x00, // Code for char D + 0x05, 0x00, 0x3F, 0x25, 0x25, 0x21, 0x00, 0x00, 0x00, // Code for char E + 0x05, 0x00, 0x3F, 0x05, 0x05, 0x01, 0x00, 0x00, 0x00, // Code for char F + 0x06, 0x00, 0x1E, 0x21, 0x21, 0x29, 0x3A, 0x00, 0x00, // Code for char G + 0x05, 0x00, 0x3F, 0x04, 0x04, 0x3F, 0x00, 0x00, 0x00, // Code for char H + 0x02, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char I + 0x04, 0x00, 0x30, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00, // Code for char J + 0x05, 0x00, 0x3F, 0x0C, 0x12, 0x21, 0x00, 0x00, 0x00, // Code for char K + 0x04, 0x00, 0x3F, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, // Code for char L + 0x08, 0x00, 0x3F, 0x03, 0x0C, 0x30, 0x0C, 0x03, 0x3F, // Code for char M + 0x06, 0x00, 0x3F, 0x03, 0x0C, 0x30, 0x3F, 0x00, 0x00, // Code for char N + 0x06, 0x00, 0x1E, 0x21, 0x21, 0x21, 0x1E, 0x00, 0x00, // Code for char O + 0x05, 0x00, 0x3F, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00, // Code for char P + 0x06, 0x00, 0x1E, 0x21, 0x29, 0x11, 0x2E, 0x00, 0x00, // Code for char Q + 0x06, 0x00, 0x3F, 0x09, 0x09, 0x09, 0x36, 0x00, 0x00, // Code for char R + 0x05, 0x00, 0x12, 0x25, 0x29, 0x12, 0x00, 0x00, 0x00, // Code for char S + 0x06, 0x00, 0x01, 0x01, 0x3F, 0x01, 0x01, 0x00, 0x00, // Code for char T + 0x06, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x1F, 0x00, 0x00, // Code for char U + 0x06, 0x00, 0x03, 0x0C, 0x30, 0x0C, 0x03, 0x00, 0x00, // Code for char V + 0x08, 0x00, 0x03, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x03, // Code for char W + 0x06, 0x00, 0x21, 0x12, 0x0C, 0x12, 0x21, 0x00, 0x00, // Code for char X + 0x06, 0x00, 0x01, 0x02, 0x3C, 0x02, 0x01, 0x00, 0x00, // Code for char Y + 0x05, 0x00, 0x31, 0x29, 0x25, 0x23, 0x00, 0x00, 0x00, // Code for char Z + 0x03, 0x00, 0x7F, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char [ + 0x03, 0x00, 0x07, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char BackSlash + 0x03, 0x00, 0x41, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char ] + 0x04, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, // Code for char ^ + 0x05, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, // Code for char _ + 0x03, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char ` + 0x04, 0x00, 0x14, 0x24, 0x38, 0x00, 0x00, 0x00, 0x00, // Code for char a + 0x05, 0x00, 0x3F, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, // Code for char b + 0x04, 0x00, 0x18, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, // Code for char c + 0x05, 0x00, 0x18, 0x24, 0x24, 0x3F, 0x00, 0x00, 0x00, // Code for char d + 0x04, 0x00, 0x18, 0x34, 0x28, 0x00, 0x00, 0x00, 0x00, // Code for char e + 0x03, 0x00, 0x3E, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char f + 0x05, 0x00, 0x18, 0xA4, 0xA4, 0x7C, 0x00, 0x00, 0x00, // Code for char g + 0x04, 0x00, 0x3F, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, // Code for char h + 0x02, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char i + 0x02, 0x00, 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char j + 0x04, 0x00, 0x3F, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, // Code for char k + 0x02, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char l + 0x06, 0x00, 0x3C, 0x04, 0x3C, 0x04, 0x38, 0x00, 0x00, // Code for char m + 0x04, 0x00, 0x3C, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00, // Code for char n + 0x05, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, // Code for char o + 0x05, 0x00, 0xFC, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00, // Code for char p + 0x05, 0x00, 0x18, 0x24, 0x24, 0xFC, 0x00, 0x00, 0x00, // Code for char q + 0x03, 0x00, 0x3C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char r + 0x04, 0x00, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00, // Code for char s + 0x03, 0x00, 0x1E, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char t + 0x04, 0x00, 0x1C, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x00, // Code for char u + 0x04, 0x00, 0x0C, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, // Code for char v + 0x06, 0x00, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x00, 0x00, // Code for char w + 0x04, 0x00, 0x24, 0x18, 0x24, 0x00, 0x00, 0x00, 0x00, // Code for char x + 0x04, 0x00, 0x9C, 0x60, 0x1C, 0x00, 0x00, 0x00, 0x00, // Code for char y + 0x04, 0x00, 0x34, 0x24, 0x2C, 0x00, 0x00, 0x00, 0x00, // Code for char z + 0x03, 0x00, 0x08, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char { + 0x02, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char | + 0x03, 0x00, 0x77, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // Code for char } + 0x04, 0x02, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, // Code for char ~ + 0x02, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char + }; + +#endif // SMALL_6_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/TextDisplay.cpp Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,108 @@ +/* mbed TextDisplay Display Library Base Class + * Copyright (c) 2007-2009 sford + * Released under the MIT License: http://mbed.org/license/mit + */ + +#include "TextDisplay.h" + +//#define DEBUG "Text" +// ... +// INFO("Stuff to show %d", var); // new-line is automatically appended +// +#if (defined(DEBUG) && !defined(TARGET_LPC11U24)) +#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#else +#define INFO(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) +#endif + +TextDisplay::TextDisplay(const char *name) : Stream(name) +{ + _row = 0; + _column = 0; + if (name == NULL) { + _path = NULL; + } else { + _path = new char[strlen(name) + 2]; + sprintf(_path, "/%s", name); + } +} + +int TextDisplay::_putc(int value) +{ + INFO("_putc(%d)", value); + if(value == '\n') { + _column = 0; + _row++; + if(_row >= rows()) { + _row = 0; + } + } else { + character(_column, _row, value); + _column++; + if(_column >= columns()) { + _column = 0; + _row++; + if(_row >= rows()) { + _row = 0; + } + } + } + return value; +} + +// crude cls implementation, should generally be overwritten in derived class +RetCode_t TextDisplay::cls(uint16_t layers) +{ + INFO("cls()"); + locate(0, 0); + for(int i=0; i<columns()*rows(); i++) { + putc(' '); + } + return noerror; +} + +RetCode_t TextDisplay::locate(textloc_t column, textloc_t row) +{ + INFO("locate(%d,%d)", column, row); + _column = column; + _row = row; + return noerror; +} + +int TextDisplay::_getc() +{ + return -1; +} + +RetCode_t TextDisplay::foreground(uint16_t color) +{ + //INFO("foreground(%4X)", color); + _foreground = color; + return noerror; +} + +RetCode_t TextDisplay::background(uint16_t color) +{ + //INFO("background(%4X)", color); + _background = color; + return noerror; +} + +bool TextDisplay::claim(FILE *stream) +{ + if ( _path == NULL) { + fprintf(stderr, "claim requires a name to be given in the instantiator of the TextDisplay instance!\r\n"); + return false; + } + if (freopen(_path, "w", stream) == NULL) { + return false; // Failed, should not happen + } + // make sure we use line buffering + setvbuf(stdout, NULL, _IOLBF, columns()); + return true; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/TextDisplay.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,136 @@ +/* mbed TextDisplay Library Base Class + * Copyright (c) 2007-2009 sford + * Released under the MIT License: http://mbed.org/license/mit + * + * A common base class for Text displays + * To port a new display, derive from this class and implement + * the constructor (setup the display), character (put a character + * at a location), rows and columns (number of rows/cols) functions. + * Everything else (locate, printf, putc, cls) will come for free + * + * The model is the display will wrap at the right and bottom, so you can + * keep writing and will always get valid characters. The location is + * maintained internally to the class to make this easy + */ + +#ifndef MBED_TEXTDISPLAY_H +#define MBED_TEXTDISPLAY_H + +#include "mbed.h" + +#include "DisplayDefs.h" + +/// A text display class that supports character based +/// presentation. +/// +class TextDisplay : public Stream +{ +public: + + // functions needing implementation in derived implementation class + /// Create a TextDisplay interface + /// + /// @param name The name used in the path to access the display through + /// the stdio stream. + /// + TextDisplay(const char *name = NULL); + + /// output a character at the given position + /// + /// @note this method may be overridden in a derived class. + /// + /// @param[in] x position in pixels + /// @param[in] y position in pixels + /// @param[in] c the character to be written to the TextDisplay + /// @returns number of pixels to advance the cursor which could be the cell width + /// for non-proportional characters, or the actual character width for + /// proportional characters. + /// + virtual int character(int x, int y, int c) = 0; + + /// return number of rows on TextDisplay + /// + /// @note this method may be overridden in a derived class. + /// + /// @returns number of text rows for the display for the currently + /// active font. + /// + virtual int rows() = 0; + + /// return number if columns on TextDisplay + /// + /// @note this method may be overridden in a derived class. + /// + /// @returns number of text rows for the display for the currently + /// active font. + /// + virtual int columns() = 0; + + // functions that come for free, but can be overwritten + + /// redirect output from a stream (stoud, sterr) to display + /// + /// @note this method may be overridden in a derived class. + /// + /// @param[in] stream that shall be redirected to the TextDisplay + /// @returns true if the claim succeeded. + /// + virtual bool claim (FILE *stream); + + /// clear screen + /// + /// @note this method may be overridden in a derived class. + /// + /// @param[in] layers is ignored, but supports maintaining the same + /// API for the graphics layer. + /// @returns error code. + /// + virtual RetCode_t cls(uint16_t layers = 0) = 0; + + /// locate the cursor at a character position. + /// + /// Based on the currently active font, locate the cursor on screen. + /// + /// @note this method may be overridden in a derived class. + /// + /// @param[in] column is the horizontal offset from the left side. + /// @param[in] row is the vertical offset from the top. + /// @returns error code. + /// + virtual RetCode_t locate(textloc_t column, textloc_t row) = 0; + + /// set the foreground color + /// + /// @note this method may be overridden in a derived class. + /// + /// @param[in] color is color to use for foreground drawing. + /// @returns error code. + /// + virtual RetCode_t foreground(color_t color) = 0; + + /// set the background color + /// + /// @note this method may be overridden in a derived class. + /// + /// @param[in] color is color to use for background drawing. + /// @returns error code. + /// + virtual RetCode_t background(color_t color) = 0; + // putc (from Stream) + // printf (from Stream) + +protected: + virtual int _putc(int value); + virtual int _getc(); + + // character location + uint16_t _column; + uint16_t _row; + + // colors + color_t _foreground; + color_t _background; + char *_path; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RA8875/WebColors.h Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,38 @@ + +#ifndef WEBCOLORS_H +#define WEBCOLORS_H + +#include "RA8875.h" + +const color_t WebColors[256] = + { + RGB(0x00,0x00,0x00), RGB(0x00,0x00,0x33), RGB(0x00,0x00,0x66), RGB(0x00,0x00,0x99), RGB(0x00,0x00,0xCC), RGB(0x00,0x00,0xFF), RGB(0x00,0x33,0x00), RGB(0x00,0x33,0x33), + RGB(0x00,0x33,0x66), RGB(0x00,0x33,0x99), RGB(0x00,0x33,0xCC), RGB(0x00,0x33,0xFF), RGB(0x00,0x66,0x00), RGB(0x00,0x66,0x33), RGB(0x00,0x66,0x66), RGB(0x00,0x66,0x99), + RGB(0x00,0x66,0xCC), RGB(0x00,0x66,0xFF), RGB(0x00,0x99,0x00), RGB(0x00,0x99,0x33), RGB(0x00,0x99,0x66), RGB(0x00,0x99,0x99), RGB(0x00,0x99,0xCC), RGB(0x00,0x99,0xFF), + RGB(0x00,0xCC,0x00), RGB(0x00,0xCC,0x33), RGB(0x00,0xCC,0x66), RGB(0x00,0xCC,0x99), RGB(0x00,0xCC,0xCC), RGB(0x00,0xCC,0xFF), RGB(0x00,0xFF,0x00), RGB(0x00,0xFF,0x33), + RGB(0x00,0xFF,0x66), RGB(0x00,0xFF,0x99), RGB(0x00,0xFF,0xCC), RGB(0x00,0xFF,0xFF), RGB(0x33,0x00,0x00), RGB(0x33,0x00,0x33), RGB(0x33,0x00,0x66), RGB(0x33,0x00,0x99), + RGB(0x33,0x00,0xCC), RGB(0x33,0x00,0xFF), RGB(0x33,0x33,0x00), RGB(0x33,0x33,0x33), RGB(0x33,0x33,0x66), RGB(0x33,0x33,0x99), RGB(0x33,0x33,0xCC), RGB(0x33,0x33,0xFF), + RGB(0x33,0x66,0x00), RGB(0x33,0x66,0x33), RGB(0x33,0x66,0x66), RGB(0x33,0x66,0x99), RGB(0x33,0x66,0xCC), RGB(0x33,0x66,0xFF), RGB(0x33,0x99,0x00), RGB(0x33,0x99,0x33), + RGB(0x33,0x99,0x66), RGB(0x33,0x99,0x99), RGB(0x33,0x99,0xCC), RGB(0x33,0x99,0xFF), RGB(0x33,0xCC,0x00), RGB(0x33,0xCC,0x33), RGB(0x33,0xCC,0x66), RGB(0x33,0xCC,0x99), + RGB(0x33,0xCC,0xCC), RGB(0x33,0xCC,0xFF), RGB(0x33,0xFF,0x00), RGB(0x33,0xFF,0x33), RGB(0x33,0xFF,0x66), RGB(0x33,0xFF,0x99), RGB(0x33,0xFF,0xCC), RGB(0x33,0xFF,0xFF), + RGB(0x66,0x00,0x00), RGB(0x66,0x00,0x33), RGB(0x66,0x00,0x66), RGB(0x66,0x00,0x99), RGB(0x66,0x00,0xCC), RGB(0x66,0x00,0xFF), RGB(0x66,0x33,0x00), RGB(0x66,0x33,0x33), + RGB(0x66,0x33,0x66), RGB(0x66,0x33,0x99), RGB(0x66,0x33,0xCC), RGB(0x66,0x33,0xFF), RGB(0x66,0x66,0x00), RGB(0x66,0x66,0x33), RGB(0x66,0x66,0x66), RGB(0x66,0x66,0x99), + RGB(0x66,0x66,0xCC), RGB(0x66,0x66,0xFF), RGB(0x66,0x99,0x00), RGB(0x66,0x99,0x33), RGB(0x66,0x99,0x66), RGB(0x66,0x99,0x99), RGB(0x66,0x99,0xCC), RGB(0x66,0x99,0xFF), + RGB(0x66,0xCC,0x00), RGB(0x66,0xCC,0x33), RGB(0x66,0xCC,0x66), RGB(0x66,0xCC,0x99), RGB(0x66,0xCC,0xCC), RGB(0x66,0xCC,0xFF), RGB(0x66,0xFF,0x00), RGB(0x66,0xFF,0x33), + RGB(0x66,0xFF,0x66), RGB(0x66,0xFF,0x99), RGB(0x66,0xFF,0xCC), RGB(0x66,0xFF,0xFF), RGB(0x99,0x00,0x00), RGB(0x99,0x00,0x33), RGB(0x99,0x00,0x66), RGB(0x99,0x00,0x99), + RGB(0x99,0x00,0xCC), RGB(0x99,0x00,0xFF), RGB(0x99,0x33,0x00), RGB(0x99,0x33,0x33), RGB(0x99,0x33,0x66), RGB(0x99,0x33,0x99), RGB(0x99,0x33,0xCC), RGB(0x99,0x33,0xFF), + RGB(0x99,0x66,0x00), RGB(0x99,0x66,0x33), RGB(0x99,0x66,0x66), RGB(0x99,0x66,0x99), RGB(0x99,0x66,0xCC), RGB(0x99,0x66,0xFF), RGB(0x99,0x99,0x00), RGB(0x99,0x99,0x33), + RGB(0x99,0x99,0x66), RGB(0x99,0x99,0x99), RGB(0x99,0x99,0xCC), RGB(0x99,0x99,0xFF), RGB(0x99,0xCC,0x00), RGB(0x99,0xCC,0x33), RGB(0x99,0xCC,0x66), RGB(0x99,0xCC,0x99), + RGB(0x99,0xCC,0xCC), RGB(0x99,0xCC,0xFF), RGB(0x99,0xFF,0x00), RGB(0x99,0xFF,0x33), RGB(0x99,0xFF,0x66), RGB(0x99,0xFF,0x99), RGB(0x99,0xFF,0xCC), RGB(0x99,0xFF,0xFF), + RGB(0xCC,0x00,0x00), RGB(0xCC,0x00,0x33), RGB(0xCC,0x00,0x66), RGB(0xCC,0x00,0x99), RGB(0xCC,0x00,0xCC), RGB(0xCC,0x00,0xFF), RGB(0xCC,0x33,0x00), RGB(0xCC,0x33,0x33), + RGB(0xCC,0x33,0x66), RGB(0xCC,0x33,0x99), RGB(0xCC,0x33,0xCC), RGB(0xCC,0x33,0xFF), RGB(0xCC,0x66,0x00), RGB(0xCC,0x66,0x33), RGB(0xCC,0x66,0x66), RGB(0xCC,0x66,0x99), + RGB(0xCC,0x66,0xCC), RGB(0xCC,0x66,0xFF), RGB(0xCC,0x99,0x00), RGB(0xCC,0x99,0x33), RGB(0xCC,0x99,0x66), RGB(0xCC,0x99,0x99), RGB(0xCC,0x99,0xCC), RGB(0xCC,0x99,0xFF), + RGB(0xCC,0xCC,0x00), RGB(0xCC,0xCC,0x33), RGB(0xCC,0xCC,0x66), RGB(0xCC,0xCC,0x99), RGB(0xCC,0xCC,0xCC), RGB(0xCC,0xCC,0xFF), RGB(0xCC,0xFF,0x00), RGB(0xCC,0xFF,0x33), + RGB(0xCC,0xFF,0x66), RGB(0xCC,0xFF,0x99), RGB(0xCC,0xFF,0xCC), RGB(0xCC,0xFF,0xFF), RGB(0xFF,0x00,0x00), RGB(0xFF,0x00,0x33), RGB(0xFF,0x00,0x66), RGB(0xFF,0x00,0x99), + RGB(0xFF,0x00,0xCC), RGB(0xFF,0x00,0xFF), RGB(0xFF,0x33,0x00), RGB(0xFF,0x33,0x33), RGB(0xFF,0x33,0x66), RGB(0xFF,0x33,0x99), RGB(0xFF,0x33,0xCC), RGB(0xFF,0x33,0xFF), + RGB(0xFF,0x66,0x00), RGB(0xFF,0x66,0x33), RGB(0xFF,0x66,0x66), RGB(0xFF,0x66,0x99), RGB(0xFF,0x66,0xCC), RGB(0xFF,0x66,0xFF), RGB(0xFF,0x99,0x00), RGB(0xFF,0x99,0x33), + RGB(0xFF,0x99,0x66), RGB(0xFF,0x99,0x99), RGB(0xFF,0x99,0xCC), RGB(0xFF,0x99,0xFF), RGB(0xFF,0xCC,0x00), RGB(0xFF,0xCC,0x33), RGB(0xFF,0xCC,0x66), RGB(0xFF,0xCC,0x99), + RGB(0xFF,0xCC,0xCC), RGB(0xFF,0xCC,0xFF), RGB(0xFF,0xFF,0x00), RGB(0xFF,0xFF,0x33), RGB(0xFF,0xFF,0x66), RGB(0xFF,0xFF,0x99), RGB(0xFF,0xFF,0xCC), RGB(0xFF,0xFF,0xFF) + }; + +#endif // WEBCOLORS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,438 @@ +#include "mbed.h" +#include "RA8875.h" + +Serial Fc(p28, p27); + +int fuelcellStatus = -1; +int fuelcellAmbientRawT; +float fuelcellAmbientT; +int fuelcellStackRawV; +int fuelcellStackRawIHighByte; +int fuelcellStackRawILowByte; +int fuelcellStackRawH2Sensor; + +int fuelcellStackRawT; +int fuelcellRawOutputCurrent1; //high byte +int fuelcellRawOutputCurrent2; //low byte +int fuelcellBatteryRawV; +float fuelcellStackV; +float fuelcellStackI; +float h2SensorVoltage; +float fuelcellStackPower; +float fuelcellStackT; +float fuelcellOutputCurrent;// +float fuelcellBatteryV; +float PWRused = 0.0; + +InterruptIn S(p15); +float speed = 0.0; +float avgspeed = 0.0; +float necspeed = 0.0; +float wielomtrek = 1.75; +bool rond = 0; +Timer t; +Timer teller; +Ticker tick; + +int seconde = 0; +int sec = 0; +int min = 0; +int lmin = 39; +int lsec = 0; + +float afstandtogo = 17000.0; +float afstand = 0.0; +float tijd = 39.0*60.0; +color_t Kleur1; +color_t Kleur6; + + + +void tel(){ + rond=1; + } + + +void counters(){ + seconde++; + PWRused += (fuelcellStackPower * (1.0/3600.0)); + if(seconde >= 39*60) + { + + min = 39; + sec = 00; + lmin = 00; + lsec = 00; + Kleur1 = BrightRed; + Kleur6 = BrightRed; + } + else if(seconde >= 34*60) + { + + min = seconde/60; + sec = seconde - (min*60); + lsec--; + if(lsec < 0){ + lsec = 59; + lmin--; + } + + Kleur1 = Yellow; + Kleur6 = Yellow; + } + else + { + + min = seconde/60; + sec = seconde - (min*60); + lsec--; + if(lsec < 0){ + lsec = 59; + lmin--; + } + + Kleur1 = BrightGreen; + Kleur6 = BrightGreen; + } + + } + + void snelheidmeten(){ + if (rond){ + speed = (wielomtrek/t.read())*3,6; + afstand += wielomtrek; + t.reset(); + } + tijd -= teller.read(); + necspeed = ((afstandtogo-afstand)/tijd)*3.6; + avgspeed = (afstand/teller.read())*3.6; + + if(t.read() > 2.5) + speed = 0.0; + + rond = 0; + + } + + void checkIncomingFcData() { + + // anything in the buffer? yes check if its a valid packet. no, return + if (Fc.readable()) { + + + + fuelcellStatus = Fc.getc(); + fuelcellAmbientRawT = Fc.getc(); + fuelcellStackRawV = Fc.getc(); + fuelcellStackRawH2Sensor = Fc.getc(); + fuelcellStackRawT= Fc.getc(); + fuelcellStackRawIHighByte = Fc.getc(); + fuelcellStackRawILowByte = Fc.getc(); + fuelcellBatteryRawV = Fc.getc(); + + //calculate actual values + fuelcellAmbientT = fuelcellAmbientRawT * .5; + fuelcellStackV = fuelcellStackRawV * .33333; + fuelcellStackT = fuelcellStackRawT * .5; + fuelcellStackI = ((fuelcellStackRawIHighByte<<8) + fuelcellStackRawILowByte) * .2;// + fuelcellBatteryV = fuelcellBatteryRawV * .10; + fuelcellStackPower = fuelcellStackI * fuelcellStackV; + h2SensorVoltage = fuelcellStackRawH2Sensor *.10; + + } + } + + + + + +int main() +{ + teller.start(); + t.start(); + S.rise(&tel); + float f = 10000000; + + + RA8875 lcd(p5, p6, p7, p12, NC, "tft"); // MOSI, MISO, SCK, /ChipSelect, /reset, name + lcd.init(800, 480, 24, true, false, false); + + lcd.frequency(f); + AnalogIn ain(A5); + tick.attach(&counters, 1.0); + lcd.cls(); + wait_ms(250); + + + + + lcd.background(White); + lcd.fillrect( 0,0, 800,480, White); + lcd.fillrect( 0,79, 800,81 , Black); // hor strepen over het hele beeld + lcd.fillrect( 0,159, 800,161, Black); + lcd.fillrect( 0,239, 800,241, Black); + lcd.fillrect( 0,319, 800,321, Black); + lcd.fillrect( 0,399, 800,401, Black); + + lcd.fillrect( 759,80 , 761,240, Black); //verticale streep boven + lcd.fillrect( 759,320, 761,480, Black); //verticale streep onder + + lcd.fillrect( 371,119, 800,121, Black); //hor strepen vanaf halve cirkel + lcd.fillrect( 396,199, 800,201, Black); + lcd.fillrect( 371,359, 800,361, Black); + lcd.fillrect( 315,439, 800,441, Black); + + lcd.line( 209,0 , 280,80 , Black); //binnenste halve cirkel + lcd.line( 280,80 , 321,160, Black); + lcd.line( 321,160, 331,240, Black); + lcd.line( 331,240, 321,320, Black); + lcd.line( 321,320, 280,400, Black); + lcd.line( 280,400, 209,480, Black); + + lcd.line( 209+70,0 , 280+70,80 , Black); //buitenste halve cirkel (+70) + lcd.line( 280+70,80 , 321+70,160, Black); + lcd.line( 321+70,160, 331+70,240, Black); + lcd.line( 331+70,240, 321+70,320, Black); + lcd.line( 321+70,320, 280+70,400, Black); + lcd.line( 280+70,400, 209+70,480, Black); + + Kleur1 = BrightGreen; + Kleur6 = BrightGreen; + + lcd.SetTextFontSize(2,2); + int H = lcd.fontheight()/2; + lcd.puts(411,40-H, "STATUS FUEL CELL"); + lcd.puts(411,280-H, "GENERAL STATUS"); + + lcd.SetTextFontSize(1,1); + H = lcd.fontheight()/2; + + + color_t Kleur2; + color_t Kleur3; + color_t Kleur4; + color_t Kleur5; + + color_t KleurA; + color_t KleurB; + color_t KleurC; + color_t KleurD; + color_t KleurE; + color_t KleurF; + color_t KleurG; + color_t KleurH; + + +while(1){ + checkIncomingFcData(); + snelheidmeten(); + +if (avgspeed >= 26.0 && avgspeed <= 27.3) +{ + + Kleur2 = BrightGreen; + } + else if(avgspeed <= 25.0 || avgspeed >= 28.5) + Kleur2 = BrightRed; + else{ + Kleur2 = Yellow; + } + Kleur3 = BrightBlue; + + + Kleur4 = BrightBlue; + + + Kleur5 = BrightBlue; + + if(fuelcellStackV >= 22 && fuelcellStackV <= 45) + { + KleurA = BrightGreen; + } + else if(fuelcellStackV <= 20 || fuelcellStackV >= 48){ + KleurA = BrightRed; + } + else{ + KleurA = Yellow; + } + + +if(fuelcellStackI <= 25) + { + KleurB = BrightGreen; + } + else if(fuelcellStackI >= 27){ + KleurB = BrightRed; + } + else{ + KleurB = Yellow; + } + + + + if(fuelcellStackPower <=1000){ + KleurC = BrightGreen; + } + else if(fuelcellStackPower >= 1200){ + KleurC = BrightRed; + } + else{ + KleurC = Yellow; + } + + + if(fuelcellStackT <=38){ + KleurD = BrightGreen; + } + else if(fuelcellStackT >= 40){ + KleurD = BrightRed; + } + else{ + KleurD = Yellow; + } + + + if((ain*20*3.3) <=45){ + KleurE = BrightGreen; + } + else if((ain*20*3.3) >= 48){ + KleurE = BrightRed; + } + else{ + KleurE = Yellow; + } + + + if(fuelcellAmbientT <=28){ + KleurF = BrightGreen; + } + else if(fuelcellAmbientT >= 30){ + KleurF = BrightRed; + } + else{ + KleurF = Yellow; + } + + + + + + + + lcd.foreground(Black); + + lcd.SetTextCursor(10,40-H); //16 + lcd.printf("Total time %02d:%02d",min,sec ); + lcd.SetTextCursor(10,120-H); + lcd.printf("Average speed %.1f km/h ",avgspeed); + lcd.SetTextCursor(10,200-H); + lcd.printf("Necessary speed %.1f km/h ",necspeed); + lcd.SetTextCursor(10,280-H); + lcd.printf("Actual speed %.1f km/h ",speed); + lcd.SetTextCursor(10,360-H); + lcd.printf("Power used %.1f Wh ",PWRused); + lcd.SetTextCursor(10,440-H); + lcd.printf("Time left %02d:%02d",lmin,lsec); + + lcd.SetTextCursor(411,100-H); + lcd.printf("Voltage fuel cell %.2f V ",fuelcellStackV); + lcd.SetTextCursor(411,140-H); + lcd.printf("Current fuel cell %.2f A ",fuelcellStackI); + lcd.SetTextCursor(411,180-H); + lcd.printf("Power fuel cell %.2f W ",fuelcellStackPower); + lcd.SetTextCursor(411,220-H); + lcd.printf("Temperature fuel cell %.2f %cC ",fuelcellStackT,176); + lcd.SetTextCursor(411,340-H); + lcd.printf("Voltage supercapacitors %.2f V ",ain*20*3.3); + lcd.SetTextCursor(411,380-H); + lcd.printf("Ambient temperature %.2f %cC ",fuelcellAmbientT,176); + lcd.SetTextCursor(411,420-H); + + switch(fuelcellStatus) +{ + case 0: +lcd.printf("Status fuelcell: NORMAL "); + KleurG = BrightGreen; + KleurH = BrightGreen; + break; + + case 1: +lcd.printf("Status fuelcell: BATTERY LOW "); + KleurG = BrightRed; + KleurH = BrightRed; + break; + + case 2: +lcd.printf("Status fuelcell: FC VOLTAGE LOW "); + KleurG = BrightRed; + KleurH = BrightRed; + break; + + case 3: +lcd.printf("Status fuelcell: H2% HIGH "); + KleurG = BrightRed; + KleurH = BrightRed; + break; + + case 4: +lcd.printf("Status fuelcell: CURRENT HIGH "); + KleurG = BrightRed; + KleurH = BrightRed; + break; + + case 5: +lcd.printf("Status fuelcell: TEMPERATURE HIGH"); + KleurG = BrightRed; + KleurH = BrightRed; + break; + + case 20: +lcd.printf("Status fuelcell: MANUAL TURN OFF "); + KleurG = BrightRed; + KleurH = BrightRed; + break; + + default: +lcd.printf("Status fuelcell: NO STATUS "); + KleurG = Yellow; + KleurH = Yellow; +} + + + + + + + // vakjes in de halve cirkel + lcd.filltriangle( 210,0, 281,78, 278,0, Kleur1); //vakje 1 + lcd.filltriangle( 349,78, 281,78, 278,0, Kleur1); + + lcd.filltriangle( 281,82, 322,158, 349,82, Kleur2); //vakje 2 + lcd.filltriangle( 390,158, 322,158, 349,82, Kleur2); + + lcd.filltriangle( 322,162, 332,238, 390,162, Kleur3); //vakje 3 + lcd.filltriangle( 400,238, 332,238, 390,162, Kleur3); + + lcd.filltriangle( 332,242, 322,318, 400,242, Kleur4); //vakje 4 + lcd.filltriangle( 390,318, 322,318, 400,242, Kleur4); + + lcd.filltriangle( 322,322, 281,398, 390,322, Kleur5); //vakje 5 + lcd.filltriangle( 349,398, 281,398, 390,322, Kleur5); + + lcd.filltriangle( 281,402, 210,480, 349,402, Kleur6); //vakje 6 + lcd.filltriangle( 278,480, 210,480, 349,402, Kleur6); + + //vierkantjes aan de rechterkant + + lcd.fillrect( 762,82, 800,118, KleurA); // Vierkant A + lcd.fillrect( 762,122, 800,158, KleurB); // Vierkant B + lcd.fillrect( 762,162, 800,198, KleurC); // Vierkant C + lcd.fillrect( 762,202, 800,238, KleurD); // Vierkant D + lcd.fillrect( 762,322, 800,358, KleurE); // Vierkant E + lcd.fillrect( 762,362, 800,398, KleurF); // Vierkant F + lcd.fillrect( 762,402, 800,438, KleurG); // Vierkant G + lcd.fillrect( 762,442, 800,480, KleurH); // Vierkant H + + wait(0.2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Nov 30 11:13:18 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/4fc01daae5a5 \ No newline at end of file