• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

blues / note-arduino / 13523375661

25 Feb 2025 02:18PM CUT coverage: 90.526% (-4.3%) from 94.831%
13523375661

Pull #132

github

web-flow
Merge 94f998ff5 into 2efe3032e
Pull Request #132: WIP: Template Singleton `make_` functions

98 of 137 branches covered (71.53%)

Branch coverage included in aggregate %.

28 of 33 new or added lines in 3 files covered. (84.85%)

1 existing line in 1 file now uncovered.

332 of 338 relevant lines covered (98.22%)

15.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.3
/src/NoteI2c_Arduino.cpp
1
#include "NoteI2c_Arduino.hpp"
2

3
#if defined(NOTE_C_LOW_MEM)
4
static const char *i2cerr = "i2c {io}";
5
#endif
6

7
// Singleton instance of the NoteI2c_Arduino class
8
namespace instance {
9
    inline NoteI2c* & note_i2c (void) {
7✔
10
        static NoteI2c* note_i2c = nullptr;
11
        return note_i2c;
7✔
12
    }
13
};
14

15
NoteI2c *
16
make_note_i2c (
3✔
17
    nullptr_t
18
) {
19
    NoteI2c* & note_i2c = instance::note_i2c();
3✔
20
    if (note_i2c) {
3!
21
        delete note_i2c;
3!
22
        note_i2c = nullptr;
3✔
23
    }
24
    return note_i2c;
3✔
25
}
26

27
template <typename T>
28
NoteI2c *
29
make_note_i2c (
4✔
30
    T & i2c_parameters_
31
)
32
{
33
    NoteI2c* & note_i2c = instance::note_i2c();
4✔
34
    if (!note_i2c) {
4✔
35
        note_i2c = new NoteI2c_Arduino(i2c_parameters_);
3!
36
    }
37

38
    return note_i2c;
4✔
39
}
40

41
NoteI2c_Arduino::NoteI2c_Arduino
38✔
42
(
43
    TwoWire & i2c_bus_
44
) :
38✔
45
    _i2cPort(i2c_bus_)
38✔
46
{
47
    _i2cPort.begin();
38!
48
}
38✔
49

50
NoteI2c_Arduino::~NoteI2c_Arduino (
38✔
51
    void
52
)
38✔
53
{
54
#if WIRE_HAS_END
55
    _i2cPort.end();
38✔
56
#endif
57
}
38✔
58

