diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Makefile b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Makefile new file mode 100644 index 00000000..c5b2ddde --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Makefile @@ -0,0 +1,10 @@ +OBJS = clock.o gfx_locm3.o lcd_ili9341.o sdram.o Tamsyn5x9b_9.o Tamsyn5x9r_9.o + +BINARY = application + +# we use sin/cos from the library +LDLIBS += -lm + +LDSCRIPT = ../stm32f429i-discovery.ld + +include ../../Makefile.include diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/README.md b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/README.md new file mode 100644 index 00000000..a881fd90 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/README.md @@ -0,0 +1,7 @@ +# README + +Small test with minimal graphics lib for ltdc graphics controller. + +Two additional python scripts are provided to create your own font and bitmap header files. + +06/01/16 H2OBrain diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9b_9.c b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9b_9.c new file mode 100644 index 00000000..6e381dcc --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9b_9.c @@ -0,0 +1,864 @@ +/* + * LICENSE - see http://www.fial.com/~scott/tamsyn-font/ + * + +Tamsyn font is free. You are hereby granted permission to use, copy, modify, +and distribute it as you see fit. + +Tamsyn font is provided "as is" without any express or implied warranty. + +The author makes no representations about the suitability of this font for +a particular purpose. + +In no event will the author be held liable for damages arising from the use +of this font. + */ + +#include "Tamsyn5x9b_9.h" + +static const uint32_t chars_data_Tamsyn5x9b_9[] = { + // ' ' + + // '!' + 0x00000cff, + // '"' + 0x000005ff, + // '#' + 0x00affafa, + // '$' + 0x22fc6e44, + // '%' + 0x08936c91, + // '&' + 0x2ebd9966, + // ''' + 0x0000003f, + // '(' + 0x0c63336c, + // ')' + 0x036ccc63, + // '*' + 0x000576f4, + // '+' + 0x00637cc6, + // ',' + 0x000000f6, + // '-' + 0x0000000f, + // '.' + 0x0000000f, + // '/' + 0x003366cc, + // '0' + 0x0006bbb6, + // '1' + 0x000f6676, + // '2' + 0x000f36c7, + // '3' + 0x0007c6c7, + // '4' + 0x000cfdec, + // '5' + 0x0007c73f, + // '6' + 0x0006b736, + // '7' + 0x000336cf, + // '8' + 0x0006b6b6, + // '9' + 0x0006ceb6, + // ':' + 0x000003cf, + // ';' + 0x0001ec36, + // '<' + 0x000c636c, + // '=' + 0x00000f0f, + // '>' + 0x00036c63, + // '?' + 0x00606cd6, + // '@' + 0x0e33bbb6, + // 'A' + 0x000dfde4, + // 'B' + 0x0007b7b7, + // 'C' + 0x000e333e, + // 'D' + 0x0007bbb7, + // 'E' + 0x000f373f, + // 'F' + 0x0003373f, + // 'G' + 0x000ebb3e, + // 'H' + 0x000bbfbb, + // 'I' + 0x000f666f, + // 'J' + 0x0006dccc, + // 'K' + 0x000bb7bb, + // 'L' + 0x000f3333, + // 'M' + 0x00099ff9, + // 'N' + 0x000ddfbb, + // 'O' + 0x0006bbb6, + // 'P' + 0x000337b7, + // 'Q' + 0x00c6bbb6, + // 'R' + 0x000b77b7, + // 'S' + 0x0007c63e, + // 'T' + 0x0006666f, + // 'U' + 0x0006bbbb, + // 'V' + 0x00027bbb, + // 'W' + 0x0009ff99, + // 'X' + 0x000b666b, + // 'Y' + 0x000666bb, + // 'Z' + 0x000f36cf, + // '[' + 0x001db6df, + // '\' + 0x00cc6633, + // ']' + 0x001f6db7, + // '^' + 0x0000017a, + // '_' + 0x0000001f, + // '`' + 0x00000999, + // 'a' + 0x0000edde, + // 'b' + 0x007bb733, + // 'c' + 0x0000e33e, + // 'd' + 0x00eddecc, + // 'e' + 0x0000e7de, + // 'f' + 0x00666f6c, + // 'g' + 0x006cebbe, + // 'h' + 0x00bbb733, + // 'i' + 0x00f66706, + // 'j' + 0x7cccce0c, + // 'k' + 0x00bb7b33, + // 'l' + 0x00f66667, + // 'm' + 0x0000bbfb, + // 'n' + 0x0000bbb7, + // 'o' + 0x00006bb6, + // 'p' + 0x00337bb7, + // 'q' + 0x00ccedde, + // 'r' + 0x0000333f, + // 's' + 0x0000fc6e, + // 't' + 0x000e66f6, + // 'u' + 0x00006bbb, + // 'v' + 0x000027bb, + // 'w' + 0x0000bfbb, + // 'x' + 0x0000b66b, + // 'y' + 0x006cebbb, + // 'z' + 0x0000f36f, + // '{' + 0x18c7b19c, 0x00000007, + // '|' + 0x00003fff, + // '}' + 0xcc6f18c7, 0x00000001, + // '~' + 0x000005fa, + // '¡' + 0x00000ff3, + // '£' + 0x00f66f6c, + // '«' + 0x00004b72, + // '°' + 0x000006b6, + // '»' + 0x00002769, + // '¿' + 0x006b3606, + // 'Ä' + 0x0dfde409, + // 'Å' + 0x00dfd6d6, + // 'Æ' + 0x000d5f5e, + // 'Ç' + 0x064e333e, + // 'É' + 0x0f373f48, + // 'Ñ' + 0x0ddfb0db, + // 'Ö' + 0x06bbb605, + // '¥' + 0x00066f6b, + // 'Ü' + 0x06bbbb05, + // 'ß' + 0x0007b7be, + // 'à' + 0x00edde21, + // 'á' + 0x00edde48, + // 'â' + 0x0edde052, + // 'ä' + 0x00edde05, + // 'å' + 0x00edd6d6, + // 'æ' + 0x0000f5ef, + // 'ç' + 0x0064e33e, + // 'è' + 0x00e7de21, + // 'é' + 0x00e7de48, + // 'ê' + 0x0e7de052, + // 'ë' + 0x00e7de05, + // 'ì' + 0x00f66721, + // 'í' + 0x00f66748, + // 'î' + 0x0f667052, + // 'ï' + 0x00f66705, + // 'ñ' + 0x0bbb70db, + // 'ò' + 0x006bb621, + // 'ó' + 0x006bb648, + // 'ô' + 0x06bb6052, + // 'ö' + 0x006bb605, + // '÷' + 0x00060f06, + // '¢' + 0x004e33e4, + // 'ù' + 0x006bbb21, + // 'ú' + 0x006bbb24, + // 'û' + 0x06bbb052, + // 'ü' + 0x006bbb05, + // 'ÿ' + 0x6cebbb0 +}; + +static const char_t chars_Tamsyn5x9b_9[] = { + { + .utf8_value = 32, + .bbox = { 0, 0, 0, 0 }, + .data = &chars_data_Tamsyn5x9b_9[0] + },{ + .utf8_value = 33, + .bbox = { 1, 1, 3, 7 }, + .data = &chars_data_Tamsyn5x9b_9[0] + },{ + .utf8_value = 34, + .bbox = { 0, 1, 4, 4 }, + .data = &chars_data_Tamsyn5x9b_9[1] + },{ + .utf8_value = 35, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[2] + },{ + .utf8_value = 36, + .bbox = { 0, 1, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[3] + },{ + .utf8_value = 37, + .bbox = { 0, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[4] + },{ + .utf8_value = 38, + .bbox = { 0, 1, 5, 7 }, + .data = &chars_data_Tamsyn5x9b_9[5] + },{ + .utf8_value = 39, + .bbox = { 1, 1, 3, 4 }, + .data = &chars_data_Tamsyn5x9b_9[6] + },{ + .utf8_value = 40, + .bbox = { 0, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[7] + },{ + .utf8_value = 41, + .bbox = { 0, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[8] + },{ + .utf8_value = 42, + .bbox = { 0, 1, 4, 6 }, + .data = &chars_data_Tamsyn5x9b_9[9] + },{ + .utf8_value = 43, + .bbox = { 0, 2, 5, 7 }, + .data = &chars_data_Tamsyn5x9b_9[10] + },{ + .utf8_value = 44, + .bbox = { 1, 5, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[11] + },{ + .utf8_value = 45, + .bbox = { 0, 4, 4, 5 }, + .data = &chars_data_Tamsyn5x9b_9[12] + },{ + .utf8_value = 46, + .bbox = { 1, 5, 3, 7 }, + .data = &chars_data_Tamsyn5x9b_9[13] + },{ + .utf8_value = 47, + .bbox = { 0, 2, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[14] + },{ + .utf8_value = 48, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[15] + },{ + .utf8_value = 49, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[16] + },{ + .utf8_value = 50, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[17] + },{ + .utf8_value = 51, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[18] + },{ + .utf8_value = 52, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[19] + },{ + .utf8_value = 53, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[20] + },{ + .utf8_value = 54, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[21] + },{ + .utf8_value = 55, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[22] + },{ + .utf8_value = 56, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[23] + },{ + .utf8_value = 57, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[24] + },{ + .utf8_value = 58, + .bbox = { 1, 2, 3, 7 }, + .data = &chars_data_Tamsyn5x9b_9[25] + },{ + .utf8_value = 59, + .bbox = { 1, 2, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[26] + },{ + .utf8_value = 60, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[27] + },{ + .utf8_value = 61, + .bbox = { 0, 3, 4, 6 }, + .data = &chars_data_Tamsyn5x9b_9[28] + },{ + .utf8_value = 62, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[29] + },{ + .utf8_value = 63, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[30] + },{ + .utf8_value = 64, + .bbox = { 0, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[31] + },{ + .utf8_value = 65, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[32] + },{ + .utf8_value = 66, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[33] + },{ + .utf8_value = 67, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[34] + },{ + .utf8_value = 68, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[35] + },{ + .utf8_value = 69, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[36] + },{ + .utf8_value = 70, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[37] + },{ + .utf8_value = 71, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[38] + },{ + .utf8_value = 72, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[39] + },{ + .utf8_value = 73, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[40] + },{ + .utf8_value = 74, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[41] + },{ + .utf8_value = 75, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[42] + },{ + .utf8_value = 76, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[43] + },{ + .utf8_value = 77, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[44] + },{ + .utf8_value = 78, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[45] + },{ + .utf8_value = 79, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[46] + },{ + .utf8_value = 80, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[47] + },{ + .utf8_value = 81, + .bbox = { 0, 2, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[48] + },{ + .utf8_value = 82, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[49] + },{ + .utf8_value = 83, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[50] + },{ + .utf8_value = 84, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[51] + },{ + .utf8_value = 85, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[52] + },{ + .utf8_value = 86, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[53] + },{ + .utf8_value = 87, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[54] + },{ + .utf8_value = 88, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[55] + },{ + .utf8_value = 89, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[56] + },{ + .utf8_value = 90, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[57] + },{ + .utf8_value = 91, + .bbox = { 0, 1, 3, 8 }, + .data = &chars_data_Tamsyn5x9b_9[58] + },{ + .utf8_value = 92, + .bbox = { 0, 2, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[59] + },{ + .utf8_value = 93, + .bbox = { 1, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9b_9[60] + },{ + .utf8_value = 94, + .bbox = { 1, 1, 4, 4 }, + .data = &chars_data_Tamsyn5x9b_9[61] + },{ + .utf8_value = 95, + .bbox = { 0, 7, 5, 8 }, + .data = &chars_data_Tamsyn5x9b_9[62] + },{ + .utf8_value = 96, + .bbox = { 1, 1, 4, 5 }, + .data = &chars_data_Tamsyn5x9b_9[63] + },{ + .utf8_value = 97, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[64] + },{ + .utf8_value = 98, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[65] + },{ + .utf8_value = 99, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[66] + },{ + .utf8_value = 100, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[67] + },{ + .utf8_value = 101, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[68] + },{ + .utf8_value = 102, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[69] + },{ + .utf8_value = 103, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[70] + },{ + .utf8_value = 104, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[71] + },{ + .utf8_value = 105, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[72] + },{ + .utf8_value = 106, + .bbox = { 0, 1, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[73] + },{ + .utf8_value = 107, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[74] + },{ + .utf8_value = 108, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[75] + },{ + .utf8_value = 109, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[76] + },{ + .utf8_value = 110, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[77] + },{ + .utf8_value = 111, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[78] + },{ + .utf8_value = 112, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[79] + },{ + .utf8_value = 113, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[80] + },{ + .utf8_value = 114, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[81] + },{ + .utf8_value = 115, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[82] + },{ + .utf8_value = 116, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[83] + },{ + .utf8_value = 117, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[84] + },{ + .utf8_value = 118, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[85] + },{ + .utf8_value = 119, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[86] + },{ + .utf8_value = 120, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[87] + },{ + .utf8_value = 121, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[88] + },{ + .utf8_value = 122, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[89] + },{ + .utf8_value = 123, + .bbox = { 0, 1, 5, 8 }, + .data = &chars_data_Tamsyn5x9b_9[90] + },{ + .utf8_value = 124, + .bbox = { 1, 1, 3, 8 }, + .data = &chars_data_Tamsyn5x9b_9[92] + },{ + .utf8_value = 125, + .bbox = { 0, 1, 5, 8 }, + .data = &chars_data_Tamsyn5x9b_9[93] + },{ + .utf8_value = 126, + .bbox = { 0, 1, 4, 4 }, + .data = &chars_data_Tamsyn5x9b_9[95] + },{ + .utf8_value = 161, + .bbox = { 1, 3, 3, 9 }, + .data = &chars_data_Tamsyn5x9b_9[96] + },{ + .utf8_value = 163, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[97] + },{ + .utf8_value = 171, + .bbox = { 0, 4, 5, 7 }, + .data = &chars_data_Tamsyn5x9b_9[98] + },{ + .utf8_value = 176, + .bbox = { 0, 2, 4, 5 }, + .data = &chars_data_Tamsyn5x9b_9[99] + },{ + .utf8_value = 187, + .bbox = { 0, 4, 5, 7 }, + .data = &chars_data_Tamsyn5x9b_9[100] + },{ + .utf8_value = 191, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[101] + },{ + .utf8_value = 196, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[102] + },{ + .utf8_value = 197, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[103] + },{ + .utf8_value = 198, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[104] + },{ + .utf8_value = 199, + .bbox = { 0, 2, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[105] + },{ + .utf8_value = 201, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[106] + },{ + .utf8_value = 209, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[107] + },{ + .utf8_value = 214, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[108] + },{ + .utf8_value = 165, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[109] + },{ + .utf8_value = 220, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[110] + },{ + .utf8_value = 223, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[111] + },{ + .utf8_value = 224, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[112] + },{ + .utf8_value = 225, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[113] + },{ + .utf8_value = 226, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[114] + },{ + .utf8_value = 228, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[115] + },{ + .utf8_value = 229, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[116] + },{ + .utf8_value = 230, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[117] + },{ + .utf8_value = 231, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[118] + },{ + .utf8_value = 232, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[119] + },{ + .utf8_value = 233, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[120] + },{ + .utf8_value = 234, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[121] + },{ + .utf8_value = 235, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[122] + },{ + .utf8_value = 236, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[123] + },{ + .utf8_value = 237, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[124] + },{ + .utf8_value = 238, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[125] + },{ + .utf8_value = 239, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[126] + },{ + .utf8_value = 241, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[127] + },{ + .utf8_value = 242, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[128] + },{ + .utf8_value = 243, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[129] + },{ + .utf8_value = 244, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[130] + },{ + .utf8_value = 246, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[131] + },{ + .utf8_value = 247, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[132] + },{ + .utf8_value = 162, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[133] + },{ + .utf8_value = 249, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[134] + },{ + .utf8_value = 250, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[135] + },{ + .utf8_value = 251, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[136] + },{ + .utf8_value = 252, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9b_9[137] + },{ + .utf8_value = 255, + .bbox = { 0, 1, 4, 9 }, + .data = &chars_data_Tamsyn5x9b_9[138] + } +}; + +const font_t font_Tamsyn5x9b_9 = { + .fontsize = 9, + .lineheight = 9, + .ascent = 7, + .descent = 2, + .charwidth = 5, + .char_count = 138, + .chars = chars_Tamsyn5x9b_9, + .chars_data = chars_data_Tamsyn5x9b_9, +}; + diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9b_9.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9b_9.h new file mode 100644 index 00000000..8ce93ac2 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9b_9.h @@ -0,0 +1,26 @@ +/* + * LICENSE - see http://www.fial.com/~scott/tamsyn-font/ + * + +Tamsyn font is free. You are hereby granted permission to use, copy, modify, +and distribute it as you see fit. + +Tamsyn font is provided "as is" without any express or implied warranty. + +The author makes no representations about the suitability of this font for +a particular purpose. + +In no event will the author be held liable for damages arising from the use +of this font. + */ + + +#ifndef _TAMSYN5X9B_9_ +#define _TAMSYN5X9B_9_ + +#include +#include "fonts.h" + +extern const font_t font_Tamsyn5x9b_9; + +#endif diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9r_9.c b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9r_9.c new file mode 100644 index 00000000..cc34132e --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9r_9.c @@ -0,0 +1,864 @@ +/* + * LICENSE - see http://www.fial.com/~scott/tamsyn-font/ + * + +Tamsyn font is free. You are hereby granted permission to use, copy, modify, +and distribute it as you see fit. + +Tamsyn font is provided "as is" without any express or implied warranty. + +The author makes no representations about the suitability of this font for +a particular purpose. + +In no event will the author be held liable for damages arising from the use +of this font. + */ + +#include "Tamsyn5x9r_9.h" + +static const uint32_t chars_data_Tamsyn5x9r_9[] = { + // ' ' + + // '!' + 0x0000002f, + // '"' + 0x0000016d, + // '#' + 0x005f5afa, + // '$' + 0x027861e4, + // '%' + 0x00cd24b3, + // '&' + 0x00b5d256, + // ''' + 0x00000007, + // '(' + 0x00889254, + // ')' + 0x002a4911, + // '*' + 0x0002f6f4, + // '+' + 0x00427c84, + // ',' + 0x0000001b, + // '-' + 0x0000000f, + // '.' + 0x00000003, + // '/' + 0x000094a4, + // '0' + 0x00069996, + // '1' + 0x0000749a, + // '2' + 0x000f2487, + // '3' + 0x0007864f, + // '4' + 0x0004f564, + // '5' + 0x0007871f, + // '6' + 0x00069716, + // '7' + 0x0002244f, + // '8' + 0x00069696, + // '9' + 0x00068e96, + // ':' + 0x000000c3, + // ';' + 0x000006c3, + // '<' + 0x00004454, + // '=' + 0x00000f0f, + // '>' + 0x00001511, + // '?' + 0x00202487, + // '@' + 0x0e11dd96, + // 'A' + 0x0009fa64, + // 'B' + 0x00079797, + // 'C' + 0x000e111e, + // 'D' + 0x00079997, + // 'E' + 0x000f171f, + // 'F' + 0x0001171f, + // 'G' + 0x000e9d1e, + // 'H' + 0x00099f99, + // 'I' + 0x00007497, + // 'J' + 0x00069888, + // 'K' + 0x00095359, + // 'L' + 0x000f1111, + // 'M' + 0x000999f9, + // 'N' + 0x00099db9, + // 'O' + 0x00069996, + // 'P' + 0x00011797, + // 'Q' + 0x00c69996, + // 'R' + 0x00095797, + // 'S' + 0x0007861e, + // 'T' + 0x0042109f, + // 'U' + 0x00069999, + // 'V' + 0x00066999, + // 'W' + 0x0009f999, + // 'X' + 0x00099699, + // 'Y' + 0x00421151, + // 'Z' + 0x000f124f, + // '[' + 0x00e4924f, + // '\' + 0x00024489, + // ']' + 0x00f24927, + // '^' + 0x0000002a, + // '_' + 0x0000001f, + // '`' + 0x00000111, + // 'a' + 0x0000e99e, + // 'b' + 0x00799711, + // 'c' + 0x00000c4e, + // 'd' + 0x00e99e88, + // 'e' + 0x0000e35e, + // 'f' + 0x00222f2c, + // 'g' + 0x0068e99e, + // 'h' + 0x00999711, + // 'i' + 0x0003a4c2, + // 'j' + 0x00724984, + // 'k' + 0x00953511, + // 'l' + 0x0003a493, + // 'm' + 0x000099fd, + // 'n' + 0x00009997, + // 'o' + 0x00006996, + // 'p' + 0x00117997, + // 'q' + 0x0088e99e, + // 'r' + 0x0000113d, + // 's' + 0x0000f42e, + // 't' + 0x000c22f2, + // 'u' + 0x00006999, + // 'v' + 0x00006699, + // 'w' + 0x0000ff99, + // 'x' + 0x00009669, + // 'y' + 0x0068e999, + // 'z' + 0x0000f24f, + // '{' + 0x0c44744c, + // '|' + 0x0000007f, + // '}' + 0x0322e223, + // '~' + 0x000000db, + // '¡' + 0x0000003d, + // '£' + 0x00f2272c, + // '«' + 0x00004932, + // '°' + 0x00000696, + // '»' + 0x00002649, + // '¿' + 0x00e12404, + // 'Ä' + 0x009fac0a, + // 'Å' + 0x009fa4ac, + // 'Æ' + 0x000d5f5e, + // 'Ç' + 0x064e111e, + // 'É' + 0x0f171f48, + // 'Ñ' + 0x09db90db, + // 'Ö' + 0x06999609, + // '¥' + 0x084f9151, + // 'Ü' + 0x06999905, + // 'ß' + 0x0005959e, + // 'à' + 0x00e99e21, + // 'á' + 0x00e99e48, + // 'â' + 0x0e99e0a4, + // 'ä' + 0x00e99e0a, + // 'å' + 0x0e99e4ac, + // 'æ' + 0x0000f5ef, + // 'ç' + 0x0001ac4e, + // 'è' + 0x00e35e21, + // 'é' + 0x00e35e48, + // 'ê' + 0x0e35e0a4, + // 'ë' + 0x00e35e0a, + // 'ì' + 0x0003a4d1, + // 'í' + 0x0003a4d4, + // 'î' + 0x001d262a, + // 'ï' + 0x0003a4c5, + // 'ñ' + 0x099970db, + // 'ò' + 0x00699621, + // 'ó' + 0x00699648, + // 'ô' + 0x06996052, + // 'ö' + 0x00699609, + // '÷' + 0x000021c2, + // '¢' + 0x004e55e4, + // 'ù' + 0x00699921, + // 'ú' + 0x00699948, + // 'û' + 0x06999052, + // 'ü' + 0x00699905, + // 'ÿ' + 0x68e9990 +}; + +static const char_t chars_Tamsyn5x9r_9[] = { + { + .utf8_value = 32, + .bbox = { 0, 0, 0, 0 }, + .data = &chars_data_Tamsyn5x9r_9[0] + },{ + .utf8_value = 33, + .bbox = { 1, 1, 2, 7 }, + .data = &chars_data_Tamsyn5x9r_9[0] + },{ + .utf8_value = 34, + .bbox = { 0, 1, 3, 4 }, + .data = &chars_data_Tamsyn5x9r_9[1] + },{ + .utf8_value = 35, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[2] + },{ + .utf8_value = 36, + .bbox = { 0, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9r_9[3] + },{ + .utf8_value = 37, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[4] + },{ + .utf8_value = 38, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[5] + },{ + .utf8_value = 39, + .bbox = { 1, 1, 2, 4 }, + .data = &chars_data_Tamsyn5x9r_9[6] + },{ + .utf8_value = 40, + .bbox = { 0, 1, 3, 9 }, + .data = &chars_data_Tamsyn5x9r_9[7] + },{ + .utf8_value = 41, + .bbox = { 1, 1, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[8] + },{ + .utf8_value = 42, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[9] + },{ + .utf8_value = 43, + .bbox = { 0, 2, 5, 7 }, + .data = &chars_data_Tamsyn5x9r_9[10] + },{ + .utf8_value = 44, + .bbox = { 1, 6, 3, 9 }, + .data = &chars_data_Tamsyn5x9r_9[11] + },{ + .utf8_value = 45, + .bbox = { 0, 4, 4, 5 }, + .data = &chars_data_Tamsyn5x9r_9[12] + },{ + .utf8_value = 46, + .bbox = { 1, 6, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[13] + },{ + .utf8_value = 47, + .bbox = { 1, 2, 4, 8 }, + .data = &chars_data_Tamsyn5x9r_9[14] + },{ + .utf8_value = 48, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[15] + },{ + .utf8_value = 49, + .bbox = { 0, 2, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[16] + },{ + .utf8_value = 50, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[17] + },{ + .utf8_value = 51, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[18] + },{ + .utf8_value = 52, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[19] + },{ + .utf8_value = 53, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[20] + },{ + .utf8_value = 54, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[21] + },{ + .utf8_value = 55, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[22] + },{ + .utf8_value = 56, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[23] + },{ + .utf8_value = 57, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[24] + },{ + .utf8_value = 58, + .bbox = { 1, 3, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[25] + },{ + .utf8_value = 59, + .bbox = { 1, 3, 3, 9 }, + .data = &chars_data_Tamsyn5x9r_9[26] + },{ + .utf8_value = 60, + .bbox = { 0, 2, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[27] + },{ + .utf8_value = 61, + .bbox = { 0, 3, 4, 6 }, + .data = &chars_data_Tamsyn5x9r_9[28] + },{ + .utf8_value = 62, + .bbox = { 0, 2, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[29] + },{ + .utf8_value = 63, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[30] + },{ + .utf8_value = 64, + .bbox = { 0, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9r_9[31] + },{ + .utf8_value = 65, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[32] + },{ + .utf8_value = 66, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[33] + },{ + .utf8_value = 67, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[34] + },{ + .utf8_value = 68, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[35] + },{ + .utf8_value = 69, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[36] + },{ + .utf8_value = 70, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[37] + },{ + .utf8_value = 71, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[38] + },{ + .utf8_value = 72, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[39] + },{ + .utf8_value = 73, + .bbox = { 0, 2, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[40] + },{ + .utf8_value = 74, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[41] + },{ + .utf8_value = 75, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[42] + },{ + .utf8_value = 76, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[43] + },{ + .utf8_value = 77, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[44] + },{ + .utf8_value = 78, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[45] + },{ + .utf8_value = 79, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[46] + },{ + .utf8_value = 80, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[47] + },{ + .utf8_value = 81, + .bbox = { 0, 2, 4, 8 }, + .data = &chars_data_Tamsyn5x9r_9[48] + },{ + .utf8_value = 82, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[49] + },{ + .utf8_value = 83, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[50] + },{ + .utf8_value = 84, + .bbox = { 0, 2, 5, 7 }, + .data = &chars_data_Tamsyn5x9r_9[51] + },{ + .utf8_value = 85, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[52] + },{ + .utf8_value = 86, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[53] + },{ + .utf8_value = 87, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[54] + },{ + .utf8_value = 88, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[55] + },{ + .utf8_value = 89, + .bbox = { 0, 2, 5, 7 }, + .data = &chars_data_Tamsyn5x9r_9[56] + },{ + .utf8_value = 90, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[57] + },{ + .utf8_value = 91, + .bbox = { 0, 1, 3, 9 }, + .data = &chars_data_Tamsyn5x9r_9[58] + },{ + .utf8_value = 92, + .bbox = { 1, 2, 4, 8 }, + .data = &chars_data_Tamsyn5x9r_9[59] + },{ + .utf8_value = 93, + .bbox = { 1, 1, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[60] + },{ + .utf8_value = 94, + .bbox = { 0, 2, 3, 4 }, + .data = &chars_data_Tamsyn5x9r_9[61] + },{ + .utf8_value = 95, + .bbox = { 0, 7, 5, 8 }, + .data = &chars_data_Tamsyn5x9r_9[62] + },{ + .utf8_value = 96, + .bbox = { 0, 1, 3, 4 }, + .data = &chars_data_Tamsyn5x9r_9[63] + },{ + .utf8_value = 97, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[64] + },{ + .utf8_value = 98, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[65] + },{ + .utf8_value = 99, + .bbox = { 1, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[66] + },{ + .utf8_value = 100, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[67] + },{ + .utf8_value = 101, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[68] + },{ + .utf8_value = 102, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[69] + },{ + .utf8_value = 103, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[70] + },{ + .utf8_value = 104, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[71] + },{ + .utf8_value = 105, + .bbox = { 0, 1, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[72] + },{ + .utf8_value = 106, + .bbox = { 1, 1, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[73] + },{ + .utf8_value = 107, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[74] + },{ + .utf8_value = 108, + .bbox = { 0, 1, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[75] + },{ + .utf8_value = 109, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[76] + },{ + .utf8_value = 110, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[77] + },{ + .utf8_value = 111, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[78] + },{ + .utf8_value = 112, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[79] + },{ + .utf8_value = 113, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[80] + },{ + .utf8_value = 114, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[81] + },{ + .utf8_value = 115, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[82] + },{ + .utf8_value = 116, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[83] + },{ + .utf8_value = 117, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[84] + },{ + .utf8_value = 118, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[85] + },{ + .utf8_value = 119, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[86] + },{ + .utf8_value = 120, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[87] + },{ + .utf8_value = 121, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[88] + },{ + .utf8_value = 122, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[89] + },{ + .utf8_value = 123, + .bbox = { 0, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9r_9[90] + },{ + .utf8_value = 124, + .bbox = { 1, 1, 2, 8 }, + .data = &chars_data_Tamsyn5x9r_9[91] + },{ + .utf8_value = 125, + .bbox = { 0, 1, 4, 8 }, + .data = &chars_data_Tamsyn5x9r_9[92] + },{ + .utf8_value = 126, + .bbox = { 0, 2, 4, 4 }, + .data = &chars_data_Tamsyn5x9r_9[93] + },{ + .utf8_value = 161, + .bbox = { 1, 3, 2, 9 }, + .data = &chars_data_Tamsyn5x9r_9[94] + },{ + .utf8_value = 163, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[95] + },{ + .utf8_value = 171, + .bbox = { 0, 4, 5, 7 }, + .data = &chars_data_Tamsyn5x9r_9[96] + },{ + .utf8_value = 176, + .bbox = { 0, 2, 4, 5 }, + .data = &chars_data_Tamsyn5x9r_9[97] + },{ + .utf8_value = 187, + .bbox = { 0, 4, 5, 7 }, + .data = &chars_data_Tamsyn5x9r_9[98] + },{ + .utf8_value = 191, + .bbox = { 0, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[99] + },{ + .utf8_value = 196, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[100] + },{ + .utf8_value = 197, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[101] + },{ + .utf8_value = 198, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[102] + },{ + .utf8_value = 199, + .bbox = { 0, 2, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[103] + },{ + .utf8_value = 201, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[104] + },{ + .utf8_value = 209, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[105] + },{ + .utf8_value = 214, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[106] + },{ + .utf8_value = 165, + .bbox = { 0, 1, 5, 7 }, + .data = &chars_data_Tamsyn5x9r_9[107] + },{ + .utf8_value = 220, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[108] + },{ + .utf8_value = 223, + .bbox = { 0, 2, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[109] + },{ + .utf8_value = 224, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[110] + },{ + .utf8_value = 225, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[111] + },{ + .utf8_value = 226, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[112] + },{ + .utf8_value = 228, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[113] + },{ + .utf8_value = 229, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[114] + },{ + .utf8_value = 230, + .bbox = { 0, 3, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[115] + },{ + .utf8_value = 231, + .bbox = { 1, 3, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[116] + },{ + .utf8_value = 232, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[117] + },{ + .utf8_value = 233, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[118] + },{ + .utf8_value = 234, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[119] + },{ + .utf8_value = 235, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[120] + },{ + .utf8_value = 236, + .bbox = { 0, 1, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[121] + },{ + .utf8_value = 237, + .bbox = { 0, 1, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[122] + },{ + .utf8_value = 238, + .bbox = { 0, 0, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[123] + },{ + .utf8_value = 239, + .bbox = { 0, 1, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[124] + },{ + .utf8_value = 241, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[125] + },{ + .utf8_value = 242, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[126] + },{ + .utf8_value = 243, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[127] + },{ + .utf8_value = 244, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[128] + },{ + .utf8_value = 246, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[129] + },{ + .utf8_value = 247, + .bbox = { 0, 2, 3, 7 }, + .data = &chars_data_Tamsyn5x9r_9[130] + },{ + .utf8_value = 162, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[131] + },{ + .utf8_value = 249, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[132] + },{ + .utf8_value = 250, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[133] + },{ + .utf8_value = 251, + .bbox = { 0, 0, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[134] + },{ + .utf8_value = 252, + .bbox = { 0, 1, 4, 7 }, + .data = &chars_data_Tamsyn5x9r_9[135] + },{ + .utf8_value = 255, + .bbox = { 0, 1, 4, 9 }, + .data = &chars_data_Tamsyn5x9r_9[136] + } +}; + +const font_t font_Tamsyn5x9r_9 = { + .fontsize = 9, + .lineheight = 9, + .ascent = 7, + .descent = 2, + .charwidth = 5, + .char_count = 138, + .chars = chars_Tamsyn5x9r_9, + .chars_data = chars_data_Tamsyn5x9r_9, +}; + diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9r_9.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9r_9.h new file mode 100644 index 00000000..b51a6572 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/Tamsyn5x9r_9.h @@ -0,0 +1,25 @@ +/* + * LICENSE - see http://www.fial.com/~scott/tamsyn-font/ + * + * + * Tamsyn font is free. You are hereby granted permission to use, copy, modify, + * and distribute it as you see fit. + * + * Tamsyn font is provided "as is" without any express or implied warranty. + * + * The author makes no representations about the suitability of this font for + * a particular purpose. + * + * In no event will the author be held liable for damages arising from the use + * of this font. + */ + +#ifndef _TAMSYN5X9R_9_ +#define _TAMSYN5X9R_9_ + +#include +#include "fonts.h" + +extern const font_t font_Tamsyn5x9r_9; + +#endif diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/application.c b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/application.c new file mode 100644 index 00000000..10c00056 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/application.c @@ -0,0 +1,177 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2016 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include +#include "clock.h" +#include "sdram.h" +#include "lcd_ili9341.h" +#include "Tamsyn5x9r_9.h" +#include "Tamsyn5x9b_9.h" + +#include "application_balls.h" + +void spi5_isr() { + if (ILI9341_SPI_IS_SELECTED()) { + ili9341_spi5_isr(); + } else { + spi_disable_tx_buffer_empty_interrupt(SPI5); + (void)SPI_DR(SPI5); + } +} + +#define MIN1(x) (x<1?1:x) + +#define DISPLAY_TIMEOUT 33 // ~30fps +#define BALL_MOVE_TIMEOUT MIN1(DISPLAY_TIMEOUT/10) +int main(void) { + /* init timers. */ + clock_setup(); + + /* set up SDRAM. */ + sdram_init(); + + /* init LTDC (gfx + * cm3 and spi are also initialized by this function call) */ + ili9341_init( + (uint16_t*[]){ + (uint16_t*)(SDRAM_BASE_ADDRESS + 0*ILI9341_SURFACE_SIZE), + (uint16_t*)(SDRAM_BASE_ADDRESS + 1*ILI9341_SURFACE_SIZE) + }, + (uint16_t*[]){ + (uint16_t*)(SDRAM_BASE_ADDRESS + 2*ILI9341_SURFACE_SIZE), + (uint16_t*)(SDRAM_BASE_ADDRESS + 3*ILI9341_SURFACE_SIZE) + } + + ); + + + /* + * Application start.. + */ + + /* rotate LCD for 90 degrees */ + gfx_rotate(GFX_ROTATION_270_DEGREES); + + /* set background color */ + ltdc_set_background_color(0,0,0); + + //ltdc_reload(LTDC_SRCR_RELOAD_VBR); + //while (LTDC_SRCR_IS_RELOADING()); + + /* clear unused layers */ + ili9341_set_layer1(); + gfx_fill_screen(GFX_COLOR_BLACK); + ili9341_flip_layer1_buffer(); + + ili9341_set_layer2(); + + gfx_fill_screen(ILI9341_LAYER2_COLOR_KEY); // color key sets alpha to 0 + ili9341_flip_layer2_buffer(); + gfx_fill_screen(ILI9341_LAYER2_COLOR_KEY); // color key sets alpha to 0 + ili9341_flip_layer2_buffer(); + + ltdc_reload(LTDC_SRCR_RELOAD_VBR); + while (LTDC_SRCR_IS_RELOADING()); + + /* draw background */ + ili9341_set_layer1(); + gfx_fill_screen(GFX_COLOR_BLACK); + + gfx_set_font_scale(3); + gfx_puts2(10, 10, "LTDC Demo", &font_Tamsyn5x9b_9 , GFX_COLOR_WHITE); + gfx_set_font_scale(1); + gfx_set_font(&font_Tamsyn5x9r_9); + gfx_set_text_color(GFX_COLOR_BLUE2); + gfx_puts3(gfx_width()-10, 14, "Bouncing rectangular balls\nflying around in späce!", GFX_ALIGNMENT_RIGHT); + + /* define ball movement plane */ + draw_plane = (plane_t) { .x = 1, .y = 40, .w = gfx_width()-2, .h = gfx_height()-40-2, .color=GFX_COLOR_DARKGREY }; + /* draw the stage (draw_plane) */ + gfx_draw_rect(0,39,gfx_width(),gfx_height()-40, GFX_COLOR_WHITE); + gfx_fill_rect(draw_plane.x, draw_plane.y, draw_plane.w, draw_plane.h, draw_plane.color); + + ili9341_flip_layer1_buffer(); + + /* update dislay.. */ + ltdc_reload(LTDC_SRCR_RELOAD_VBR); + + /* create some balls */ + uint32_t ball_count = 0; + ball_t *bp = balls; + ball_create(bp++, 100, 10,20,20, .5,-.2, GFX_COLOR_BLUE); ball_count++; + ball_create(bp++, 130, 20,20,20, .2,-.7, GFX_COLOR_BLUE2); ball_count++; + ball_create(bp++, 190,100,20,20, -.3, .2, GFX_COLOR_ORANGE); ball_count++; + ball_create(bp++, 100,150,20,20, .1,-.5, GFX_COLOR_YELLOW); ball_count++; + ball_create(bp++, 20,160,20,20, .2, .6, GFX_COLOR_GREEN2); ball_count++; + ball_create(bp++, 70, 80,20,20, -.2, .3, GFX_COLOR_RED); ball_count++; + ball_create(bp++, 180, 50,20,20, .4, .8, GFX_COLOR_CYAN); ball_count++; + ball_create(bp++, 70,160,20,20, -.2, .6, GFX_COLOR_MAGENTA); ball_count++; + ball_create(bp++, 250,170,20,20, .2,-.3, GFX_COLOR_GREEN); ball_count++; + ball_create(bp++, 212,165,20,20, .5, .3, GFX_COLOR_BROWN); ball_count++; + + while (1) { + uint64_t ctime = mtime(); + static uint64_t draw_timeout = 0, ball_move_timeout = 0; + static char fps_s[7] = " fps"; + + if (ball_move_timeout <= ctime) { + ball_move_timeout = ctime+BALL_MOVE_TIMEOUT; + /* move balls */ + ball_move(balls, ball_count); + } + + if (!LTDC_SRCR_IS_RELOADING() && (draw_timeout <= ctime)) { + /* calculate fps */ + uint32_t fps = 1000/(ctime-draw_timeout+DISPLAY_TIMEOUT); + fps_s[2] = 48+fps%10; + fps /= 10; + if (fps) { + fps_s[1] = 48+fps%10; + fps /= 10; + if (fps) + fps_s[0] = 48+fps%10; + } + /* set next timeout */ + draw_timeout = ctime+DISPLAY_TIMEOUT; + + /* select layer to draw on */ + ili9341_set_layer2(); + /* clear the whole screen */ + gfx_fill_screen(ILI9341_LAYER2_COLOR_KEY); + /* draw balls */ + ball_draw(balls, ball_count); + + /* draw fps */ + gfx_set_font_scale(1); + gfx_puts2( + gfx_width() -6*font_Tamsyn5x9b_9.charwidth *gfx_get_font_scale()-3, + gfx_height()-font_Tamsyn5x9b_9.lineheight*gfx_get_font_scale()-3, + fps_s, &font_Tamsyn5x9b_9 , GFX_COLOR_WHITE); + + /* swap the double buffer */ + ili9341_flip_layer2_buffer(); + + /* update dislay */ + ltdc_reload(LTDC_SRCR_RELOAD_VBR); + } + } +} + + diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/application_balls.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/application_balls.h new file mode 100644 index 00000000..068e5dcf --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/application_balls.h @@ -0,0 +1,132 @@ +#include + +typedef struct { + float x,y,w,h; + uint16_t color; +} plane_t; +typedef struct { + float x,y,w,h,sh,sv; + uint16_t color; +} ball_t; + +plane_t draw_plane; +ball_t balls[10]; + +static inline +void +ball_create(ball_t *b, float x, float y, float w, float h, float sh, float sv, uint16_t color) { + b->x=x; + b->y=y; + b->w=w; + b->h=h; + b->sh=sh; + b->sv=sv; + b->color=color; +} +static inline +bool +ball_hittest(ball_t *b1, ball_t *b2) { + return (((b1->x + b1->w >= b2->x) && (b1->x <= b2->x + b2->w)) && ((b1->y + b1->h >= b2->y) && (b1->y <= b2->y + b2->h))); +} +static inline +void +ball_move(ball_t *bs, size_t bs_len) { + size_t l,ll; + ball_t *b, *bsp; + + /* change x */ + b = bs; + l = bs_len; + while (l--) { + b->x += b->sh; + b++; + } + + /* hittest x */ + bsp = bs; + l = bs_len; + while (l--) { + ball_t *bb; + + b = bsp++; + if ((b->x < 0) || ((b->x+b->w) > draw_plane.w)) { // hittest borders + b->sh = -b->sh; + b->x += b->sh; + } else { + ll = l; + bb = bsp; + while (ll--) { + if (ball_hittest(b,bb)) { + float s; + s = b->sh - bb->sh; + b->x -= b->sh; + bb->x -= bb->sh; + bb->sh += s; + b->sh -= s; + } + bb++; + } + } + } + + + /* change y */ + b = bs; + l = bs_len; + while (l--) { + b->y += b->sv; + b++; + } + + /* hittest y */ + bsp = bs; + l = bs_len; + while (l--) { + ball_t *bb; + + b = bsp++; + if ((b->y < 0) || ((b->y+b->h) > draw_plane.h)) { // hittest borders + b->sv = -b->sv; + b->y += b->sv; + } else { + ll = l; + bb = bsp; + while (ll--) { + if (ball_hittest(b,bb)) { + float s; + s = b->sv - bb->sv; + b->y -= b->sv; + bb->y -= bb->sv; + bb->sv += s; + b->sv -= s; + } + bb++; + } + } + } +} +static inline +void +ball_draw(ball_t *bs, size_t bs_len) { + char buf[2] = " "; + uint32_t b_id = 0; + gfx_set_font_scale(2); + while (bs_len--) { + gfx_fill_round_rect( + (int16_t)(draw_plane.x + bs->x), + (int16_t)(draw_plane.y + bs->y), + (int16_t)bs->w, + (int16_t)bs->h, + 5, + bs->color + ); + buf[0]=48+b_id++%10; + gfx_puts2( + (int16_t)(draw_plane.x + bs->x + bs->w/2) - font_Tamsyn5x9b_9.charwidth/2*gfx_get_font_scale(), + (int16_t)(draw_plane.y + bs->y + bs->h/2) - font_Tamsyn5x9b_9.lineheight/2*gfx_get_font_scale(), + buf, + &font_Tamsyn5x9b_9 , + GFX_COLOR_WHITE); + bs++; + } +} diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/clock.c b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/clock.c new file mode 100644 index 00000000..29158627 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/clock.c @@ -0,0 +1,75 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Chuck McManis + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* + * Now this is just the clock setup code from systick-blink as it is the + * transferrable part. + */ + +#include +#include +#include + +/* Common function descriptions */ +#include "clock.h" + +/* milliseconds since boot */ +static volatile uint64_t system_millis; + +/* Called when systick fires */ +void sys_tick_handler(void) +{ + system_millis++; +} + +/* simple sleep for delay milliseconds */ +void milli_sleep(uint32_t delay) +{ + uint64_t wake = system_millis + delay; + while (wake > system_millis) { + continue; + } +} + +/* Getter function for the current time */ +uint64_t mtime(void) +{ + return system_millis; +} + +/* + * clock_setup(void) + * + * This function sets up both the base board clock rate + * and a 1khz "system tick" count. The SYSTICK counter is + * a standard feature of the Cortex-M series. + */ +void clock_setup(void) +{ + /* Base board frequency, set to 168Mhz */ + rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]); + + /* clock rate / 168000 to get 1mS interrupt rate */ + systick_set_reload(168000); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); + systick_counter_enable(); + + /* this done last */ + systick_interrupt_enable(); +} diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/clock.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/clock.h new file mode 100644 index 00000000..b77af86d --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/clock.h @@ -0,0 +1,17 @@ +/* + * This include file describes the functions exported by clock.c + */ +#ifndef __CLOCK_H +#define __CLOCK_H + +#include + +/* + * Definitions for functions being abstracted out + */ +void milli_sleep(uint32_t); +uint64_t mtime(void); +void clock_setup(void); + +#endif /* generic header protector */ + diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/fonts.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/fonts.h new file mode 100644 index 00000000..4ead820e --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/fonts.h @@ -0,0 +1,84 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2016 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + +/** + * Fonts library + */ +#ifndef FONTS_H +#define FONTS_H + +#include +#include + +/* + * the holds the offsets for the data relative to the default char size + * and the data width/height + * eg. : + m,o = font.getmask2(c, mode="1") + bbox = m.getbbox() + x1 = (charwidth - bbox[2])/2 + y1 = (o[1]-offset[1] + bbox[1]) + x2 = x1 + bbox[2]-bbox[0] + y2 = y1 + bbox[3]-bbox[1] + */ +typedef struct { + uint32_t x1, y1, x2, y2; +} char_data_bbox_t; + +typedef struct { + uint32_t utf8_value; + char_data_bbox_t bbox; + const uint32_t *data; // pointer to char_data_offset +} char_t; + +typedef struct { + uint8_t fontsize; + uint8_t lineheight; + uint8_t ascent; + uint8_t descent; + uint8_t charwidth; + uint16_t char_count; + const char_t *chars; // pointer to chars array (sorted by utf8_value) + const uint32_t *chars_data; // pointer to chars_data array +} font_t; + +/* binary search for char */ +static inline +const char_t* +font_get_char_index(uint32_t utf8_value, const font_t *font) { + uint32_t s,e,i,j,cc; + s=j=0; + e=font->char_count-1; + while (1) { + i = (s+e)>>1; + cc = font->chars[i].utf8_value; + if (utf8_value < cc) e = i; + else + if (utf8_value > cc) s = i; + else { + return &font->chars[i]; + } + if (i==j) return NULL; + j=i; + } +} + +#endif + diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/gfx_locm3.c b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/gfx_locm3.c new file mode 100644 index 00000000..7319d9ce --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/gfx_locm3.c @@ -0,0 +1,645 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2016 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + + + +#include "gfx_locm3.h" + +gfx_state_t __gfx_state; + +void +gfx_init(uint16_t *surface, int32_t width, int32_t height) { + *(uint16_t*)&__gfx_state.width_orig = width; + *(uint16_t*)&__gfx_state.height_orig = height; + *(uint32_t*)&__gfx_state.pixel_count = (uint32_t)width*(uint32_t)height; + __gfx_state.width = width; + __gfx_state.height = height; + __gfx_state.visible_area = (visible_area_t){0,0,width,height}; + __gfx_state.rotation = 0; + __gfx_state.cursor_y = __gfx_state.cursor_x = __gfx_state.cursor_x_orig = 0; + __gfx_state.fontscale = 1; + __gfx_state.textcolor = 0; + __gfx_state.wrap = true; + __gfx_state.surface = surface; + __gfx_state.font = NULL; +} +void gfx_set_surface(uint16_t *surface) { + __gfx_state.surface = surface; +} +uint16_t * +gfx_get_surface() { + return __gfx_state.surface; +} + +void +gfx_set_surface_visible_area_max() { + __gfx_state.visible_area = (visible_area_t){0,0,__gfx_state.width,__gfx_state.height}; +} +void +gfx_set_surface_visible_area(int16_t x1, int16_t y1, int16_t x2, int16_t y2) { + if (x1<0) x1=0; + if (y1<0) y1=0; + if (x2= __gfx_state.visible_area.x2) { + return; + } + if (y < __gfx_state.visible_area.y1 || y >= __gfx_state.visible_area.y2) { + return; + } + + pixel_addr = __gfx_state.surface; + switch (__gfx_state.rotation) { + case GFX_ROTATION_0_DEGREES : + pixel_addr += (x + y*__gfx_state.width_orig); + break; + case GFX_ROTATION_180_DEGREES : + pixel_addr += __gfx_state.pixel_count - (x + y*__gfx_state.width_orig); + break; + case GFX_ROTATION_90_DEGREES : + pixel_addr += __gfx_state.pixel_count - (x*__gfx_state.width_orig + (__gfx_state.width_orig-y)); + break; + case GFX_ROTATION_270_DEGREES : + pixel_addr += (x*__gfx_state.width_orig + (__gfx_state.width_orig-y)); + break; + } + *pixel_addr = color; + + return; +} + +// Bresenham's algorithm - thx wikpedia +void gfx_draw_line(int16_t x0, int16_t y0, + int16_t x1, int16_t y1, + uint16_t fg) { + int16_t steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { + swap(x0, y0); + swap(x1, y1); + } + + if (x0 > x1) { + swap(x0, x1); + swap(y0, y1); + } + + int16_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int16_t err = dx / 2; + int16_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1; + } + + for (; x0<=x1; x0++) { + if (steep) { + gfx_draw_pixel(y0, x0, fg); + } else { + gfx_draw_pixel(x0, y0, fg); + } + err -= dy; + if (err < 0) { + y0 += ystep; + err += dx; + } + } +} +void gfx_draw_hline(int16_t x, int16_t y, int16_t length, uint16_t color) { + if (length<0) { + length = -length; + x -= length; + } + while (length-- != 0) { + gfx_draw_pixel(x++,y,color); + } +} +void gfx_draw_vline(int16_t x, int16_t y, int16_t length, uint16_t color) { + if (length<0) { + length = -length; + y -= length; + } + while (length-- != 0) { + gfx_draw_pixel(x,y++,color); + } +} + +void gfx_draw_rect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { + int16_t x_s,y_e; + if (w<0) { + w = -w; + x-= w; + } + if (h<0) { + h = -h; + x-= h; + } + x_s = x; + y_e = y+h; + while (w-- != 0) { + gfx_draw_pixel(x,y ,color); + gfx_draw_pixel(x,y_e,color); + x++; + } + x--; + while (h-- != 0) { + gfx_draw_pixel(x_s,y,color); + gfx_draw_pixel(x ,y,color); + y++; + } +} + +void gfx_fill_rect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { + int16_t x_cp,w_cp; + while (h--) { + x_cp=x; + w_cp=w; + while (w_cp--) { + gfx_draw_pixel(x_cp,y,color); + x_cp++; + } + y++; + } +} + + + + +// Draw RGB565 data +void gfx_draw_raw_rbg565_buffer(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t *img) { + int16_t x_cp,w_cp; + while (h--) { + x_cp=x; + w_cp=w; + while (w_cp--) { + gfx_draw_pixel(x_cp,y,*img++); + x_cp++; + } + y++; + } +} + + +// Draw a circle outline +void gfx_draw_circle(int16_t x0, int16_t y0, int16_t r, uint16_t fg) { + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + gfx_draw_pixel(x0 , y0+r, fg); + gfx_draw_pixel(x0 , y0-r, fg); + gfx_draw_pixel(x0+r, y0 , fg); + gfx_draw_pixel(x0-r, y0 , fg); + + while (x= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + gfx_draw_pixel(x0 + x, y0 + y, fg); + gfx_draw_pixel(x0 - x, y0 + y, fg); + gfx_draw_pixel(x0 + x, y0 - y, fg); + gfx_draw_pixel(x0 - x, y0 - y, fg); + gfx_draw_pixel(x0 + y, y0 + x, fg); + gfx_draw_pixel(x0 - y, y0 + x, fg); + gfx_draw_pixel(x0 + y, y0 - x, fg); + gfx_draw_pixel(x0 - y, y0 - x, fg); + } +} + +void gfx_draw_circle_helper( int16_t x0, int16_t y0, + int16_t r, uint8_t cornername, uint16_t fg) { + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + while (x= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + if (cornername & 0x4) { + gfx_draw_pixel(x0 + x, y0 + y, fg); + gfx_draw_pixel(x0 + y, y0 + x, fg); + } + if (cornername & 0x2) { + gfx_draw_pixel(x0 + x, y0 - y, fg); + gfx_draw_pixel(x0 + y, y0 - x, fg); + } + if (cornername & 0x8) { + gfx_draw_pixel(x0 - y, y0 + x, fg); + gfx_draw_pixel(x0 - x, y0 + y, fg); + } + if (cornername & 0x1) { + gfx_draw_pixel(x0 - y, y0 - x, fg); + gfx_draw_pixel(x0 - x, y0 - y, fg); + } + } +} + +void gfx_fill_circle(int16_t x0, int16_t y0, int16_t r, + uint16_t fg) { + gfx_draw_vline(x0, y0-r, 2*r+1, fg); + gfx_fill_circle_helper(x0, y0, r, 3, 0, fg); +} + +// Used to do circles and roundrects +void gfx_fill_circle_helper(int16_t x0, int16_t y0, int16_t r, + uint8_t cornername, int16_t delta, uint16_t fg) { + + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + while (x= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x1) { + gfx_draw_vline(x0+x, y0-y, 2*y+1+delta, fg); + gfx_draw_vline(x0+y, y0-x, 2*x+1+delta, fg); + } + if (cornername & 0x2) { + gfx_draw_vline(x0-x, y0-y, 2*y+1+delta, fg); + gfx_draw_vline(x0-y, y0-x, 2*x+1+delta, fg); + } + } +} + + +// Draw a rounded rectangle +void gfx_draw_round_rect(int16_t x, int16_t y, int16_t w, + int16_t h, int16_t r, uint16_t fg) { + // smarter version + gfx_draw_hline(x+r , y , w-2*r, fg); // Top + gfx_draw_hline(x+r , y+h-1, w-2*r, fg); // Bottom + gfx_draw_vline(x , y+r , h-2*r, fg); // Left + gfx_draw_vline(x+w-1, y+r , h-2*r, fg); // Right + // draw four corners + gfx_draw_circle_helper(x+r , y+r , r, 1, fg); + gfx_draw_circle_helper(x+w-r-1, y+r , r, 2, fg); + gfx_draw_circle_helper(x+w-r-1, y+h-r-1, r, 4, fg); + gfx_draw_circle_helper(x+r , y+h-r-1, r, 8, fg); +} + +// Fill a rounded rectangle +void gfx_fill_round_rect(int16_t x, int16_t y, int16_t w, + int16_t h, int16_t r, uint16_t fg) { + // smarter version + gfx_fill_rect(x+r, y, w-2*r, h, fg); + + // draw four corners + gfx_fill_circle_helper(x+w-r-1, y+r, r, 1, h-2*r-1, fg); + gfx_fill_circle_helper(x+r , y+r, r, 2, h-2*r-1, fg); +} + + +// Draw a triangle +void gfx_draw_triangle(int16_t x0, int16_t y0, + int16_t x1, int16_t y1, + int16_t x2, int16_t y2, uint16_t fg) { + gfx_draw_line(x0, y0, x1, y1, fg); + gfx_draw_line(x1, y1, x2, y2, fg); + gfx_draw_line(x2, y2, x0, y0, fg); +} + +// Fill a triangle +void gfx_fill_triangle ( int16_t x0, int16_t y0, + int16_t x1, int16_t y1, + int16_t x2, int16_t y2, uint16_t fg) { + + int16_t a, b, y, last; + + // Sort coordinates by Y order (y2 >= y1 >= y0) + if (y0 > y1) { + swap(y0, y1); swap(x0, x1); + } + if (y1 > y2) { + swap(y2, y1); swap(x2, x1); + } + if (y0 > y1) { + swap(y0, y1); swap(x0, x1); + } + + if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing + a = b = x0; + if(x1 < a) a = x1; + else if(x1 > b) b = x1; + if(x2 < a) a = x2; + else if(x2 > b) b = x2; + gfx_draw_hline(a, y0, b-a+1, fg); + return; + } + + int16_t + dx01 = x1 - x0, + dy01 = y1 - y0, + dx02 = x2 - x0, + dy02 = y2 - y0, + dx12 = x2 - x1, + dy12 = y2 - y1, + sa = 0, + sb = 0; + + // For upper part of triangle, find scanline crossings for segments + // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 + // is included here (and second loop will be skipped, avoiding a /0 + // error there), otherwise scanline y1 is skipped here and handled + // in the second loop...which also avoids a /0 error here if y0=y1 + // (flat-topped triangle). + if(y1 == y2) last = y1; // Include y1 scanline + else last = y1-1; // Skip it + + for(y=y0; y<=last; y++) { + a = x0 + sa / dy01; + b = x0 + sb / dy02; + sa += dx01; + sb += dx02; + /* longhand: + a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) swap(a,b); + gfx_draw_hline(a, y, b-a+1, fg); + } + + // For lower part of triangle, find scanline crossings for segments + // 0-2 and 1-2. This loop is skipped if y1=y2. + sa = dx12 * (y - y1); + sb = dx02 * (y - y0); + for(; y<=y2; y++) { + a = x1 + sa / dy12; + b = x0 + sb / dy02; + sa += dx12; + sb += dx02; + /* longhand: + a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) swap(a,b); + gfx_draw_hline(a, y, b-a+1, fg); + } +} + + + + +/** + * Text functions + */ + +/* Write utf8 text */ +void gfx_write(const uint32_t c) { + if (!__gfx_state.font) return; + if (c == '\n') { + __gfx_state.cursor_y += __gfx_state.fontscale*__gfx_state.font->lineheight; + __gfx_state.cursor_x = __gfx_state.cursor_x_orig; + } else if (c == '\r') { + __gfx_state.cursor_x = __gfx_state.cursor_x_orig; + } else { + if (__gfx_state.wrap && (__gfx_state.cursor_x > (__gfx_state.visible_area.x2 - __gfx_state.fontscale*__gfx_state.font->charwidth))) { + __gfx_state.cursor_y += __gfx_state.fontscale*__gfx_state.font->lineheight; + __gfx_state.cursor_x = __gfx_state.cursor_x_orig; //__gfx_state.visible_area.x1; + } + gfx_draw_char(__gfx_state.cursor_x, __gfx_state.cursor_y, + c, + __gfx_state.textcolor, __gfx_state.fontscale); + __gfx_state.cursor_x += __gfx_state.fontscale*__gfx_state.font->charwidth; + } +} + +void gfx_puts(const char *s) { + while (*s) { + int32_t value; + s = utf8_read_value(s,&value); + gfx_write(value); + } +} +void gfx_puts2(int16_t x, int16_t y, const char *s, const font_t *font, uint16_t col) { + gfx_set_cursor(x,y); + gfx_set_font(font); + gfx_set_text_color(col); + //gfx_setTextSize(1); + gfx_puts(s); +} +/* this is not utf8 right now.. */ +void gfx_puts3(int16_t x, int16_t y, const char *s, const gfx_alignment_t alignment) { + if (!__gfx_state.font) return; + if (!(alignment&GFX_ALIGNMENT_RIGHT)) { + gfx_set_cursor(x,y); + gfx_puts(s); + return; + } + + const char *s_end = utf8_find_character_in_string(0,s,s+1024); + const char *next_nl,*last_nl; + + last_nl = utf8_find_character_in_string('\n', s,s_end); + if (!last_nl) { + gfx_set_cursor(x-utf8_find_pointer_diff(s,s_end)*__gfx_state.font->charwidth,y); + gfx_puts(s); + return; + } + + uint32_t line_count = 0; + while (scharwidth,y+line_count*__gfx_state.font->lineheight); + do { + int32_t value; + s = utf8_read_value(s,&value); + gfx_write(value); + } while (s!=next_nl); + s++;line_count++; + } +} + +/** + * This function gets the index of the char for the font data + * converts it's bit array address to a 32bit and mask + * and draws a point of size to it's location + * + * @param x x position + * @param y y position + * @param c utf8 char id + * @param col RGB565 color + * @param size Size in multiples of 1 + */ +void gfx_draw_char(int16_t x, int16_t y, uint32_t c, + uint16_t col, uint8_t size) { + uint32_t i, j, bm; + const char_t *cp; + const uint32_t *cp_data_p; + + if (!__gfx_state.font) return; + /* get the data-index for this char code from the lookup table */ + cp = font_get_char_index(c,__gfx_state.font); + if (cp == NULL) return; + + cp_data_p = cp->data; + bm = 1; // bit_mask + for (j=cp->bbox.y1; jbbox.y2; j++) { + for (i=cp->bbox.x1; ibbox.x2; i++) { + if (*cp_data_p & bm) { + // default size + if (size == 1) gfx_draw_pixel(x+i, y+j, col); + // big size + else gfx_fill_rect (x+i*size, y+j*size, size, size, col); + } + bm <<= 1; + // overflow + if (!bm) { + bm = 1; + cp_data_p++; + } + } + } +} + +void gfx_set_cursor(int16_t x, int16_t y) { + __gfx_state.cursor_x_orig = x; + __gfx_state.cursor_x = x; + __gfx_state.cursor_y = y; +} + +void gfx_set_font_scale(uint8_t s) { + __gfx_state.fontscale = (s > 0) ? s : 1; +} + +void gfx_set_text_color(uint16_t col) { + __gfx_state.textcolor = col; +} +void gfx_set_font(const font_t *font) { + __gfx_state.font = font; +} + +void gfx_set_text_wrap(uint8_t w) { + __gfx_state.wrap = w; +} + +uint16_t +gfx_get_char_width() { + if (!__gfx_state.font) return 0; + return __gfx_state.font->charwidth*__gfx_state.fontscale; +} +uint16_t +gfx_get_line_height() { + if (!__gfx_state.font) return 0; + return __gfx_state.font->lineheight*__gfx_state.fontscale; +} +uint16_t +gfx_get_string_width(char *s) { + return strlen(s) * gfx_get_char_width(); +} + +uint8_t +gfx_get_font_scale() { + return __gfx_state.fontscale; +} +uint16_t +gfx_get_text_color() { + return __gfx_state.textcolor; +} +const font_t * +gfx_get_font() { + return __gfx_state.font; +} +uint8_t +gfx_get_text_wrap() { + return __gfx_state.wrap; +} + diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/gfx_locm3.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/gfx_locm3.h new file mode 100644 index 00000000..fbb15483 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/gfx_locm3.h @@ -0,0 +1,174 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2016 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + +#ifndef _GFX_LOCM3_H_ +#define _GFX_LOCM3_H_ + + +#include +#include +#include +#include +#include + +#include "h2_utf8.h" +#include "fonts.h" + +#define swap(a, b) { int16_t t = a; a = b; b = t; } + +typedef union { + struct { int16_t x,y; }; + struct { int16_t w,h; }; +} gfx_vec2_t; + +/* + * Python + * def get_rgb565(x) : + * return ((x&0xf80000)>>8) | ((x&0xfc00)>>5) | ((x&0xf8)>>3) + * + * print print "0x%X"%get_rgb565(some_rgb_value) + */ +#define GFX_COLOR_WHITE 0xFFFF +#define GFX_COLOR_BLACK 0x0000 +#define GFX_COLOR_DARKGREY 0x4228 +#define GFX_COLOR_GREY 0xF7DE +#define GFX_COLOR_BLUE 0x001F +#define GFX_COLOR_BLUE2 0x051F +#define GFX_COLOR_RED 0xF800 +#define GFX_COLOR_MAGENTA 0xF81F +#define GFX_COLOR_GREEN 0x07E0 +#define GFX_COLOR_GREEN2 0xB723 +#define GFX_COLOR_CYAN 0x7FFF +#define GFX_COLOR_YELLOW 0xFFE0 +#define GFX_COLOR_ORANGE 0xFBE4 +#define GFX_COLOR_GRAY 0x7BEF //1111 0111 1101 1110 +#define GFX_COLOR_BROWN 0xBBCA + +typedef enum { + GFX_ROTATION_0_DEGREES, + GFX_ROTATION_90_DEGREES, + GFX_ROTATION_180_DEGREES, + GFX_ROTATION_270_DEGREES +} gfx_rotation_t; + +typedef enum { + GFX_ALIGNMENT_TOP = 1<<0, + GFX_ALIGNMENT_BOTTOM = 1<<1, + GFX_ALIGNMENT_LEFT = 1<<2, + GFX_ALIGNMENT_RIGHT = 1<<3, +} gfx_alignment_t; + +typedef struct { + int16_t x1,y1,x2,y2; +} visible_area_t; + +typedef struct { + const int16_t width_orig, height_orig; + const uint32_t pixel_count; + int16_t width, height; + visible_area_t visible_area; + int16_t cursor_x, cursor_y, cursor_x_orig; + uint16_t textcolor; + uint8_t fontscale; + gfx_rotation_t rotation; + uint8_t wrap; + const font_t *font; + uint16_t *surface; // current pixel buffer +} gfx_state_t; + + +extern gfx_state_t __gfx_state; + + +void gfx_init(uint16_t *surface, int32_t w, int32_t h); +/** + * set pixel buffer address to render graphics on.. + * @param surface pixel buffer address + */ +void gfx_set_surface(uint16_t *surface); +uint16_t * +gfx_get_surface(void); + +void +gfx_set_surface_visible_area_max(void); +void +gfx_set_surface_visible_area(int16_t x1, int16_t y1, int16_t x2, int16_t y2); +visible_area_t +gfx_get_surface_visible_area(void); + + +void gfx_fill_screen(uint16_t color); + +void gfx_rotate(gfx_rotation_t rotation); +uint16_t gfx_height(void); +uint16_t gfx_width(void); +gfx_rotation_t gfx_get_rotation(void); + +void gfx_draw_pixel(int16_t x, int16_t y, uint16_t color); + +void gfx_draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); +void gfx_draw_hline(int16_t x, int16_t y, int16_t length, uint16_t color); +void gfx_draw_vline(int16_t x, int16_t y, int16_t length, uint16_t color); +void gfx_draw_rect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); +void gfx_fill_rect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); +void gfx_draw_raw_rbg565_buffer(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t *img); + +void gfx_draw_circle(int16_t x0, int16_t y0, int16_t r, uint16_t color); +void gfx_draw_circle_helper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color); +void gfx_fill_circle(int16_t x0, int16_t y0, int16_t r, uint16_t color); +void gfx_fill_circle_helper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color); + +void gfx_draw_round_rect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color); +void gfx_fill_round_rect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color); + +void gfx_draw_triangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color); +void gfx_fill_triangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color); + + +void gfx_draw_char(int16_t x, int16_t y, uint32_t c, uint16_t color, uint8_t size); +void gfx_set_cursor(int16_t x, int16_t y); +void gfx_set_text_color(uint16_t col); +void gfx_set_font_scale(uint8_t s); +void gfx_set_text_wrap(uint8_t w); +void gfx_set_font(const font_t *font); +void gfx_puts(const char *); +void gfx_puts2(int16_t x, int16_t y, const char *s, const font_t *font, uint16_t col); +void gfx_puts3(int16_t x, int16_t y, const char *s, const gfx_alignment_t alignment); +void gfx_write(const uint32_t); + + +uint16_t +gfx_get_char_width(void); +uint16_t +gfx_get_line_height(void); +uint16_t +gfx_get_string_width(char *); + +uint8_t +gfx_get_font_scale(void); +uint16_t +gfx_get_text_color(void); +const font_t * +gfx_get_font(void); +uint8_t +gfx_get_text_wrap(void); + + +#endif diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/h2_utf8.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/h2_utf8.h new file mode 100644 index 00000000..a1eab529 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/h2_utf8.h @@ -0,0 +1,134 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2016 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + +#ifndef H2_UTF8_H +#define H2_UTF8_H + +#ifndef NULL +#define NULL 0 +#endif + +#include + +/** + * + * @param text utf8 string + * @param value pointer which holds the utf value after the function returns + * @return pointer to the next value in string (-1 for invalid value) + */ +static inline +const char * +utf8_read_value(const char* text, int32_t *value) { + char tmp; uint8_t cnt,i; + + tmp = *text++; + + if (!(tmp & 0b10000000)) { + *value = tmp; + return text; + } else + if ((tmp & 0b11100000)==0b11000000) { + *value = tmp & ~0b11100000; + cnt = 1; + } else + if ((tmp & 0b11110000)==0b11100000) { + *value = tmp & ~0b11110000; + cnt = 2; + } else + if ((tmp & 0b11111000)==0b11110000) { + *value = tmp & ~0b11111000; + cnt = 3; + } else { + *value=-1; + return text; + } + + for (i=cnt; i; i--) { + tmp = *text++; + if ((tmp & 0b11000000)!=0b10000000) { + *value=-1; + return text; + } + + *value = (*value<<6) | (tmp & ~0b11000000); + } + + return text; +} + + +// utf-8 ... +static inline +const char * +utf8_find_character_index(int index, const char *text_start, const char *text_end, int *index_rest) { + const char *result; + if (index<0) { + result = text_end; + while (index && result!=text_start) { + index++; + result--; + while (((*result)&192)==128 && result!=text_start) { // skip next utf8-character (secondary bytes) + result--; + } + } + } else { + result = text_start; + while (index && result!=text_end) { + index--; + result++; + while (((*result)&192)==128 && result!=text_end) { // skip last utf8-character (secondary bytes) + result++; + } + } + } + + if (index_rest!=NULL) + *index_rest = index; + + return result; +} + + +//untestet! +static inline +const char * utf8_find_character_in_string(const char chr, const char *text_start, const char *text_end) {//, int *index_rest) { + const char *result = text_start; + while (result!=text_end) { + if (*result==chr) break; + result = utf8_find_character_index(1, result, text_end, NULL); + } + return result; +} +static inline +int utf8_find_pointer_diff(const char *text_start, const char *text_end) { + int diff = 0; + while (text_start + * Copyright (C) 2014 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ +#include "lcd_ili9341.h" +#include + +volatile int rx_pend; +volatile uint16_t spi_rx_buf; + +void ili9341_spi5_isr() { + spi_rx_buf = SPI_DR(SPI5); + --rx_pend; +} + +/* send spi data */ +static inline void ili9341_send_data(uint8_t data); + +/* send spi command */ +static inline void ili9341_send_command(uint8_t data); + +/* interrupt driven send command via ssp */ +void +ili9341_send_command(uint8_t data) { + ILI9341_WRX_RESET(); + ILI9341_SPI_SELECT(); + + rx_pend++; + spi_send(ILI9341_SPI, data); + while(rx_pend); + + ILI9341_SPI_DESELECT(); +} + +/* interrupt driven send data via ssp */ +void +ili9341_send_data(uint8_t data) { + ILI9341_WRX_SET(); + ILI9341_SPI_SELECT(); + + rx_pend++; + spi_send(ILI9341_SPI, data); + while(rx_pend); + + ILI9341_SPI_DESELECT(); +} + + + +uint16_t ili9341_x; +uint16_t ili9341_y; +ili9341_options_t ili9341_opts; + +void ili9341_init_pins(void); +void lcd9341_init_ltdc(void); +void ili9341_init_layers(void); +void ili9341_init_lcd(void); + + +/** + * Setup LCD screen to be driven by ltdc + * + * surface buffers have ILI9341_BUFFERS_PER_LAYER elements + * which point to memory areas where each have a size of + * ILI9341_SURFACE_SIZE + * + * @param layer1_surface_buffers + * @param layer2_surface_buffers + */ +void ili9341_init(uint16_t *layer1_surface_buffers[], uint16_t *layer2_surface_buffers[]) { + int i; + + //Initialize pins used + ili9341_init_pins(); + //SPI chip select high + ILI9341_SPI_DESELECT(); + //Initialize LCD for LTDC + ili9341_init_lcd(); + //Initialize LTDC + lcd9341_init_ltdc(); + //Initialize LTDC layers + ili9341_init_layers(); + //Set cursor X and Y + ili9341_x = ili9341_y = 0; + + ili9341_opts.width = ILI9341_WIDTH; + ili9341_opts.height = ILI9341_HEIGHT; + //ili9341_opts.orientation = ILI9341_PORTRAIT; + //ili9341_opts.orient = ILI9341_ORIENTATION_0_DEGREE; + ili9341_opts.current_layer = 0; + ili9341_opts.layer1_opacity = 255; + ili9341_opts.layer2_opacity = 0; + ili9341_opts.current_layer1_surface_idx = 0; + ili9341_opts.current_layer2_surface_idx = 0; + for (i=0; i>16)&0xff, + (ltdc_get_rgb888_from_rgb565(ILI9341_LAYER2_COLOR_KEY)>> 8)&0xff, + (ltdc_get_rgb888_from_rgb565(ILI9341_LAYER2_COLOR_KEY)>> 0)&0xff + ); + ltdc_layer_ctrl_enable(LTDC_LAYER_2, LTDC_LxCR_COLKEY_ENABLE); + + /* the length of one line of pixels in bytes + 3 then : + Line Lenth = Active high width x number of bytes per pixel + 3 + Active high width = LCD_PIXEL_WIDTH + number of bytes per pixel = 2 (pixel_format : RGB565) + */ + /* the pitch is the increment from the start of one line of pixels to the + start of the next line in bytes, then : + Pitch = Active high width x number of bytes per pixel + */ + /* I was too lazy to add makros for this */ + ltdc_set_fb_line_length(LTDC_LAYER_1, (240*2+3), (240*2)); + ltdc_set_fb_line_length(LTDC_LAYER_2, (240*2+3), (240*2)); + + + /* Configure the number of lines */ + ltdc_set_fb_line_count(LTDC_LAYER_1, 320); + ltdc_set_fb_line_count(LTDC_LAYER_2, 320); + + /* Start Address configuration : the LCD Frame buffer is defined on SDRAM */ + ltdc_set_fbuffer_address(LTDC_LAYER_1, (uint32_t)ili9341_opts.layer1_surface_buffers[0]); + + /* Start Address configuration : the LCD Frame buffer is defined on SDRAM w/ Offset */ + ltdc_set_fbuffer_address(LTDC_LAYER_2, (uint32_t)ili9341_opts.layer2_surface_buffers[0]); + + + /* All the layer configs are shadow registers which can be reloaded + * either immediately with LTDC_SRCR_RELOAD_IMR or in the vsync phase + * (i guess) with LTDC_SRCR_RELOAD_VBR + * if you want to do double buffering just set the new buffer address + * and say ltdc_reload(LTDC_SRCR_RELOAD_VBR) + */ + ltdc_reload(LTDC_SRCR_RELOAD_IMR); + + /* Enable foreground & background Layers */ + ltdc_layer_ctrl_enable(LTDC_LAYER_1, LTDC_LxCR_LAYER_ENABLE); + ltdc_layer_ctrl_enable(LTDC_LAYER_2, LTDC_LxCR_LAYER_ENABLE); + ltdc_reload(LTDC_SRCR_RELOAD_IMR); + + /* enable dithering to add artsy graphical artifacts */ + ltdc_ctrl_enable(LTDC_GCR_DITHER_ENABLE); + + + /* turn ltdc on, uh yeah! */ + ltdc_ctrl_enable(LTDC_GCR_LTDC_ENABLE); + + /* finally make both layers visible + */ + ltdc_set_constant_alpha(LTDC_LAYER_1, 255); + ltdc_set_constant_alpha(LTDC_LAYER_2, 255); + ltdc_reload(LTDC_SRCR_RELOAD_IMR); + + /* + * alpha is set by either color_keying, constant_alpha or + * layer blending (which probably also includes color_keying) + * according to the blending options selected above + * color keying is enabled only for layer 2 with the key + * ILI9341_LAYER2_COLOR_KEY + */ +} + diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/lcd_ili9341.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/lcd_ili9341.h new file mode 100644 index 00000000..c592c67f --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/lcd_ili9341.h @@ -0,0 +1,272 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Chuck McManis + * Copyright (C) 2014 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + +#ifndef LTDC_ILI9341_H +#define LTDC_ILI9341_H + +/** + * Includes + */ + +#include + +#include +#include +#include +#include + +#include "gfx_locm3.h" + +#include "sdram.h" + +#ifndef ILI9341_LAYER2_COLOR_KEY +#define ILI9341_LAYER2_COLOR_KEY 0x000C //0x01ad +#endif + +//Commands +#define ILI9341_RESET 0x01 +#define ILI9341_SLEEP_OUT 0x11 +#define ILI9341_GAMMA 0x26 +#define ILI9341_DISPLAY_OFF 0x28 +#define ILI9341_DISPLAY_ON 0x29 +#define ILI9341_COLUMN_ADDR 0x2A +#define ILI9341_PAGE_ADDR 0x2B +#define ILI9341_GRAM 0x2C +#define ILI9341_MAC 0x36 +#define ILI9341_PIXEL_FORMAT 0x3A +#define ILI9341_WDB 0x51 +#define ILI9341_WCD 0x53 +#define ILI9341_RGB_INTERFACE 0xB0 +#define ILI9341_FRC 0xB1 +#define ILI9341_BPC 0xB5 +#define ILI9341_DFC 0xB6 +#define ILI9341_POWER1 0xC0 +#define ILI9341_POWER2 0xC1 +#define ILI9341_VCOM1 0xC5 +#define ILI9341_VCOM2 0xC7 +#define ILI9341_POWERA 0xCB +#define ILI9341_POWERB 0xCF +#define ILI9341_PGAMMA 0xE0 +#define ILI9341_NGAMMA 0xE1 +#define ILI9341_DTCA 0xE8 +#define ILI9341_DTCB 0xEA +#define ILI9341_POWER_SEQ 0xED +#define ILI9341_3GAMMA_EN 0xF2 +#define ILI9341_INTERFACE 0xF6 +#define ILI9341_PRC 0xF7 + + + +#ifndef ILI9341_SPI +#define ILI9341_SPI SPI5 +#endif + +#ifndef ILI9341_CS_PIN +//This pin is used on STM32F429 discovery board +#define ILI9341_CS_CLK RCC_GPIOC +#define ILI9341_CS_PORT GPIOC +#define ILI9341_CS_PIN GPIO2 +#endif + +#ifndef ILI9341_WRX_PIN +//This pin is used on STM32F429 discovery board +#define ILI9341_WRX_CLK RCC_GPIOD +#define ILI9341_WRX_PORT GPIOD +#define ILI9341_WRX_PIN GPIO13 +#endif + +//Reset pin +#ifndef ILI9341_RST_PIN +//Reset pin +#define ILI9341_RST_CLK RCC_GPIOD +#define ILI9341_RST_PORT GPIOD +#define ILI9341_RST_PIN GPIO12 +#endif + +#define ILI9341_RST_SET() gpio_set (ILI9341_RST_PORT, ILI9341_RST_PIN) +#define ILI9341_RST_RESET() gpio_clear(ILI9341_RST_PORT, ILI9341_RST_PIN) +#define ILI9341_SPI_IS_SELECTED() (!gpio_get(ILI9341_CS_PORT, ILI9341_CS_PIN)) +#define ILI9341_SPI_DESELECT() gpio_set (ILI9341_CS_PORT, ILI9341_CS_PIN) +#define ILI9341_SPI_SELECT() gpio_clear(ILI9341_CS_PORT, ILI9341_CS_PIN) +#define ILI9341_WRX_SET() gpio_set (ILI9341_WRX_PORT, ILI9341_WRX_PIN) +#define ILI9341_WRX_RESET() gpio_clear(ILI9341_WRX_PORT, ILI9341_WRX_PIN) + + +/* LCD settings */ +#define ILI9341_WIDTH 240 +#define ILI9341_HEIGHT 320 + + +#define ILI9341_SURFACE_SIZE ((ILI9341_WIDTH*ILI9341_HEIGHT)*sizeof(uint16_t)) + + +/* double buffering (values other than 2 were not tested and make not too much sense..) */ +#define ILI9341_BUFFERS_PER_LAYER 2 + + + +typedef struct { + uint16_t width; + uint16_t height; + uint8_t current_layer; + uint8_t layer1_opacity; + uint8_t layer2_opacity; + uint8_t current_layer1_surface_idx; + uint8_t current_layer2_surface_idx; + uint16_t *layer1_surface_buffers[ILI9341_BUFFERS_PER_LAYER]; + uint16_t *layer2_surface_buffers[ILI9341_BUFFERS_PER_LAYER]; +} ili9341_options_t; + +extern ili9341_options_t ili9341_opts; +void ili9341_init(uint16_t *layer1_surface_buffers[], uint16_t *layer2_surface_buffers[]); +void ili9341_spi5_isr(void); + + +/* Wait for vertical synchronisation */ +static inline void ili9341_vsync(void); + +/* Flip the double_buffer */ +static inline void ili9341_flip_layer1_buffer(void); +static inline void ili9341_flip_layer2_buffer(void); + +/* Simple delay */ +static inline void ili9341_delay(volatile unsigned int delay); + +/* Select layer to draw on with gfxcm3 */ +static inline void ili9341_set_layer1(void); +static inline void ili9341_set_layer2(void); +static inline void ili9341_set_layer1_opacity(uint8_t opacity); +static inline void ili9341_set_layer2_opacity(uint8_t opacity); +static inline void ili9341_update_layer_opacity(void); + + + +/* this is what vsync would probably look like */ +static inline +void +ili9341_vsync() { + while (!ltdc_get_display_status(LTDC_CDSR_VSYNCS)); +} + +static inline +uint16_t* +ili9341_get_current_layer_buffer_address(void); + +static inline +uint16_t* +ili9341_get_current_layer_buffer_address() { + return __gfx_state.surface; +} + +/* double buffering feature (2 buffers for each layer makes 2*2) */ +static inline +void +ili9341_flip_layer1_buffer() { + ltdc_set_fbuffer_address( + LTDC_LAYER_1, + (uint32_t)ili9341_opts.layer1_surface_buffers[ili9341_opts.current_layer1_surface_idx] + ); + + ili9341_opts.current_layer1_surface_idx = (ili9341_opts.current_layer1_surface_idx + 1) % ILI9341_BUFFERS_PER_LAYER; + + /* vsync or so by the controller shadow register update command */ + //ltdc_reload(LTDC_SRCR_RELOAD_VBR); +} +static inline +void +ili9341_flip_layer2_buffer() { + ltdc_set_fbuffer_address( + LTDC_LAYER_2, + (uint32_t)ili9341_opts.layer2_surface_buffers[ili9341_opts.current_layer2_surface_idx] + ); + + ili9341_opts.current_layer2_surface_idx = (ili9341_opts.current_layer2_surface_idx + 1) % ILI9341_BUFFERS_PER_LAYER; + + /* vsync or so by the controller shadow register update command */ + //ltdc_reload(LTDC_SRCR_RELOAD_VBR); +} + + +/* draw_pixel and fill draw on layer1 after this is called */ +static inline +void +ili9341_set_layer1(void) { + __gfx_state.surface = ili9341_opts.layer1_surface_buffers[ili9341_opts.current_layer1_surface_idx]; + ili9341_opts.current_layer = 0; +} + +/* draw_pixel and fill draw on layer2 after this is called */ +static inline +void +ili9341_set_layer2(void) { + __gfx_state.surface = ili9341_opts.layer2_surface_buffers[ili9341_opts.current_layer2_surface_idx]; + ili9341_opts.current_layer = 1; +} + +/* set layer 1 alpha (to hide and stuff) */ +static inline +void +ili9341_set_layer1_opacity(uint8_t opacity) { + ili9341_opts.layer1_opacity = opacity; + ili9341_update_layer_opacity(); +} + +/* set layer 2 alpha (to hide and stuff) */ +static inline +void +ili9341_set_layer2_opacity(uint8_t opacity) { + ili9341_opts.layer2_opacity = opacity; + ili9341_update_layer_opacity(); +} + +/* + * set alpha and reload the shadow register after opacity update + * disables layer rendering if opacity is 0 (not really worth anything) + */ +static inline +void +ili9341_update_layer_opacity(void) { + if (ili9341_opts.layer1_opacity) + ltdc_layer_ctrl_enable(LTDC_LAYER_1, LTDC_LxCR_LAYER_ENABLE); + else + ltdc_layer_ctrl_disable(LTDC_LAYER_1, LTDC_LxCR_LAYER_ENABLE); + + if (ili9341_opts.layer2_opacity) + ltdc_layer_ctrl_enable(LTDC_LAYER_2, LTDC_LxCR_LAYER_ENABLE); + else + ltdc_layer_ctrl_disable(LTDC_LAYER_2, LTDC_LxCR_LAYER_ENABLE); + + + ltdc_set_constant_alpha(LTDC_LAYER_1, ili9341_opts.layer1_opacity); + ltdc_set_constant_alpha(LTDC_LAYER_2, ili9341_opts.layer2_opacity); + ltdc_reload(LTDC_SRCR_RELOAD_VBR); +} + + +/* a fancy delay with a volatile argument */ +static inline +void +ili9341_delay(volatile unsigned int delay) { + for (; delay != 0; delay--); +} + +#endif + diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/sdram.c b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/sdram.c new file mode 100644 index 00000000..26527df7 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/sdram.c @@ -0,0 +1,139 @@ +#include "sdram.h" +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Chuck McManis + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* + * This then is the initialization code extracted from the + * sdram example. + */ +#include +#include +#include +#include +#include "clock.h" + +/* + * This is just syntactic sugar but it helps, all of these + * GPIO pins get configured in exactly the same way. + */ +static struct { + uint32_t gpio; + uint16_t pins; +} sdram_pins[6] = { + {GPIOB, GPIO5 | GPIO6 }, + {GPIOC, GPIO0 }, + {GPIOD, GPIO0 | GPIO1 | GPIO8 | GPIO9 | GPIO10 | GPIO14 | GPIO15}, + {GPIOE, GPIO0 | GPIO1 | GPIO7 | GPIO8 | GPIO9 | GPIO10 | + GPIO11 | GPIO12 | GPIO13 | GPIO14 | GPIO15 }, + {GPIOF, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 | GPIO5 | GPIO11 | + GPIO12 | GPIO13 | GPIO14 | GPIO15 }, + {GPIOG, GPIO0 | GPIO1 | GPIO4 | GPIO5 | GPIO8 | GPIO15} +}; + +static struct sdram_timing timing = { + .trcd = 2, /* RCD Delay */ + .trp = 2, /* RP Delay */ + .twr = 2, /* Write Recovery Time */ + .trc = 7, /* Row Cycle Delay */ + .tras = 4, /* Self Refresh Time */ + .txsr = 7, /* Exit Self Refresh Time */ + .tmrd = 2, /* Load to Active Delay */ +}; + +/* + * Initialize the SD RAM controller. + */ +void +sdram_init(void) { + int i; + uint32_t cr_tmp, tr_tmp; /* control, timing registers */ + + /* + * First all the GPIO pins that end up as SDRAM pins + */ + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_GPIOD); + rcc_periph_clock_enable(RCC_GPIOE); + rcc_periph_clock_enable(RCC_GPIOF); + rcc_periph_clock_enable(RCC_GPIOG); + + for (i = 0; i < 6; i++) { + gpio_mode_setup(sdram_pins[i].gpio, + GPIO_MODE_AF, GPIO_PUPD_NONE, + sdram_pins[i].pins); + gpio_set_output_options(sdram_pins[i].gpio, GPIO_OTYPE_PP, + GPIO_OSPEED_50MHZ, sdram_pins[i].pins); + gpio_set_af(sdram_pins[i].gpio, GPIO_AF12, sdram_pins[i].pins); + } + + /* Enable the SDRAM Controller */ +#if 1 + rcc_periph_clock_enable(RCC_FSMC); +#else + rcc_peripheral_enable_clock(&RCC_AHB3ENR, RCC_AHB3ENR_FMCEN); +#endif + + /* Note the STM32F429-DISCO board has the ram attached to bank 2 */ + /* Timing parameters computed for a 168Mhz clock */ + /* These parameters are specific to the SDRAM chip on the board */ + + cr_tmp = FMC_SDCR_RPIPE_1CLK; + cr_tmp |= FMC_SDCR_SDCLK_2HCLK; + cr_tmp |= FMC_SDCR_CAS_3CYC; + cr_tmp |= FMC_SDCR_NB4; + cr_tmp |= FMC_SDCR_MWID_16b; + cr_tmp |= FMC_SDCR_NR_12; + cr_tmp |= FMC_SDCR_NC_8; + + /* We're programming BANK 2, but per the manual some of the parameters + * only work in CR1 and TR1 so we pull those off and put them in the + * right place. + */ + FMC_SDCR1 |= (cr_tmp & FMC_SDCR_DNC_MASK); + FMC_SDCR2 = cr_tmp; + + tr_tmp = sdram_timing(&timing); + FMC_SDTR1 |= (tr_tmp & FMC_SDTR_DNC_MASK); + FMC_SDTR2 = tr_tmp; + + /* Now start up the Controller per the manual + * - Clock config enable + * - PALL state + * - set auto refresh + * - Load the Mode Register + */ + sdram_command(SDRAM_BANK2, SDRAM_CLK_CONF, 1, 0); + milli_sleep(1); /* sleep at least 100uS */ + sdram_command(SDRAM_BANK2, SDRAM_PALL, 1, 0); + sdram_command(SDRAM_BANK2, SDRAM_AUTO_REFRESH, 4, 0); + tr_tmp = SDRAM_MODE_BURST_LENGTH_2 | + SDRAM_MODE_BURST_TYPE_SEQUENTIAL | + SDRAM_MODE_CAS_LATENCY_3 | + SDRAM_MODE_OPERATING_MODE_STANDARD | + SDRAM_MODE_WRITEBURST_MODE_SINGLE; + sdram_command(SDRAM_BANK2, SDRAM_LOAD_MODE, 1, tr_tmp); + + /* + * set the refresh counter to insure we kick off an + * auto refresh often enough to prevent data loss. + */ + FMC_SDRTR = 683; + /* and Poof! a 8 megabytes of ram shows up in the address space */ +} diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/sdram.h b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/sdram.h new file mode 100644 index 00000000..157f30af --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/sdram.h @@ -0,0 +1,32 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Chuck McManis + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef __SDRAM_H +#define __SDRAM_H + +#define SDRAM_BASE_ADDRESS ((uint8_t *)(0xd0000000)) + +/* Initialize the SDRAM chip on the board */ +void sdram_init(void); + +#ifndef NULL +#define NULL (void *)(0) +#endif + +#endif diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/Create_Font.py b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/Create_Font.py new file mode 100644 index 00000000..6f80d79a --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/Create_Font.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# This file is part of the libopencm3 project. +# +# Copyright (C) 2016 Oliver Meier +# +# This library is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see . +# + + +# Generate a sfl file with FontBuilder (output->description->simple) +# then run this script over it to build a c file + + +from sys import argv,stdout +from os.path import isfile, dirname, basename, splitext, join +from PIL import Image, ImageFont, ImageDraw +import codecs + +print len(argv),argv + +if len(argv)<3 or len(argv)>4 or (len(argv)==4 and not isfile(argv[3])) : + print "usage: ./Create_Font.py font.ttf fontsize [charsetfile-utf8.txt]" + exit(0) + +fontfile = argv[1] +fontsize = None +try : + fontsize = int(argv[2]) +except : + print "Fontsize is not a number!" + exit(0) + +if len(argv)==4 : + charsetfile = argv[3] +else : + charsetfile = join(dirname(argv[0]),"default_charset.txt") + + +#fontfile = "Tamsyn5x9r.pcf" +#fontfile = "Tamsyn5x9b.pcf" +#fontfile = "/usr/share/fonts/liberation/LiberationMono-Regular.ttf" +#fontfile = "/usr/share/fonts/liberation/LiberationMono-Bold.ttf" +#fontfile = "/usr/share/fonts/dejavu/DejaVuSansMono.ttf" +#fontfile = "/usr/share/fonts/dejavu/DejaVuSansMono-Bold.ttf" +#fontfile = "/usr/share/fonts/gnu-free/FreeMono.ttf" +#fontsize = 9 +datasize = 32 + +charset = codecs.open(charsetfile,'r','utf-8').read().replace('\n','').replace('\r','') +# sort charset and remove duplicates +charset = ''.join(sorted(set(charset), key=charset.index)) +font = ImageFont.truetype(fontfile,size=fontsize) + +filtered_charset = u"" +for c in charset : + if c<>u' ' : + m,o = font.getmask2(c, mode="1") + if m.getbbox()==None : + print "Dropping:",c.encode('utf-8') + continue + filtered_charset+=c +charset = filtered_charset + + + +#render all the text (needed to determine img size) +dummy_img,offset = font.getmask2(charset, mode="1") + +ascent,descent = font.getmetrics() +lineheight = dummy_img.size[1]+offset[1] +charwidth = font.getsize("MMM")[0]-font.getsize("MM")[0] +totalwidth = charwidth*len(charset) +charset_imgsize = (totalwidth,lineheight) + + + +charset_image = Image.new(mode="1", size=charset_imgsize) +d=ImageDraw.Draw(charset_image) +d.rectangle(((0,0),charset_imgsize), fill=0, outline=None) +offx=0 + + +fontname = splitext(basename(fontfile))[0]+"_"+str(fontsize) +fontname = fontname.replace("-","_") + +print "Creating font", fontname + + +chars_table_name = "chars_"+fontname +data_table_name = "chars_data_"+fontname +chars_table = "static const char_t "+chars_table_name+"[] = {\n\t" +data_table = "static const uint"+str(datasize)+"_t "+data_table_name+"[] = {" +data_table_offset = 0; v=0; i=0; fmt = "0x%%0%dx, "%(datasize/8*2) +for c in charset : + x1 = y1 = x2 = y2 = 0 + bbox = (0,0,0,0) + if c<>u' ' : + m,o = font.getmask2(c, mode="1") + bbox = m.getbbox() + x1 = (charwidth - bbox[2])/2 + y1 = (o[1]-offset[1] + bbox[1]) + x2 = x1 + bbox[2]-bbox[0] + y2 = y1 + bbox[3]-bbox[1] + + + stdout.write((u"%s"%c).encode('utf-8')) + #print "",x1,x2,y1,y2 + + # dummy image + if c<>u' ' : + d.draw.draw_bitmap((offx+x1,y1),m.crop(bbox),255) + offx += charwidth + + # finish last data_table entry + if v<>0 : + data_table+= fmt %v + data_table_offset += 1 + #data_table+= "\n\t" + + # fill data in chars table + chars_table+= """{ + .utf8_value = %d, + .bbox = { % 2d,% 2d,% 2d,% 2d }, + .data = &%s[%d] + },""" %( + ord(c), + x1,y1,x2,y2, + data_table_name,data_table_offset + ) + + # fill data in chars data table + data_table+= "\n\t// '%s'\n\t" %c + + i=0; v=0; lc = 0 + for y in range(bbox[1],bbox[3]) : + for x in range(bbox[0],bbox[2]) : + v |= (m.getpixel((x,y))==255) << i + i+=1 + if i==datasize : + data_table+= fmt %v + i=0; v=0 + data_table_offset += 1 + lc+=1 + if lc==8 : + data_table+= "\n\t" + lc=0 + +if v<>0 : + data_table+= fmt %v + i=0; v=0 + data_table_offset += 1 + data_table+= "\n\t" + +data_table = data_table[:-3] + "\n};" + +chars_table = chars_table[:-1] + "\n};" + + + +charset_image.save(fontname+".pbm") + + +fnu = fontname.upper() + +fontsize_definition = "%s %d"%(fnu,fontsize) + +header_filename = "%s.h"%fontname +header_file = """ +#ifndef _%s_ +#define _%s_ + +#include +#include "fonts.h" + +extern const font_t font_%s; + +#endif +""" %( + fnu,fnu, + fontname +) + +c_filename = "%s.c"%fontname +c_file = """ +#include "%s" + +%s + +%s + +const font_t font_%s = { + .fontsize = %d, + .lineheight = %d, + .ascent = %d, + .descent = %d, + .charwidth = %d, + .char_count = %d, + .chars = %s, + .chars_data = %s, +}; + +""" %( + header_filename, + data_table, + chars_table, + fontname, fontsize, lineheight, ascent, descent, charwidth, + len(charset),chars_table_name, data_table_name, +) + + +open(header_filename,'w').write(header_file.encode('utf-8')) +open(c_filename,'w').write(c_file.encode('utf-8')) + +print "\ndone." diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/ImageToRGB565_array.py b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/ImageToRGB565_array.py new file mode 100644 index 00000000..b55f4f5a --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/ImageToRGB565_array.py @@ -0,0 +1,80 @@ +# This file is part of the libopencm3 project. +# +# Copyright (C) 2016 Oliver Meier +# +# This library is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see . +# + +from PIL import Image +from sys import argv +from os.path import isfile, splitext +from math import floor + +if (not(len(argv)==2 or len(argv)==3)) or not isfile(argv[1]) : + print "usage Image...py filename.png width_in_px" + exit(0) + +infile = argv[1] + +basename = splitext(infile)[0] +outfile = basename+"_RGB565.h" +if isfile(outfile) : + print outfile , "already exists" + exit(0) + + +# die here if not an image +try : + img = Image.open(infile) +except IOError, ex : + print "Opening image failed" + print "\tPIL(IOError) :",ex.message + exit(0) + +if len(argv)==3 : + try : + width = int(argv[2]) + if img.size[0]<>width : + new_size = (width,int(img.size[1]*width/img.size[0])) + print "resizing image from",img.size,"to",new_size + img = img.resize(new_size,Image.ANTIALIAS) + img.show(title="Resized image") + except : + print "Invalid width" + print "usage Image...py filename.png width_in_px" + exit(0) + +print "image size is",img.size +width = img.size[0] +data = img.tobytes(encoder_name='raw') + +pixels_per_line = 16 +of = open(outfile,'w') +of.write("#include \n") +of.write("#define %s_WIDTH %d\n" %(basename.upper(), width)) +of.write("#define %s_HEIGHT %d\n" %(basename.upper(), len(data)/4/width)) +of.write("const uint16_t %s[] = {" %(basename)) +i = 0 +while i>3); i+=1 + g = int(ord(data[i])>>2); i+=1 + b = int(ord(data[i])>>3); i+=1 + i+=1 # skip alpha + i16 = (r<<11) | (g<<5) | b + of.write("0x%04x" %(i16)) +of.write("\n};") +of.close() diff --git a/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/default_charset.txt b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/default_charset.txt new file mode 100644 index 00000000..54fc1dde --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/lcd-ltdc/tools/default_charset.txt @@ -0,0 +1 @@ + !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~¡╜£╧╛▌⌡∙╕ª«¬≡⌐ε°±²ⁿ∩µ⌠·≈√º»¼½≤¿╖╡╢╟ÄÅÆÇ╘É╥╙▐╓╫╪╤ÑπαΓσÖ₧¥δΘΩÜφΦßàáâ╞äåæçèéêëìíîï╨ñòóôΣö÷¢ùúûü∞τÿ diff --git a/libopencm3 b/libopencm3 index 28592a7c..0cb1db09 160000 --- a/libopencm3 +++ b/libopencm3 @@ -1 +1 @@ -Subproject commit 28592a7ca38cdea18028df1b58df38f30d9d14d2 +Subproject commit 0cb1db09674cdf1413da696462f161142a98ec3b