Skip to content

Commit f8960f5

Browse files
committed
[driver] Refactor all I2C driver to use fibers
1 parent 93c4805 commit f8960f5

33 files changed

+712
-1418
lines changed

src/modm/architecture/interface/i2c_device.hpp

Lines changed: 26 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include "i2c.hpp"
1616
#include "i2c_master.hpp"
1717
#include "i2c_transaction.hpp"
18-
#include <modm/processing/resumable.hpp>
18+
#include <modm/processing/fiber.hpp>
1919

2020
namespace modm
2121
{
@@ -41,7 +41,7 @@ namespace modm
4141
* @ingroup modm_architecture_i2c_device
4242
*/
4343
template < class I2cMaster, uint8_t NestingLevels = 10, class Transaction = I2cWriteReadTransaction >
44-
class I2cDevice : protected modm::NestedResumable< NestingLevels + 1 >
44+
class I2cDevice
4545
{
4646
public:
4747
/// @param address the slave address not yet shifted left (address < 128).
@@ -60,69 +60,49 @@ class I2cDevice : protected modm::NestedResumable< NestingLevels + 1 >
6060

6161
/// Attaches a configuration handler, which is called before a transaction,
6262
/// whenever the configuration has to be changed.
63-
void inline
63+
void
6464
attachConfigurationHandler(I2c::ConfigurationHandler handler)
6565
{
6666
configuration = handler;
6767
}
6868

6969
/// @retval true device responds to address
7070
/// @retval false no device with address found
71-
modm::ResumableResult<bool>
71+
bool
7272
ping()
7373
{
74-
RF_BEGIN();
75-
76-
RF_WAIT_UNTIL( transaction.configurePing() and startTransaction() );
77-
78-
RF_WAIT_WHILE( isTransactionRunning() );
79-
80-
RF_END_RETURN( wasTransactionSuccessful() );
74+
modm::this_fiber::poll([&]{ return transaction.configurePing(); });
75+
return runTransaction();
8176
}
8277

8378
/// Starts a write-read transaction and waits until finished.
84-
modm::ResumableResult<bool>
79+
bool
8580
writeRead(const uint8_t *writeBuffer, std::size_t writeSize,
8681
uint8_t *readBuffer, std::size_t readSize)
8782
{
88-
RF_BEGIN();
89-
90-
RF_WAIT_UNTIL( startWriteRead(writeBuffer, writeSize, readBuffer, readSize) );
91-
92-
RF_WAIT_WHILE( isTransactionRunning() );
93-
94-
RF_END_RETURN( wasTransactionSuccessful() );
83+
modm::this_fiber::poll([&]{ return transaction.configureWriteRead(writeBuffer, writeSize, readBuffer, readSize); });
84+
return runTransaction();
9585
}
9686

9787
/// Starts a write transaction and waits until finished.
98-
modm::ResumableResult<bool>
88+
bool
9989
write(const uint8_t *buffer, std::size_t size)
10090
{
101-
RF_BEGIN();
102-
103-
RF_WAIT_UNTIL( startWrite(buffer, size) );
104-
105-
RF_WAIT_WHILE( isTransactionRunning() );
106-
107-
RF_END_RETURN( wasTransactionSuccessful() );
91+
modm::this_fiber::poll([&]{ return transaction.configureWrite(buffer, size); });
92+
return runTransaction();
10893
}
10994

11095
/// Starts a write transaction and waits until finished.
111-
modm::ResumableResult<bool>
96+
bool
11297
read(uint8_t *buffer, std::size_t size)
11398
{
114-
RF_BEGIN();
115-
116-
RF_WAIT_UNTIL( startRead(buffer, size) );
117-
118-
RF_WAIT_WHILE( isTransactionRunning() );
119-
120-
RF_END_RETURN( wasTransactionSuccessful() );
99+
modm::this_fiber::poll([&]{ return transaction.configureRead(buffer, size); });
100+
return runTransaction();
121101
}
122102

123103
protected:
124104
/// Configures the transaction with a write/read operation and starts it.
125-
bool inline
105+
bool
126106
startWriteRead(const uint8_t *writeBuffer, std::size_t writeSize,
127107
uint8_t *readBuffer, std::size_t readSize)
128108
{
@@ -131,15 +111,15 @@ class I2cDevice : protected modm::NestedResumable< NestingLevels + 1 >
131111
}
132112

133113
/// Configures the transaction with a write operation and starts it.
134-
bool inline
114+
bool
135115
startWrite(const uint8_t *buffer, std::size_t size)
136116
{
137117
return ( transaction.configureWrite(buffer, size) and
138118
startTransaction() );
139119
}
140120

141121
/// Configures the transaction with a read operation and starts it.
142-
bool inline
122+
bool
143123
startRead(uint8_t *buffer, std::size_t size)
144124
{
145125
return ( transaction.configureRead(buffer, size) and
@@ -148,44 +128,40 @@ class I2cDevice : protected modm::NestedResumable< NestingLevels + 1 >
148128

149129
protected:
150130
/// Starts the transaction with our own transaction object.
151-
bool inline
131+
bool
152132
startTransaction()
153133
{
154134
return startTransaction(&this->transaction);
155135
}
156136

157137
/// Starts the transaction with a separate transaction object.
158-
bool inline
138+
bool
159139
startTransaction(modm::I2cTransaction *transaction)
160140
{
161141
return I2cMaster::start(transaction, configuration);
162142
}
163143

164144
/// @returns `true` when transaction is busy.
165-
bool inline
145+
bool
166146
isTransactionRunning()
167147
{
168148
return transaction.isBusy();
169149
}
170150

171151
/// @returns `true` when transaction did not return an error.
172-
bool inline
152+
bool
173153
wasTransactionSuccessful()
174154
{
175155
return (transaction.getState() != modm::I2c::TransactionState::Error);
176156
}
177157

178158
/// Starts our own transaction and waits until finished.
179-
modm::ResumableResult<bool>
159+
bool
180160
runTransaction()
181161
{
182-
RF_BEGIN();
183-
184-
RF_WAIT_UNTIL( startTransaction() );
185-
186-
RF_WAIT_WHILE( isTransactionRunning() );
187-
188-
RF_END_RETURN( wasTransactionSuccessful() );
162+
modm::this_fiber::poll([&]{ return startTransaction(); });
163+
modm::this_fiber::poll([&]{ return not isTransactionRunning(); });
164+
return wasTransactionSuccessful();
189165
}
190166

191167
protected:

src/modm/architecture/module.lb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ class I2cDevice(Module):
234234
module.description = "I²C Devices"
235235

236236
def prepare(self, module, options):
237-
module.depends(":architecture:i2c", ":processing:resumable")
237+
module.depends(":architecture:i2c", ":architecture:fiber")
238238
return True
239239

240240
def build(self, env):

src/modm/driver/adc/ads101x.hpp

Lines changed: 94 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright (c) 2022, Jonas Kazem Andersen
33
* Copyright (c) 2022, Rasmus Kleist Hørlyck Sørensen
4+
* Copyright (c) 2025, Niklas Hauser
45
*
56
* This file is part of the modm project.
67
*
@@ -10,10 +11,10 @@
1011
*/
1112
// ----------------------------------------------------------------------------
1213

13-
#ifndef MODM_ADS101X_HPP
14-
#define MODM_ADS101X_HPP
14+
#pragma once
1515

1616
#include <modm/architecture/interface/i2c_device.hpp>
17+
#include <modm/architecture/interface/register.hpp>
1718

1819
namespace modm
1920
{
@@ -187,62 +188,118 @@ struct ads101x
187188
* @ingroup modm_driver_ads101x
188189
*/
189190
template <typename I2cMaster>
190-
class Ads101x : public ads101x, public modm::I2cDevice<I2cMaster, 2>
191+
class Ads101x : public ads101x, public modm::I2cDevice<I2cMaster>
191192
{
192193
public:
193194
/**
194195
* @param data
195196
* @param address
196197
*/
197-
Ads101x(Data &data, uint8_t address = 0x49);
198+
Ads101x(Data &data, uint8_t address = 0x49)
199+
: I2cDevice<I2cMaster>(address), data(data) {}
198200

199201
/// Call this function before using the device
200-
modm::ResumableResult<bool>
201-
initialize();
202+
bool
203+
initialize()
204+
{
205+
InputMultiplexer_t::set(config, InputMultiplexer::Input0);
206+
FullScaleRange_t::set(config, FullScaleRange::V2_048);
207+
DeviceOperatingMode_t::set(config, DeviceOperatingMode::SingleShot);
208+
DataRate_t::set(config, DataRate::Sps1600);
209+
ComparatorQueue_t::set(config, ComparatorQueue::Disable);
210+
data.lsbSizeIndex = i(FullScaleRange::V2_048) >> 9;
211+
212+
return writeRegister(Register::Config, config.value);
213+
}
202214

203215
/// Determine if the device is currently performing a conversion
204-
modm::ResumableResult<bool>
205-
isBusy();
216+
bool
217+
isBusy()
218+
{
219+
uint8_t buffer[2] = {i(Register::Config)};
220+
if (not this->writeRead(buffer, 1, buffer, 2)) return false;
221+
return not ((uint16_t(buffer[0]) << 8) & i(ConfigRegister::OS));
222+
}
206223

207224
/// Start a single conversion with the specified input
208-
modm::ResumableResult<bool>
209-
startSingleShotConversion();
225+
bool
226+
startSingleShotConversion()
227+
{
228+
DeviceOperatingMode_t::set(config, DeviceOperatingMode::SingleShot);
229+
return writeRegister(Register::Config, i(ConfigRegister::OS) | config.value);
230+
}
210231

211232
/// Start continuous conversions with the specified datarate and input
212-
modm::ResumableResult<bool>
213-
startContinuousConversion(DataRate dataRate = DataRate::Sps1600);
233+
bool
234+
startContinuousConversion(DataRate dataRate = DataRate::Sps1600)
235+
{
236+
DataRate_t::set(config, dataRate);
237+
DeviceOperatingMode_t::set(config, DeviceOperatingMode::Continuous);
238+
return writeRegister(Register::Config, i(ConfigRegister::OS) | config.value);
239+
}
214240

215241
/// Start a single conversion with the specified input
216242
/// @warning ADS1015 only
217-
modm::ResumableResult<bool>
218-
startSingleShotConversion(InputMultiplexer input = InputMultiplexer::Input0);
243+
bool
244+
startSingleShotConversion(InputMultiplexer input = InputMultiplexer::Input0)
245+
{
246+
InputMultiplexer_t::set(config, input);
247+
DeviceOperatingMode_t::set(config, DeviceOperatingMode::SingleShot);
248+
return writeRegister(Register::Config, i(ConfigRegister::OS) | config.value);
249+
}
219250

220251
/// Start continuous conversions with the specified datarate and input
221252
/// @warning ADS1015 only
222-
modm::ResumableResult<bool>
223-
startContinuousConversion(InputMultiplexer input = InputMultiplexer::Input0, DataRate dataRate = DataRate::Sps1600);
253+
bool
254+
startContinuousConversion(InputMultiplexer input = InputMultiplexer::Input0, DataRate dataRate = DataRate::Sps1600)
255+
{
256+
DataRate_t::set(config, dataRate);
257+
InputMultiplexer_t::set(config, input);
258+
DeviceOperatingMode_t::set(config, DeviceOperatingMode::Continuous);
259+
return writeRegister(Register::Config, config.value);
260+
}
224261

225262
/// Read the last conversion result
226263
/// @attention Following power-up, the conversion result remains zero until the first conversion is completed
227-
modm::ResumableResult<bool>
228-
readConversionResult();
264+
bool
265+
readConversionResult()
266+
{
267+
uint8_t buffer = i(Register::Conversion);
268+
return this->writeRead(&buffer, 1, data.data, 2);
269+
}
229270

230271
/// Enable the conversion-ready function of the ALERT/RDY pin
231272
/// @attention enabling the conversion-ready function disables the comparator and sets the ComparatorQue value to one conversion
232-
modm::ResumableResult<bool>
233-
enableConversionReadyFunction();
273+
bool
274+
enableConversionReadyFunction()
275+
{
276+
if (not (writeRegister(Register::LowThreshold, 0x0000) and
277+
writeRegister(Register::HighThreshold, 0xFFFF)))
278+
return false;
279+
280+
ComparatorQueue_t::set(config, ComparatorQueue::OneConversion);
281+
return writeRegister(Register::Config, config.value);
282+
}
234283

235284
/// Enable the comparator
236285
/// @warning ADS1014 and ADS1015 only
237286
/// @warning To use the comparator-function the high threshold must be greater than the low threshold
238-
modm::ResumableResult<bool>
239-
enableComparator(ComparatorMode mode, ComparatorPolarity polarity, ComparatorLatch latch, ComparatorQueue queue);
287+
bool
288+
enableComparator(ComparatorMode mode, ComparatorPolarity polarity, ComparatorLatch latch, ComparatorQueue queue)
289+
{
290+
ComparatorMode_t::set(config, mode);
291+
ComparatorPolarity_t::set(config, polarity);
292+
ComparatorLatch_t::set(config, latch);
293+
ComparatorQueue_t::set(config, queue);
294+
295+
return writeRegister(Register::Config, config.value);
296+
}
240297

241298
/// Set the low threshold used by the comparator queue
242299
/// @warning ADS1014 and ADS1015 only
243300
/// @warning The low threshold value must be smaller than the high threshold value
244301
/// @attention The high threshold value must be updated whenever the PGA settings are changed
245-
modm::ResumableResult<bool>
302+
bool
246303
setLowThreshold(uint16_t threshold)
247304
{
248305
return writeRegister(Register::LowThreshold, (threshold << 4) & 0xFFF0);
@@ -252,31 +309,33 @@ class Ads101x : public ads101x, public modm::I2cDevice<I2cMaster, 2>
252309
/// @warning ADS1014 and ADS1015 only
253310
/// @warning The high threshold value must be greater than the low threshold value
254311
/// @attention The high threshold value must be updated whenever the PGA settings are changed
255-
modm::ResumableResult<bool>
312+
bool
256313
setHighThreshold(uint16_t threshold)
257314
{
258315
return writeRegister(Register::HighThreshold, (threshold << 4) | 0x0F);
259316
}
260317

261318
/// Set the full scale range by programming the PGA and corresponding LSB size
262-
modm::ResumableResult<bool>
263-
setFullScaleRange(FullScaleRange fullScaleRange);
319+
bool
320+
setFullScaleRange(FullScaleRange fullScaleRange)
321+
{
322+
FullScaleRange_t::set(config, fullScaleRange);
323+
data.lsbSizeIndex = i(fullScaleRange) >> 9;
324+
return writeRegister(Register::Config, config.value);
325+
}
264326

265327
private:
266-
modm::ResumableResult<bool>
267-
writeRegister(Register reg, uint16_t data);
328+
bool
329+
writeRegister(Register reg, uint16_t data)
330+
{
331+
uint8_t buffer[] = {i(reg), data >> 8, data};
332+
return this->write(buffer, sizeof(buffer));
333+
}
268334

269335
Data &data;
270336

271-
/// Command buffer for writing to device
272-
uint8_t buffer[3];
273-
274337
/// Configuration variable for writing to the configuration register
275338
ConfigRegister_t config;
276339
};
277340

278341
}
279-
280-
#include "ads101x_impl.hpp"
281-
282-
#endif // MODM_ADS101X_HPP

src/modm/driver/adc/ads101x.lb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,3 @@ def prepare(module, options):
2727
def build(env):
2828
env.outbasepath = "modm/src/modm/driver/adc"
2929
env.copy("ads101x.hpp")
30-
env.copy("ads101x_impl.hpp")

0 commit comments

Comments
 (0)