59
const char *
60
NoteI2c_Arduino::receive (
22✔
61
    uint16_t device_address_,
62
    uint8_t * buffer_,
63
    uint16_t requested_byte_count_,
64
    uint32_t * available_
65
)
66
{
67
    const char *result = nullptr;
22✔
68

69
    const size_t retry_count = 3;
22✔
70
    size_t i = 0;
22✔
71
    do {
72
        uint8_t transmission_error = 0;
76✔
73

74
        // Request response data from Notecard
75
        _i2cPort.beginTransmission(static_cast<uint8_t>(device_address_));
76✔
76
        _i2cPort.write(static_cast<uint8_t>(0));
76✔
77
        _i2cPort.write(static_cast<uint8_t>(requested_byte_count_));
76✔
78
        transmission_error = _i2cPort.endTransmission();
76✔
79

80
        switch (transmission_error) {
76✔
81
        case 0:
43✔
82
            // I2C transmission was successful
83
            result = nullptr;
43✔
84
            break;
43✔
85
        case 1:
13✔
86
            result = ERRSTR("i2c: data too long to fit in transmit buffer {io}",i2cerr);
13✔
87
            break;
13✔
88
        case 2:
4✔
89
            result = ERRSTR("i2c: received NACK on transmit of address {io}",i2cerr);
4✔
90
            break;
4✔
91
        case 3:
4✔
92
            result = ERRSTR("i2c: received NACK on transmit of data {io}",i2cerr);
4✔
93
            break;
4✔
94
        case 4:
4✔
95
            result = ERRSTR("i2c: unknown error on TwoWire::endTransmission() {io}",i2cerr);
4✔
96
            break;
4✔
97
        case 5:
4✔
98
            result = ERRSTR("i2c: timeout {io}",i2cerr);
4✔
99
            break;
4✔
100
        default:
4✔
101
            result = ERRSTR("i2c: unknown error encounter during I2C transmission {io}",i2cerr);
4✔
102
        }
103

104
        // Read and cache response from Notecard
105
        if (!transmission_error) {
76✔
106
            // Delay briefly ensuring that the Notecard can
107
            // deliver the data in real-time to the I2C ISR
108
            ::delay(2);
43✔
109

110
            const int request_length = requested_byte_count_ + NoteI2c::REQUEST_HEADER_SIZE;
43✔
111
            const int response_length = _i2cPort.requestFrom((int)device_address_, request_length);
43✔
112
            if (!response_length) {
43✔
113
                result = ERRSTR("serial-over-i2c: no response to read request {io}",i2cerr);
15✔
114
            } else if (response_length != request_length) {
28✔
115
                result = ERRSTR("serial-over-i2c: unexpected raw byte count {io}",i2cerr);
8✔
116
            } else {
117
                // Ensure available byte count is within expected range
118
                static const size_t AVAILABLE_MAX = (NoteI2c::REQUEST_MAX_SIZE - NoteI2c::REQUEST_HEADER_SIZE);
119
                uint32_t available = _i2cPort.read();
20✔
120
                if (available > AVAILABLE_MAX) {
20✔
121
                    result = ERRSTR("serial-over-i2c: available byte count greater than max allowed {io}",i2cerr);
8✔
122
                } else if (requested_byte_count_ != static_cast<uint8_t>(_i2cPort.read())) {
12✔
123
                    // Ensure protocol response length matches size request
124
                    result = ERRSTR("serial-over-i2c: unexpected protocol byte count {io}",i2cerr);
8✔
125
                } else {
126
                    // Update available with remaining bytes
127
                    *available_ = available;
4✔
128

129
                    for (size_t i = 0 ; i < requested_byte_count_ ; ++i) {
51✔
130
                        //TODO: Perf test against indexed buffer reads
131
                        *buffer_++ = _i2cPort.read();
47✔
132
                    }
133
                    result = nullptr;
4✔
134
                    break;
4✔
135
                }
136
            }
137
        }
138

139
        // Flash stalls have been observed on the Notecard ESP. Delaying
140
        // between retries provides time for the Notecard to recover from
141
        // the resource contention.
142
        ::delay(1000);
72✔
143
        NOTE_C_LOG_ERROR(result);
144
        NOTE_C_LOG_WARN("serial-over-i2c: reattempting to read Notecard response");
145
    } while (result && (i++ < retry_count));
72!
146

147
    return result;
22✔
148
}
149

150
bool
151
NoteI2c_Arduino::reset (
3✔
152
    uint16_t device_address_
153
)
154
{
155
    (void)device_address_;
156
#if WIRE_HAS_END
157
    _i2cPort.end();
3✔
158
#endif
159
    _i2cPort.begin();
3✔
160
    return true;
3✔
161
}
162

163
const char *
164
NoteI2c_Arduino::transmit (
8✔
165
    uint16_t device_address_,
166
    uint8_t * buffer_,
167
    uint16_t size_
168
)
169
{
170
    const char * result = nullptr;
8✔
171
    uint8_t transmission_error = 0;
8✔
172

173
    _i2cPort.beginTransmission(static_cast<uint8_t>(device_address_));
8✔
174
    _i2cPort.write(static_cast<uint8_t>(size_));
8✔
175
    _i2cPort.write(buffer_, size_);
8✔
176
    transmission_error = _i2cPort.endTransmission();
8✔
177

178
    if (transmission_error) {
8✔
179
        switch (transmission_error) {
6✔
180
        case 1:
1✔
181
            result = ERRSTR("i2c: data too long to fit in transmit buffer {io}",i2cerr);
1✔
182
            break;
1✔
183
        case 2:
1✔
184
            result = ERRSTR("i2c: received NACK on transmit of address {io}",i2cerr);
1✔
185
            break;
1✔
186
        case 3:
1✔
187
            result = ERRSTR("i2c: received NACK on transmit of data {io}",i2cerr);
1✔
188
            break;
1✔
189
        case 4:
1✔
190
            result = ERRSTR("i2c: unknown error on TwoWire::endTransmission() {io}",i2cerr);
1✔
191
            break;
1✔
192
        case 5:
1✔
193
            result = ERRSTR("i2c: timeout {io}",i2cerr);
1✔
194
            break;
1✔
195
        default:
1✔
196
            result = ERRSTR("i2c: unknown error encounter during I2C transmission {io}",i2cerr);
1✔
197
        }
198
    }
199

200
    return result;
8✔
201
}
202

203
// Explicitly instantiate the template function for the supported types
204
template NoteI2c * make_note_i2c<TwoWire>(TwoWire &);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc