Merge with home

This commit is contained in:
Marián 2022-11-24 22:50:38 +01:00 committed by GitHub
parent e1e6535551
commit 8d0e1f2aef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,30 +1,26 @@
/**
* ---------------------------------------------------------------+
* --------------------------------------------------------------------------------------+
* @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 21.11.2022
* @update 24.11.2022
* @file ssd1306.c
* @version 3.0
* @tested AVR Atmega328
* @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
* ---------------------------------------------------------------+
* --------------------------------------------------------------------------------------+
* @usage Basic Setup for OLED Display
*/
#include <avr/pgmspace.h>
#include <string.h>
#include "font.h"
#include "twi.h"
#include "ssd1306.h"
// +---------------------------+
@ -128,17 +124,17 @@ const uint8_t INIT_SSD1306[] PROGMEM = {
0, SSD1306_DISPLAY_ON // 0xAF = Set Display ON
};
// @var array Chache memory Lcd 8 * 128 = 1024
static char cacheMemLcd[CACHE_SIZE_MEM];
unsigned short int _indexCol = START_COLUMN_ADDR; // @var global - cache index column
unsigned short int _indexPage = START_PAGE_ADDR; // @var global - cache index page
/**
* @desc SSD1306 Init
*
* @param uint8_t address
* @param void
*
* @return uint8_t
*/
uint8_t SSD1306_Init (uint8_t address)
uint8_t SSD1306_Init (void)
{
const uint8_t *commands = INIT_SSD1306; // variables
unsigned short int no_of_commands = pgm_read_byte(commands++); // number of commands
@ -152,7 +148,7 @@ uint8_t SSD1306_Init (uint8_t address)
// TWI Start & SLAW
// -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (address); // start & SLAW
status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW
if (SSD1306_SUCCESS != status) { // check status
return status; // error
}
@ -242,17 +238,17 @@ uint8_t SSD1306_Send_Command (uint8_t command)
/**
* @desc SSD1306 Normal colors
*
* @param uint8_t address
* @param void
*
* @return uint8_t
*/
uint8_t SSD1306_NormalScreen (uint8_t address)
uint8_t SSD1306_NormalScreen (void)
{
uint8_t status = INIT_STATUS; // TWI init status 0xFF
// TWI start & SLAW
// -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (address); // start & SLAW
status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW
if (SSD1306_SUCCESS != status) { // check status
return status; // error
}
@ -269,17 +265,17 @@ uint8_t SSD1306_NormalScreen (uint8_t address)
/**
* @desc SSD1306 Inverse colors
*
* @param uint8_t address
* @param void
*
* @return uint8_t
*/
uint8_t SSD1306_InverseScreen (uint8_t address)
uint8_t SSD1306_InverseScreen (void)
{
uint8_t status = INIT_STATUS;
uint8_t status = INIT_STATUS; // TWI init status 0xFF
// TWI start & SLAW
// -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (address); // start & SLAW
status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW
if (SSD1306_SUCCESS != status) { // check status
return status; // error
}
@ -294,20 +290,20 @@ uint8_t SSD1306_InverseScreen (uint8_t address)
}
/**
* @desc SSD1306 Update screen
* @desc SSD1306 Clear screen
*
* @param uint8_t address
* @param void
*
* @return uint8_t
*/
uint8_t SSD1306_UpdateScreen (uint8_t address)
uint8_t SSD1306_ClearScreen (void)
{
uint8_t status = INIT_STATUS; // TWI init status 0xFF
uint16_t i = 0; // counter
// TWI start & SLAW
// -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (address); // start & SLAW
status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW
if (SSD1306_SUCCESS != status) { // check status
return status; // error
}
@ -317,14 +313,14 @@ uint8_t SSD1306_UpdateScreen (uint8_t address)
if (SSD1306_SUCCESS != status) { // check status
return status; // error
}
// TWI send cache memory lcd
// send clear byte to memory lcd
// -------------------------------------------------------------------------------------
while (i < CACHE_SIZE_MEM) {
status = TWI_MT_Send_Data (cacheMemLcd[i]); // send data
status = TWI_MT_Send_Data (CLEAR_COLOR); // send data 0x00
if (SSD1306_SUCCESS != status) { // check status
return status; // error
}
i++; // next value
i++; // update counter
}
// TWI stop
// -------------------------------------------------------------------------------------
@ -333,18 +329,6 @@ uint8_t SSD1306_UpdateScreen (uint8_t address)
return SSD1306_SUCCESS; // success
}
/**
* @desc SSD1306 Clear screen
*
* @param void
*
* @return void
*/
void SSD1306_ClearScreen (void)
{
memset (cacheMemLcd, 0x00, CACHE_SIZE_MEM); // null cache memory lcd
}
/**
* @desc SSD1306 Set position
*
@ -353,30 +337,91 @@ void SSD1306_ClearScreen (void)
*
* @return void
*/
void SSD1306_SetPosition (uint8_t x, uint8_t y)
uint8_t SSD1306_SetPosition (uint8_t x, uint8_t y)
{
_counter = x + (y << 7); // calculate counter
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
}
/**
* @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_UpdTxtPosition (void)
uint8_t SSD1306_UpdatePosition (void)
{
uint8_t y = _counter >> 7; // y / 8
uint8_t x = _counter - (y << 7); // y % 8
uint8_t x_new = x + CHARS_COLS_LENGTH + 1; // x + character length + 1
uint8_t status = INIT_STATUS; // TWI init status 0xFF
uint8_t x = _indexCol + CHARS_COLS_LENGTH + 1; // check end col position
if (x_new > END_COLUMN_ADDR) { // check position
if (y > END_PAGE_ADDR) { // if more than allowable number of pages
// 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
} else if (y < (END_PAGE_ADDR-1)) { // if x reach the end but page in range
_counter = ((++y) << 7); // update
}
}
@ -392,17 +437,48 @@ uint8_t SSD1306_UpdTxtPosition (void)
*/
uint8_t SSD1306_DrawChar (char ch)
{
uint8_t i = 0;
uint8_t status = INIT_STATUS; // TWI init status 0xFF
uint16_t i = 0; // counter
// 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_UpdTxtPosition () == SSD1306_ERROR) {
return SSD1306_ERROR; // error
// -------------------------------------------------------------------------------------
status = SSD1306_UpdatePosition();
if (SSD1306_SUCCESS != status) { // check status
return status; // error
}
while (i < CHARS_COLS_LENGTH) { // loop through 5 bits
cacheMemLcd[_counter++] = pgm_read_byte(&FONTS[ch-32][i++]); // read byte
// TWI start & SLAW
// -------------------------------------------------------------------------------------
status = SSD1306_Send_StartAndSLAW (SSD1306_ADDR); // start & SLAW
if (SSD1306_SUCCESS != status) { // check status
return status; // error
}
_counter++; // update position
// 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
// -------------------------------------------------------------------------------------
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
}
_indexCol = _indexCol + CHARS_COLS_LENGTH + 1; // update global col
// TWI stop
// -------------------------------------------------------------------------------------
TWI_Stop ();
return SSD1306_SUCCESS; // success
}
@ -412,15 +488,19 @@ uint8_t SSD1306_DrawChar (char ch)
*
* @param char * string
*
* @return void
* @return uint8_t
*/
void SSD1306_DrawString (char *str)
uint8_t SSD1306_DrawString (char *str)
{
int i = 0; // init
uint8_t i = 0; // char counter
while (str[i] != '\0') { // loop through character of string
SSD1306_DrawChar (str[i++]); // draw string
// send characters of string
// -------------------------------------------------------------------------------------
while (str[i] != '\0') {
SSD1306_DrawChar (str[i++]); // send char
}
return SSD1306_SUCCESS; // success
}
/**
@ -433,77 +513,46 @@ void SSD1306_DrawString (char *str)
*/
uint8_t SSD1306_DrawPixel (uint8_t x, uint8_t y)
{
uint8_t page = 0;
uint8_t pixel = 0;
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; // out of range
return SSD1306_ERROR; // error
}
page = y >> 3; // find page (y / 8)
pixel = 1 << (y - (page << 3)); // which pixel (y % 8)
_counter = x + (page << 7); // update counter
cacheMemLcd[_counter++] |= pixel; // save pixel
// set position
// -------------------------------------------------------------------------------------
status = SSD1306_SetPosition (x, page); // update position
if (SSD1306_SUCCESS != status) { // check status
return status; // 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 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
}
/**
* @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)
{
int16_t D; // determinant
int16_t delta_x, delta_y; // deltas
int16_t trace_x = 1, trace_y = 1; // steps
delta_x = x2 - x1; // delta x
delta_y = y2 - y1; // delta y
if (delta_x < 0) { // check if x2 > x1
delta_x = -delta_x; // negate delta x
trace_x = -trace_x; // negate step x
}
if (delta_y < 0) { // check if y2 > y1
delta_y = -delta_y; // negate delta y
trace_y = -trace_y; // negate step y
}
// condition for m < 1 (dy < dx)
// -------------------------------------------------------------------------------------
if (delta_y < delta_x) { //
D = (delta_y << 1) - delta_x; // calculate determinant
SSD1306_DrawPixel (x1, y1); // draw first pixel
while (x1 != x2) { // check if x1 equal x2
x1 += trace_x; // update x1
if (D >= 0) { // positive?
y1 += trace_y; // update y1
D -= 2*delta_x; // update determinant
}
D += 2*delta_y; // update deteminant
SSD1306_DrawPixel (x1, y1); // draw next pixel
}
// condition for m >= 1 (dy >= dx)
// -------------------------------------------------------------------------------------
} else {
D = delta_y - (delta_x << 1); // calculate determinant
SSD1306_DrawPixel (x1, y1); // draw first pixel
while (y1 != y2) { // check if y2 equal y1
y1 += trace_y; // update y1
if (D <= 0) { // positive?
x1 += trace_x; // update y1
D += 2*delta_y; // update determinant
}
D -= 2*delta_x; // update deteminant
SSD1306_DrawPixel (x1, y1); // draw next pixel
}
}
return SSD1306_SUCCESS; // success return
}