diff --git a/lib/font.c b/lib/font.c deleted file mode 100644 index 1f93ebd..0000000 --- a/lib/font.c +++ /dev/null @@ -1,116 +0,0 @@ -/** - * ---------------------------------------------------------------+ - * @desc FONTs - * ---------------------------------------------------------------+ - * Copyright (C) 2020 Marian Hrinko. - * Written by Marian Hrinko (mato.hrinko@gmail.com) - * - * @author Marian Hrinko - * @datum 07.10.2020 - * @file font.c - * @tested AVR Atmega16, Atmega8, Atmega328 - * - * @depend - * ---------------------------------------------------------------+ - */ -#include "font.h" - -/** @array Charset */ -const uint8_t FONTS[][CHARS_COLS_LENGTH] PROGMEM = { - { 0x00, 0x00, 0x00, 0x00, 0x00 }, // 20 space - { 0x81, 0x81, 0x18, 0x81, 0x81 }, // 21 ! - { 0x00, 0x07, 0x00, 0x07, 0x00 }, // 22 " - { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // 23 # - { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // 24 $ - { 0x23, 0x13, 0x08, 0x64, 0x62 }, // 25 % - { 0x36, 0x49, 0x55, 0x22, 0x50 }, // 26 & - { 0x00, 0x05, 0x03, 0x00, 0x00 }, // 27 ' - { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // 28 ( - { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // 29 ) - { 0x14, 0x08, 0x3e, 0x08, 0x14 }, // 2a * - { 0x08, 0x08, 0x3e, 0x08, 0x08 }, // 2b + - { 0x00, 0x50, 0x30, 0x00, 0x00 }, // 2c , - { 0x08, 0x08, 0x08, 0x08, 0x08 }, // 2d - - { 0x00, 0x60, 0x60, 0x00, 0x00 }, // 2e . - { 0x20, 0x10, 0x08, 0x04, 0x02 }, // 2f / - { 0x3e, 0x51, 0x49, 0x45, 0x3e }, // 30 0 - { 0x00, 0x42, 0x7f, 0x40, 0x00 }, // 31 1 - { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 32 2 - { 0x21, 0x41, 0x45, 0x4b, 0x31 }, // 33 3 - { 0x18, 0x14, 0x12, 0x7f, 0x10 }, // 34 4 - { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 35 5 - { 0x3c, 0x4a, 0x49, 0x49, 0x30 }, // 36 6 - { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 37 7 - { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 38 8 - { 0x06, 0x49, 0x49, 0x29, 0x1e }, // 39 9 - { 0x00, 0x36, 0x36, 0x00, 0x00 }, // 3a : - { 0x00, 0x56, 0x36, 0x00, 0x00 }, // 3b ; - { 0x08, 0x14, 0x22, 0x41, 0x00 }, // 3c < - { 0x14, 0x14, 0x14, 0x14, 0x14 }, // 3d = - { 0x00, 0x41, 0x22, 0x14, 0x08 }, // 3e > - { 0x02, 0x01, 0x51, 0x09, 0x06 }, // 3f ? - { 0x32, 0x49, 0x79, 0x41, 0x3e }, // 40 @ - { 0x7e, 0x11, 0x11, 0x11, 0x7e }, // 41 A - { 0x7f, 0x49, 0x49, 0x49, 0x36 }, // 42 B - { 0x3e, 0x41, 0x41, 0x41, 0x22 }, // 43 C - { 0x7f, 0x41, 0x41, 0x22, 0x1c }, // 44 D - { 0x7f, 0x49, 0x49, 0x49, 0x41 }, // 45 E - { 0x7f, 0x09, 0x09, 0x09, 0x01 }, // 46 F - { 0x3e, 0x41, 0x49, 0x49, 0x7a }, // 47 G - { 0x7f, 0x08, 0x08, 0x08, 0x7f }, // 48 H - { 0x00, 0x41, 0x7f, 0x41, 0x00 }, // 49 I - { 0x20, 0x40, 0x41, 0x3f, 0x01 }, // 4a J - { 0x7f, 0x08, 0x14, 0x22, 0x41 }, // 4b K - { 0x7f, 0x40, 0x40, 0x40, 0x40 }, // 4c L - { 0x7f, 0x02, 0x0c, 0x02, 0x7f }, // 4d M - { 0x7f, 0x04, 0x08, 0x10, 0x7f }, // 4e N - { 0x3e, 0x41, 0x41, 0x41, 0x3e }, // 4f O - { 0x7f, 0x09, 0x09, 0x09, 0x06 }, // 50 P - { 0x3e, 0x41, 0x51, 0x21, 0x5e }, // 51 Q - { 0x7f, 0x09, 0x19, 0x29, 0x46 }, // 52 R - { 0x46, 0x49, 0x49, 0x49, 0x31 }, // 53 S - { 0x01, 0x01, 0x7f, 0x01, 0x01 }, // 54 T - { 0x3f, 0x40, 0x40, 0x40, 0x3f }, // 55 U - { 0x1f, 0x20, 0x40, 0x20, 0x1f }, // 56 V - { 0x3f, 0x40, 0x38, 0x40, 0x3f }, // 57 W - { 0x63, 0x14, 0x08, 0x14, 0x63 }, // 58 X - { 0x07, 0x08, 0x70, 0x08, 0x07 }, // 59 Y - { 0x61, 0x51, 0x49, 0x45, 0x43 }, // 5a Z - { 0x00, 0x7f, 0x41, 0x41, 0x00 }, // 5b [ - { 0x02, 0x04, 0x08, 0x10, 0x20 }, // 5c backslash - { 0x00, 0x41, 0x41, 0x7f, 0x00 }, // 5d ] - { 0x04, 0x02, 0x01, 0x02, 0x04 }, // 5e ^ - { 0x40, 0x40, 0x40, 0x40, 0x40 }, // 5f _ - { 0x00, 0x01, 0x02, 0x04, 0x00 }, // 60 ` - { 0x20, 0x54, 0x54, 0x54, 0x78 }, // 61 a - { 0x7f, 0x48, 0x44, 0x44, 0x38 }, // 62 b - { 0x38, 0x44, 0x44, 0x44, 0x20 }, // 63 c - { 0x38, 0x44, 0x44, 0x48, 0x7f }, // 64 d - { 0x38, 0x54, 0x54, 0x54, 0x18 }, // 65 e - { 0x08, 0x7e, 0x09, 0x01, 0x02 }, // 66 f - { 0x0c, 0x52, 0x52, 0x52, 0x3e }, // 67 g - { 0x7f, 0x08, 0x04, 0x04, 0x78 }, // 68 h - { 0x00, 0x44, 0x7d, 0x40, 0x00 }, // 69 i - { 0x20, 0x40, 0x44, 0x3d, 0x00 }, // 6a j - { 0x7f, 0x10, 0x28, 0x44, 0x00 }, // 6b k - { 0x00, 0x41, 0x7f, 0x40, 0x00 }, // 6c l - { 0x7c, 0x04, 0x18, 0x04, 0x78 }, // 6d m - { 0x7c, 0x08, 0x04, 0x04, 0x78 }, // 6e n - { 0x38, 0x44, 0x44, 0x44, 0x38 }, // 6f o - { 0x7c, 0x14, 0x14, 0x14, 0x08 }, // 70 p - { 0x08, 0x14, 0x14, 0x14, 0x7c }, // 71 q - { 0x7c, 0x08, 0x04, 0x04, 0x08 }, // 72 r - { 0x48, 0x54, 0x54, 0x54, 0x20 }, // 73 s - { 0x04, 0x3f, 0x44, 0x40, 0x20 }, // 74 t - { 0x3c, 0x40, 0x40, 0x20, 0x7c }, // 75 u - { 0x1c, 0x20, 0x40, 0x20, 0x1c }, // 76 v - { 0x3c, 0x40, 0x30, 0x40, 0x3c }, // 77 w - { 0x44, 0x28, 0x10, 0x28, 0x44 }, // 78 x - { 0x0c, 0x50, 0x50, 0x50, 0x3c }, // 79 y - { 0x44, 0x64, 0x54, 0x4c, 0x44 }, // 7a z - { 0x00, 0x08, 0x36, 0x41, 0x00 }, // 7b { - { 0x00, 0x00, 0x7f, 0x00, 0x00 }, // 7c | - { 0x00, 0x41, 0x36, 0x08, 0x00 }, // 7d } - { 0x10, 0x08, 0x08, 0x10, 0x08 }, // 7e ~ - { 0x00, 0x00, 0x00, 0x00, 0x00 } // 7f -}; diff --git a/lib/font.h b/lib/font.h index 0130b8e..3ecaccb 100644 --- a/lib/font.h +++ b/lib/font.h @@ -22,7 +22,105 @@ // ----------------------------------- // number of columns for chars #define CHARS_COLS_LENGTH 5 + // @const Characters - extern const uint8_t FONTS[][CHARS_COLS_LENGTH]; + static const uint8_t FONTS[][CHARS_COLS_LENGTH] PROGMEM = { + { 0x00, 0x00, 0x00, 0x00, 0x00 }, // 20 space + { 0x81, 0x81, 0x18, 0x81, 0x81 }, // 21 ! + { 0x00, 0x07, 0x00, 0x07, 0x00 }, // 22 " + { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // 23 # + { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // 24 $ + { 0x23, 0x13, 0x08, 0x64, 0x62 }, // 25 % + { 0x36, 0x49, 0x55, 0x22, 0x50 }, // 26 & + { 0x00, 0x05, 0x03, 0x00, 0x00 }, // 27 ' + { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // 28 ( + { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // 29 ) + { 0x14, 0x08, 0x3e, 0x08, 0x14 }, // 2a * + { 0x08, 0x08, 0x3e, 0x08, 0x08 }, // 2b + + { 0x00, 0x50, 0x30, 0x00, 0x00 }, // 2c , + { 0x08, 0x08, 0x08, 0x08, 0x08 }, // 2d - + { 0x00, 0x60, 0x60, 0x00, 0x00 }, // 2e . + { 0x20, 0x10, 0x08, 0x04, 0x02 }, // 2f / + { 0x3e, 0x51, 0x49, 0x45, 0x3e }, // 30 0 + { 0x00, 0x42, 0x7f, 0x40, 0x00 }, // 31 1 + { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 32 2 + { 0x21, 0x41, 0x45, 0x4b, 0x31 }, // 33 3 + { 0x18, 0x14, 0x12, 0x7f, 0x10 }, // 34 4 + { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 35 5 + { 0x3c, 0x4a, 0x49, 0x49, 0x30 }, // 36 6 + { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 37 7 + { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 38 8 + { 0x06, 0x49, 0x49, 0x29, 0x1e }, // 39 9 + { 0x00, 0x36, 0x36, 0x00, 0x00 }, // 3a : + { 0x00, 0x56, 0x36, 0x00, 0x00 }, // 3b ; + { 0x08, 0x14, 0x22, 0x41, 0x00 }, // 3c < + { 0x14, 0x14, 0x14, 0x14, 0x14 }, // 3d = + { 0x00, 0x41, 0x22, 0x14, 0x08 }, // 3e > + { 0x02, 0x01, 0x51, 0x09, 0x06 }, // 3f ? + { 0x32, 0x49, 0x79, 0x41, 0x3e }, // 40 @ + { 0x7e, 0x11, 0x11, 0x11, 0x7e }, // 41 A + { 0x7f, 0x49, 0x49, 0x49, 0x36 }, // 42 B + { 0x3e, 0x41, 0x41, 0x41, 0x22 }, // 43 C + { 0x7f, 0x41, 0x41, 0x22, 0x1c }, // 44 D + { 0x7f, 0x49, 0x49, 0x49, 0x41 }, // 45 E + { 0x7f, 0x09, 0x09, 0x09, 0x01 }, // 46 F + { 0x3e, 0x41, 0x49, 0x49, 0x7a }, // 47 G + { 0x7f, 0x08, 0x08, 0x08, 0x7f }, // 48 H + { 0x00, 0x41, 0x7f, 0x41, 0x00 }, // 49 I + { 0x20, 0x40, 0x41, 0x3f, 0x01 }, // 4a J + { 0x7f, 0x08, 0x14, 0x22, 0x41 }, // 4b K + { 0x7f, 0x40, 0x40, 0x40, 0x40 }, // 4c L + { 0x7f, 0x02, 0x0c, 0x02, 0x7f }, // 4d M + { 0x7f, 0x04, 0x08, 0x10, 0x7f }, // 4e N + { 0x3e, 0x41, 0x41, 0x41, 0x3e }, // 4f O + { 0x7f, 0x09, 0x09, 0x09, 0x06 }, // 50 P + { 0x3e, 0x41, 0x51, 0x21, 0x5e }, // 51 Q + { 0x7f, 0x09, 0x19, 0x29, 0x46 }, // 52 R + { 0x46, 0x49, 0x49, 0x49, 0x31 }, // 53 S + { 0x01, 0x01, 0x7f, 0x01, 0x01 }, // 54 T + { 0x3f, 0x40, 0x40, 0x40, 0x3f }, // 55 U + { 0x1f, 0x20, 0x40, 0x20, 0x1f }, // 56 V + { 0x3f, 0x40, 0x38, 0x40, 0x3f }, // 57 W + { 0x63, 0x14, 0x08, 0x14, 0x63 }, // 58 X + { 0x07, 0x08, 0x70, 0x08, 0x07 }, // 59 Y + { 0x61, 0x51, 0x49, 0x45, 0x43 }, // 5a Z + { 0x00, 0x7f, 0x41, 0x41, 0x00 }, // 5b [ + { 0x02, 0x04, 0x08, 0x10, 0x20 }, // 5c backslash + { 0x00, 0x41, 0x41, 0x7f, 0x00 }, // 5d ] + { 0x04, 0x02, 0x01, 0x02, 0x04 }, // 5e ^ + { 0x40, 0x40, 0x40, 0x40, 0x40 }, // 5f _ + { 0x00, 0x01, 0x02, 0x04, 0x00 }, // 60 ` + { 0x20, 0x54, 0x54, 0x54, 0x78 }, // 61 a + { 0x7f, 0x48, 0x44, 0x44, 0x38 }, // 62 b + { 0x38, 0x44, 0x44, 0x44, 0x20 }, // 63 c + { 0x38, 0x44, 0x44, 0x48, 0x7f }, // 64 d + { 0x38, 0x54, 0x54, 0x54, 0x18 }, // 65 e + { 0x08, 0x7e, 0x09, 0x01, 0x02 }, // 66 f + { 0x0c, 0x52, 0x52, 0x52, 0x3e }, // 67 g + { 0x7f, 0x08, 0x04, 0x04, 0x78 }, // 68 h + { 0x00, 0x44, 0x7d, 0x40, 0x00 }, // 69 i + { 0x20, 0x40, 0x44, 0x3d, 0x00 }, // 6a j + { 0x7f, 0x10, 0x28, 0x44, 0x00 }, // 6b k + { 0x00, 0x41, 0x7f, 0x40, 0x00 }, // 6c l + { 0x7c, 0x04, 0x18, 0x04, 0x78 }, // 6d m + { 0x7c, 0x08, 0x04, 0x04, 0x78 }, // 6e n + { 0x38, 0x44, 0x44, 0x44, 0x38 }, // 6f o + { 0x7c, 0x14, 0x14, 0x14, 0x08 }, // 70 p + { 0x08, 0x14, 0x14, 0x14, 0x7c }, // 71 q + { 0x7c, 0x08, 0x04, 0x04, 0x08 }, // 72 r + { 0x48, 0x54, 0x54, 0x54, 0x20 }, // 73 s + { 0x04, 0x3f, 0x44, 0x40, 0x20 }, // 74 t + { 0x3c, 0x40, 0x40, 0x20, 0x7c }, // 75 u + { 0x1c, 0x20, 0x40, 0x20, 0x1c }, // 76 v + { 0x3c, 0x40, 0x30, 0x40, 0x3c }, // 77 w + { 0x44, 0x28, 0x10, 0x28, 0x44 }, // 78 x + { 0x0c, 0x50, 0x50, 0x50, 0x3c }, // 79 y + { 0x44, 0x64, 0x54, 0x4c, 0x44 }, // 7a z + { 0x00, 0x08, 0x36, 0x41, 0x00 }, // 7b { + { 0x00, 0x00, 0x7f, 0x00, 0x00 }, // 7c | + { 0x00, 0x41, 0x36, 0x08, 0x00 }, // 7d } + { 0x10, 0x08, 0x08, 0x10, 0x08 }, // 7e ~ + { 0x00, 0x00, 0x00, 0x00, 0x00 } // 7f + }; #endif diff --git a/lib/ssd1306.c b/lib/ssd1306.c index eaa4e49..d8e47b3 100644 --- a/lib/ssd1306.c +++ b/lib/ssd1306.c @@ -1,26 +1,27 @@ -/** - * --------------------------------------------------------------------------------------+ +/** + * --------------------------------------------------------------------------------------+ * @desc SSD1306 OLED Driver - * --------------------------------------------------------------------------------------+ + * --------------------------------------------------------------------------------------+ * Copyright (C) 2020 Marian Hrinko. * Written by Marian Hrinko (mato.hrinko@gmail.com) * * @author Marian Hrinko - * @datum 06.10.2020 - * @update 24.11.2022 + * @date 06.10.2020 + * @update 06.12.2022 * @file ssd1306.c - * @version 3.0 + * @version 2.0.0 * @tested AVR Atmega328p * - * @depend font.h, twi.h - * --------------------------------------------------------------------------------------+ - * @descr Version 1.0 -> applicable for 1 display - * Version 2.0 -> rebuild to 'cacheMemLcd' array - * Version 3.0 -> remove 'cacheMemLcd' approach - * --------------------------------------------------------------------------------------+ + * @depend ssd1306.h + * --------------------------------------------------------------------------------------+ + * @descr Version 1.0.0 -> applicable for 1 display + * Version 2.0.0 -> rebuild to 'cacheMemLcd' array + * Version 3.0.0 -> simplified alphanumeric version + * --------------------------------------------------------------------------------------+ * @usage Basic Setup for OLED Display */ +// @includes #include "ssd1306.h" // +---------------------------+ @@ -102,83 +103,106 @@ const uint8_t INIT_SSD1306[] PROGMEM = { 18, // number of initializers 0, SSD1306_DISPLAY_OFF, // 0xAE = Set Display OFF - 1, SSD1306_SET_MUX_RATIO, 0x3F, // 0xA8 + 1, SSD1306_SET_MUX_RATIO, 63, // 0xA8 - 64MUX for 128 x 64 version + // - 32MUX for 128 x 32 version 1, SSD1306_MEMORY_ADDR_MODE, 0x00, // 0x20 = Set Memory Addressing Mode // 0x00 - Horizontal Addressing Mode // 0x01 - Vertical Addressing Mode // 0x02 - Page Addressing Mode (RESET) - 2, SSD1306_SET_COLUMN_ADDR, START_COLUMN_ADDR, END_COLUMN_ADDR, // 0x21 = Set Column Address - 2, SSD1306_SET_PAGE_ADDR, START_PAGE_ADDR, END_PAGE_ADDR, // 0x22 = Set Page Address + 2, SSD1306_SET_COLUMN_ADDR, START_COLUMN_ADDR, END_COLUMN_ADDR, // 0x21 = Set Column Address, 0 - 127 + 2, SSD1306_SET_PAGE_ADDR, START_PAGE_ADDR, END_PAGE_ADDR, // 0x22 = Set Page Address, 0 - 7 0, SSD1306_SET_START_LINE, // 0x40 1, SSD1306_DISPLAY_OFFSET, 0x00, // 0xD3 0, SSD1306_SEG_REMAP_OP, // 0xA0 / remap 0xA1 0, SSD1306_COM_SCAN_DIR_OP, // 0xC0 / remap 0xC8 - 1, SSD1306_COM_PIN_CONF, 0x12, // 0xDA - 1, SSD1306_SET_CONTRAST, 0x7F, // 0x81 + 1, SSD1306_COM_PIN_CONF, 0x12, // 0xDA, 0x12 - Disable COM Left/Right remap, Alternative COM pin configuration + // 0x12 - for 128 x 64 version + // 0x02 - for 128 x 32 version + 1, SSD1306_SET_CONTRAST, 0x7F, // 0x81, 0x7F - reset value (max 0xFF) 0, SSD1306_DIS_ENT_DISP_ON, // 0xA4 0, SSD1306_DIS_NORMAL, // 0xA6 - 1, SSD1306_SET_OSC_FREQ, 0x80, // 0xD5 - 1, SSD1306_SET_PRECHARGE, 0xc2, // 0xD9, 1st Period = higher value less blinking + 1, SSD1306_SET_OSC_FREQ, 0x80, // 0xD5, 0x80 => D=1; DCLK = Fosc / D <=> DCLK = Fosc + 1, SSD1306_SET_PRECHARGE, 0xc2, // 0xD9, higher value less blinking + // 0xC2, 1st phase = 2 DCLK, 2nd phase = 13 DCLK 1, SSD1306_VCOM_DESELECT, 0x20, // Set V COMH Deselect, reset value 0x22 = 0,77xUcc - 1, SSD1306_SET_CHAR_REG, 0x14, // 0x8D + 1, SSD1306_SET_CHAR_REG, 0x14, // 0x8D, Enable charge pump during display on 0, SSD1306_DISPLAY_ON // 0xAF = Set Display ON }; -unsigned short int _indexCol = START_COLUMN_ADDR; // @var global - cache index column -unsigned short int _indexPage = START_PAGE_ADDR; // @var global - cache index page +// @var array Chache memory Lcd 8 * 128 = 1024 +static char cacheMemLcd[CACHE_SIZE_MEM]; /** * @desc SSD1306 Init * - * @param void + * @param uint8_t address * * @return uint8_t */ -uint8_t SSD1306_Init (void) +uint8_t SSD1306_Init (uint8_t address) { - const uint8_t *commands = INIT_SSD1306; // variables - unsigned short int no_of_commands = pgm_read_byte(commands++); // number of commands - uint8_t no_of_arguments; // number od arguments - uint8_t command; // command - uint8_t status = INIT_STATUS; // TWI init status 0xFF + // variables + const uint8_t *commands = INIT_SSD1306; + // number of commands + unsigned short int no_of_commands = pgm_read_byte(commands++); + // argument + uint8_t no_of_arguments; + // command + uint8_t command; + // init status + uint8_t status = INIT_STATUS; - // TWI INIT + // TWI: Init // ------------------------------------------------------------------------------------- TWI_Init (); - // TWI Start & SLAW + // TWI: start & SLAW // ------------------------------------------------------------------------------------- - status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW - if (SSD1306_SUCCESS != status) { // check status - return status; // error + status = SSD1306_Send_StartAndSLAW (address); + // request - start TWI + if (SSD1306_SUCCESS != status) { + // error + return status; } - // MAIN LOOP + + // loop through commands + while (no_of_commands) { + + // number of arguments + no_of_arguments = pgm_read_byte (commands++); + // command + command = pgm_read_byte (commands++); + + // send command // ------------------------------------------------------------------------------------- - while (no_of_commands) { // commands loop - no_of_arguments = pgm_read_byte (commands++); // number of arguments - command = pgm_read_byte (commands++); // command - // SEND COMMAND - // ----------------------------------------------------------------------------------- - status = SSD1306_Send_Command (command); // send command - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // SEND ARGUMENTS - // ----------------------------------------------------------------------------------- - while (no_of_arguments--) { - status = SSD1306_Send_Command (pgm_read_byte(commands++)); // send argument - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } + status = SSD1306_Send_Command (command); + // request - start TWI + if (SSD1306_SUCCESS != status) { + // error + return status; } - no_of_commands--; // next command + // send arguments + // ------------------------------------------------------------------------------------- + while (no_of_arguments--) { + // send command + status = SSD1306_Send_Command (pgm_read_byte(commands++)); + // request - start TWI + if (SSD1306_SUCCESS != status) { + // error + return status; + } + } + // decrement + no_of_commands--; } - // TWI STOP + + // TWI: Stop // ------------------------------------------------------------------------------------- TWI_Stop (); - return SSD1306_SUCCESS; // success + // success + return SSD1306_SUCCESS; } /** @@ -190,22 +214,29 @@ uint8_t SSD1306_Init (void) */ uint8_t SSD1306_Send_StartAndSLAW (uint8_t address) { - uint8_t status = INIT_STATUS; // TWI init status 0xFF + // init status + uint8_t status = INIT_STATUS; - // TWI START + // TWI: start // ------------------------------------------------------------------------------------- - status = TWI_MT_Start (); // start - if (SSD1306_SUCCESS != status) { // check status - return status; // error + status = TWI_MT_Start (); + // request - start TWI + if (SSD1306_SUCCESS != status) { + // error + return status; } - // TWI start & SLAW + + // TWI: send SLAW // ------------------------------------------------------------------------------------- - status = TWI_MT_Send_SLAW (address); // start & SLAW - if (SSD1306_SUCCESS != status) { // check status - return status; // error + status = TWI_MT_Send_SLAW (address); + // request - send SLAW + if (SSD1306_SUCCESS != status) { + // error + return status; } - - return SSD1306_SUCCESS; // success + + // success + return SSD1306_SUCCESS; } /** @@ -217,76 +248,150 @@ uint8_t SSD1306_Send_StartAndSLAW (uint8_t address) */ uint8_t SSD1306_Send_Command (uint8_t command) { - uint8_t status = INIT_STATUS; // TWI init status 0xFF + // init status + uint8_t status = INIT_STATUS; - // TWI send control byte - // ------------------------------------------------------------------------------------- - status = TWI_MT_Send_Data (SSD1306_COMMAND); // send control byte - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // TWI send command - // ------------------------------------------------------------------------------------- - status = TWI_MT_Send_Data (command); // send command - if (SSD1306_SUCCESS != status) { // check status - return status; // error + // send control byte + // ------------------------------------------------------------------------------------- + status = TWI_MT_Send_Data (SSD1306_COMMAND); + // request - start TWI + if (SSD1306_SUCCESS != status) { + // error + return status; } - return SSD1306_SUCCESS; // success + // send command + // ------------------------------------------------------------------------------------- + status = TWI_MT_Send_Data (command); + // request - start TWI + if (SSD1306_SUCCESS != status) { + // error + return status; + } + + // success + return SSD1306_SUCCESS; } /** * @desc SSD1306 Normal colors * - * @param void + * @param uint8_t address * * @return uint8_t */ -uint8_t SSD1306_NormalScreen (void) +uint8_t SSD1306_NormalScreen (uint8_t address) { - uint8_t status = INIT_STATUS; // TWI init status 0xFF + // init status + uint8_t status = INIT_STATUS; - // TWI start & SLAW + // TWI: start & SLAW // ------------------------------------------------------------------------------------- - status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // TWI send command - // ------------------------------------------------------------------------------------- - status = SSD1306_Send_Command (SSD1306_DIS_NORMAL); // command 0xA6 - if (SSD1306_SUCCESS != status) { // check status - return status; // error + status = SSD1306_Send_StartAndSLAW (address); + // request succesfull + if (SSD1306_SUCCESS != status) { + // error + return status; } - return SSD1306_SUCCESS; // success + // send command + // ------------------------------------------------------------------------------------- + status = SSD1306_Send_Command (SSD1306_DIS_NORMAL); + // request succesfull + if (SSD1306_SUCCESS != status) { + // error + return status; + } + + // success + return SSD1306_SUCCESS; } /** * @desc SSD1306 Inverse colors * - * @param void + * @param uint8_t address * * @return uint8_t */ -uint8_t SSD1306_InverseScreen (void) +uint8_t SSD1306_InverseScreen (uint8_t address) { - uint8_t status = INIT_STATUS; // TWI init status 0xFF + // init status + uint8_t status = INIT_STATUS; - // TWI start & SLAW + // TWI: start & SLAW // ------------------------------------------------------------------------------------- - status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // TWI send command - // ------------------------------------------------------------------------------------- - status = SSD1306_Send_Command (SSD1306_DIS_INVERSE); // command 0xA7 - if (SSD1306_SUCCESS != status) { // check status - return status; // error + status = SSD1306_Send_StartAndSLAW (address); + // request succesfull + if (SSD1306_SUCCESS != status) { + // error + return status; } - return SSD1306_SUCCESS; // success + // send command + // ------------------------------------------------------------------------------------- + status = SSD1306_Send_Command (SSD1306_DIS_INVERSE); + // request succesfull + if (SSD1306_SUCCESS != status) { + // error + return status; + } + + // success + return SSD1306_SUCCESS; +} + +/** + * @desc SSD1306 Update screen + * + * @param uint8_t address + * + * @return uint8_t + */ +uint8_t SSD1306_UpdateScreen (uint8_t address) +{ + // init status + uint8_t status = INIT_STATUS; + // init i + uint16_t i = 0; + + // TWI: start & SLAW + // ------------------------------------------------------------------------------------- + status = SSD1306_Send_StartAndSLAW (address); + // request succesfull + if (SSD1306_SUCCESS != status) { + // error + return status; + } + + // control byte data stream + // ------------------------------------------------------------------------------------- + status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); + // request succesfull + if (SSD1306_SUCCESS != status) { + // error + return status; + } + + // send cache memory lcd + // ------------------------------------------------------------------------------------- + while (i < CACHE_SIZE_MEM) { + // send data + status = TWI_MT_Send_Data (cacheMemLcd[i]); + // request succesfull + if (SSD1306_SUCCESS != status) { + // error + return status; + } + // increment + i++; + } + + // stop TWI + TWI_Stop (); + + // success + return SSD1306_SUCCESS; } /** @@ -294,138 +399,60 @@ uint8_t SSD1306_InverseScreen (void) * * @param void * - * @return uint8_t + * @return void */ -uint8_t SSD1306_ClearScreen (void) +void SSD1306_ClearScreen (void) { - uint8_t status = INIT_STATUS; // TWI init status 0xFF - uint16_t i = 0; // counter - - // TWI start & SLAW - // ------------------------------------------------------------------------------------- - status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // TWI control byte data stream - // ------------------------------------------------------------------------------------- - status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); // send data 0x40 - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // send clear byte to memory lcd - // ------------------------------------------------------------------------------------- - while (i < CACHE_SIZE_MEM) { - status = TWI_MT_Send_Data (CLEAR_COLOR); // send data 0x00 - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - i++; // update counter - } - // TWI stop - // ------------------------------------------------------------------------------------- - TWI_Stop (); - - return SSD1306_SUCCESS; // success + // null cache memory lcd + memset (cacheMemLcd, 0x00, CACHE_SIZE_MEM); } /** * @desc SSD1306 Set position * * @param uint8_t column -> 0 ... 127 - * @param uint8_t page -> 0 ... 7 + * @param uint8_t page -> 0 ... 7 or 3 * * @return void */ -uint8_t SSD1306_SetPosition (uint8_t x, uint8_t y) +void SSD1306_SetPosition (uint8_t x, uint8_t y) { - uint8_t status = INIT_STATUS; // TWI init status 0xFF - - // TWI start & SLAW - // ------------------------------------------------------------------------------------- - status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // COLUMN - // ------------------------------------------------------------------------------------- - status = SSD1306_Send_Command (SSD1306_SET_COLUMN_ADDR); // 0x21 - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // start COLUMN - status = SSD1306_Send_Command (x); - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // end COLUMN - status = SSD1306_Send_Command (END_COLUMN_ADDR); // 127 - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // update column index - _indexCol = x; - - // PAGE - // ------------------------------------------------------------------------------------- - status = SSD1306_Send_Command (SSD1306_SET_PAGE_ADDR); // 0x22 - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // start PAGE - status = SSD1306_Send_Command (y); - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // end PAGE - status = SSD1306_Send_Command (END_PAGE_ADDR); // 7 for 128x64 - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // update column index - _indexPage = y; - - // TWI stop - // ------------------------------------------------------------------------------------- - TWI_Stop (); - - return SSD1306_SUCCESS; // success + // calculate counter + _counter = x + (y << 7); } /** - * @desc SSD1306 Update text poisition - this ensure that character will not be divided - * at the end of row, the whole character will be depicted on the new row + * @desc SSD1306 Update text poisition - this ensure that character will not be divided at the end of row, + * the whole character will be depicted on the new row * * @param void * * @return uint8_t */ -uint8_t SSD1306_UpdatePosition (void) +uint8_t SSD1306_UpdTxtPosition (void) { - uint8_t status = INIT_STATUS; // TWI init status 0xFF - uint8_t x = _indexCol + CHARS_COLS_LENGTH + 1; // check end col position + // y / 8 + uint8_t y = _counter >> 7; + // y % 8 + uint8_t x = _counter - (y << 7); + // x + character length + 1 + uint8_t x_new = x + CHARS_COLS_LENGTH + 1; // check position - // ------------------------------------------------------------------------------------- - if (x > END_COLUMN_ADDR) { - // last page not reached - // ----------------------------------------------------------------------------------- - if (_indexPage < END_PAGE_ADDR) { - _indexCol = 0; // update column - _indexPage = _indexPage + 1; // update page - status = SSD1306_SetPosition (_indexCol, _indexPage); // update position - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - } - // last page reached - // ----------------------------------------------------------------------------------- - if (_indexPage >= END_PAGE_ADDR) { - return SSD1306_ERROR; // return out of range + if (x_new > END_COLUMN_ADDR) { + // if more than allowable number of pages + if (y > END_PAGE_ADDR) { + // return out of range + return SSD1306_ERROR; + // if x reach the end but page in range + } else if (y < (END_PAGE_ADDR-1)) { + // update + _counter = ((++y) << 7); } } - return SSD1306_SUCCESS; // success + // success + return SSD1306_SUCCESS; } /** @@ -435,52 +462,29 @@ uint8_t SSD1306_UpdatePosition (void) * * @return uint8_t */ -uint8_t SSD1306_DrawChar (char ch) +uint8_t SSD1306_DrawChar (char character) { - uint8_t status = INIT_STATUS; // TWI init status 0xFF - uint16_t i = 0; // counter + // variables + uint8_t i = 0; // update text position - // ------------------------------------------------------------------------------------- - status = SSD1306_UpdatePosition(); - if (SSD1306_SUCCESS != status) { // check status - return status; // error + // this ensure that character will not be divided at the end of row, the whole character will be depicted on the new row + if (SSD1306_UpdTxtPosition () == SSD1306_ERROR) { + // error + return SSD1306_ERROR; } - // TWI start & SLAW - // ------------------------------------------------------------------------------------- - status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // TWI control byte data stream - // ------------------------------------------------------------------------------------- - status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); // send data 0x40 - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // send character byte to memory lcd - // ------------------------------------------------------------------------------------- + + // loop through 5 bits while (i < CHARS_COLS_LENGTH) { - status = TWI_MT_Send_Data (pgm_read_byte (&FONTS[ch-32][i])); // send data col - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - i++; // update counter - } - // send empty column to memory lcd - // ------------------------------------------------------------------------------------- - status = TWI_MT_Send_Data (CLEAR_COLOR); // ONE empty column - if (SSD1306_SUCCESS != status) { // check status - return status; // error + // read byte + cacheMemLcd[_counter++] = pgm_read_byte(&FONTS[character-32][i++]); } - _indexCol = _indexCol + CHARS_COLS_LENGTH + 1; // update global col + // update position + _counter++; - // TWI stop - // ------------------------------------------------------------------------------------- - TWI_Stop (); - - return SSD1306_SUCCESS; // success + // success + return SSD1306_SUCCESS; } /** @@ -488,19 +492,17 @@ uint8_t SSD1306_DrawChar (char ch) * * @param char * string * - * @return uint8_t + * @return void */ -uint8_t SSD1306_DrawString (char *str) +void SSD1306_DrawString (char *str) { - uint8_t i = 0; // char counter - - // send characters of string - // ------------------------------------------------------------------------------------- + // init + int i = 0; + // loop through character of string while (str[i] != '\0') { - SSD1306_DrawChar (str[i++]); // send char + // draw string + SSD1306_DrawChar (str[i++]); } - - return SSD1306_SUCCESS; // success } /** @@ -513,46 +515,112 @@ uint8_t SSD1306_DrawString (char *str) */ uint8_t SSD1306_DrawPixel (uint8_t x, uint8_t y) { - uint8_t page = 0; // page - uint8_t pixel = 0; // pixel - uint8_t status = INIT_STATUS; // TWI init status 0xFF - - if ((x > MAX_X) && (y > MAX_Y)) { // if out of range - return SSD1306_ERROR; // error - } + uint8_t page = 0; + uint8_t pixel = 0; - page = y >> 3; // find page (y / 8) - pixel = 1 << (y - (page << 3)); // which pixel (y % 8) - - // set position - // ------------------------------------------------------------------------------------- - status = SSD1306_SetPosition (x, page); // update position - if (SSD1306_SUCCESS != status) { // check status - return status; // error + // if out of range + if ((x > MAX_X) && (y > MAX_Y)) { + // out of range + return SSD1306_ERROR; } + // find page (y / 8) + page = y >> 3; + // which pixel (y % 8) + pixel = 1 << (y - (page << 3)); + // update counter + _counter = x + (page << 7); + // save pixel + cacheMemLcd[_counter++] |= pixel; - // TWI start & SLAW - // ------------------------------------------------------------------------------------- - status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // TWI control byte data stream - // ------------------------------------------------------------------------------------- - status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); // send data 0x40 - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - // send clear byte to memory lcd - // ------------------------------------------------------------------------------------- - status = TWI_MT_Send_Data (pixel); // send pixel - if (SSD1306_SUCCESS != status) { // check status - return status; // error - } - - // TWI stop - // ------------------------------------------------------------------------------------- - TWI_Stop (); - - return SSD1306_SUCCESS; // success + // success + return SSD1306_SUCCESS; +} + +/** + * @desc Draw line by Bresenham algoritm + * + * @param uint8_t x start position / 0 <= cols <= MAX_X-1 + * @param uint8_t x end position / 0 <= cols <= MAX_X-1 + * @param uint8_t y start position / 0 <= rows <= MAX_Y-1 + * @param uint8_t y end position / 0 <= rows <= MAX_Y-1 + * + * @return uint8_t + */ +uint8_t SSD1306_DrawLine (uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2) +{ + // determinant + int16_t D; + // deltas + int16_t delta_x, delta_y; + // steps + int16_t trace_x = 1, trace_y = 1; + + // delta x + delta_x = x2 - x1; + // delta y + delta_y = y2 - y1; + + // check if x2 > x1 + if (delta_x < 0) { + // negate delta x + delta_x = -delta_x; + // negate step x + trace_x = -trace_x; + } + + // check if y2 > y1 + if (delta_y < 0) { + // negate detla y + delta_y = -delta_y; + // negate step y + trace_y = -trace_y; + } + + // Bresenham condition for m < 1 (dy < dx) + if (delta_y < delta_x) { + // calculate determinant + D = (delta_y << 1) - delta_x; + // draw first pixel + SSD1306_DrawPixel (x1, y1); + // check if x1 equal x2 + while (x1 != x2) { + // update x1 + x1 += trace_x; + // check if determinant is positive + if (D >= 0) { + // update y1 + y1 += trace_y; + // update determinant + D -= 2*delta_x; + } + // update deteminant + D += 2*delta_y; + // draw next pixel + SSD1306_DrawPixel (x1, y1); + } + // for m > 1 (dy > dx) + } else { + // calculate determinant + D = delta_y - (delta_x << 1); + // draw first pixel + SSD1306_DrawPixel (x1, y1); + // check if y2 equal y1 + while (y1 != y2) { + // update y1 + y1 += trace_y; + // check if determinant is positive + if (D <= 0) { + // update y1 + x1 += trace_x; + // update determinant + D += 2*delta_y; + } + // update deteminant + D -= 2*delta_x; + // draw next pixel + SSD1306_DrawPixel (x1, y1); + } + } + // success return + return SSD1306_SUCCESS; } diff --git a/lib/ssd1306.h b/lib/ssd1306.h index b514e42..dd726f6 100644 --- a/lib/ssd1306.h +++ b/lib/ssd1306.h @@ -1,47 +1,45 @@ -/** - * ---------------------------------------------------------------+ +/** + * -------------------------------------------------------------------------------------+ * @desc SSD1306 OLED Driver - * ---------------------------------------------------------------+ + * -------------------------------------------------------------------------------------+ * Copyright (C) 2020 Marian Hrinko. * Written by Marian Hrinko (mato.hrinko@gmail.com) * * @author Marian Hrinko - * @datum 06.10.2020 - * @update 19.07.2021 + * @date 06.10.2020 + * @update 21.11.2022 * @file ssd1306.h - * @version 2.0 - * @tested AVR Atmega328 + * @version 2.0.0 + * @tested AVR Atmega328p * - * @depend font.h, twi.h - * ---------------------------------------------------------------+ - * @descr Version 1.0 -> applicable for 1 display - * Version 2.0 -> rebuild to 'cacheMemLcd' array - * ---------------------------------------------------------------+ + * @depend string.h, font.h, twi.h + * -------------------------------------------------------------------------------------+ + * @descr Version 1.0.0 -> applicable for 1 display + * Version 2.0.0 -> rebuild to 'cacheMemLcd' array + * Version 3.0.0 -> simplified alphanumeric version + * -------------------------------------------------------------------------------------+ * @usage Basic Setup for OLED Display */ #ifndef __SSD1306_H__ #define __SSD1306_H__ - // includes - #include + // @includes + #include // memset function #include "font.h" #include "twi.h" - // Success - // ------------------------------------------- + // Success / Error + // ------------------------------------------------------------------------------------ #define SSD1306_SUCCESS 0 - - // Error - // ------------------------------------------- #define SSD1306_ERROR 1 // Address definition - // ----------------------------------- - #define SSD1306_ADDR 0x3C + // ------------------------------------------------------------------------------------ + #define SSD1306_ADDRESS 0x3C // Command definition - // ----------------------------------- + // ------------------------------------------------------------------------------------ #define SSD1306_COMMAND 0x80 // Continuation bit=1, D/C=0; 1000 0000 #define SSD1306_COMMAND_STREAM 0x00 // Continuation bit=0, D/C=0; 0000 0000 #define SSD1306_DATA 0xC0 // Continuation bit=1, D/C=1; 1100 0000 @@ -73,24 +71,26 @@ #define SSD1306_VCOM_DESELECT 0xDB // Clear Color - // ----------------------------------- + // ------------------------------------------------------------------------------------ #define CLEAR_COLOR 0x00 // Init Status - // ----------------------------------- + // ------------------------------------------------------------------------------------ #define INIT_STATUS 0xFF // AREA definition - // ----------------------------------- + // ------------------------------------------------------------------------------------ #define START_PAGE_ADDR 0 - #define END_PAGE_ADDR 7 + #define END_PAGE_ADDR 7 // 7 for 128x64, 3 for 128x32 version #define START_COLUMN_ADDR 0 #define END_COLUMN_ADDR 127 + #define RAM_X_END END_COLUMN_ADDR + 1 + #define RAM_Y_END END_PAGE_ADDR + 1 #define CACHE_SIZE_MEM (1 + END_PAGE_ADDR) * (1 + END_COLUMN_ADDR) #define MAX_X END_COLUMN_ADDR - #define MAX_Y (END_PAGE_ADDR+1)*8 + #define MAX_Y (END_PAGE_ADDR + 1) * 8 // @var set area unsigned int _counter; @@ -98,11 +98,11 @@ /** * @desc SSD1306 Init * - * @param void + * @param uint8_t * * @return uint8_t */ - uint8_t SSD1306_Init (void); + uint8_t SSD1306_Init (uint8_t); /** * @desc SSD1306 Send Start and SLAW request @@ -127,27 +127,36 @@ * * @param void * - * @return uint8_t + * @return void */ - uint8_t SSD1306_ClearScreen (void); + void SSD1306_ClearScreen (void); /** * @desc SSD1306 Normal colors * - * @param void + * @param uint8_t * * @return uint8_t */ - uint8_t SSD1306_NormalScreen (void); + uint8_t SSD1306_NormalScreen (uint8_t); /** * @desc SSD1306 Inverse colors * - * @param void + * @param uint8_t * * @return uint8_t */ - uint8_t SSD1306_InverseScreen (void); + uint8_t SSD1306_InverseScreen (uint8_t); + + /** + * @desc SSD1306 Update screen + * + * @param uint8_t + * + * @return uint8_t + */ + uint8_t SSD1306_UpdateScreen (uint8_t); /** * @desc SSD1306 Update text position @@ -156,7 +165,7 @@ * * @return uint8_t */ - uint8_t SSD1306_UpdatePosition (void); + uint8_t SSD1306_UpdTxtPosition (void); /** * @desc SSD1306 Set position @@ -164,9 +173,9 @@ * @param uint8_t * @param uint8_t * - * @return uint8_t + * @return void */ - uint8_t SSD1306_SetPosition (uint8_t, uint8_t); + void SSD1306_SetPosition (uint8_t, uint8_t); /** * @desc SSD1306 Draw character @@ -182,9 +191,9 @@ * * @param char * * - * @return uint8_t + * @return void */ - uint8_t SSD1306_DrawString (char *); + void SSD1306_DrawString (char *); /** * @desc Draw pixel diff --git a/lib/twi.c b/lib/twi.c index da01dc1..73d9d7b 100644 --- a/lib/twi.c +++ b/lib/twi.c @@ -1,7 +1,7 @@ /** - * ---------------------------------------------------------------+ + * --------------------------------------------------------------------------------------+ * @desc Two Wire Interface / I2C Communication - * ---------------------------------------------------------------+ + * --------------------------------------------------------------------------------------+ * Copyright (C) 2020 Marian Hrinko. * Written by Marian Hrinko (mato.hrinko@gmail.com) * @@ -10,13 +10,12 @@ * @file twi.c * @tested AVR Atmega16, ATmega8, Atmega328 * - * @depend - * ---------------------------------------------------------------+ + * @depend twi.h + * --------------------------------------------------------------------------------------+ * @usage Master Transmit Operation */ // include libraries -#include #include "twi.h" /** @@ -28,20 +27,23 @@ */ void TWI_Init (void) { - // +++++++++++++++++++++++++++++++++++++++++++++ + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Calculation fclk: // - // fclk = (fcpu)/(16+2*TWBR*4^Prescaler) - // --------------------------------------------- + // fclk = (fcpu)/(16+2*TWBR*4^Prescaler) m16 + // fclk = (fcpu)/(16+2*TWBR*Prescaler) m328p + // ------------------------------------------------------------------------------------- // Calculation TWBR: // // TWBR = {(fcpu/fclk) - 16 } / (2*4^Prescaler) - // +++++++++++++++++++++++++++++++++++++++++++++ - // @param1 value of TWBR, - // fclk = 400kHz (m16); TWBR = 3 - // fclk = 100kHz (m16); TWBR = 20 + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // @param1 value of TWBR (m16) + // fclk = 400kHz; TWBR = 3 + // fclk = 100kHz; TWBR = 20 + // @param1 value of TWBR (m328p) + // fclk = 400kHz; TWBR = 2 // @param2 value of Prescaler = 1 - TWI_FREQ (3, 1); + TWI_FREQ (2, 1); } /** @@ -56,7 +58,7 @@ char TWI_MT_Start (void) // null status flag TWI_TWSR &= ~0xA8; // START - // ---------------------------------------------- + // ------------------------------------------------------------------------------------- // request for bus TWI_START(); // wait till flag set @@ -80,7 +82,7 @@ char TWI_MT_Start (void) char TWI_MT_Send_SLAW (char address) { // SLA+W - // ---------------------------------------------- + // ------------------------------------------------------------------------------------- TWI_TWDR = (address << 1); // enable TWI_ENABLE(); @@ -106,7 +108,7 @@ char TWI_MT_Send_SLAW (char address) char TWI_MT_Send_Data (char data) { // DATA - // ---------------------------------------------- + // ------------------------------------------------------------------------------------- TWI_TWDR = data; // enable TWI_ENABLE(); @@ -132,7 +134,7 @@ char TWI_MT_Send_Data (char data) char TWI_MR_Send_SLAR (char address) { // SLA+R - // ---------------------------------------------- + // ------------------------------------------------------------------------------------- TWI_TWDR = (address << 1) | 0x01; // enable TWI_ENABLE(); @@ -158,7 +160,7 @@ char TWI_MR_Send_SLAR (char address) void TWI_Stop (void) { // End TWI - // ------------------------------------------------- + // ------------------------------------------------------------------------------------- // send stop sequence TWI_STOP (); // wait for TWINT flag is set diff --git a/lib/twi.h b/lib/twi.h index 626d38a..387b8ba 100644 --- a/lib/twi.h +++ b/lib/twi.h @@ -1,7 +1,7 @@ /** - * ---------------------------------------------------------------+ + * --------------------------------------------------------------------------------------+ * @desc Two Wire Interface / I2C Communication - * ---------------------------------------------------------------+ + * --------------------------------------------------------------------------------------+ * Copyright (C) 2020 Marian Hrinko. * Written by Marian Hrinko (mato.hrinko@gmail.com) * @@ -10,16 +10,19 @@ * @file twi.h * @tested AVR Atmega16, ATmega8, Atmega328 * - * @depend - * ---------------------------------------------------------------+ + * @depend avr/io.h + * --------------------------------------------------------------------------------------+ * @usage Basic Master Transmit Operation */ #ifndef __TWI_H__ #define __TWI_H__ + // @includes + #include + // define register for TWI communication - // ------------------------------------------- + // ------------------------------------------------------------------------------------- #if defined(__AVR_ATmega16__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) #define TWI_TWAR TWAR // TWI (Slave) Address Register @@ -31,22 +34,22 @@ #endif // Success - // ------------------------------------------- + // ------------------------------------------------------------------------------------- #ifndef SUCCESS #define SUCCESS 0 #endif // Error - // ------------------------------------------- + // ------------------------------------------------------------------------------------- #ifndef ERROR #define ERROR 1 #endif - // ++++++++++++++++++++++++++++++++++++++++++ + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // M A S T E R M O D E // - // ++++++++++++++++++++++++++++++++++++++++++ + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Master Mode - Transmitter / Receiver #define TWI_START_ACK 0x08 // A START condition has been transmitted #define TWI_REP_START_ACK 0x10 // A repeated START condition has been transmitted @@ -62,11 +65,11 @@ #define TWI_MR_DATA_ACK 0x50 // Data byte has been received; ACK has been received #define TWI_MR_DATA_NACK 0x58 // Data byte has been received; NOT ACK has been received - // ++++++++++++++++++++++++++++++++++++++++++ + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // S L A V E M O D E // - // ++++++++++++++++++++++++++++++++++++++++++ + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Slave Receiver Mode #define TWI_SR_SLAW_ACK 0x60 // Own Slave address has been received; ACK returned #define TWI_SR_ALMOA_ACK 0x68 // Arbitration Lost in SLA+R/W as Master; Own Slave address has been received; ACK returned @@ -85,7 +88,7 @@ #define TWI_ST_DATA_LOST_ACK 0xC8 // Last data byte in TWDR has been transmitted (TWEA = '0'); ACK has been received // TWI CLK frequency - // ------------------------------------------- + // ------------------------------------------------------------------------------------- // @param TWBR // @param Prescaler // TWPS1 TWPS0 - PRESCALER @@ -96,21 +99,21 @@ #define TWI_FREQ(BIT_RATE, PRESCALER) { TWI_TWBR = BIT_RATE; TWI_TWSR |= (TWI_TWSR & 0x03) | PRESCALER; } // TWI start condition - // ------------------------------------------- + // ------------------------------------------------------------------------------------- // (1 << TWEN) - TWI Enable // (1 << TWINT) - TWI Interrupt Flag - must be cleared by set // (1 << TWSTA) - TWI Start #define TWI_START() { TWI_TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTA); } // TWI stop condition - // ------------------------------------------- + // ------------------------------------------------------------------------------------- // (1 << TWEN) - TWI Enable // (1 << TWINT) - TWI Interrupt Flag - must be cleared by set // (1 << TWSTO) - TWI Stop #define TWI_STOP() { TWI_TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTO); } // TWI enable - // ------------------------------------------- + // ------------------------------------------------------------------------------------- // (1 << TWEN) - TWI Enable // (1 << TWINT) - TWI Interrupt Flag - must be cleared by set #define TWI_ENABLE() { TWI_TWCR = (1 << TWEN) | (1 << TWINT); } @@ -128,7 +131,7 @@ * * @return void */ - void TWI_Init(void); + void TWI_Init (void); /** * @desc TWI MT Start @@ -137,7 +140,7 @@ * * @return char */ - char TWI_MT_Start(void); + char TWI_MT_Start (void); /** * @desc TWI Send SLAW @@ -146,7 +149,7 @@ * * @return unsigned char */ - char TWI_MT_Send_SLAW(char); + char TWI_MT_Send_SLAW (char); /** * @desc TWI Send data @@ -155,7 +158,7 @@ * * @return char */ - char TWI_MT_Send_Data(char); + char TWI_MT_Send_Data (char); /** * @desc TWI Send SLAR @@ -164,7 +167,7 @@ * * @return unsigned char */ - char TWI_MR_Send_SLAR(char); + char TWI_MR_Send_SLAR (char); /** * @desc TWI stop @@ -173,6 +176,6 @@ * * @return void */ - void TWI_Stop(void); + void TWI_Stop (void); #endif diff --git a/main.c b/main.c index 7eb953d..16972d2 100644 --- a/main.c +++ b/main.c @@ -6,20 +6,21 @@ * Written by Marian Hrinko (mato.hrinko@gmail.com) * * @author Marian Hrinko - * @datum 06.10.2020 + * @date 06.10.2020 * @update 19.07.2021 * @file main.c + * @version 2.0.0 * @tested AVR Atmega328p * - * @depend ssd1306.h + * @depend lib/ssd1306.h * ---------------------------------------------------------------+ - * @descr Version 1.0 -> applicable for 1 display - * Version 2.0 -> rebuild to 'cacheMemLcd' array + * @descr Version 1.0.0 -> applicable for 1 display + * Version 2.0.0 -> rebuild to 'cacheMemLcd' array + * Version 3.0.0 -> simplified alphanumeric version * ---------------------------------------------------------------+ */ // include libraries -#include #include "lib/ssd1306.h" /** @@ -31,22 +32,32 @@ */ int main(void) { -/* - uint8_t x = 0; - uint8_t y = 0; -*/ + uint8_t addr = SSD1306_ADDRESS; + // init ssd1306 - SSD1306_Init (); + SSD1306_Init (addr); + // clear screen SSD1306_ClearScreen (); + // draw line + SSD1306_DrawLine (0, MAX_X, 4, 4); + // set position + SSD1306_SetPosition (7, 1); // draw string - SSD1306_DrawString ("SSD1306 MATIASUS"); -/* - while (x < 10) { + SSD1306_DrawString ("SSD1306 OLED DRIVER"); + // draw line + SSD1306_DrawLine (0, MAX_X, 18, 18); + // set position + SSD1306_SetPosition (40, 3); + // draw string + SSD1306_DrawString ("MATIASUS"); + // set position + SSD1306_SetPosition (53, 5); + // draw string + SSD1306_DrawString ("2021"); + // update + SSD1306_UpdateScreen (addr); - SSD1306_DrawPixel (x++,y++); - } -*/ // return value return 0; }