Commits vergleichen

..

Keine gemeinsamen Commits. "master" und "V1.0.0" haben vollständig unterschiedliche Historien.

11 geänderte Dateien mit 523 neuen und 844 gelöschten Zeilen

Datei anzeigen

@ -42,7 +42,7 @@ MCU = atmega328p
# Main Oscillator Frequency
# This is only used to define F_CPU in all assembler and c-sources.
F_CPU = 16000000UL
F_CPU = 14745600UL
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
@ -52,7 +52,7 @@ TARGET = main
# List C source files here. (C dependencies are automatically generated.)
SRC = $(wildcard *.c)
SRC = $(TARGET).c i2c.c lcd.c
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
@ -111,7 +111,7 @@ CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
CFLAGS += -DF_CPU=$(F_CPU)
#CFLAGS += -finput-charset=utf-8 -fexec-charset=iso-8859-15
CFLAGS += -finput-charset=utf-8 -fexec-charset=iso-8859-15
@ -207,7 +207,7 @@ AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
AVRDUDE_FLAGS += -b 19200
AVRDUDE_FLAGS += -B 1

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 1.0 MiB

140
font.c
Datei anzeigen

@ -1,140 +0,0 @@
/*
* font.c
* i2c
*
* Created by Michael Köhler on 16.09.18.
* Copyright 2018 Skie-Systems. All rights reserved.
*
*/
#include "font.h"
const char ssd1306oled_font[][6] PROGMEM = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // sp
{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00}, // !
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00}, // "
{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14}, // #
{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12}, // $
{0x00, 0x62, 0x64, 0x08, 0x13, 0x23}, // %
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50}, // &
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00}, // '
{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00}, // (
{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00}, // )
{0x00, 0x14, 0x08, 0x3E, 0x08, 0x14}, // *
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08}, // +
{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00}, // ,
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08}, // -
{0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, // .
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02}, // /
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00}, // 1
{0x00, 0x42, 0x61, 0x51, 0x49, 0x46}, // 2
{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31}, // 3
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10}, // 4
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39}, // 5
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03}, // 7
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36}, // 8
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E}, // 9
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00}, // :
{0x00, 0x00, 0x56, 0x36, 0x00, 0x00}, // ;
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00}, // <
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14}, // =
{0x00, 0x00, 0x41, 0x22, 0x14, 0x08}, // >
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06}, // ?
{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E}, // @
{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}, // A
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36}, // B
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22}, // C
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C}, // D
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41}, // E
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01}, // F
{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A}, // G
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F}, // H
{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00}, // I
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01}, // J
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41}, // K
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40}, // L
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F}, // M
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F}, // N
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E}, // O
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06}, // P
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46}, // R
{0x00, 0x46, 0x49, 0x49, 0x49, 0x31}, // S
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01}, // T
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F}, // U
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F}, // V
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F}, // W
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63}, // X
{0x00, 0x07, 0x08, 0x70, 0x08, 0x07}, // Y
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43}, // Z
{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00}, // [
{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55}, // backslash
{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00}, // ]
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04}, // ^
{0x00, 0x40, 0x40, 0x40, 0x40, 0x40}, // _
{0x00, 0x00, 0x01, 0x02, 0x04, 0x00}, // '
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78}, // a
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38}, // b
{0x00, 0x38, 0x44, 0x44, 0x44, 0x20}, // c
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F}, // d
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18}, // e
{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02}, // f
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C}, // g
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78}, // h
{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00}, // i
{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00}, // j
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00}, // k
{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00}, // l
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78}, // m
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78}, // n
{0x00, 0x38, 0x44, 0x44, 0x44, 0x38}, // o
{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18}, // p
{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC}, // q
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08}, // r
{0x00, 0x48, 0x54, 0x54, 0x54, 0x20}, // s
{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20}, // t
{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C}, // u
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C}, // v
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C}, // w
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44}, // x
{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C}, // y
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44}, // z
{0x00, 0x00, 0x08, 0x77, 0x41, 0x00}, // {
{0x00, 0x00, 0x00, 0x63, 0x00, 0x00}, // ¦
{0x00, 0x00, 0x41, 0x77, 0x08, 0x00}, // }
{0x00, 0x08, 0x04, 0x08, 0x08, 0x04}, // ~
/* end of normal char-set */
/* put your own signs/chars here, edit special_char too */
/* be sure that your first special char stand here */
{0x00, 0x3A, 0x40, 0x40, 0x20, 0x7A}, // ü, !!! Important: this must be special_char[0] !!!
{0x00, 0x3D, 0x40, 0x40, 0x40, 0x3D}, // Ü
{0x00, 0x21, 0x54, 0x54, 0x54, 0x79}, // ä
{0x00, 0x7D, 0x12, 0x11, 0x12, 0x7D}, // Ä
{0x00, 0x39, 0x44, 0x44, 0x44, 0x39}, // ö
{0x00, 0x3D, 0x42, 0x42, 0x42, 0x3D}, // Ö
{0x00, 0x02, 0x05, 0x02, 0x00, 0x00}, // °
{0x00, 0x7E, 0x01, 0x49, 0x55, 0x73}, // ß
{0x00, 0x7C, 0x10, 0x10, 0x08, 0x1C}, // µ
{0x00, 0x30, 0x48, 0x20, 0x48, 0x30}, // ω
{0x00, 0x5C, 0x62, 0x02, 0x62, 0x5C} // Ω
};
const char special_char[][2] PROGMEM = {
// define position of special char in font
// {special char, position in font}
// be sure that last element of this
// array are {0xff, 0xff} and first element
// are {first special char, first element after normal char-set in font}
{'ü', 95}, // special_char[0]
{'Ü', 96},
{'ä', 97},
{'Ä', 98},
{'ö', 99},
{'Ö', 100},
{'°', 101},
{'ß', 102},
{'µ', 103},
{'ω', 104},
{'Ω', 105},
{0xff, 0xff} // end of table special_char
};

16
font.h
Datei anzeigen

@ -1,16 +0,0 @@
/*
* font.h
* i2c
*
* Created by Michael Köhler on 13.09.18.
* Copyright 2018 Skie-Systems. All rights reserved.
*
*/
#ifndef _font_h_
#define _font_h_
#include <avr/pgmspace.h>
extern const char ssd1306oled_font[][6] PROGMEM;
extern const char special_char[][2] PROGMEM;
#endif

71
i2c.c
Datei anzeigen

