@ -36,8 +36,6 @@ All text above, and the splash screen below must be included in any redistributi
# define rotation 0
# define rotation 0
# define pgm_read_byte(addr) (*(const uint8_t *)(addr))
int8_t cursor_y = 0 ;
int8_t cursor_y = 0 ;
int8_t cursor_x = 0 ;
int8_t cursor_x = 0 ;
@ -175,45 +173,9 @@ uint8_t buffer[SSD1306_LCDWIDTH * SSD1306_LCDHEIGHT / 8] = {
int8_t _vccstate ;
int8_t _vccstate ;
int16_t i2cd ;
int16_t i2cd ;
i2c_t i2c_device ;
# define ssd1306_swap(a, b) { int16_t t = a; a = b; b = t; }
# define ssd1306_swap(a, b) { int16_t t = a; a = b; b = t; }
// the most basic function, set a single pixel
void ssd1306_drawPixel ( int16_t x , int16_t y , uint16_t color )
{
if ( ( x < 0 ) | | ( x > = WIDTH ) | | ( y < 0 ) | | ( y > = HEIGHT ) )
return ;
// check rotation, move pixel around if necessary
switch ( rotation ) {
case 1 :
ssd1306_swap ( x , y ) ;
x = WIDTH - x - 1 ;
break ;
case 2 :
x = WIDTH - x - 1 ;
y = HEIGHT - y - 1 ;
break ;
case 3 :
ssd1306_swap ( x , y ) ;
y = HEIGHT - y - 1 ;
break ;
}
// x is which column
switch ( color ) {
case WHITE :
buffer [ x + ( y / 8 ) * SSD1306_LCDWIDTH ] | = ( 1 < < ( y & 7 ) ) ;
break ;
case BLACK :
buffer [ x + ( y / 8 ) * SSD1306_LCDWIDTH ] & = ~ ( 1 < < ( y & 7 ) ) ;
break ;
case INVERSE :
buffer [ x + ( y / 8 ) * SSD1306_LCDWIDTH ] ^ = ( 1 < < ( y & 7 ) ) ;
break ;
}
}
//Section : 10.1.12 Set Display ON/OFF (AEh/AFh) | Page 37
//Section : 10.1.12 Set Display ON/OFF (AEh/AFh) | Page 37
void ssd1306_i2c_set_display_off ( i2c_t * i2c_dev )
void ssd1306_i2c_set_display_off ( i2c_t * i2c_dev )
@ -231,8 +193,19 @@ void ssd1306_i2c_set_display_on(i2c_t *i2c_dev)
// Section : 10.1.16 Set Display Clock Divide Ratio/ Oscillator Frequency (D5h) | Page : 40
// 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 )
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_command ( i2c_dev , SSD1306_SETDISPLAYCLOCKDIV ) ; // 0xD5
ssd1306_i2c_command ( i2c_dev , SSD1306_SETDISPLAYCLOCKDIV ) ; // 0xD5
ssd1306_i2c_command ( i2c_dev , 0x80 ) ; // the suggested ratio 0x80
ssd1306_i2c_command ( i2c_dev , value ) ; // the suggested ratio 0x80
}
}
// Section : 10.1.11 Set Multiplex Ratio (A8h) | Page : 37
// Section : 10.1.11 Set Multiplex Ratio (A8h) | Page : 37
@ -301,62 +274,73 @@ void ssd1306_i2c_set_com_scan_direction(i2c_t *i2c_dev, uint8_t incremental)
ssd1306_i2c_command ( i2c_dev , SSD1306_COMSCANDEC ) ;
ssd1306_i2c_command ( i2c_dev , SSD1306_COMSCANDEC ) ;
}
}
}
}
// Init SSD1306
void ssd1306_begin ( i2c_t * i2c_dev , uint16_t vccstate , uint16_t i2caddr )
{
// I2C Init
_vccstate = vccstate ;
ssd1306_i2c_set_display_off ( i2c_dev ) ;
ssd1306_i2c_set_display_clkDiv_oscFreq ( i2c_dev , 0x00 , 0x00 ) ;
ssd1306_i2c_set_multiplex_ratio ( i2c_dev , HEIGHT - 1 ) ; // Pages start at 0 and ends at 63
ssd1306_i2c_set_display_offset ( i2c_dev , 0x00 ) ; // No Offset
ssd1306_i2c_set_display_start_line ( i2c_dev , 0 ) ; // Start line 0
ssd1306_i2c_set_chage_pump ( i2c_dev , vccstate ) ;
ssd1306_i2c_set_memory_addressing_mode ( i2c_dev , SSD1306_MEMORY_MODE_HORIZONTAL ) ;
ssd1306_i2c_set_segment_remap ( i2c_dev , 1 ) ;
ssd1306_i2c_set_com_scan_direction ( i2c_dev , 0 ) ; //Decremental TODO : Make a define for it
# if defined SSD1306_128_32
ssd1306_i2c_command ( i2c_dev , SSD1306_SETCOMPINS ) ; // 0xDA
ssd1306_i2c_command ( i2c_dev , 0x02 ) ;
ssd1306_i2c_command ( i2c_dev , SSD1306_SETCONTRAST ) ; // 0x81
ssd1306_i2c_command ( i2c_dev , 0x8F ) ;
# elif defined SSD1306_128_64
// Section : 10.1.18 Set COM Pins Hardware Configuration (DAh) | Page : 40
ssd1306_i2c_command ( i2c_dev , SSD1306_SETCOMPINS ) ; // 0xDA
void ssd1306_i2c_set_com_pins ( i2c_t * i2c_dev , uint8_t alignment )
ssd1306_i2c_command ( i2c_dev , 0x12 ) ;
{
ssd1306_i2c_command ( i2c_dev , SSD1306_SETCOMPINS ) ;
ssd1306_i2c_command ( i2c_dev , alignment ) ;
}
void ssd1306_i2c_set_contrast ( i2c_t * i2c_dev , uint8_t contrast )
{
ssd1306_i2c_command ( i2c_dev , SSD1306_SETCONTRAST ) ; // 0x81
ssd1306_i2c_command ( i2c_dev , SSD1306_SETCONTRAST ) ; // 0x81
if ( vccstate = = SSD1306_EXTERNALVCC ) {
ssd1306_i2c_command ( i2c_dev , contrast ) ;
ssd1306_i2c_command ( i2c_dev , 0x9F ) ;
}
} else {
ssd1306_i2c_command ( i2c_dev , 0xCF ) ;
void ssd1306_i2c_set_prechage_period ( i2c_t * i2c_dev , uint8_t period )
{
ssd1306_i2c_command ( i2c_dev , SSD1306_SETPRECHARGE ) ; // 0xd9
ssd1306_i2c_command ( i2c_dev , period ) ;
}
void ssd1306_i2c_set_com_deselect_level ( i2c_t * i2c_dev , uint8_t voltageLevel )
{
ssd1306_i2c_command ( i2c_dev , SSD1306_SETVCOMDETECT ) ; // 0xDB
ssd1306_i2c_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_command ( i2c_dev , SSD1306_DISPLAYALLON_RESUME ) ; // 0xA4
}
else
{
ssd1306_i2c_command ( i2c_dev , SSD1306_DISPLAYALLON ) ; // 0xA4
}
}
# elif defined SSD1306_96_16
}
ssd1306_i2c_command ( i2c_dev , SSD1306_SETCOMPINS ) ; // 0xDA
ssd1306_i2c_command ( i2c_dev , 0x2 ) ; // ada x12
void ssd1306_i2c_set_display_invert_pixel ( i2c_t * i2c_dev , uint8_t inverted )
ssd1306_i2c_command ( i2c_dev , SSD1306_SETCONTRAST ) ; // 0x81
{
if ( vccstate = = SSD1306_EXTERNALVCC ) {
if ( inverted )
ssd1306_i2c_command ( i2c_dev , 0x10 ) ;
{
} else {
ssd1306_i2c_command ( i2c_dev , SSD1306_INVERTDISPLAY ) ; // 0xA6
ssd1306_i2c_command ( i2c_dev , 0xAF ) ;
}
else
{
ssd1306_i2c_command ( i2c_dev , SSD1306_NORMALDISPLAY ) ; // 0xA6
}
}
}
# endif
void ssd1306_i2c_set_scroll ( i2c_t * i2c_dev , uint8_t onOff )
ssd1306_i2c_command ( i2c_dev , SSD1306_SETPRECHARGE ) ; // 0xd9
{
if ( vccstate = = SSD1306_EXTERNALVCC ) {
if ( onOff )
ssd1306_i2c_command ( i2c_dev , 0x22 ) ;
{
} else {
ssd1306_i2c_command ( i2c_dev , SSD1306_ACTIVATE_SCROLL ) ;
ssd1306_i2c_command ( i2c_dev , 0xF1 ) ;
}
}
ssd1306_i2c_command ( i2c_dev , SSD1306_SETVCOMDETECT ) ; // 0xDB
else
ssd1306_i2c_command ( i2c_dev , 0x40 ) ;
{
ssd1306_i2c_command ( i2c_dev , SSD1306_DISPLAYALLON_RESUME ) ; // 0xA4
ssd1306_i2c_command ( i2c_dev , SSD1306_DEACTIVATE_SCROLL ) ;
ssd1306_i2c_command ( i2c_dev , SSD1306_NORMALDISPLAY ) ; // 0xA6
}
}
ssd1306_i2c_command ( i2c_dev , SSD1306_DEACTIVATE_SCROLL ) ;
// Init SSD1306
void ssd1306_begin ( i2c_t * i2c_dev , uint16_t i2caddr )
{
ssd1306_i2c_set_display_on ( i2c_dev ) ;
}
}
void ssd1306_invertDisplay ( i2c_t * i2c_dev , uint16_t i )
void ssd1306_invertDisplay ( i2c_t * i2c_dev , uint16_t i )
@ -504,14 +488,6 @@ void ssd1306_dim(i2c_t *i2c_dev, uint16_t dim)
ssd1306_i2c_command ( i2c_dev , contrast ) ;
ssd1306_i2c_command ( i2c_dev , contrast ) ;
}
}
// clear everything
void ssd1306_clearDisplay ( )
{
memset ( buffer , 0 ,
( SSD1306_LCDWIDTH * SSD1306_LCDHEIGHT / 8 ) * sizeof ( int ) ) ;
cursor_y = 0 ;
cursor_x = 0 ;
}
void ssd1306_drawFastHLineInternal ( int16_t x , int16_t y , int16_t w , uint16_t color )
void ssd1306_drawFastHLineInternal ( int16_t x , int16_t y , int16_t w , uint16_t color )
{
{
@ -841,31 +817,17 @@ void ssd1306_drawString(int8_t *str)
// Draw a character
// Draw a character
void ssd1306_drawChar ( int16_t x , int16_t y , uint8_t c , int16_t color , int16_t size )
void ssd1306_drawChar ( int16_t x , int16_t y , uint8_t c , int16_t color , int16_t size )
{
{
//Adapted and optimized for oled_lcd.c
}
if ( ( x > = WIDTH ) | | // Clip right
// the most basic function, set a single pixel
( y > = HEIGHT ) | | // Clip bottom
void ssd1306_drawPixel ( int16_t x , int16_t y , uint16_t color )
( ( x + 6 * size - 1 ) < 0 ) | | // Clip left
{
( ( y + 8 * size - 1 ) < 0 ) ) // Clip top
//Adapted and optimized for oled_lcd.c
return ;
}
int16_t i ;
int16_t j ;
// clear everything
for ( i = 0 ; i < 6 ; i + + ) {
void ssd1306_clearDisplay ( )
int16_t line ;
{
if ( i = = 5 )
//Adapted and optimized for oled_lcd.c
line = 0x0 ;
else
line = pgm_read_byte ( font + ( c * 5 ) + i ) ;
for ( j = 0 ; j < 8 ; j + + ) {
if ( line & 0x1 ) {
if ( size = = 1 ) // default size
ssd1306_drawPixel ( x + i , y + j , color ) ;
else { // big size
ssd1306_fillRect ( x + ( i * size ) ,
y + ( j * size ) , size ,
size , color ) ;
}
}
line > > = 1 ;
}
}
}
}