Add Adafuit Init Command List for testing purpose 0.91 / 128x32 oled

This commit is contained in:
Matiasus 2023-12-19 22:42:11 +01:00
parent d9b7bb7511
commit 3444217ae6
4 changed files with 196 additions and 343 deletions

View File

@ -13,7 +13,7 @@
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# #
# Final file # Final file
TARGET = main TARGET = main
# #
# Library directory # Library directory
LIBDIR = lib LIBDIR = lib
@ -22,7 +22,7 @@ LIBDIR = lib
DEVICE = atmega328p DEVICE = atmega328p
# #
# Frequency # Frequency
FCPU = 8000000 FCPU = 16000000
# #
# Optimization # Optimization
OPTIMIZE = Os OPTIMIZE = Os
@ -53,7 +53,7 @@ AVRSIZE = avr-size
SFLAGS = --mcu=$(DEVICE) --format=avr SFLAGS = --mcu=$(DEVICE) --format=avr
# #
# Target and dependencies .c # Target and dependencies .c
SOURCES := $(wildcard *.c $(LIBDIR)/*.c) SOURCES := $(wildcard *.c $(LIBDIR)/*.c $(LIBDIR)/*/*.c)
# #
# Target and dependencies .o # Target and dependencies .o
OBJECTS = $(SOURCES:.c=.o) OBJECTS = $(SOURCES:.c=.o)
@ -75,7 +75,7 @@ AVRDUDE_PORT = /dev/ttyUSB0
AVRDUDE_PROG = usbasp AVRDUDE_PROG = usbasp
# #
# AVRDUDE BAUD RATE # AVRDUDE BAUD RATE
AVRDUDE_BAUD = 57600 AVRDUDE_BAUD = 19200
# #
# AVRDUDE BAUD RATE # AVRDUDE BAUD RATE
AVROBJ_FORMAT = ihex AVROBJ_FORMAT = ihex
@ -91,8 +91,8 @@ main: $(TARGET).hex
# Create hex file # Create hex file
$(TARGET).hex: $(TARGET).elf $(TARGET).hex: $(TARGET).elf
$(OBJCOPY) $(OBJFLAGS) $(TARGET).elf $(TARGET).hex $(OBJCOPY) $(OBJFLAGS) $(TARGET).elf $(TARGET).hex
@echo "-----------------------------------------------------------------------"
$(AVRSIZE) $(TARGET).elf $(AVRSIZE) $(TARGET).elf
# #
# Create .elf file # Create .elf file
$(TARGET).elf:$(OBJECTS) $(TARGET).elf:$(OBJECTS)
@ -105,17 +105,24 @@ $(TARGET).elf:$(OBJECTS)
# #
# Program avr - send file to programmer # Program avr - send file to programmer
flash: flash:
@echo "-----------------------------------------------------------------------"
$(AVRDUDE) $(AVRDUDE_FLAGS) flash:w:$(TARGET).hex:i $(AVRDUDE) $(AVRDUDE_FLAGS) flash:w:$(TARGET).hex:i
#
# Size
size:
@echo "-----------------------------------------------------------------------"
$(AVRSIZE) -C --mcu=$(DEVICE) $(TARGET).elf
# #
# Clean # Clean
clean: clean:
@echo "-----------------------------------------------------------------------"
rm -f $(OBJECTS) $(TARGET).elf $(TARGET).map rm -f $(OBJECTS) $(TARGET).elf $(TARGET).map
# #
# Cleanall # Cleanall
cleanall: cleanall:
rm -f $(OBJECTS) $(TARGET).hex $(TARGET).elf $(TARGET).map @echo "-----------------------------------------------------------------------"
rm -f $(OBJECTS) $(TARGET).hex $(TARGET).elf $(TARGET).map

View File