@ -8,16 +8,7 @@
#include "i2c.h"
#if defined (__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || \
defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168PA__) || \
defined(__AVR_ATmega88P__) || \
defined(__AVR_ATmega8__) || \
defined(__AVR_ATmega48P__) || \
defined(__AVR_ATmega1284P__) || \
defined (__AVR_ATmega324A__) || defined (__AVR_ATmega324P__) || defined (__AVR_ATmega324PA__) || \
defined (__AVR_ATmega644__) || defined (__AVR_ATmega644A__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) || \
defined (__AVR_ATmega1284P__) || \
defined (__AVR_ATmega2560__)
#if defined (__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega1284P__) || defined (__AVR_ATmega324A__) || defined (__AVR_ATmega324P__) || defined (__AVR_ATmega324PA__) || defined (__AVR_ATmega644__) || defined (__AVR_ATmega644A__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) || defined (__AVR_ATmega1284P__)
#if PSC_I2C != 1 && PSC_I2C != 4 && PSC_I2C != 16 && PSC_I2C != 64
#error "Wrong prescaler for TWI !"
#elif SET_TWBR < 0 || SET_TWBR > 255
@ -25,15 +16,7 @@ defined (__AVR_ATmega2560__)
#endif
uint8_t I2C_ErrorCode;
/**********************************************
Public Function: i2c_init
Purpose: Initialise TWI/I2C interface
Input Parameter: none
Return Value: none
**********************************************/
void i2c_init(void){
// set clock
switch (PSC_I2C) {
@ -54,16 +37,6 @@ void i2c_init(void){
// enable
TWCR = (1 << TWEN);
}
/**********************************************
Public Function: i2c_start
Purpose: Start TWI/I2C interface
Input Parameter:
- uint8_t i2c_addr: Adress of reciever
Return Value: none
**********************************************/
void i2c_start(uint8_t i2c_addr){
// i2c start
TWCR = (1 << TWINT)|(1 << TWSTA)|(1 << TWEN);
@ -89,29 +62,10 @@ void i2c_start(uint8_t i2c_addr){
}
};
}
/**********************************************
Public Function: i2c_stop
Purpose: Stop TWI/I2C interface
Input Parameter: none
Return Value: none
**********************************************/
void i2c_stop(void){
// i2c stop
TWCR = (1 << TWINT)|(1 << TWSTO)|(1 << TWEN);
}
/**********************************************
Public Function: i2c_byte
Purpose: Send byte at TWI/I2C interface
Input Parameter:
- uint8_t byte: Byte to send to reciever
Return Value: none
**********************************************/
void i2c_byte(uint8_t byte){
TWDR = byte;
TWCR = (1 << TWINT)|( 1 << TWEN);
@ -125,17 +79,6 @@ void i2c_byte(uint8_t byte){
}
};
}
/**********************************************
Public Function: i2c_readAck
Purpose: read acknowledge from TWI/I2C Interface
Input Parameter: none
Return Value: uint8_t
- TWDR: recieved value at TWI/I2C-Interface, 0 at timeout
- 0: Error at read
**********************************************/
uint8_t i2c_readAck(void){
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
uint16_t timeout = F_CPU/F_I2C*2.0;
@ -149,18 +92,6 @@ uint8_t i2c_readAck(void){
};
return TWDR;
}
/**********************************************
Public Function: i2c_readNAck
Purpose: read non-acknowledge from TWI/I2C Interface
Input Parameter: none
Return Value: uint8_t
- TWDR: recieved value at TWI/I2C-Interface
- 0: Error at read
**********************************************/
uint8_t i2c_readNAck(void){
TWCR = (1<<TWINT)|(1<<TWEN);
uint16_t timeout = F_CPU/F_I2C*2.0;

8
i2c.h
Datei anzeigen

@ -9,10 +9,6 @@
#ifndef i2c_h
#define i2c_h
#ifdef __cplusplus
extern "C" {
#endif
/* TODO: setup i2c/twi */
#define F_I2C 100000UL// clock i2c
#define PSC_I2C 1 // prescaler i2c
@ -39,8 +35,4 @@ void i2c_byte(uint8_t byte); // send data_byte
uint8_t i2c_readAck(void); // read byte with ACK
uint8_t i2c_readNAck(void); // read byte with NACK
#ifdef __cplusplus
}
#endif
#endif /* i2c_h */

744
lcd.c
Datei anzeigen

@ -1,11 +1,11 @@
/*
* This file is part of lcd library for ssd1306/ssd1309/sh1106 oled-display.
* This file is part of lcd library for ssd1306/sh1106 oled-display.
*
* lcd library for ssd1306/ssd1309/sh1106 oled-display is free software: you can redistribute it and/or modify
* lcd library for ssd1306/sh1106 oled-display is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
*
* lcd library for ssd1306/ssd1309/sh1106 oled-display is distributed in the hope that it will be useful,
* lcd library for ssd1306/sh1106 oled-display is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
@ -13,14 +13,14 @@
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*
* Diese Datei ist Teil von lcd library for ssd1306/ssd1309/sh1106 oled-display.
* Diese Datei ist Teil von lcd library for ssd1306/sh1106 oled-display.
*
* lcd library for ssd1306/ssd1309/sh1106 oled-display ist Freie Software: Sie können es unter den Bedingungen
* lcd library for ssd1306/sh1106 oled-display ist Freie Software: Sie können es unter den Bedingungen
* der GNU General Public License, wie von der Free Software Foundation,
* Version 3 der Lizenz oder jeder späteren
* veröffentlichten Version, weiterverbreiten und/oder modifizieren.
*
* lcd library for ssd1306/ssd1309/sh1106 oled-display wird in der Hoffnung, dass es nützlich sein wird, aber
* lcd library for ssd1306/sh1106 oled-display wird in der Hoffnung, dass es nützlich sein wird, aber
* OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
* Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
* Siehe die GNU General Public License für weitere Details.
@ -33,39 +33,130 @@
* Created by Michael Köhler on 22.12.16.
* Copyright 2016 Skie-Systems. All rights reserved.
*
* lib for OLED-Display with ssd1306/ssd1309/sh1106-Controller
* lib for OLED-Display with ssd1306/sh1106-Controller
* first dev-version only for I2C-Connection
* at ATMega328P like Arduino Uno
*
* at GRAPHICMODE lib needs static SRAM for display:
* at GRAPHICMODE lib needs SRAM for display
* DISPLAY-WIDTH * DISPLAY-HEIGHT + 2 bytes
*
* at TEXTMODE lib need static SRAM for display:
* 2 bytes (cursorPosition)
*/
#include "lcd.h"
#include "font.h"
#include <string.h>
#if defined SPI
#include <util/delay.h>
#endif
static struct {
uint8_t x;
uint8_t y;
} cursorPosition;
static uint8_t charMode = NORMALSIZE;
uint8_t cursorPosition=0;
#if defined GRAPHICMODE
#include <stdlib.h>
static uint8_t displayBuffer[DISPLAY_HEIGHT/8][DISPLAY_WIDTH];
#elif defined TEXTMODE
#else
#error "No valid displaymode! Refer lcd.h"
static uint8_t displayBuffer[DISPLAYSIZE];
uint16_t actualIndex = 0;
#endif
/* Standard ASCII 6x8 font */
static const uint8_t ssd1306oled_font6x8 [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // "
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $
0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %
0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &
0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -
0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .
0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :
0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <
0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >
0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R
0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W
0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X
0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y
0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // backslash
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]
0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^
0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _
0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '
0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b
0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d
0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n
0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r
0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w
0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, // z
0x00, 0x00, 0x08, 0x77, 0x41, 0x00, // {
0x00, 0x00, 0x00, 0x63, 0x00, 0x00, // ¦
0x00, 0x00, 0x41, 0x77, 0x08, 0x00, // }
0x00, 0x08, 0x04, 0x08, 0x08, 0x04, // ~
0x00, 0x3D, 0x40, 0x40, 0x20, 0x7D, // ü
0x00, 0x3D, 0x40, 0x40, 0x40, 0x3D, // Ü
0x00, 0x21, 0x54, 0x54, 0x54, 0x79, // ä
0x00, 0x7D, 0x12, 0x11, 0x12, 0x7D, // Ä
0x00, 0x39, 0x44, 0x44, 0x44, 0x39, // ö
0x00, 0x3D, 0x42, 0x42, 0x42, 0x3D, // Ö
0x00, 0x02, 0x05, 0x02, 0x00, 0x00, // °
0x00, 0x7E, 0x01, 0x49, 0x55, 0x73, // ß
};
const uint8_t init_sequence [] PROGMEM = { // Initialization Sequence
LCD_DISP_OFF, // Display OFF (sleep mode)
@ -80,77 +171,38 @@ const uint8_t init_sequence [] PROGMEM = { // Initialization Sequence
0x81, 0x3F, // Set contrast control register
0xA1, // Set Segment Re-map. A0=address mapped; A1=address 127 mapped.
0xA6, // Set display mode. A6=Normal; A7=Inverse
0xA8, DISPLAY_HEIGHT-1, // Set multiplex ratio(1 to 64)
0xA8, 0x3F, // Set multiplex ratio(1 to 64)
0xA4, // Output RAM to Display
// 0xA4=Output follows RAM content; 0xA5,Output ignores RAM content
0xD3, 0x00, // Set display offset. 00 = no offset
0xD5, // --set display clock divide ratio/oscillator frequency
0xF0, // --set divide ratio
0xD9, 0x22, // Set pre-charge period
// Set com pins hardware configuration
#if DISPLAY_HEIGHT==64
0xDA, 0x12,
#elif DISPLAY_HEIGHT==32
0xDA, 0x02,
#endif
0xDA, 0x12, // Set com pins hardware configuration
0xDB, // --set vcomh
0x20, // 0x20,0.77xVcc
0x8D, 0x14, // Set DC-DC enable
};
#pragma mark LCD COMMUNICATION
void lcd_command(uint8_t cmd[], uint8_t size) {
#if defined I2C
i2c_start((LCD_I2C_ADR << 1) | 0);
i2c_start(LCD_I2C_ADR);
i2c_byte(0x00); // 0x00 for command, 0x40 for data
for (uint8_t i=0; i<size; i++) {
i2c_byte(cmd[i]);
}
i2c_stop();
#elif defined SPI
LCD_PORT &= ~(1 << CS_PIN);
LCD_PORT &= ~(1 << DC_PIN);
for (uint8_t i=0; i<size; i++) {
SPDR = cmd[i];
while(!(SPSR & (1<<SPIF)));
}
LCD_PORT |= (1 << CS_PIN);
#endif
}
void lcd_data(uint8_t data[], uint16_t size) {
#if defined I2C
i2c_start((LCD_I2C_ADR << 1) | 0);
i2c_start(LCD_I2C_ADR);
i2c_byte(0x40); // 0x00 for command, 0x40 for data
for (uint16_t i = 0; i<size; i++) {
i2c_byte(data[i]);
}
i2c_stop();
#elif defined SPI
LCD_PORT &= ~(1 << CS_PIN);
LCD_PORT |= (1 << DC_PIN);
for (uint16_t i = 0; i<size; i++) {
SPDR = data[i];
while(!(SPSR & (1<<SPIF)));
}
LCD_PORT |= (1 << CS_PIN);
#endif
}
#pragma mark -
#pragma mark GENERAL FUNCTIONS
void lcd_init(uint8_t dispAttr){
#if defined I2C
i2c_init();
#elif defined SPI
DDRB |= (1 << PB2)|(1 << PB3)|(1 << PB5);
SPCR = (1 << SPE)|(1<<MSTR)|(1<<SPR0);
LCD_DDR |= (1 << CS_PIN)|(1 << DC_PIN)|(1 << RES_PIN);
LCD_PORT |= (1 << CS_PIN)|(1 << DC_PIN)|(1 << RES_PIN);
LCD_PORT &= ~(1 << RES_PIN);
_delay_ms(10);
LCD_PORT |= (1 << RES_PIN);
#endif
uint8_t commandSequence[sizeof(init_sequence)+1];
for (uint8_t i = 0; i < sizeof (init_sequence); i++) {
commandSequence[i] = (pgm_read_byte(&init_sequence[i]));
@ -159,217 +211,23 @@ void lcd_init(uint8_t dispAttr){
lcd_command(commandSequence, sizeof(commandSequence));
lcd_clrscr();
}
void lcd_gotoxy(uint8_t x, uint8_t y){
x = x * sizeof(FONT[0]);
lcd_goto_xpix_y(x,y);
}
void lcd_goto_xpix_y(uint8_t x, uint8_t y){
if( x > (DISPLAY_WIDTH) || y > (DISPLAY_HEIGHT/8-1)) return;// out of display
cursorPosition.x=x;
cursorPosition.y=y;
#if defined (SSD1306) || defined (SSD1309)
uint8_t commandSequence[] = {0xb0+y, 0x21, x, 0x7f};
#elif defined SH1106
uint8_t commandSequence[] = {0xb0+y, 0x21, 0x00+((2+x) & (0x0f)), 0x10+( ((2+x) & (0xf0)) >> 4 ), 0x7f};
#endif
lcd_command(commandSequence, sizeof(commandSequence));
}
void lcd_clrscr(void){
#ifdef GRAPHICMODE
for (uint8_t i = 0; i < DISPLAY_HEIGHT/8; i++){
memset(displayBuffer[i], 0x00, sizeof(displayBuffer[i]));
lcd_gotoxy(0,i);
lcd_data(displayBuffer[i], sizeof(displayBuffer[i]));
}
#elif defined TEXTMODE
uint8_t displayBuffer[DISPLAY_WIDTH];
memset(displayBuffer, 0x00, sizeof(displayBuffer));
for (uint8_t i = 0; i < DISPLAY_HEIGHT/8; i++){
lcd_gotoxy(0,i);
lcd_data(displayBuffer, sizeof(displayBuffer));
}
#endif
lcd_home();
}
void lcd_home(void){
lcd_gotoxy(0, 0);
}
void lcd_invert(uint8_t invert){
i2c_start(LCD_I2C_ADR);
uint8_t commandSequence[1];
if (invert != YES) {
commandSequence[0] = 0xA6;
if (invert == YES) {
commandSequence[0] = 0xA7;
} else {
commandSequence[0] = 0xA7;
}
lcd_command(commandSequence, 1);
}
void lcd_sleep(uint8_t sleep){
uint8_t commandSequence[1];
if (sleep != YES) {
commandSequence[0] = 0xAF;
} else {
commandSequence[0] = 0xAE;
}
lcd_command(commandSequence, 1);
}
void lcd_set_contrast(uint8_t contrast){
uint8_t commandSequence[2] = {0x81, contrast};
lcd_command(commandSequence, sizeof(commandSequence));
}
void lcd_putc(char c){
switch (c) {
case '\b':
// backspace
lcd_gotoxy(cursorPosition.x-charMode, cursorPosition.y);
lcd_putc(' ');
lcd_gotoxy(cursorPosition.x-charMode, cursorPosition.y);
break;
case '\t':
// tab
if( (cursorPosition.x+charMode*4) < (DISPLAY_WIDTH/ sizeof(FONT[0])-charMode*4) ){
lcd_gotoxy(cursorPosition.x+charMode*4, cursorPosition.y);
}else{
lcd_gotoxy(DISPLAY_WIDTH/ sizeof(FONT[0]), cursorPosition.y);
}
break;
case '\n':
// linefeed
if(cursorPosition.y < (DISPLAY_HEIGHT/8-1)){
lcd_gotoxy(cursorPosition.x, cursorPosition.y+charMode);
}
break;
case '\r':
// carrige return
lcd_gotoxy(0, cursorPosition.y);
break;
default:
// char doesn't fit in line
if( (cursorPosition.x >= DISPLAY_WIDTH-sizeof(FONT[0])) || (c < ' ') ) break;
// mapping char
c -= ' ';
if (c >= pgm_read_byte(&special_char[0][1]) ) {
char temp = c;
c = 0xff;
for (uint8_t i=0; pgm_read_byte(&special_char[i][1]) != 0xff; i++) {
if ( pgm_read_byte(&special_char[i][0])-' ' == temp ) {
c = pgm_read_byte(&special_char[i][1]);
break;
}
}
if ( c == 0xff ) break;
}
// print char at display
#ifdef GRAPHICMODE
if (charMode == DOUBLESIZE) {
uint16_t doubleChar[sizeof(FONT[0])];
uint8_t dChar;
if ((cursorPosition.x+2*sizeof(FONT[0]))>DISPLAY_WIDTH) break;
for (uint8_t i=0; i < sizeof(FONT[0]); i++) {
doubleChar[i] = 0;
dChar = pgm_read_byte(&(FONT[(uint8_t)c][i]));
for (uint8_t j=0; j<8; j++) {
if ((dChar & (1 << j))) {
doubleChar[i] |= (1 << (j*2));
doubleChar[i] |= (1 << ((j*2)+1));
}
}
}
for (uint8_t i = 0; i < sizeof(FONT[0]); i++)
{
// load bit-pattern from flash
displayBuffer[cursorPosition.y+1][cursorPosition.x+(2*i)] = doubleChar[i] >> 8;
displayBuffer[cursorPosition.y+1][cursorPosition.x+(2*i)+1] = doubleChar[i] >> 8;
displayBuffer[cursorPosition.y][cursorPosition.x+(2*i)] = doubleChar[i] & 0xff;
displayBuffer[cursorPosition.y][cursorPosition.x+(2*i)+1] = doubleChar[i] & 0xff;
}
cursorPosition.x += sizeof(FONT[0])*2;
} else {
if ((cursorPosition.x+sizeof(FONT[0]))>DISPLAY_WIDTH) break;
for (uint8_t i = 0; i < sizeof(FONT[0]); i++)
{
// load bit-pattern from flash
displayBuffer[cursorPosition.y][cursorPosition.x+i] =pgm_read_byte(&(FONT[(uint8_t)c][i]));
}
cursorPosition.x += sizeof(FONT[0]);
}
#elif defined TEXTMODE
if (charMode == DOUBLESIZE) {
uint16_t doubleChar[sizeof(FONT[0])];
uint8_t dChar;
if ((cursorPosition.x+2*sizeof(FONT[0]))>DISPLAY_WIDTH) break;
for (uint8_t i=0; i < sizeof(FONT[0]); i++) {
doubleChar[i] = 0;
dChar = pgm_read_byte(&(FONT[(uint8_t)c][i]));
for (uint8_t j=0; j<8; j++) {
if ((dChar & (1 << j))) {
doubleChar[i] |= (1 << (j*2));
doubleChar[i] |= (1 << ((j*2)+1));
}
}
}
uint8_t data[sizeof(FONT[0])*2];
for (uint8_t i = 0; i < sizeof(FONT[0]); i++)
{
// print font to ram, print 6 columns
data[i<<1]=(doubleChar[i] & 0xff);
data[(i<<1)+1]=(doubleChar[i] & 0xff);
}
lcd_data(data, sizeof(FONT[0])*2);
#if defined (SSD1306) || defined (SSD1309)
uint8_t commandSequence[] = {0xb0+cursorPosition.y+1,
0x21,
cursorPosition.x,
0x7f};
#elif defined SH1106
uint8_t commandSequence[] = {0xb0+cursorPosition.y+1,
0x21,
0x00+((2+cursorPosition.x) & (0x0f)),
0x10+( ((2+cursorPosition.x) & (0xf0)) >> 4 ),
0x7f};
#endif
lcd_command(commandSequence, sizeof(commandSequence));
for (uint8_t i = 0; i < sizeof(FONT[0]); i++)
{
// print font to ram, print 6 columns
data[i<<1]=(doubleChar[i] >> 8);
data[(i<<1)+1]=(doubleChar[i] >> 8);
}
lcd_data(data, sizeof(FONT[0])*2);
commandSequence[0] = 0xb0+cursorPosition.y;
#if defined (SSD1306) || defined (SSD1309)
commandSequence[2] = cursorPosition.x+(2*sizeof(FONT[0]));
#elif defined SH1106
commandSequence[2] = 0x00+((2+cursorPosition.x+(2*sizeof(FONT[0]))) & (0x0f));
commandSequence[3] = 0x10+( ((2+cursorPosition.x+(2*sizeof(FONT[0]))) & (0xf0)) >> 4 );
#endif
lcd_command(commandSequence, sizeof(commandSequence));
cursorPosition.x += sizeof(FONT[0])*2;
} else {
uint8_t data[sizeof(FONT[0])];
if ((cursorPosition.x+sizeof(FONT[0]))>DISPLAY_WIDTH) break;
for (uint8_t i = 0; i < sizeof(FONT[0]); i++)
{
// print font to ram, print 6 columns
data[i]=(pgm_read_byte(&(FONT[(uint8_t)c][i])));
}
lcd_data(data, sizeof(FONT[0]));
cursorPosition.x += sizeof(FONT[0]);
}
#endif
break;
}
}
void lcd_charMode(uint8_t mode){
charMode = mode;
}
void lcd_puts(const char* s){
while (*s) {
lcd_putc(*s++);
@ -381,50 +239,261 @@ void lcd_puts_p(const char* progmem_s){
lcd_putc(c);
}
}
#ifdef GRAPHICMODE
#pragma mark -
#pragma mark GRAPHIC FUNCTIONS
uint8_t lcd_drawPixel(uint8_t x, uint8_t y, uint8_t color){
if( x > DISPLAY_WIDTH-1 || y > (DISPLAY_HEIGHT-1)) return 1; // out of Display
#if defined TEXTMODE
void lcd_clrscr(void){
uint8_t clearLine[DISPLAY_WIDTH];
memset(clearLine, 0x00, DISPLAY_WIDTH);
for (uint8_t j = 0; j < DISPLAY_HEIGHT/8; j++){
lcd_gotoxy(0,j);
lcd_data(clearLine, sizeof(clearLine));
if( color == WHITE){
displayBuffer[(y / 8)][x] |= (1 << (y % 8));
} else {
displayBuffer[(y / 8)][x] &= ~(1 << (y % 8));
}
return 0;
lcd_home();
}
void lcd_gotoxy(uint8_t x, uint8_t y) {
if( x > (DISPLAY_WIDTH/6) || y > (DISPLAY_HEIGHT/8-1)) return;// out of display
cursorPosition=x;
x = x * 6; // one char: 6 pixel width
#if defined SSD1306
uint8_t commandSequence[] = {0xb0+y, 0x21, x, 0x7f};
#elif defined SH1106
uint8_t commandSequence[] = {0xb0+y, 0x21, 0x00+((2+x) & (0x0f)), 0x10+( ((2+x) & (0xf0)) >> 4 ), 0x7f};
#endif
lcd_command(commandSequence, sizeof(commandSequence));
}
void lcd_putc(char c){
if((c > 127 ||
cursorPosition > 20 ||
c < 32) &&
(c != 'ü' &&
c != 'ö' &&
c != '°' &&
c != 'ä' &&
c != 'ß' &&
c != 'Ü' &&
c != 'Ö' &&
c != 'Ä' ) ) return;
cursorPosition++;
i2c_start(LCD_I2C_ADR);
i2c_byte(0x40); // 0x00 for command, 0x40 for data
switch (c) {
case 'ü':
c = 95; // ü
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
break;
case 'ö':
c = 99; // ö
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
break;
case '°':
c = 101; // °
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
break;
case 'ä':
c = 97; // ä
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
break;
case 'ß':
c = 102; // ß
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
break;
case 'Ü':
c = 96; // Ü
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
break;
case 'Ö':
c = 100; // Ö
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
break;
case 'Ä':
c = 98; // Ä
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
break;
default:
c -= 32;
if( c < 127-32 ) {
for (uint8_t i = 0; i < 6; i++)
{
i2c_byte(pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i])); // print font to ram, print 6 columns
}
//return;
}
break;
}
i2c_stop();
}
#elif defined GRAPHICMODE
void lcd_clrscr(void){
memset(displayBuffer, 0x00, sizeof(displayBuffer));
#if defined SSD1306
lcd_data(displayBuffer, sizeof(displayBuffer));
#elif defined SH1106
for (uint8_t i=0; i <= DISPLAY_HEIGHT/8; i++) {
uint8_t actualLine[DISPLAY_WIDTH];
for (uint8_t j=0; j< DISPLAY_WIDTH; j++) {
actualLine[j]=displayBuffer[i*DISPLAY_WIDTH+j];
}
lcd_data(actualLine, sizeof(actualLine));
lcd_gotoxy(0, i);
}
#endif
lcd_home();
}
void lcd_gotoxy(uint8_t x, uint8_t y){
if( x > (DISPLAY_WIDTH/6) || y > (DISPLAY_HEIGHT/8-1)) return;// out of display
cursorPosition=x;
x = x * 6; // one char: 6 pixel width
actualIndex = (x)+(y*DISPLAY_WIDTH);
#if defined SSD1306
uint8_t commandSequence[] = {0xb0+y, 0x21, x, 0x7f};
#elif defined SH1106
uint8_t commandSequence[] = {0xb0+y, 0x21, 0x00+((2+x) & (0x0f)), 0x10+( ((2+x) & (0xf0)) >> 4 ), 0x7f};
#endif
lcd_command(commandSequence, sizeof(commandSequence));
}
void lcd_putc(char c){
if((actualIndex+1)%127 != 0){
if((c > 127 ||
cursorPosition > 20 ||
c < 32) &&
(c != 'ü' &&
c != 'ö' &&
c != '°' &&
c != 'ä' &&
c != 'ß' &&
c != 'Ü' &&
c != 'Ö' &&
c != 'Ä' ) ) return;
cursorPosition++;
switch (c) {
case 'ü':
c = 95; // ü - 188
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]); // print font to ram, print 6 columns
}
break;
case 'ö':
c = 99; // ö
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]); // print font to ram, print 6 columns
}
break;
case '°':
c = 101; // °
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]); // print font to ram, print 6 columns
}
break;
case 'ä':
c = 97; // ä
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]); // print font to ram, print 6 columns
}
break;
case 'ß':
c = 102; // ß
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]); // print font to ram, print 6 columns
}
break;
case 'Ü':
c = 96; // Ü
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]); // print font to ram, print 6 columns
}
break;
case 'Ö':
c = 100; // Ö
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]); // print font to ram, print 6 columns
}
break;
case 'Ä':
c = 98; // Ä
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]); // print font to ram, print 6 columns
}
break;
default:
c -= 32;
for (uint8_t i = 0; i < 6; i++)
{
displayBuffer[actualIndex+i] = pgm_read_byte(&ssd1306oled_font6x8[c * 6 + i]);
}
break;
}
}
actualIndex += 6;
}
uint8_t lcd_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color){
uint8_t result;
void lcd_drawPixel(uint8_t x, uint8_t y, uint8_t color){
if( x > DISPLAY_WIDTH-1 || y > (DISPLAY_HEIGHT-1)) return; // out of Display
if( color == WHITE){
displayBuffer[(uint8_t)(y / (DISPLAY_HEIGHT/8)) * DISPLAY_WIDTH +x] |= (1 << (y % (DISPLAY_HEIGHT/8)));
} else {
displayBuffer[(uint8_t)(y / (DISPLAY_HEIGHT/8)) * DISPLAY_WIDTH +x] &= ~(1 << (y % (DISPLAY_HEIGHT/8)));
}
}
void lcd_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color){
if( x1 > DISPLAY_WIDTH-1 ||
x2 > DISPLAY_WIDTH-1 ||
y1 > DISPLAY_HEIGHT-1 ||
y2 > DISPLAY_HEIGHT-1) return;
int dx = abs(x2-x1), sx = x1<x2 ? 1 : -1;
int dy = -abs(y2-y1), sy = y1<y2 ? 1 : -1;
int err = dx+dy, e2; /* error value e_xy */
while(1){
result = lcd_drawPixel(x1, y1, color);
lcd_drawPixel(x1, y1, color);
if (x1==x2 && y1==y2) break;
e2 = 2*err;
if (e2 > dy) { err += dy; x1 += sx; } /* e_xy+e_x > 0 */
if (e2 < dx) { err += dx; y1 += sy; } /* e_xy+e_y < 0 */
}
return result;
}
uint8_t lcd_drawRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color){
uint8_t result;
result = lcd_drawLine(px1, py1, px2, py1, color);
result = lcd_drawLine(px2, py1, px2, py2, color);
result = lcd_drawLine(px2, py2, px1, py2, color);
result = lcd_drawLine(px1, py2, px1, py1, color);
return result;
void lcd_drawRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color){
if( px1 > DISPLAY_WIDTH-1 ||
px2 > DISPLAY_WIDTH-1 ||
py1 > DISPLAY_HEIGHT-1 ||
py2 > DISPLAY_HEIGHT-1) return;
lcd_drawLine(px1, py1, px2, py1, color);
lcd_drawLine(px2, py1, px2, py2, color);
lcd_drawLine(px2, py2, px1, py2, color);
lcd_drawLine(px1, py2, px1, py1, color);
}
uint8_t lcd_fillRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color){
uint8_t result;
void lcd_fillRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color){
if( px1 > px2){
uint8_t temp = px1;
px1 = px2;
@ -434,24 +503,24 @@ uint8_t lcd_fillRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t
py2 = temp;
}
for (uint8_t i=0; i<=(py2-py1); i++){
result = lcd_drawLine(px1, py1+i, px2, py1+i, color);
lcd_drawLine(px1, py1+i, px2, py1+i, color);
}
return result;
}
uint8_t lcd_drawCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color){
uint8_t result;
void lcd_drawCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color){
if( ((center_x + radius) > DISPLAY_WIDTH-1) ||
((center_y + radius) > DISPLAY_HEIGHT-1) ||
center_x < radius ||
center_y < radius) return;
int16_t f = 1 - radius;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * radius;
int16_t x = 0;
int16_t y = radius;
result = lcd_drawPixel(center_x , center_y+radius, color);
result = lcd_drawPixel(center_x , center_y-radius, color);
result = lcd_drawPixel(center_x+radius, center_y , color);
result = lcd_drawPixel(center_x-radius, center_y , color);
lcd_drawPixel(center_x , center_y+radius, color);
lcd_drawPixel(center_x , center_y-radius, color);
lcd_drawPixel(center_x+radius, center_y , color);
lcd_drawPixel(center_x-radius, center_y , color);
while (x<y) {
if (f >= 0) {
@ -463,63 +532,34 @@ uint8_t lcd_drawCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8
ddF_x += 2;
f += ddF_x;
result = lcd_drawPixel(center_x + x, center_y + y, color);
result = lcd_drawPixel(center_x - x, center_y + y, color);
result = lcd_drawPixel(center_x + x, center_y - y, color);
result = lcd_drawPixel(center_x - x, center_y - y, color);
result = lcd_drawPixel(center_x + y, center_y + x, color);
result = lcd_drawPixel(center_x - y, center_y + x, color);
result = lcd_drawPixel(center_x + y, center_y - x, color);
result = lcd_drawPixel(center_x - y, center_y - x, color);
lcd_drawPixel(center_x + x, center_y + y, color);
lcd_drawPixel(center_x - x, center_y + y, color);
lcd_drawPixel(center_x + x, center_y - y, color);
lcd_drawPixel(center_x - x, center_y - y, color);
lcd_drawPixel(center_x + y, center_y + x, color);
lcd_drawPixel(center_x - y, center_y + x, color);
lcd_drawPixel(center_x + y, center_y - x, color);
lcd_drawPixel(center_x - y, center_y - x, color);
}
return result;
}
uint8_t lcd_fillCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color) {
uint8_t result;
void lcd_fillCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color) {
for(uint8_t i=0; i<= radius;i++){
result = lcd_drawCircle(center_x, center_y, i, color);
lcd_drawCircle(center_x, center_y, i, color);
}
return result;
}
uint8_t lcd_drawBitmap(uint8_t x, uint8_t y, const uint8_t *picture, uint8_t width, uint8_t height, uint8_t color){
uint8_t result,i,j, byteWidth = (width+7)/8;
for (j = 0; j < height; j++) {
for(i=0; i < width;i++){
if(pgm_read_byte(picture + j * byteWidth + i / 8) & (128 >> (i & 7))){
result = lcd_drawPixel(x+i, y+j, color);
} else {
result = lcd_drawPixel(x+i, y+j, !color);
}
}
}
return result;
}
void lcd_display() {
#if defined (SSD1306) || defined (SSD1309)
#if defined SSD1306
lcd_gotoxy(0,0);
lcd_data(&displayBuffer[0][0], DISPLAY_WIDTH*DISPLAY_HEIGHT/8);
lcd_data(displayBuffer, sizeof(displayBuffer));
#elif defined SH1106
for (uint8_t i = 0; i < DISPLAY_HEIGHT/8; i++){
lcd_gotoxy(0,i);
lcd_data(displayBuffer[i], sizeof(displayBuffer[i]));
for (uint8_t i=0; i < DISPLAY_HEIGHT/8; i++) {
lcd_gotoxy(0, i);
uint8_t actualLine[DISPLAY_WIDTH];
for (uint8_t j=0; j < DISPLAY_WIDTH; j++) {
actualLine[j]=displayBuffer[i*DISPLAY_WIDTH+j];
}
lcd_data(actualLine, sizeof(actualLine));
}
#endif
}
void lcd_clear_buffer() {
for (uint8_t i = 0; i < DISPLAY_HEIGHT/8; i++){
memset(displayBuffer[i], 0x00, sizeof(displayBuffer[i]));
}
}
uint8_t lcd_check_buffer(uint8_t x, uint8_t y) {
if( x > DISPLAY_WIDTH-1 || y > (DISPLAY_HEIGHT-1)) return 0; // out of Display
return displayBuffer[(y / (DISPLAY_HEIGHT/8))][x] & (1 << (y % (DISPLAY_HEIGHT/8)));
}
void lcd_display_block(uint8_t x, uint8_t line, uint8_t width) {
if (line > (DISPLAY_HEIGHT/8-1) || x > DISPLAY_WIDTH - 1){return;}
if (x + width > DISPLAY_WIDTH) { // no -1 here, x alone is width 1
width = DISPLAY_WIDTH - x;
}
lcd_goto_xpix_y(x,line);
lcd_data(&displayBuffer[line][x], width);
}
#endif

119
lcd.h
Datei anzeigen

@ -1,11 +1,11 @@
/*
* This file is part of lcd library for ssd1306/ssd1309/sh1106 oled-display.
* This file is part of lcd library for ssd1306/sh1106 oled-display.
*
* lcd library for ssd1306/ssd1309/sh1106 oled-display is free software: you can redistribute it and/or modify
* lcd library for ssd1306/sh1106 oled-display is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
*
* lcd library for ssd1306/ssd1309/sh1106 oled-display is distributed in the hope that it will be useful,
* lcd library for ssd1306/sh1106 oled-display is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
@ -13,14 +13,14 @@
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*
* Diese Datei ist Teil von lcd library for ssd1306/ssd1309/sh1106 oled-display.
* Diese Datei ist Teil von lcd library for ssd1306/sh1106 oled-display.
*
* lcd library for ssd1306/ssd1309/sh1106 oled-display ist Freie Software: Sie können es unter den Bedingungen
* lcd library for ssd1306/sh1106 oled-display ist Freie Software: Sie können es unter den Bedingungen
* der GNU General Public License, wie von der Free Software Foundation,
* Version 3 der Lizenz oder jeder späteren
* veröffentlichten Version, weiterverbreiten und/oder modifizieren.
*
* lcd library for ssd1306/ssd1309/sh1106 oled-display wird in der Hoffnung, dass es nützlich sein wird, aber
* lcd library for ssd1306/sh1106 oled-display wird in der Hoffnung, dass es nützlich sein wird, aber
* OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
* Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
* Siehe die GNU General Public License für weitere Details.
@ -33,7 +33,7 @@
* Created by Michael Köhler on 22.12.16.
* Copyright 2016 Skie-Systems. All rights reserved.
*
* lib for OLED-Display with ssd1306/ssd1309/sh1106-Controller
* lib for OLED-Display with ssd1306/sh1106-Controller
* first dev-version only for I2C-Connection
* at ATMega328P like Arduino Uno
*
@ -44,8 +44,11 @@
#ifndef LCD_H
#define LCD_H
#ifdef __cplusplus
extern "C" {
#ifndef YES
#define YES 1
#define NO 0
#else
#error "Check #defines for YES and NO in other sources !"
#endif
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 303
@ -54,49 +57,18 @@ extern "C" {
#include <inttypes.h>
#include <avr/pgmspace.h>
/* TODO: define bus */
#define I2C // I2C or SPI
/* TODO: define displaycontroller */
#define SH1106 // or SSD1306, check datasheet of your display
/* TODO: define displaymode */
#define TEXTMODE // TEXTMODE for only text to display,
// GRAPHICMODE for text and graphic
/* TODO: define font */
#define FONT ssd1306oled_font// set font here, refer font-name at font.h/font.c
/* TODO: define I2C-adress for display */
// using 7-bit-adress for lcd-library
// if you use your own library for twi check I2C-adress-handle
#define LCD_I2C_ADR (0x78 >> 1) // 7 bit slave-adress without r/w-bit
// r/w-bit are set/unset by library
// e.g. 8 bit slave-adress:
// 0x78 = adress 0x3C with cleared r/w-bit (write-mode)
#ifdef I2C
#include "i2c.h" // library for I2C-communication
// if you want to use other lib for I2C
// edit i2c_xxx commands in this library
// i2c_start(), i2c_byte(), i2c_stop()
#elif defined SPI
// if you want to use your other lib/function for SPI replace SPI-commands
#define LCD_PORT PORTB
#define LCD_DDR DDRB
#define RES_PIN PB0
#define DC_PIN PB1
#define CS_PIN PB2
/* TODO: define displaycontroller */
#define SH1106 // or SSD1306, check datasheet of your display
/* TODO: define displaymode */
#define GRAPHICMODE // TEXTMODE for only text to display,
// GRAPHICMODE for text and graphic
#endif
#ifndef YES
#define YES 1
#endif
#define NORMALSIZE 1
#define DOUBLESIZE 2
#define LCD_I2C_ADR 0x7A
#define LCD_DISP_OFF 0xAE
#define LCD_DISP_ON 0xAF
@ -106,44 +78,31 @@ extern "C" {
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 64
#define DISPLAYSIZE DISPLAY_WIDTH*DISPLAY_HEIGHT/8
void lcd_command(uint8_t cmd[], uint8_t size); // transmit command to display
void lcd_data(uint8_t data[], uint16_t size); // transmit data to display
void lcd_init(uint8_t dispAttr);
void lcd_home(void); // set cursor to 0,0
void lcd_invert(uint8_t invert); // invert display
void lcd_set_contrast(uint8_t contrast); // set contrast for display
void lcd_puts(const char* s); // print string, \n-terminated, from ram on screen (TEXTMODE)
// or buffer (GRAPHICMODE)
void lcd_puts_p(const char* progmem_s); // print string from flash on screen (TEXTMODE)
// or buffer (GRAPHICMODE)
void lcd_command(uint8_t cmd[], uint8_t size); // transmit command to display
void lcd_data(uint8_t data[], uint16_t size); // transmit data to display
void lcd_init(uint8_t dispAttr);
void lcd_home(void); // set cursor to 0,0
void lcd_invert(uint8_t invert); // invert display
void lcd_sleep(uint8_t sleep); // display goto sleep (power off)
void lcd_set_contrast(uint8_t contrast); // set contrast for display
void lcd_puts(const char* s); // print string, \n-terminated, from ram on screen (TEXTMODE)
// or buffer (GRAPHICMODE)
void lcd_puts_p(const char* progmem_s); // print string from flash on screen (TEXTMODE)
// or buffer (GRAPHICMODE)
void lcd_clrscr(void); // clear screen (and buffer at GRFAICMODE)
void lcd_gotoxy(uint8_t x, uint8_t y); // set curser at pos x, y. x means character,
void lcd_clrscr(void); // clear screen (and buffer at GRFAICMODE)
void lcd_gotoxy(uint8_t x, uint8_t y); // set curser at pos x, y. x means character,
// y means line (page, refer lcd manual)
void lcd_goto_xpix_y(uint8_t x, uint8_t y); // set curser at pos x, y. x means pixel,
// y means line (page, refer lcd manual)
void lcd_putc(char c); // print character on screen at TEXTMODE
void lcd_putc(char c); // print character on screen at TEXTMODE
// at GRAPHICMODE print character to buffer
void lcd_charMode(uint8_t mode); // set size of chars
#if defined GRAPHICMODE
uint8_t lcd_drawPixel(uint8_t x, uint8_t y, uint8_t color);
uint8_t lcd_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color);
uint8_t lcd_drawRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color);
uint8_t lcd_fillRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color);
uint8_t lcd_drawCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color);
uint8_t lcd_fillCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color);
uint8_t lcd_drawBitmap(uint8_t x, uint8_t y, const uint8_t picture[], uint8_t width, uint8_t height, uint8_t color);
void lcd_display(void); // copy buffer to display RAM
void lcd_clear_buffer(void); // clear display buffer
uint8_t lcd_check_buffer(uint8_t x, uint8_t y); // read a pixel value from the display buffer
void lcd_display_block(uint8_t x, uint8_t line, uint8_t width); // display (part of) a display line
#endif
#ifdef __cplusplus
}
void lcd_drawPixel(uint8_t x, uint8_t y, uint8_t color);
void lcd_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color);
void lcd_drawRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color);
void lcd_fillRect(uint8_t px1, uint8_t py1, uint8_t px2, uint8_t py2, uint8_t color);
void lcd_drawCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color);
void lcd_fillCircle(uint8_t center_x, uint8_t center_y, uint8_t radius, uint8_t color);
void lcd_display(void); // copy buffer to display RAM
#endif
#endif /* LCD_H */

