SSD1306 OLED display driver  1.3.5
This library is developed to control SSD1306 i2c/spi OLED display
ssd1306_i2c_embedded.c
1 /*
2  Copyright (C) 2016-2017 Alexey Dynda
3 
4  This file is part of SSD1306 library.
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 
21 #include "ssd1306_i2c_embedded.h"
22 #include "intf/ssd1306_interface.h"
23 #include "ssd1306_i2c_conf.h"
24 #include "ssd1306_i2c.h"
25 
26 #ifdef SSD1306_I2C_SW_SUPPORTED
27 
28 #include <Arduino.h>
29 
36 static uint8_t s_scl = (1<<SSD1306_SCL);
37 static uint8_t s_sda = (1<<SSD1306_SDA);
38 static uint8_t s_sa = SSD1306_SA;
39 
40 #include <avr/interrupt.h>
41 
42  #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
43  // at 8Mhz each command takes ~ 0.125us
44  #define DDR_REG DDRB
45  #define PORT_REG PORTB
46  #else // For Atmega
47  // at 16Mhz each command takes ~ 0.0625us
48  #define DDR_REG DDRC
49  #define PORT_REG PORTC
50  #endif
51 
52 
53 #ifndef F_CPU
54  #warning "F_CPU is not defined, there can be I2C issues"
55  #define F_CPU 8000000
56 #endif
57 #define CPU_CYCLE_NS (1000000000/F_CPU)
58 
59 // each delay loop takes 4 cycles: nop(1), dec(1), jnz(2)
60 #define DELAY_LOOP_CYCLES 4
61 #define ssd1306_delay(x) for(uint8_t i2=x; i2>0; i2--){__asm__("nop\n\t");}
62 
66 #define SSD1306_I2C_START_STOP_DELAY 600
67 #define SSD1306_I2C_RISE_TIME 300
68 #define SSD1306_I2C_FALL_TIME 300
69 #define SSD1306_I2C_DATA_HOLD_TIME 300
70 #define SSD1306_I2C_IDLE_TIME 1300
71 #define SSD1306_I2C_CLOCK 2500
72 
73 
74 #define I2C_START_STOP_DELAY ((SSD1306_I2C_START_STOP_DELAY/CPU_CYCLE_NS + DELAY_LOOP_CYCLES/2)/DELAY_LOOP_CYCLES)
75 
76 #define I2C_RISE_TIME ((SSD1306_I2C_RISE_TIME/CPU_CYCLE_NS)/DELAY_LOOP_CYCLES)
77 
78 #define I2C_DATA_HOLD_TIME ((SSD1306_I2C_DATA_HOLD_TIME/CPU_CYCLE_NS + DELAY_LOOP_CYCLES/2)/DELAY_LOOP_CYCLES)
79 
80 #define I2C_IDLE_TIME (((SSD1306_I2C_IDLE_TIME/CPU_CYCLE_NS) + DELAY_LOOP_CYCLES/2)/DELAY_LOOP_CYCLES)
81 
82 #define I2C_HALF_CLOCK (((SSD1306_I2C_CLOCK - SSD1306_I2C_FALL_TIME - SSD1306_I2C_RISE_TIME - SSD1306_I2C_FALL_TIME)/CPU_CYCLE_NS/2 \
83  )/DELAY_LOOP_CYCLES)
84 
85 
86 /* I2C HIGH = PORT as INPUT(0) and PULL-UP ENABLE (1) */
87 //#define DIGITAL_WRITE_HIGH(DREG, PREG, BIT) { DREG &= ~(1 << BIT); PREG |= (1 << BIT); }
88 #define DIGITAL_WRITE_HIGH(DREG, PREG, BIT) { DREG &= ~BIT; PREG |= BIT; }
89 
90 /* I2C LOW = PORT as OUTPUT(1) and OUTPUT LOW (0) */
91 //#define DIGITAL_WRITE_LOW(DREG, PREG, BIT) { DREG |= (1 << BIT); PREG &= ~(1 << BIT); }
92 #define DIGITAL_WRITE_LOW(DREG, PREG, BIT) { DREG |= BIT; PREG &= ~BIT; }
93 
94 static uint8_t oldSREG;
95 static uint8_t interruptsOff = 0;
96 
101 {
102  oldSREG = SREG;
103  cli();
104  interruptsOff = 1;
105  DIGITAL_WRITE_LOW(DDR_REG, PORT_REG, s_sda); // Set to LOW
106  ssd1306_delay(I2C_START_STOP_DELAY);
107  DIGITAL_WRITE_LOW(DDR_REG, PORT_REG, s_scl); // Set to LOW
108  ssd1306_delay(I2C_HALF_CLOCK);
109  ssd1306_i2cSendByte_Embedded((s_sa << 1) | 0);
110 }
111 
113 {
114  DIGITAL_WRITE_LOW(DDR_REG, PORT_REG, s_sda); // Set to LOW
115  ssd1306_delay(I2C_RISE_TIME); // Fall time is the same as rise time
116  DIGITAL_WRITE_HIGH(DDR_REG, PORT_REG, s_scl); // Set to HIGH
117  ssd1306_delay(I2C_START_STOP_DELAY);
118  DIGITAL_WRITE_HIGH(DDR_REG, PORT_REG, s_sda); // Set to HIGH
119  ssd1306_delay(I2C_IDLE_TIME);
120  if (interruptsOff)
121  {
122  SREG = oldSREG;
123  interruptsOff = 0;
124  }
125 }
126 
132 {
133  uint8_t i;
134  for(i=8; i>0; i--)
135  {
136  if(data & 0x80)
137  DIGITAL_WRITE_HIGH(DDR_REG, PORT_REG, s_sda)
138  else
139  DIGITAL_WRITE_LOW(DDR_REG, PORT_REG, s_sda);
140  data<<=1;
141  ssd1306_delay(I2C_RISE_TIME); // Fall time is the same as rise time
142 
143  DIGITAL_WRITE_HIGH(DDR_REG, PORT_REG, s_scl);
144  ssd1306_delay(I2C_HALF_CLOCK);
145 
146  DIGITAL_WRITE_LOW(DDR_REG, PORT_REG, s_scl);
147  ssd1306_delay(I2C_HALF_CLOCK);
148  }
149  // generating confirmation impulse
150  DIGITAL_WRITE_HIGH(DDR_REG, PORT_REG, s_sda);
151  ssd1306_delay(I2C_RISE_TIME); // Fall time is the same as rise time
152  DIGITAL_WRITE_HIGH(DDR_REG, PORT_REG, s_scl);
153  ssd1306_delay(I2C_HALF_CLOCK);
154  DIGITAL_WRITE_LOW(DDR_REG, PORT_REG, s_scl);
155  ssd1306_delay(I2C_HALF_CLOCK);
156 }
157 
158 void ssd1306_i2cInit_Embedded(int8_t scl, int8_t sda, uint8_t sa)
159 {
160  if (scl>=0) s_scl = (1<<scl);
161  if (sda>=0) s_sda = (1<<sda);
162  if (sa) s_sa = sa;
168 }
169 
170 #endif
void ssd1306_i2cInit_Embedded(int8_t scl, int8_t sda, uint8_t sa)
void(* ssd1306_sendByte)(uint8_t data)
void ssd1306_i2cStart_Embedded(void)
void(* ssd1306_dataStart)()
void(* ssd1306_endTransmission)()
#define SSD1306_SCL
SCL, Pin 3 on SSD1306 Board.
void ssd1306_i2cSendByte_Embedded(uint8_t data)
void ssd1306_i2cStop_Embedded(void)
void ssd1306_i2cCommandStart()
void ssd1306_i2cDataStart()
void(* ssd1306_startTransmission)()
#define SSD1306_SDA
SDA, Pin 4 on SSD1306 Board.
void(* ssd1306_commandStart)()
#define SSD1306_SA