@ -1,6 +1,6 @@
/** /**
* --------------------------------------------------------------------------------------+ * --------------------------------------------------------------------------------------+
* @desc SSD1306 OLED Driver * @brief SSD1306 OLED Driver
* --------------------------------------------------------------------------------------+ * --------------------------------------------------------------------------------------+
* Copyright (C) 2020 Marian Hrinko. * Copyright (C) 2020 Marian Hrinko.
* Written by Marian Hrinko (mato.hrinko@gmail.com) * Written by Marian Hrinko (mato.hrinko@gmail.com)
@ -24,116 +24,76 @@
// @includes // @includes
#include "ssd1306.h" #include "ssd1306.h"
// +---------------------------+ // @const List of init commands with arguments by Adafruit
// | Set MUX Ratio | // @link https://github.com/adafruit/Adafruit_SSD1306
// +---------------------------+ const uint8_t INIT_SSD1306_ADAFRUIT[] PROGMEM = {
// | 0xA8, 0x3F | 17, // number of initializers
// +---------------------------+ SSD1306_DISPLAY_OFF, 0, // 0xAE / Set Display OFF
// | SSD1306_SET_OSC_FREQ, 1, 0x80, // 0xD5 / 0x80 => D=1; DCLK = Fosc / D <=> DCLK = Fosc
// +---------------------------+ SSD1306_SET_MUX_RATIO, 1, 0x1F, // 0xA8 / 0x3F (64MUX) for 128 x 64 version
// | Set Display Offset | // / 0x1F (32MUX) for 128 x 32 version
// +---------------------------+ SSD1306_DISPLAY_OFFSET, 1, 0x00, // 0xD3
// | 0xD3, 0x00 | SSD1306_SET_START_LINE, 0, // 0x40
// +---------------------------+ SSD1306_SET_CHAR_REG, 1, 0x14, // 0x8D / Enable charge pump during display on
// | SSD1306_MEMORY_ADDR_MODE, 1, 0x00, // 0x20 / Set Memory Addressing Mode
// +---------------------------+ // 0x00 / Horizontal Addressing Mode
// | Set Display Start Line | // 0x01 / Vertical Addressing Mode
// +---------------------------+ // 0x02 / Page Addressing Mode (RESET)
// | 0x40 | SSD1306_SEG_REMAP_OP, 0, // 0xA0 / remap 0xA1
// +---------------------------+ SSD1306_COM_SCAN_DIR_OP, 0, // 0xC8
// | SSD1306_COM_PIN_CONF, 0, 0x02, // 0xDA / 0x12 - Disable COM Left/Right remap, Alternative COM pin configuration
// +---------------------------+ // 0x12 - for 128 x 64 version
// | Set Segment Remap | // 0x02 - for 128 x 32 version
// +---------------------------+ SSD1306_SET_CONTRAST, 1, 0x8F, // 0x81 / 0x8F - reset value (max 0xFF)
// | 0xA0 / 0xA1 | SSD1306_SET_PRECHARGE, 1, 0xc2, // 0xD9 / higher value less blinking
// +---------------------------+ // 0xC2, 1st phase = 2 DCLK, 2nd phase = 13 DCLK
// | SSD1306_VCOM_DESELECT, 1, 0x40, // 0xDB / Set V COMH Deselect, reset value 0x22 = 0,77xUcc
// +---------------------------+ SSD1306_DIS_ENT_DISP_ON, 0, // 0xA4
// | Set COM Output Scan | SSD1306_DIS_NORMAL, 0, // 0xA6
// | Direction | SSD1306_DEACT_SCROLL, 0, // 0x2E
// +---------------------------+ SSD1306_DISPLAY_ON, 0 // 0xAF / Set Display ON
// | 0xC0 / 0xC8 | };
// +---------------------------+
// |
// +---------------------------+
// | Set COM Pins hardware |
// | configuration |
// +---------------------------+
// | 0xDA, 0x02 |
// +---------------------------+
// |
// +---------------------------+
// | Set Contrast Control |
// +---------------------------+
// | 0x81, 0x7F |
// +---------------------------+
// |
// +---------------------------+
// | Disable Entire Display On |
// +---------------------------+
// | 0xA4 |
// +---------------------------+
// |
// +---------------------------+
// | Set Normal Display |
// +---------------------------+
// | 0xA6 |
// +---------------------------+
// |
// +---------------------------+
// | Set Osc Frequency |
// +---------------------------+
// | 0xD5, 0x80 |
// +---------------------------+
// |
// +---------------------------+
// | Enable charge pump |
// | regulator |
// +---------------------------+
// | 0x8D, 0x14 |
// +---------------------------+
// |
// +---------------------------+
// | Display On |
// +---------------------------+
// | 0xAF |
// +---------------------------+
// @array Init command // @const uint8_t - List of init commands according to datasheet SSD1306
const uint8_t INIT_SSD1306[] PROGMEM = { const uint8_t INIT_SSD1306[] PROGMEM = {
18, // number of initializers 17, // number of initializers
0, SSD1306_DISPLAY_OFF, // 0xAE = Set Display OFF SSD1306_DISPLAY_OFF, 0, // 0xAE = Set Display OFF
1, SSD1306_SET_MUX_RATIO, 63, // 0xA8 - 64MUX for 128 x 64 version SSD1306_SET_MUX_RATIO, 1, 0x1F, // 0xA8 - 0x3F for 128 x 64 version (64MUX)
// - 32MUX for 128 x 32 version // - 0x1F for 128 x 32 version (32MUX)
1, SSD1306_MEMORY_ADDR_MODE, 0x00, // 0x20 = Set Memory Addressing Mode SSD1306_MEMORY_ADDR_MODE, 1, 0x00, // 0x20 = Set Memory Addressing Mode
// 0x00 - Horizontal Addressing Mode // 0x00 - Horizontal Addressing Mode
// 0x01 - Vertical Addressing Mode // 0x01 - Vertical Addressing Mode
// 0x02 - Page Addressing Mode (RESET) // 0x02 - Page Addressing Mode (RESET)
2, SSD1306_SET_COLUMN_ADDR, START_COLUMN_ADDR, END_COLUMN_ADDR, // 0x21 = Set Column Address, 0 - 127 SSD1306_SET_START_LINE, 0, // 0x40
2, SSD1306_SET_PAGE_ADDR, START_PAGE_ADDR, END_PAGE_ADDR, // 0x22 = Set Page Address, 0 - 7 SSD1306_DISPLAY_OFFSET, 1, 0x00, // 0xD3
0, SSD1306_SET_START_LINE, // 0x40 SSD1306_SEG_REMAP_OP, 0, // 0xA0 / remap 0xA1
1, SSD1306_DISPLAY_OFFSET, 0x00, // 0xD3 SSD1306_COM_SCAN_DIR_OP, 0, // 0xC0 / remap 0xC8
0, SSD1306_SEG_REMAP_OP, // 0xA0 / remap 0xA1 SSD1306_COM_PIN_CONF, 1, 0x02, // 0xDA, 0x12 - Disable COM Left/Right remap, Alternative COM pin configuration
0, SSD1306_COM_SCAN_DIR_OP, // 0xC0 / remap 0xC8
1, SSD1306_COM_PIN_CONF, 0x12, // 0xDA, 0x12 - Disable COM Left/Right remap, Alternative COM pin configuration
// 0x12 - for 128 x 64 version // 0x12 - for 128 x 64 version
// 0x02 - for 128 x 32 version // 0x02 - for 128 x 32 version
1, SSD1306_SET_CONTRAST, 0x7F, // 0x81, 0x7F - reset value (max 0xFF) SSD1306_SET_CONTRAST, 1, 0x7F, // 0x81, 0x7F - reset value (max 0xFF)
0, SSD1306_DIS_ENT_DISP_ON, // 0xA4 SSD1306_DIS_ENT_DISP_ON, 0, // 0xA4
0, SSD1306_DIS_NORMAL, // 0xA6 SSD1306_DIS_NORMAL, 0, // 0xA6
1, SSD1306_SET_OSC_FREQ, 0x80, // 0xD5, 0x80 => D=1; DCLK = Fosc / D <=> DCLK = Fosc SSD1306_SET_OSC_FREQ, 1, 0x80, // 0xD5, 0x80 => D=1; DCLK = Fosc / D <=> DCLK = Fosc
1, SSD1306_SET_PRECHARGE, 0xc2, // 0xD9, higher value less blinking SSD1306_SET_PRECHARGE, 1, 0xc2, // 0xD9, higher value less blinking
// 0xC2, 1st phase = 2 DCLK, 2nd phase = 13 DCLK // 0xC2, 1st phase = 2 DCLK, 2nd phase = 13 DCLK
1, SSD1306_VCOM_DESELECT, 0x20, // Set V COMH Deselect, reset value 0x22 = 0,77xUcc SSD1306_VCOM_DESELECT, 1, 0x20, // Set V COMH Deselect, reset value 0x22 = 0,77xUcc
1, SSD1306_SET_CHAR_REG, 0x14, // 0x8D, Enable charge pump during display on SSD1306_SET_CHAR_REG, 1, 0x14, // 0x8D, Enable charge pump during display on
0, SSD1306_DISPLAY_ON // 0xAF = Set Display ON SSD1306_DEACT_SCROLL, 0, // 0x2E
SSD1306_DISPLAY_ON, 0 // 0xAF = Set Display ON
}; };
// @var array Chache memory Lcd 8 * 128 = 1024 // @var array Chache memory Lcd 8 * 128 = 1024
static char cacheMemLcd[CACHE_SIZE_MEM]; static char cacheMemLcd[CACHE_SIZE_MEM];
/** /**
* @desc SSD1306 Init * +------------------------------------------------------------------------------------+
* |== PRIVATE FUNCTIONS ===============================================================|
* +------------------------------------------------------------------------------------+
*/
/**
* @brief SSD1306 Init
* *
* @param uint8_t address * @param uint8_t address
* *
@ -141,72 +101,48 @@ static char cacheMemLcd[CACHE_SIZE_MEM];
*/ */
uint8_t SSD1306_Init (uint8_t address) uint8_t SSD1306_Init (uint8_t address)
{ {
// variables const uint8_t * list = INIT_SSD1306;
const uint8_t *commands = INIT_SSD1306; uint8_t status = INIT_STATUS; // init status
// number of commands uint8_t arguments;
unsigned short int no_of_commands = pgm_read_byte(commands++); uint8_t commands = pgm_read_byte (list++);
// argument
uint8_t no_of_arguments;
// command
uint8_t command;
// init status
uint8_t status = INIT_STATUS;
// TWI: Init // TWI: Init
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
TWI_Init (); TWI_Init ();
// TWI: start & SLAW // TWI: start & SLAW
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (address); status = SSD1306_Send_StartAndSLAW (address);
// request - start TWI
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// Commands & Arguments
// 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
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = SSD1306_Send_Command (command); while (commands--) {
// request - start TWI // Command
// -----------------------------------------------------------------------------------
status = SSD1306_Send_Command (pgm_read_byte(list++));
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// Arguments
// send arguments // -----------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------- arguments = pgm_read_byte (list++);
while (no_of_arguments--) { while (arguments--) {
// send command status = SSD1306_Send_Command (pgm_read_byte(list++)); // argument
status = SSD1306_Send_Command (pgm_read_byte(commands++));
// request - start TWI
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
} }
// decrement
no_of_commands--;
} }
// TWI: Stop // TWI: Stop
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
TWI_Stop (); TWI_Stop ();
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc SSD1306 Send Start and SLAW request * @brief SSD1306 Send Start and SLAW request
* *
* @param uint8_t * @param uint8_t
* *
@ -214,33 +150,26 @@ uint8_t SSD1306_Init (uint8_t address)
*/ */
uint8_t SSD1306_Send_StartAndSLAW (uint8_t address) uint8_t SSD1306_Send_StartAndSLAW (uint8_t address)
{ {
// init status
uint8_t status = INIT_STATUS; uint8_t status = INIT_STATUS;
// TWI: start // TWI: start
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = TWI_MT_Start (); status = TWI_MT_Start ();
// request - start TWI
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// TWI: send SLAW // TWI: send SLAW
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = TWI_MT_Send_SLAW (address); status = TWI_MT_Send_SLAW (address);
// request - send SLAW
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc SSD1306 Send command * @brief SSD1306 Send command
* *
* @param uint8_t command * @param uint8_t command
* *
@ -248,33 +177,32 @@ uint8_t SSD1306_Send_StartAndSLAW (uint8_t address)
*/ */
uint8_t SSD1306_Send_Command (uint8_t command) uint8_t SSD1306_Send_Command (uint8_t command)
{ {
// init status
uint8_t status = INIT_STATUS; uint8_t status = INIT_STATUS;
// send control byte // send control byte
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = TWI_MT_Send_Data (SSD1306_COMMAND); status = TWI_MT_Send_Data (SSD1306_COMMAND);
// request - start TWI
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// send command // send command
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = TWI_MT_Send_Data (command); status = TWI_MT_Send_Data (command);
// request - start TWI
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc SSD1306 Normal colors * +------------------------------------------------------------------------------------+
* |== PUBLIC FUNCTIONS ================================================================|
* +------------------------------------------------------------------------------------+
*/
/**
* @brief SSD1306 Normal colors
* *
* @param uint8_t address * @param uint8_t address
* *
@ -282,33 +210,29 @@ uint8_t SSD1306_Send_Command (uint8_t command)
*/ */
uint8_t SSD1306_NormalScreen (uint8_t address) uint8_t SSD1306_NormalScreen (uint8_t address)
{ {
// init status
uint8_t status = INIT_STATUS; uint8_t status = INIT_STATUS;
// TWI: start & SLAW // TWI: start & SLAW
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (address); status = SSD1306_Send_StartAndSLAW (address);
// request succesfull
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// send command // send command
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = SSD1306_Send_Command (SSD1306_DIS_NORMAL); status = SSD1306_Send_Command (SSD1306_DIS_NORMAL);
// request succesfull
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// TWI: Stop
// -------------------------------------------------------------------------------------
TWI_Stop ();
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc SSD1306 Inverse colors * @brief SSD1306 Inverse colors
* *
* @param uint8_t address * @param uint8_t address
* *
@ -316,33 +240,29 @@ uint8_t SSD1306_NormalScreen (uint8_t address)
*/ */
uint8_t SSD1306_InverseScreen (uint8_t address) uint8_t SSD1306_InverseScreen (uint8_t address)
{ {
// init status
uint8_t status = INIT_STATUS; uint8_t status = INIT_STATUS;
// TWI: start & SLAW // TWI: start & SLAW
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (address); status = SSD1306_Send_StartAndSLAW (address);
// request succesfull
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// send command // send command
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = SSD1306_Send_Command (SSD1306_DIS_INVERSE); status = SSD1306_Send_Command (SSD1306_DIS_INVERSE);
// request succesfull
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// TWI: Stop
// -------------------------------------------------------------------------------------
TWI_Stop ();
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc SSD1306 Update screen * @brief SSD1306 Update screen
* *
* @param uint8_t address * @param uint8_t address
* *
@ -350,52 +270,38 @@ uint8_t SSD1306_InverseScreen (uint8_t address)
*/ */
uint8_t SSD1306_UpdateScreen (uint8_t address) uint8_t SSD1306_UpdateScreen (uint8_t address)
{ {
// init status
uint8_t status = INIT_STATUS; uint8_t status = INIT_STATUS;
// init i
uint16_t i = 0; uint16_t i = 0;
// TWI: start & SLAW // TWI: start & SLAW
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (address); status = SSD1306_Send_StartAndSLAW (address);
// request succesfull
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// control byte data stream // control byte data stream
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); status = TWI_MT_Send_Data (SSD1306_DATA_STREAM);
// request succesfull
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// send cache memory lcd // send cache memory lcd
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
while (i < CACHE_SIZE_MEM) { while (i < CACHE_SIZE_MEM) {
// send data status = TWI_MT_Send_Data (cacheMemLcd[i++]); // send data
status = TWI_MT_Send_Data (cacheMemLcd[i]);
// request succesfull
if (SSD1306_SUCCESS != status) { if (SSD1306_SUCCESS != status) {
// error
return status; return status;
} }
// increment
i++;
} }
// stop TWI // stop TWI
// -------------------------------------------------------------------------------------
TWI_Stop (); TWI_Stop ();
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc SSD1306 Clear screen * @brief SSD1306 Clear screen
* *
* @param void * @param void
* *
@ -403,12 +309,11 @@ uint8_t SSD1306_UpdateScreen (uint8_t address)
*/ */
void SSD1306_ClearScreen (void) void SSD1306_ClearScreen (void)
{ {
// null cache memory lcd memset (cacheMemLcd, 0x00, CACHE_SIZE_MEM); // null cache memory lcd
memset (cacheMemLcd, 0x00, CACHE_SIZE_MEM);
} }
/** /**
* @desc SSD1306 Set position * @brief SSD1306 Set position
* *
* @param uint8_t column -> 0 ... 127 * @param uint8_t column -> 0 ... 127
* @param uint8_t page -> 0 ... 7 or 3 * @param uint8_t page -> 0 ... 7 or 3
@ -417,12 +322,11 @@ void SSD1306_ClearScreen (void)
*/ */
void SSD1306_SetPosition (uint8_t x, uint8_t y) void SSD1306_SetPosition (uint8_t x, uint8_t y)
{ {
// calculate counter _counter = x + (y << 7); // update counter
_counter = x + (y << 7);
} }
/** /**
* @desc SSD1306 Update text poisition - this ensure that character will not be divided at the end of row, * @brief 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 * the whole character will be depicted on the new row
* *
* @param void * @param void
@ -431,32 +335,23 @@ void SSD1306_SetPosition (uint8_t x, uint8_t y)
*/ */
uint8_t SSD1306_UpdatePosition (void) uint8_t SSD1306_UpdatePosition (void)
{ {
// y / 8 uint8_t y = _counter >> 7; // y / 8
uint8_t y = _counter >> 7; uint8_t x = _counter - (y << 7); // y % 8
// y % 8 uint8_t x_new = x + CHARS_COLS_LENGTH + 1; // x + character length + 1
uint8_t x = _counter - (y << 7);
// x + character length + 1 if (x_new > END_COLUMN_ADDR) { // check position
uint8_t x_new = x + CHARS_COLS_LENGTH + 1; if (y > END_PAGE_ADDR) { // if more than allowable number of pages
return SSD1306_ERROR; // return out of range
// check position } else if (y < (END_PAGE_ADDR-1)) { // if x reach the end but page in range
if (x_new > END_COLUMN_ADDR) { _counter = ((++y) << 7); // update
// 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);
} }
} }
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc SSD1306 Draw character * @brief SSD1306 Draw character
* *
* @param char character * @param char character
* *
@ -464,31 +359,21 @@ uint8_t SSD1306_UpdatePosition (void)
*/ */
uint8_t SSD1306_DrawChar (char character) uint8_t SSD1306_DrawChar (char character)
{ {
// variables
uint8_t i = 0; uint8_t i = 0;
// update text position
// 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_UpdatePosition () == SSD1306_ERROR) { if (SSD1306_UpdatePosition () == SSD1306_ERROR) {
// error
return SSD1306_ERROR; return SSD1306_ERROR;
} }
// loop through 5 bits
while (i < CHARS_COLS_LENGTH) { while (i < CHARS_COLS_LENGTH) {
// read byte
cacheMemLcd[_counter++] = pgm_read_byte(&FONTS[character-32][i++]); cacheMemLcd[_counter++] = pgm_read_byte(&FONTS[character-32][i++]);
} }
// update position
_counter++; _counter++;
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc SSD1306 Draw String * @brief SSD1306 Draw String
* *
* @param char * string * @param char * string
* *
@ -496,17 +381,14 @@ uint8_t SSD1306_DrawChar (char character)
*/ */
void SSD1306_DrawString (char *str) void SSD1306_DrawString (char *str)
{ {
// init
int i = 0; int i = 0;
// loop through character of string
while (str[i] != '\0') { while (str[i] != '\0') {
// draw string
SSD1306_DrawChar (str[i++]); SSD1306_DrawChar (str[i++]);
} }
} }
/** /**
* @desc Draw pixel * @brief Draw pixel
* *
* @param uint8_t x -> 0 ... MAX_X * @param uint8_t x -> 0 ... MAX_X
* @param uint8_t y -> 0 ... MAX_Y * @param uint8_t y -> 0 ... MAX_Y
@ -517,27 +399,20 @@ uint8_t SSD1306_DrawPixel (uint8_t x, uint8_t y)
{ {
uint8_t page = 0; uint8_t page = 0;
uint8_t pixel = 0; uint8_t pixel = 0;
// if out of range if ((x > MAX_X) || (y > MAX_Y)) { // if out of range
if ((x > MAX_X) || (y > MAX_Y)) { return SSD1306_ERROR; // out of range
// out of range
return SSD1306_ERROR;
} }
// find page (y / 8) page = y >> 3; // find page (y / 8)
page = y >> 3; pixel = 1 << (y - (page << 3)); // which pixel (y % 8)
// which pixel (y % 8) _counter = x + (page << 7); // update counter
pixel = 1 << (y - (page << 3)); cacheMemLcd[_counter++] |= pixel; // save pixel
// update counter
_counter = x + (page << 7);
// save pixel
cacheMemLcd[_counter++] |= pixel;
// success
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }
/** /**
* @desc Draw line by Bresenham algoritm * @brief Draw line by Bresenham algoritm
* *
* @param uint8_t x start position / 0 <= cols <= MAX_X-1 * @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 x end position / 0 <= cols <= MAX_X-1
@ -548,79 +423,52 @@ uint8_t SSD1306_DrawPixel (uint8_t x, uint8_t y)
*/ */
uint8_t SSD1306_DrawLine (uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2) uint8_t SSD1306_DrawLine (uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2)
{ {
// determinant int16_t D; // determinant
int16_t D; int16_t delta_x, delta_y; // deltas
// deltas int16_t trace_x = 1, trace_y = 1; // steps
int16_t delta_x, delta_y;
// steps
int16_t trace_x = 1, trace_y = 1;
// delta x delta_x = x2 - x1; // delta x
delta_x = x2 - x1; delta_y = y2 - y1; // delta y
// delta y
delta_y = y2 - y1; if (delta_x < 0) { // check if x2 > x1
delta_x = -delta_x; // negate delta x
// check if x2 > x1 trace_x = -trace_x; // negate step x
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) { // check if y2 > y1
if (delta_y < 0) { delta_y = -delta_y; // negate detla y
// negate detla y trace_y = -trace_y; // negate step y
delta_y = -delta_y;
// negate step y
trace_y = -trace_y;
} }
// Bresenham condition for m < 1 (dy < dx) // Bresenham condition for m < 1 (dy < dx)
// -------------------------------------------------------------------------------------
if (delta_y < delta_x) { if (delta_y < delta_x) {
// calculate determinant D = (delta_y << 1) - delta_x; // calculate determinant
D = (delta_y << 1) - delta_x; SSD1306_DrawPixel (x1, y1); // draw first pixel
// draw first pixel while (x1 != x2) { // check if x1 equal x2
SSD1306_DrawPixel (x1, y1); x1 += trace_x; // update x1
// check if x1 equal x2 if (D >= 0) { // check if determinant is positive
while (x1 != x2) { y1 += trace_y; // update y1
// update x1 D -= 2*delta_x; // update determinant
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; // update deteminant
D += 2*delta_y; SSD1306_DrawPixel (x1, y1); // draw next pixel
// draw next pixel
SSD1306_DrawPixel (x1, y1);
} }
// for m > 1 (dy > dx) // for m > 1 (dy > dx)
// -------------------------------------------------------------------------------------
} else { } else {
// calculate determinant D = delta_y - (delta_x << 1); // calculate determinant
D = delta_y - (delta_x << 1); SSD1306_DrawPixel (x1, y1); // draw first pixel
// draw first pixel while (y1 != y2) { // check if y2 equal y1
SSD1306_DrawPixel (x1, y1); y1 += trace_y; // update y1
// check if y2 equal y1 if (D <= 0) { // check if determinant is positive
while (y1 != y2) { x1 += trace_x; // update y1
// update y1 D += 2*delta_y; // update determinant
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; // update deteminant
D -= 2*delta_x; SSD1306_DrawPixel (x1, y1); // draw next pixel
// draw next pixel
SSD1306_DrawPixel (x1, y1);
} }
} }
// success return
return SSD1306_SUCCESS; return SSD1306_SUCCESS;
} }

View File

@ -81,7 +81,7 @@
// AREA definition // AREA definition
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
#define START_PAGE_ADDR 0 #define START_PAGE_ADDR 0
#define END_PAGE_ADDR 7 // 7 for 128x64, 3 for 128x32 version #define END_PAGE_ADDR 3 // 7 for 128x64, 3 for 128x32 version
#define START_COLUMN_ADDR 0 #define START_COLUMN_ADDR 0
#define END_COLUMN_ADDR 127 #define END_COLUMN_ADDR 127
#define RAM_X_END END_COLUMN_ADDR + 1 #define RAM_X_END END_COLUMN_ADDR + 1

56
main.c
View File

@ -1,20 +1,19 @@
/** /**
* --------------------------------------------------------------------------------------+ * --------------------------------------------------------------------------------------+
* @desc OLED SSD1306 example * @name OLED SSD1306 example
* --------------------------------------------------------------------------------------+ * --------------------------------------------------------------------------------------+
* Copyright (C) 2020 Marian Hrinko. * Copyright (C) 2020 Marian Hrinko.
* Written by Marian Hrinko (mato.hrinko@gmail.com) * Written by Marian Hrinko (mato.hrinko@gmail.com)
* *
* @author Marian Hrinko * @author Marian Hrinko
* @date 06.10.2020 * @date 06.10.2020
* @update 19.07.2021
* @file main.c * @file main.c
* @version 2.0.0 * @version 2.0.0
* @tested AVR Atmega328p * @test AVR Atmega328p
* *
* @depend lib/ssd1306.h * @depend lib/ssd1306.h
* --------------------------------------------------------------------------------------+ * --------------------------------------------------------------------------------------+
* @descr Version 1.0.0 -> applicable for 1 display * @brief Version 1.0.0 -> applicable for 1 display
* Version 2.0.0 -> rebuild to 'cacheMemLcd' array * Version 2.0.0 -> rebuild to 'cacheMemLcd' array
* Version 3.0.0 -> simplified alphanumeric version for 1 display * Version 3.0.0 -> simplified alphanumeric version for 1 display
* --------------------------------------------------------------------------------------+ * --------------------------------------------------------------------------------------+
@ -22,6 +21,7 @@
// include libraries // include libraries
#include "lib/ssd1306.h" #include "lib/ssd1306.h"
#include <util/delay.h>
/** /**
* @desc Main function * @desc Main function
@ -32,32 +32,30 @@
*/ */
int main(void) int main(void)
{ {
uint8_t addr = SSD1306_ADDR; // LCD INIT
// -------------------------------------------------------------------------------------
SSD1306_Init (SSD1306_ADDR); // 0x3C
// init ssd1306 // DRAWING
SSD1306_Init (addr); // -------------------------------------------------------------------------------------
SSD1306_ClearScreen (); // clear screen
SSD1306_DrawLine (0, MAX_X, 4, 4); // draw line
SSD1306_SetPosition (7, 1); // set position
SSD1306_DrawString ("SSD1306 OLED DRIVER"); // draw string
SSD1306_DrawLine (0, MAX_X, 18, 18); // draw line
SSD1306_SetPosition (40, 3); // set position
SSD1306_DrawString ("MATIASUS"); // draw string
SSD1306_SetPosition (53, 5); // set position
SSD1306_DrawString ("2021"); // draw string
SSD1306_UpdateScreen (SSD1306_ADDR); // update
// clear screen _delay_ms (1000);
SSD1306_ClearScreen (); SSD1306_InverseScreen (SSD1306_ADDR);
// draw line
SSD1306_DrawLine (0, MAX_X, 4, 4);
// set position
SSD1306_SetPosition (7, 1);
// draw string
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);
// return value _delay_ms (1000);
SSD1306_NormalScreen (SSD1306_ADDR);
// RETURN
// -------------------------------------------------------------------------------------
return 0; return 0;
} }