BIN
oled.jpg

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 1.1 MiB

43
readme Normale Datei
Datei anzeigen

@ -0,0 +1,43 @@
Library for oled-displays with SSD1306 or SH1106 display-controller connected with I2C at an AVR Atmel Atmega like Atmega328P.
This library allows you to display text or/and graphic at oled-display.
The library need less then 2000 bytes flash-memory in textmode and less then 3200 bytes in graphicmode so you can use oled-displays e.g with Atmega48PA.
Library is only tested with 128x64 Pixel display, lower resolution not tested but should work too.
If you want to use your own I2C library you have to fit i2c-function at lcd-library.
Settings for I2C-bus have to set at i2c.h
Settings for display have to set at lcd.h
If you want to use characters like e.g. ä set your compiler input-charset to utf-8 and your compiler exec-charset to iso-8859-15 (look at makefile line 115).
example:
//****main.c****//
#include "lcd.h"
int main(void){
lcd_init(LCD_DISP_ON); // init lcd and turn on
lcd_puts("Hello World"); // put string from RAM to display (TEXTMODE) or buffer (GRAPHICMODE)
lcd_gotoxy(0,2); // set cursor to first column at line 3
lcd_puts_p(PSTR("String from flash")); // puts string form flash to display (TEXTMODE) or buffer (GRAPHICMODE)
#if defined GRAPHICMODE
lcd_drawCircle(64,32,7,WHITE); // draw circle to buffer
lcd_display(); // send buffer to display
#endif
for(;;){
//main loop
}
return 0;
}
For Arduino-Users:
Remember that this library is a c-library. Type
extern "C"{
#include "lcd.h"
}
for include.

