Version v2.0.0

This commit is contained in:
matiasus 2022-12-15 21:26:03 +01:00
parent 067b11ffab
commit 2a3553f074
7 changed files with 585 additions and 510 deletions

View File

@ -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
};

View File

@ -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

View File

@ -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;
}

View File

@ -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 <string.h>
// @includes
#include <string.h> // 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

View File

@ -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 <avr/io.h>
#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

View File

@ -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 <avr/io.h>
// 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

43
main.c
View File

@ -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 <stdio.h>
#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;
}