Skip to content

Commit 2a37449

Browse files
committed
atsam4s added support for repeated start on i2c
1 parent 55ede66 commit 2a37449

1 file changed

Lines changed: 74 additions & 11 deletions

File tree

targets/core/atmel/atsam4s/i2c.hpp

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ namespace klib::core::atsam4s::io {
5454
* @brief Internal write implementation
5555
*
5656
* @note software doesnt check if stop is correctly send
57-
*
58-
* @tparam SendStop
59-
* @param address
60-
* @param data
61-
* @param size
62-
* @return true
63-
* @return false
57+
*
58+
* @tparam SendStop
59+
* @tparam std::span<const uint8_t>
60+
* @param address
61+
* @param data
62+
* @return true
63+
* @return false
6464
*/
6565
template <bool SendStop = true, typename T = std::span<const uint8_t>>
6666
constexpr static bool write_impl(const uint8_t address, const T& data) {
@@ -116,22 +116,36 @@ namespace klib::core::atsam4s::io {
116116
* @note software doesnt check if stop is correctly send
117117
*
118118
* @tparam SendStop
119+
* @tparam RepeatedStart
119120
* @tparam std::span<const uint8_t>
120121
* @param address
121122
* @param data
122123
* @return true
123124
* @return false
124125
*/
125-
template <bool SendStop = true, typename T = std::span<const uint8_t>>
126-
constexpr static bool read_impl(const uint8_t address, const T& data) {
126+
template <bool SendStop = true, bool RepeatedStart = false, typename T = std::span<uint8_t>>
127+
constexpr static bool read_impl(const uint8_t address, const T& data, const uint32_t device_address = 0, const uint8_t device_address_size = 0) {
127128
// hardware does not writes with less than 1 byte
128129
if (!data.size()) {
129130
// return we could not transmit the data
130131
return false;
131132
}
132133

133-
// set the address we want to read from
134-
read_write_set_address<true>(address);
134+
// check if we have a repeated start condition
135+
if constexpr (RepeatedStart) {
136+
// make sure the SendStop flag is true
137+
static_assert(SendStop, "Repeated starts require the SendStop flag to be enabled");
138+
139+
// set the address we want to read from
140+
read_write_set_address<true>(address, device_address_size);
141+
142+
// set the data to transmit
143+
I2c::port->IADR = device_address;
144+
}
145+
else {
146+
// set the address we want to read from
147+
read_write_set_address<true>(address);
148+
}
135149

136150
// start the transaction
137151
I2c::port->CR = 0x1;
@@ -164,6 +178,23 @@ namespace klib::core::atsam4s::io {
164178
return (wait_for_status(mask) & mask) == 0x1;
165179
}
166180

181+
template <typename T = std::span<uint8_t>, typename G = std::span<uint8_t>>
182+
constexpr static bool write_read_impl(const uint8_t address, const T& tx, const G& rx) {
183+
// check if data is out of range
184+
if (tx.size() > 3) {
185+
return false;
186+
}
187+
188+
// get the device address
189+
uint32_t addr = 0;
190+
for (uint8_t i = 0; i < tx.size(); i++) {
191+
addr = (addr << 8) | tx[i];
192+
}
193+
194+
// read the data
195+
return read_impl<true, true>(address, rx, addr, tx.size());
196+
}
197+
167198
public:
168199
/**
169200
* @brief Init the i2c bus
@@ -244,6 +275,38 @@ namespace klib::core::atsam4s::io {
244275
constexpr static bool write(const uint8_t address, const multispan<const uint8_t>& data) {
245276
return write_impl<SendStop>(address, data);
246277
}
278+
279+
/**
280+
* @brief Write up to 3 bytes and read data. This
281+
* uses the repeated start in the i2c protocol. If
282+
* you do not want to use repeated start use
283+
* write/read instead
284+
*
285+
* @param address
286+
* @param tx
287+
* @param rx
288+
* @return true
289+
* @return false
290+
*/
291+
constexpr static bool write_read(const uint8_t address, const std::span<const uint8_t>& tx, const std::span<uint8_t>& rx) {
292+
return write_read_impl(address, tx, rx);
293+
}
294+
295+
/**
296+
* @brief Write up to 3 bytes and read data. This
297+
* uses the repeated start in the i2c protocol. If
298+
* you do not want to use repeated start use
299+
* write/read instead
300+
*
301+
* @param address
302+
* @param tx
303+
* @param rx
304+
* @return true
305+
* @return false
306+
*/
307+
constexpr static bool write_read(const uint8_t address, const std::span<const uint8_t>& tx, const klib::multispan<uint8_t>& rx) {
308+
return write_read_impl(address, tx, rx);
309+
}
247310
};
248311
}
249312

0 commit comments

Comments
 (0)