130
readme.md
Datei anzeigen

@ -1,130 +0,0 @@
# OLED for AVR mikrocontrollers
Library for oled-displays with SSD1306, SSD1309 or SH1106 display-controller connected with I2C or SPI at an AVR Atmel Atmega like Atmega328P.
<img src="https://github.com/Sylaina/oled-display/blob/master/oled.jpg?raw=true" width="500">
This library allows you to display text or/and graphic at oled-display.
The library need less than 2 kilobytes flash-memory and 3 bytes sram in textmode, in graphicmode library need less than 3 kilobytes flash-memory and 1027 bytes static sram so you can use oled-displays e.g with Atmega48PA (only with textmode).
Library is only tested with 128x64 Pixel display, lower resolution not tested but should work too.
If you want to use your own I2C library you have to fit i2c-function at lcd-library.
Settings for I2C-bus have to set at i2c.h
Settings for display have to set at lcd.h
If you want to use characters like e.g. ä set your compiler input-charset to utf-8 and your compiler exec-charset to iso-8859-15 (look at makefile line 115).
Testcondition: Display: SSD1306 OLED, Compiler Optimizelevel: -Os, µC: Atmega328p @ 8 MHz internal RC
Memory:
<table>
<tr>
<th>Modul</th>
<th>Flash</th>
<th>Static RAM</th>
</tr>
<tr>
<td>I2C-Core</td>
<td>220 Bytes</td>
<td>0 Bytes</td>
</tr>
<tr>
<td>FONT</td>
<td>644 Bytes</td>
<td>0 Bytes</td>
</tr>
<tr>
<td>OLED (Text-Mode)</td>
<td>1395 Bytes</td>
<td>3 Bytes</td>
</tr>
<tr>
<td>OLED (Graphic-Mode)</td>
<td>2541 Bytes</td>
<td>1027 Bytes</td>
</tr>
</table>
Speed (print 20 charaters (1 line) in normal size to display):
<table>
<tr>
<th>Mode</th>
<th>Time</th>
<th>I2C-Speed</th>
</tr>
<tr>
<td>OLED (Text-Mode)</td>
<td>4.411 ms</td>
<td>400 kHz</td>
</tr>
<tr>
<td>OLED (Text-Mode)</td>
<td>15.384 ms</td>
<td>100 kHz</td>
</tr>
<tr>
<td>OLED (Graphic-Mode)</td>
<td>26.603 ms</td>
<td>400 kHz</td>
</tr>
<tr>
<td>OLED (Graphic-Mode)</td>
<td>96.294 ms</td>
<td>100 kHz</td>
</tr>
</table>
example:
```c
//****main.c****//
#include "lcd.h"
int main(void){
lcd_init(LCD_DISP_ON); // init lcd and turn on
lcd_puts("Hello World"); // put string from RAM to display (TEXTMODE) or buffer (GRAPHICMODE)
lcd_gotoxy(0,2); // set cursor to first column at line 3
lcd_puts_p(PSTR("String from flash")); // puts string form flash to display (TEXTMODE) or buffer (GRAPHICMODE)
#if defined GRAPHICMODE
lcd_drawCircle(64,32,7,WHITE); // draw circle to buffer
lcd_display(); // send buffer to display
#endif
for(;;){
//main loop
}
return 0;
}
```
example for chars with double height:
```c
//****main.c****//
#include "lcd.h"
int main(void){
lcd_init(LCD_DISP_ON);
lcd_clrscr();
lcd_set_contrast(0x00);
lcd_gotoxy(4,1);
lcd_puts("Normal Size");
lcd_charMode(DOUBLESIZE);
lcd_gotoxy(0,4);
lcd_puts(" Double \r\n Size");
lcd_charMode(NORMALSIZE);
#ifdef GRAPHICMODE
lcd_display();
#endif
for(;;){
//main loop
}
return 0;
}
```
<img src="https://github.com/Sylaina/oled-display/blob/master/bigchars.JPG?raw=true" width="500">