-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathplatform_i2c.cpp
More file actions
130 lines (113 loc) · 3.5 KB
/
Copy pathplatform_i2c.cpp
File metadata and controls
130 lines (113 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2026 Dilshan R Jayakody. All rights reserved.
#ifdef ARDUINO
#include <Arduino.h>
#include "platform_i2c.h"
#include "platform_def.h"
// Set to 100kHz standard mode speed.
#define I2C_DELAY() delayMicroseconds(4)
/**
* @brief Initializes the I2C bus by configuring the SDA and SCL pins as inputs.
* @note This function should be called before any other I2C operations.
*/
void PlatformI2C::init () {
pinMode(I2C_SDA_PIN, INPUT);
pinMode(I2C_SCL_PIN, INPUT);
}
/**
* @brief Generates an I2C start condition on the bus.
*/
void PlatformI2C::start() {
pinMode(I2C_SDA_PIN, OUTPUT); digitalWrite(I2C_SDA_PIN, LOW);
I2C_DELAY();
pinMode(I2C_SCL_PIN, OUTPUT); digitalWrite(I2C_SCL_PIN, LOW);
I2C_DELAY();
}
/**
* @brief Generates an I2C restart condition on the bus.
* @note This function is typically used when the master wants to initiate a new
* communication sequence without releasing the bus.
*/
void PlatformI2C::restart() {
pinMode(I2C_SDA_PIN, INPUT);
I2C_DELAY();
pinMode(I2C_SCL_PIN, INPUT);
I2C_DELAY();
start();
}
/**
* @brief Generates an I2C stop condition on the bus.
* @note This function should be called after completing a communication sequence
* to release the bus for other devices.
*/
unsigned char PlatformI2C::write(unsigned char data) {
// Clock out 8-bits.
for (int i = 0; i < 8; i++) {
if (data & 0x80) {
pinMode(I2C_SDA_PIN, INPUT);
} else {
pinMode(I2C_SDA_PIN, OUTPUT); digitalWrite(I2C_SDA_PIN, LOW);
}
data <<= 1;
I2C_DELAY();
pinMode(I2C_SCL_PIN, INPUT);
I2C_DELAY();
pinMode(I2C_SCL_PIN, OUTPUT); digitalWrite(I2C_SCL_PIN, LOW);
I2C_DELAY();
}
// Read 9th bit - ACK/NACK from the slave.
pinMode(I2C_SDA_PIN, INPUT);
I2C_DELAY();
pinMode(I2C_SCL_PIN, INPUT);
I2C_DELAY();
unsigned char ack = (digitalRead(I2C_SDA_PIN) == LOW);
pinMode(I2C_SCL_PIN, OUTPUT); digitalWrite(I2C_SCL_PIN, LOW);
I2C_DELAY();
return ack;
}
/**
* @brief Reads a byte of data from the I2C bus and sends an ACK or NACK signal.
* @param send_ack If true, sends an ACK signal after reading; otherwise, sends a
* NACK signal.
* @return The byte of data read from the I2C bus.
*/
unsigned char PlatformI2C::read(unsigned char send_ack) {
unsigned char data = 0;
pinMode(I2C_SDA_PIN, INPUT);
for (int i = 0; i < 8; i++) {
I2C_DELAY();
pinMode(I2C_SCL_PIN, INPUT);
I2C_DELAY();
data <<= 1;
if (digitalRead(I2C_SDA_PIN) == HIGH) data |= 0x01;
pinMode(I2C_SCL_PIN, OUTPUT); digitalWrite(I2C_SCL_PIN, LOW);
}
// Send ACK or NACK master signal.
if (send_ack) {
pinMode(I2C_SDA_PIN, OUTPUT); digitalWrite(I2C_SDA_PIN, LOW);
} else {
pinMode(I2C_SDA_PIN, INPUT);
}
I2C_DELAY();
pinMode(I2C_SCL_PIN, INPUT);
I2C_DELAY();
pinMode(I2C_SCL_PIN, OUTPUT); digitalWrite(I2C_SCL_PIN, LOW);
pinMode(I2C_SDA_PIN, INPUT);
I2C_DELAY();
return data;
}
/**
* @brief Generates an I2C stop condition on the bus.
* @note This function should be called after completing a communication sequence
* to release the bus for other devices.
*/
void PlatformI2C::stop() {
pinMode(I2C_SDA_PIN, OUTPUT); digitalWrite(I2C_SDA_PIN, LOW);
I2C_DELAY();
pinMode(I2C_SCL_PIN, INPUT);
I2C_DELAY();
pinMode(I2C_SDA_PIN, INPUT);
I2C_DELAY();
}
#undef I2C_DELAY
#endif