49 static const Pin::Mask DEFAULT_SCL_MASK = Pin::Mask::P28;
50 static const Pin::Mask DEFAULT_SDA_MASK = Pin::Mask::P29;
66 template<
size_t BUFFER_SIZE,
size_t STACK_SIZE>
67 I2CSlave (
const uint8_t address, uint8_t (&buffer)[BUFFER_SIZE],
const uint32_t (&stack)[STACK_SIZE],
68 const Pin::Mask sclMask = DEFAULT_SCL_MASK,
const Pin::Mask sdaMask = DEFAULT_SDA_MASK)
70 m_slaveAddress(address),
74 m_bufferUpperBound(BUFFER_SIZE - 1),
75 m_bufferPtr(BUFFER_SIZE) {
92 I2CSlave (
const uint8_t address, uint8_t *buffer,
const size_t bufferSize,
const uint32_t *stack,
93 const size_t stackSize,
const Pin::Mask sclMask = DEFAULT_SCL_MASK,
94 const Pin::Mask sdaMask = DEFAULT_SDA_MASK)
96 m_slaveAddress(address),
100 m_bufferUpperBound(bufferSize - 1),
101 m_bufferPtr(bufferSize) {
113 const uint_fast8_t slaveAddress = this->m_slaveAddress;
118 const uint_fast8_t address = this->read_address();
119 if ((address >> 1) == slaveAddress) {
121 if (address & BIT_0) {
122 this->m_requestEnded =
false;
126 const bool restart = this->read_to_end();
128 this->reset_receive_buffer();
145 return this->m_bufferUpperBound - this->m_bufferPtr + 1;
154 if (this->m_bufferPtr <= this->m_bufferUpperBound)
155 return this->m_buffer[this->m_bufferPtr++];
168 if (!this->m_requestEnded) {
172 " mov %[_dataMask], #128 \n\t"
173 " waitpne %[_SCLMask], %[_SCLMask] \n\t"
174 " or dira, %[_SDAMask] \n\t"
177 " test %[_data], %[_dataMask] wz \n\t"
178 " muxnz outa, %[_SDAMask] \n\t"
179 " waitpeq %[_SCLMask], %[_SCLMask] \n\t"
180 " shr %[_dataMask], #1 wz \n\t"
181 " waitpne %[_SCLMask], %[_SCLMask] \n\t"
182 "if_nz brs #loop%= \n\t"
185 " andn dira, %[_SDAMask] \n\t"
186 " waitpeq %[_SCLMask], %[_SCLMask] \n\t"
187 " test %[_SDAMask], ina wz \n\t"
188 "if_z mov %[_requestEnded], #0 \n\t"
189 "if_nz mov %[_requestEnded], #1 \n\t"
191 [_dataMask]
"+r"(dataMask),
192 [_requestEnded]
"+r"(this->m_requestEnded)
194 [_SDAMask]
"r"(this->m_sda.get_mask()),
195 [_SCLMask]
"r"(this->m_scl.get_mask()),
209 virtual void on_request () = 0;
218 virtual void on_receive () = 0;
224 void await_start ()
const {
227 " waitpeq %[_SDAMask], %[_SDAMask] \n\t"
228 " waitpne %[_SDAMask], %[_SDAMask] \n\t"
229 " test %[_SCLMask], ina wz \n\t"
230 "if_z brs #loop%= \n\t"
233 [_SDAMask]
"r"(this->m_sda.get_mask()),
234 [_SCLMask]
"r"(this->m_scl.get_mask()));
240 uint_fast8_t read_address ()
const {
245 FC_START(
"ReadAddressStart",
"ReadAddressEnd")
246 " mov %[_result], #0 \n\t"
247 " mov %[_bitCounter], #8 \n\t"
249 " waitpne %[_SCLMask], %[_SCLMask] \n\t"
250 " waitpeq %[_SCLMask], %[_SCLMask] \n\t"
251 " test %[_SDAMask], ina wc \n\t"
252 " rcl %[_result], #1 \n\t"
253 " djnz %[_bitCounter], #" FC_ADDR(
"nextBit%=",
"ReadAddressStart")
" \n\t"
254 FC_END(
"ReadAddressEnd")
255 :[_result]
"+r"(result),
256 [_bitCounter]
"+r"(bitCounter)
257 :[_SDAMask]
"r"(this->m_sda.get_mask()),
258 [_SCLMask]
"r"(this->m_scl.get_mask())
266 inline __attribute__((always_inline))
void send_ack ()
const {
269 " waitpne %[_SCLMask], %[_SCLMask] \n\t"
270 " or dira, %[_SDAMask] \n\t"
271 " andn outa, %[_SDAMask] \n\t"
272 " waitpeq %[_SCLMask], %[_SCLMask] \n\t"
273 " waitpne %[_SCLMask], %[_SCLMask] \n\t"
274 " andn dira, %[_SDAMask] \n\t"
276 [_SDAMask]
"r"(this->m_sda.get_mask()),
277 [_SCLMask]
"r"(this->m_scl.get_mask()));
285 bool read_to_end () {
292 " mov %[_isRestart], #2 \n\t"
293 " mov %[_bitCounter], #7 \n\t"
294 " mov %[_result], #0 \n\t"
295 " waitpne %[_SCLMask], %[_SCLMask] \n\t"
296 " waitpeq %[_SCLMask], %[_SCLMask] \n\t"
297 " test %[_SDAMask], ina wc \n\t"
298 " rcl %[_result], #1 \n\t"
299 "if_c brs #DetectRestart%= \n\t"
302 " test %[_SCLMask], ina wz \n\t"
303 "if_z brs #loop%= \n\t"
304 " test %[_SDAMask], ina wz \n\t"
305 "if_nz mov %[_isRestart], #0 \n\t"
306 "if_nz brs #ReceiveEnd%= \n\t"
307 " brs #DetectStop%= \n\t"
310 " test %[_SCLMask], ina wz \n\t"
311 "if_z brs #loop%= \n\t"
312 " test %[_SDAMask], ina wz \n\t"
313 "if_z mov %[_isRestart], #1 \n\t"
314 "if_z brs #ReceiveEnd%= \n\t"
315 " brs #DetectRestart%= \n\t"
318 " waitpne %[_SCLMask], %[_SCLMask] \n\t"
319 " waitpeq %[_SCLMask], %[_SCLMask] \n\t"
320 " test %[_SDAMask], ina wc \n\t"
321 " rcl %[_result], #1 \n\t"
322 " sub %[_bitCounter], #1 wz \n\t"
323 "if_nz brs #loop%= \n\t"
327 [_result]
"+r"(result),
328 [_bitCounter]
"+r"(bitCounter),
329 [_isRestart]
"+r"(isRestart)
331 [_SDAMask]
"r"(this->m_sda.get_mask()),
332 [_SCLMask]
"r"(this->m_scl.get_mask()));
334 if (2 == isRestart) {
336 this->append_receive_buffer(
static_cast<uint8_t
>(result));
338 return static_cast<bool>(isRestart);
346 void append_receive_buffer (
const uint8_t data) {
347 if (this->m_bufferPtr)
348 this->m_buffer[--this->m_bufferPtr] = data;
354 void reset_receive_buffer () {
355 this->m_bufferPtr = this->m_bufferUpperBound + 1;
359 const uint8_t m_slaveAddress;
370 uint32_t m_bufferUpperBound;
374 uint32_t m_bufferPtr;