123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /**
- * SSD1306xLED - Library for the SSD1306 based OLED/PLED 128x64 displays
- *
- * @author Neven Boyanov
- *
- * This is part of the Tinusaur/SSD1306xLED project.
- *
- * Copyright (c) 2018 Neven Boyanov, The Tinusaur Team. All Rights Reserved.
- * Distributed as open source software under MIT License, see LICENSE.txt file.
- * Retain in your source code the link http://tinusaur.org to the Tinusaur project.
- *
- * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled
- *
- */
- // ============================================================================
- // ACKNOWLEDGEMENTS:
- // - Some code and ideas initially based on "IIC_wtihout_ACK"
- // by http://www.14blog.com/archives/1358 (defunct)
- // - Init sequence used info from Adafruit_SSD1306.cpp init code.
- // ============================================================================
- #if defined(__GNUC__)
- #include <stdlib.h>
- #include <avr/io.h>
- #include <avr/pgmspace.h>
- #elif defined(__ICCAVR__)
- # include <ioavr.h>
- # include <intrinsics.h>
- # include <stdint.h>
- #define PROGMEM __flash
- #define pgm_read_byte(a) (*(unsigned char __flash *)(a))
- #define pgm_read_word(a) (*(unsigned __flash *)(a))
- #endif
- #include "ssd1306xled.h"
- #include "i2c.h"
- // ----------------------------------------------------------------------------
- void ssd1306_start_command(void); // Initiate transmission of command
- void ssd1306_start_data(void); // Initiate transmission of data
- void ssd1306_data_byte(uint8_t); // Transmission 1 byte of data
- void ssd1306_stop(void); // Finish transmission
- // ----------------------------------------------------------------------------
- const uint8_t PROGMEM ssd1306_init_sequence [] = { // Initialization Sequence
- 0xAE, // Set Display ON/OFF - AE=OFF, AF=ON
- 0xD5, 0xF0, // Set display clock divide ratio/oscillator frequency, set divide ratio
- 0xA8, 0x3F, // Set multiplex ratio (1 to 64) ... (height - 1)
- 0xD3, 0x00, // Set display offset. 00 = no offset
- 0x40 | 0x00, // Set start line address, at 0.
- 0x8D, 0x14, // Charge Pump Setting, 14h = Enable Charge Pump
- 0x20, 0x00, // Set Memory Addressing Mode - 00=Horizontal, 01=Vertical, 10=Page, 11=Invalid
- 0xA0 | 0x01, // Set Segment Re-map
- 0xC8, // Set COM Output Scan Direction
- 0xDA, 0x12, // Set COM Pins Hardware Configuration - 128x32:0x02, 128x64:0x12
- 0x81, 0x3F, // Set contrast control register
- 0xD9, 0x22, // Set pre-charge period (0x22 or 0xF1)
- 0xDB, 0x20, // Set Vcomh Deselect Level - 0x00: 0.65 x VCC, 0x20: 0.77 x VCC (RESET), 0x30: 0.83 x VCC
- 0xA4, // Entire Display ON (resume) - output RAM to display
- 0xA6, // Set Normal/Inverse Display mode. A6=Normal; A7=Inverse
- 0x2E, // Deactivate Scroll command
- 0xAF, // Set Display ON/OFF - AE=OFF, AF=ON
- //
- 0x22, 0x00, 0x3f, // Set Page Address (start,end)
- 0x21, 0x00, 0x7f, // Set Column Address (start,end)
- //
- // 0xD6, 0x01, // Set Zoom In, 0=disabled, 1=enabled
- /*
- 0xAE, // Display OFF (sleep mode)
- 0x20, 0x00, // Set Memory Addressing Mode - 00=Horizontal, 01=Vertical, , 10=Page, 11=Invalid
- 0xB0, // Set Page Start Address for Page Addressing Mode, 0-7
- 0xC8, // Set COM Output Scan Direction
- 0x00, // ---set low column address
- 0x10, // ---set high column address
- 0x40, // --set start line address
- 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, 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, 0xF0, // --set display clock divide ratio/oscillator frequency
- 0xD9, 0x22, // Set pre-charge period
- 0xDA, 0x12, // Set com pins hardware configuration
- 0xDB, 0x20, // --set vcomh, 0x20,0.77xVcc
- 0x8D, 0x14, // Charge Pump Setting, 14h = Enable Charge Pump
- 0xAF, // Display ON in normal mode
- */
- };
- // ============================================================================
- // NOTE: These functions are separate sub-library for handling I2C simplified output.
- // NAME: I2CSW - I2C Simple Writer.
- // Convenience definitions for manipulating PORTB pins
- // NOTE: These definitions are used only internally by the I2CSW library
- #define I2CSW_HIGH(PORT) PORTB |= (1 << PORT)
- #define I2CSW_LOW(PORT) PORTB &= ~(1 << PORT)
- // TO-DO: Implement and use the definitions below.
- #define I2CSW_SDA_DDI() // Data direction INPUT (0x17 is DDRB)
- #define I2CSW_SDA_DDO() // Data direction OUTPUT
- #define I2CSW_SDA_HI() // Port to HIGH
- #define I2CSW_SDA_LO() // Port to LOW
- #define I2CSW_SCL_DDI() // Data direction INPUT
- #define I2CSW_SCL_DDO() // Data direction OUTPUTT
- #define I2CSW_SCL_HI() // Port to HIGH
- #define I2CSW_SCL_LO() // Port to LOW
- // IMPORTANT/NOTE: There is no need to use AVR ASM instructions such as "cbi" and "sbi"
- // The compiler optimizes the bit-shift operations to those instructions.
- // ============================================================================
- void ssd1306_start_command(void)
- {
- I2C_Start();
- I2C_WriteByte(SSD1306_SADDR); // Slave address: R/W(SA0)=0 - write
- I2C_WriteByte(0x00); // Control byte: D/C=0 - write command
- }
- void ssd1306_start_data(void)
- {
- I2C_Start();
- I2C_WriteByte(SSD1306_SADDR); // Slave address, R/W(SA0)=0 - write
- I2C_WriteByte(0x40); // Control byte: D/C=1 - write data
- }
- void ssd1306_data_byte(uint8_t b)
- {
- I2C_WriteByte(b);
- }
- void ssd1306_stop(void)
- {
- I2C_Stop();
- }
- // ============================================================================
- void ssd1306_init(void)
- {
- ssd1306_start_command(); // Initiate transmission of command
- for (uint8_t i = 0; i < sizeof (ssd1306_init_sequence); i++) {
- ssd1306_data_byte(pgm_read_byte(&ssd1306_init_sequence[i])); // Send the command out
- }
- ssd1306_stop(); // Finish transmission of data
- }
- void ssd1306_setpos(uint8_t x, uint8_t y)
- {
- ssd1306_start_command();
- ssd1306_data_byte(0xb0 | (y & 0x07)); // Set page start address
- ssd1306_data_byte(x & 0x0f); // Set the lower nibble of the column start address
- ssd1306_data_byte(0x10 | (x >> 4)); // Set the higher nibble of the column start address
- ssd1306_stop(); // Finish transmission of data
- }
- void ssd1306_fill(uint8_t p)
- {
- ssd1306_setpos(0, 0);
- ssd1306_start_data(); // Initiate transmission of data
- for (uint16_t i = 128 * 8; i > 0; i--) {
- ssd1306_data_byte(p);
- }
- ssd1306_stop(); // Finish transmission of data
- }
- void ssd1306_fill4(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4)
- {
- ssd1306_setpos(0, 0);
- ssd1306_start_data(); // Initiate transmission of data
- for (uint16_t i = 0; i < 128 * 8 / 4; i++) {
- ssd1306_data_byte(p1);
- ssd1306_data_byte(p2);
- ssd1306_data_byte(p3);
- ssd1306_data_byte(p4);
- }
- ssd1306_stop(); // Finish transmission of data
- }
- // ============================================================================
|