260 lines
6.3 KiB
C++
260 lines
6.3 KiB
C++
/*
|
|
* Created: 19.06.2016 11:38:00
|
|
* Author: Ulrich
|
|
* From: https://www.ulrichradig.de/home/index.php/avr/oled-display-ssd1306
|
|
*/
|
|
|
|
#include "oled_ssd1306.h"
|
|
#include "font.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint8_t oled_x = 0, oled_y = 0, font_size = 0;
|
|
|
|
const uint8_t ssd1306_init_cmd [] PROGMEM = {
|
|
SET_DISPLAY_OFF,
|
|
COMMAND_NO_OPERATION,
|
|
SET_MEMORY_ADDR_MODE, HORIZONTAL_ADDRESSING_MODE,
|
|
SET_PAGE_START,
|
|
SET_COM_OUTPUT_REMAPPED,
|
|
SET_LOWER_COLUMN,
|
|
SET_HIGHER_COLUMN,
|
|
SET_DISPLAY_START_LINE,
|
|
ENTIRE_DISPLAY_ON,
|
|
SET_SEGMENT_REMAP_O2,
|
|
SET_DISPLAY_NORMAL,
|
|
SET_CONTRAST_CONTROL, 0xFF,
|
|
SET_MULTIPLEX_RATIO, 0x3F,
|
|
SET_DISPLAY_OFFSET, 0x00,
|
|
SET_DISPLAY_CLOCK, 0xF0,
|
|
SET_PRECHARGE_PERIOD, 0x22,
|
|
SET_COM_PINS, 0x12,
|
|
SET_VCOMH_DESELECT, 0x20,
|
|
CHARGE_BUMB_SETTING, 0x14,
|
|
SET_DISPLAY_ON };
|
|
|
|
|
|
oled_ssd1306::oled_ssd1306(){
|
|
|
|
}
|
|
|
|
oled_ssd1306::~oled_ssd1306(){
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::i2c_init(void){
|
|
I2C_PORT |= (1 << SDA_PIN | 1 << SCL_PIN); //Port Pullup
|
|
TWCR = 0;
|
|
TWSR = 0;
|
|
TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
|
|
_delay_ms(50);
|
|
}
|
|
|
|
//***************************************************************************************
|
|
uint8_t oled_ssd1306::i2c_start (void){
|
|
uint8_t timeout = 0;
|
|
TWCR = (1 << TWINT | 1 << TWSTA | 1 << TWEN);
|
|
while(!(TWCR & (1<<TWINT))){
|
|
if((timeout++) > 100) return 1;
|
|
}
|
|
TWDR = OLED_I2C_ADDR;
|
|
TWCR = (1 << TWINT | 1 << TWEN);
|
|
timeout = 0;
|
|
while(!(TWCR & (1<<TWINT))){
|
|
if((timeout++) > 100) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//***************************************************************************************
|
|
uint8_t oled_ssd1306::i2c_byte (uint8_t byte){
|
|
uint8_t timeout = 0;
|
|
TWDR = byte;
|
|
TWCR = (1 << TWINT | 1 << TWEN);
|
|
while(!(TWCR & (1<<TWINT))){
|
|
if((timeout++) > 100) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::i2c_stop (void){
|
|
TWCR = (1 << TWINT | 1 << TWSTO | 1 << TWEN);
|
|
TWCR = 0;
|
|
}
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::oled_init (void){
|
|
i2c_init();
|
|
i2c_start();
|
|
i2c_byte(COMMAND);
|
|
for (uint8_t tmp = 0; tmp< sizeof(ssd1306_init_cmd); tmp++) {
|
|
i2c_byte(pgm_read_byte(&ssd1306_init_cmd[tmp]));
|
|
}
|
|
i2c_stop();
|
|
oled_clear_screen();
|
|
}
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::oled_clear_screen (void){
|
|
oled_gotoxy(0,0);
|
|
i2c_start();
|
|
i2c_byte(DATA);
|
|
for (uint16_t i = 0; i < 128<<4 ; i++) { // 128 * (64 / Byte)
|
|
i2c_byte(0);
|
|
}
|
|
i2c_stop();
|
|
oled_gotoxy(0,0);
|
|
}
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::oled_gotoxy (uint8_t x, uint8_t y){
|
|
oled_x = x;
|
|
oled_y = y;
|
|
i2c_start();
|
|
i2c_byte(COMMAND);
|
|
i2c_byte(SET_PAGE_START|y);
|
|
i2c_byte(SET_COLUMN_ADDRESS);
|
|
i2c_byte(x * 8);
|
|
i2c_byte(SET_DISPLAY_START_LINE|0x3F);
|
|
i2c_stop();
|
|
}
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::oled_font_size (uint8_t byte){
|
|
font_size = byte;
|
|
}
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::oled_write_char (char c){
|
|
if(font_size != 0){
|
|
uint8_t tmp = 0;
|
|
oled_gotoxy(oled_x,oled_y);
|
|
i2c_start();
|
|
i2c_byte(DATA);
|
|
for (uint8_t count = 0; count < 8; count++){
|
|
tmp = pgm_read_byte(&font[(unsigned char)c][count]);
|
|
tmp = tmp & 0x0f;
|
|
tmp = ((tmp&0x01)*3)+(((tmp&0x02)<<1)*3)+(((tmp&0x04)<<2)*3)+(((tmp&0x08)<<3)*3);
|
|
i2c_byte(tmp);
|
|
i2c_byte(tmp);
|
|
}
|
|
i2c_stop();
|
|
oled_gotoxy(oled_x,oled_y + 1);
|
|
i2c_start();
|
|
i2c_byte(DATA);
|
|
for (uint8_t count = 0; count < 8; count++){
|
|
tmp = pgm_read_byte(&font[(unsigned char)c][count]);
|
|
tmp = (tmp & 0xf0)>>4;
|
|
tmp = ((tmp&0x01)*3)+(((tmp&0x02)<<1)*3)+(((tmp&0x04)<<2)*3)+(((tmp&0x08)<<3)*3);
|
|
i2c_byte(tmp);
|
|
i2c_byte(tmp);
|
|
}
|
|
i2c_stop();
|
|
oled_x +=2;
|
|
oled_y -=1;
|
|
}else{
|
|
oled_gotoxy(oled_x,oled_y);
|
|
i2c_start();
|
|
i2c_byte(DATA);
|
|
for (uint8_t count = 0; count < 8; count++){
|
|
i2c_byte(pgm_read_byte(&font[(unsigned char)c][count]));
|
|
}
|
|
i2c_stop();
|
|
oled_x +=1;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::oled_write_str (char* str){
|
|
while (*str) {
|
|
oled_write_char(*str++);
|
|
}
|
|
}
|
|
|
|
//***************************************************************************************
|
|
void oled_ssd1306::oled_write_P (const char *Buffer,...)
|
|
{
|
|
va_list ap;
|
|
va_start (ap, Buffer);
|
|
|
|
int format_flag;
|
|
char str_buffer[10];
|
|
char str_null_buffer[10];
|
|
char move = 0;
|
|
char Base = 0;
|
|
int tmp = 0;
|
|
char by;
|
|
char *ptr;
|
|
|
|
//Ausgabe der Zeichen
|
|
for(;;){
|
|
by = pgm_read_byte(Buffer++);
|
|
if(by==0) break; // end of format string
|
|
|
|
if (by == '%'){
|
|
by = pgm_read_byte(Buffer++);
|
|
if (isdigit(by)>0){
|
|
str_null_buffer[0] = by;
|
|
str_null_buffer[1] = '\0';
|
|
move = atoi(str_null_buffer);
|
|
by = pgm_read_byte(Buffer++);
|
|
}
|
|
|
|
switch (by){
|
|
case 's':
|
|
ptr = va_arg(ap,char *);
|
|
while(*ptr) { oled_write_char(*ptr++); }
|
|
break;
|
|
case 'b':
|
|
Base = 2;
|
|
goto ConversionLoop;
|
|
case 'c':
|
|
//Int to char
|
|
format_flag = va_arg(ap,int);
|
|
oled_write_char (format_flag++);
|
|
break;
|
|
case 'i':
|
|
Base = 10;
|
|
goto ConversionLoop;
|
|
case 'o':
|
|
Base = 8;
|
|
goto ConversionLoop;
|
|
case 'x':
|
|
Base = 16;
|
|
//****************************
|
|
ConversionLoop:
|
|
//****************************
|
|
itoa(va_arg(ap,int),str_buffer,Base);
|
|
int b=0;
|
|
while (str_buffer[b++] != 0){};
|
|
b--;
|
|
if (b<move){
|
|
move -=b;
|
|
for (tmp = 0;tmp<move;tmp++){
|
|
str_null_buffer[tmp] = '0';
|
|
}
|
|
//tmp ++;
|
|
str_null_buffer[tmp] = '\0';
|
|
strcat(str_null_buffer,str_buffer);
|
|
strcpy(str_buffer,str_null_buffer);
|
|
}
|
|
oled_write_str (str_buffer);
|
|
move =0;
|
|
break;
|
|
}
|
|
}else{
|
|
oled_write_char (by);
|
|
}
|
|
}
|
|
va_end(ap);
|
|
}
|
|
|