You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
KED/drivers/ssd1306_i2c/ssd1306_i2c.c

288 lines
8.7 KiB

/*********************************************************************
SSD1306 I2C Library for Raspberry Pi.
Based on Adafruit SSD1306 Arduino library. Some functions came from Adafruit GFX lib
Modified by Ilia Penev
Tested on Raspberry Pi 2 with 0.96 Yellow/Blue OLED
*********************************************************************/
/*********************************************************************
This is a library for our Monochrome OLEDs based on SSD1306 drivers
Pick one up today in the adafruit shop!
------> http://www.adafruit.com/category/63_98
These displays use SPI to communicate, 4 or 5 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above, and the splash screen below must be included in any redistribution
*********************************************************************/
#include <stdint.h>
#include <string.h>
#include "ssd1306_i2c.h"
#include "oled_fonts.h"
#include "lcd_oled.h"
#define true 1
#define false 0
#define rotation 0
int8_t cursor_y = 0;
int8_t cursor_x = 0;
int16_t i2cd;
#define ssd1306_swap(a, b) { int16_t t = a; a = b; b = t; }
//Section : 10.1.12 Set Display ON/OFF (AEh/AFh) | Page 37
void ssd1306_i2c_set_display_off(i2c_t *i2c_dev)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_DISPLAYOFF);
}
//Section : 10.1.12 Set Display ON/OFF (AEh/AFh) | Page 37
void ssd1306_i2c_set_display_on(i2c_t *i2c_dev)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_DISPLAYON);
}
// TODO: Find a ferq Calculator
// Section : 10.1.16 Set Display Clock Divide Ratio/ Oscillator Frequency (D5h) | Page : 40
void ssd1306_i2c_set_display_clkDiv_oscFreq(i2c_t *i2c_dev, uint8_t clockDivider, uint8_t oscillatorFreq)
{
uint8_t value = 0;
if(oscillatorFreq <= 15)
{
if(clockDivider <= 16)
{
value = (oscillatorFreq << 4) | clockDivider;
}
}
ssd1306_i2c_send_command(i2c_dev,SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
ssd1306_i2c_send_command(i2c_dev,value); // the suggested ratio 0x80
}
// Section : 10.1.11 Set Multiplex Ratio (A8h) | Page : 37
void ssd1306_i2c_set_multiplex_ratio(i2c_t *i2c_dev, uint8_t ratio)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SETMULTIPLEX); // 0xA8
ssd1306_i2c_send_command(i2c_dev,ratio);
}
// Section : 10.1.15 Set Display Offset (D3h) | Page : 37
void ssd1306_i2c_set_display_offset(i2c_t *i2c_dev, uint8_t offset)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SETDISPLAYOFFSET); // 0xD3
ssd1306_i2c_send_command(i2c_dev,offset);
}
// Section : 10.1.13 Set Page Start Address for Page Addressing Mode (B0h~B7h) | Page : 37
void ssd1306_i2c_set_display_start_line(i2c_t *i2c_dev, uint8_t start)
{
if(start <= 7)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SETSTARTLINE | start);
}
}
// TODO : Some things are not clear What does 0x10 do ?
// Section : 2.1 Command Table for Charge Bump Setting | Page : 60
void ssd1306_i2c_set_chage_pump(i2c_t *i2c_dev, uint8_t voltageSource)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_CHARGEPUMP); // 0x8D
if (voltageSource == SSD1306_EXTERNALVCC) {
ssd1306_i2c_send_command(i2c_dev,0x10);
} else {
ssd1306_i2c_send_command(i2c_dev,SSD1306_ENABLE_CHAGE_PUMP);
}
}
// Section :10.1.3 Set Memory Addressing Mode (20h) | Page : 34
void ssd1306_i2c_set_memory_addressing_mode(i2c_t *i2c_dev, uint8_t mode)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_MEMORYMODE);
ssd1306_i2c_send_command(i2c_dev,mode);
}
// TODO : Not very clear what this functionality does :S
// Section : 10.1.8 Set Segment Re-map (A0h/A1h)
void ssd1306_i2c_set_segment_remap(i2c_t *i2c_dev, uint8_t enable)
{
if(enable)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SEGREMAP | 0x1);
}
else
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SEGREMAP | 0x0);
}
}
// Section : 10.1.14 Set COM Output Scan Direction (C0h/C8h) | Page 37
void ssd1306_i2c_set_com_scan_direction(i2c_t *i2c_dev, uint8_t incremental)
{
if(incremental)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_COMSCANINC);
}
else
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_COMSCANDEC);
}
}
// Section : 10.1.18 Set COM Pins Hardware Configuration (DAh) | Page : 40
void ssd1306_i2c_set_com_pins(i2c_t *i2c_dev, uint8_t alignment)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SETCOMPINS);
ssd1306_i2c_send_command(i2c_dev,alignment);
}
void ssd1306_i2c_set_contrast(i2c_t *i2c_dev, uint8_t contrast)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SETCONTRAST); // 0x81
ssd1306_i2c_send_command(i2c_dev,contrast);
}
void ssd1306_i2c_set_prechage_period(i2c_t *i2c_dev, uint8_t period)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SETPRECHARGE); // 0xd9
ssd1306_i2c_send_command(i2c_dev,period);
}
void ssd1306_i2c_set_com_deselect_level(i2c_t *i2c_dev, uint8_t voltageLevel)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SETVCOMDETECT); // 0xDB
ssd1306_i2c_send_command(i2c_dev,voltageLevel);
}
void ssd1306_i2c_set_display_entire_on(i2c_t *i2c_dev, uint8_t resumeOrForce)
{
if(resumeOrForce == SSD1306_DISPLAYALLON_RESUME)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_DISPLAYALLON_RESUME); // 0xA4
}
else
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_DISPLAYALLON); // 0xA4
}
}
void ssd1306_i2c_set_display_invert_pixel(i2c_t *i2c_dev, uint8_t inverted)
{
if(inverted)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_INVERTDISPLAY); // 0xA6
}
else
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_NORMALDISPLAY); // 0xA6
}
}
void ssd1306_i2c_set_scroll(i2c_t *i2c_dev, uint8_t onOff)
{
if(onOff)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_ACTIVATE_SCROLL);
}
else
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_DEACTIVATE_SCROLL);
}
}
void ssd1306_i2c_send_command(i2c_t *i2c_dev,uint8_t c)
{
// I2C
uint8_t control = 0x00; // Co = 0, D/C = 0
uint8_t i2cDataLenght = 1; // Co = 0, D/C = 0
uint16_t address = SSD1306_I2C_ADDRESS; // Co = 0, D/C = 0
i2c_write(i2c_dev, &address, &control, &c, &i2cDataLenght);
}
// startscrollright
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// ssd1306_scrollright(0x00, 0x0F)
void ssd1306_startscrollright(i2c_t *i2c_dev, uint16_t start, uint16_t stop)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_RIGHT_HORIZONTAL_SCROLL);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,start);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,stop);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,0XFF);
ssd1306_i2c_send_command(i2c_dev,SSD1306_ACTIVATE_SCROLL);
}
// startscrollleft
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// ssd1306_scrollright(0x00, 0x0F)
void ssd1306_startscrollleft(i2c_t *i2c_dev,uint16_t start, uint16_t stop)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_LEFT_HORIZONTAL_SCROLL);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,start);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,stop);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,0XFF);
ssd1306_i2c_send_command(i2c_dev,SSD1306_ACTIVATE_SCROLL);
}
// startscrolldiagright
// Activate a diagonal scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// ssd1306_scrollright(0x00, 0x0F)
void ssd1306_startscrolldiagright(i2c_t *i2c_dev, uint16_t start, uint16_t stop)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SET_VERTICAL_SCROLL_AREA);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,SSD1306_LCDHEIGHT);
ssd1306_i2c_send_command(i2c_dev,SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,start);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,stop);
ssd1306_i2c_send_command(i2c_dev,0X01);
ssd1306_i2c_send_command(i2c_dev,SSD1306_ACTIVATE_SCROLL);
}
// startscrolldiagleft
// Activate a diagonal scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// ssd1306_scrollright(0x00, 0x0F)
void ssd1306_startscrolldiagleft(i2c_t *i2c_dev, uint16_t start, uint16_t stop)
{
ssd1306_i2c_send_command(i2c_dev,SSD1306_SET_VERTICAL_SCROLL_AREA);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,SSD1306_LCDHEIGHT);
ssd1306_i2c_send_command(i2c_dev,SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,start);
ssd1306_i2c_send_command(i2c_dev,0X00);
ssd1306_i2c_send_command(i2c_dev,stop);
ssd1306_i2c_send_command(i2c_dev,0X01);
ssd1306_i2c_send_command(i2c_dev,SSD1306_ACTIVATE_SCROLL);
}