34#ifndef _FREERTOS_DRIVERS_COMMON_BITBANG_I2C_HXX_
35#define _FREERTOS_DRIVERS_COMMON_BITBANG_I2C_HXX_
287 inline bool state_rx(uint8_t *data,
bool nack);
301 inline int transfer(
struct i2c_msg *msg,
bool stop)
override;
325 x < BitBangI2CStates::StateStart::LAST)
381 static_cast<int>(x) + 1);
389template <
class HW> __attribute__((optimize(
"-O3")))
400 state_ = State::ADDRESS;
401 stateTx_ = StateTx::FIRST;
407 uint8_t address = msg_->addr << 1;
408 if (msg_->flags & I2C_M_RD)
412 if (state_tx(address))
418 state_ = State::STOP;
419 stateStop_ = StateStop::FIRST;
423 if (msg_->flags & I2C_M_RD)
425 state_ = State::DATA_RX;
426 stateRx_ = StateRx::FIRST;
430 state_ = State::DATA_TX;
431 stateTx_ = StateTx::FIRST;
438 if (state_tx(msg_->buf[count_]))
444 state_ = State::STOP;
445 stateStop_ = StateStop::FIRST;
447 else if (++count_ >= msg_->len)
452 state_ = State::STOP;
453 stateStop_ = StateStop::FIRST;
463 stateTx_ = StateTx::FIRST;
468 if (state_rx(msg_->buf + count_, (count_ + 1 >= msg_->len)))
474 state_ = State::STOP;
475 stateStop_ = StateStop::FIRST;
477 else if (++count_ >= msg_->len)
482 state_ = State::STOP;
483 stateStop_ = StateStop::FIRST;
493 stateRx_ = StateRx::FIRST;
497 case State::RECOVERY:
498 if (state_recovery())
501 state_ = State::STOP;
502 stateStop_ = StateStop::FIRST;
514 sem_.post_from_isr(&woken);
515 os_isr_exit_yield_test(woken);
522template <
class HW> __attribute__((optimize(
"-O3")))
528 case StateStart::SDA_SET:
532 case StateStart::SCL_SET:
536 case StateStart::SDA_CLR:
547template <
class HW> __attribute__((optimize(
"-O3")))
552 case StateStop::SDA_CLR:
556 case StateStop::SCL_SET:
560 case StateStop::SDA_SET:
571template <
class HW> __attribute__((optimize(
"-O3")))
587 case StateTx::DATA_7_SCL_CLR:
588 case StateTx::DATA_6_SCL_CLR:
589 case StateTx::DATA_5_SCL_CLR:
590 case StateTx::DATA_4_SCL_CLR:
591 case StateTx::DATA_3_SCL_CLR:
592 case StateTx::DATA_2_SCL_CLR:
593 case StateTx::DATA_1_SCL_CLR:
594 case StateTx::DATA_0_SCL_CLR:
601 uint8_t mask = 0x80 >>
602 ((
static_cast<int>(stateTx_) -
603 static_cast<int>(StateTx::DATA_7_SCL_CLR)) >> 1);
615 case StateTx::DATA_7_SCL_SET:
616 case StateTx::DATA_6_SCL_SET:
617 case StateTx::DATA_5_SCL_SET:
618 case StateTx::DATA_4_SCL_SET:
619 case StateTx::DATA_3_SCL_SET:
620 case StateTx::DATA_2_SCL_SET:
621 case StateTx::DATA_1_SCL_SET:
622 case StateTx::DATA_0_SCL_SET:
627 case StateTx::ACK_SDA_SET_SCL_CLR:
632 case StateTx::ACK_SCL_SET:
636 case StateTx::ACK_SCL_CLR:
637 if (HW::SCL_Pin::get() ==
false)
640 clockStretchActive_ =
true;
643 if (clockStretchActive_)
649 clockStretchActive_ =
false;
652 bool ack = (HW::SDA_Pin::get() ==
false);
666template <
class HW> __attribute__((optimize(
"-O3")))
667inline
bool BitBangI2C<HW>::state_rx(uint8_t *data,
bool nack)
671 case StateRx::DATA_7_SCL_SET:
674 case StateRx::DATA_6_SCL_SET:
675 case StateRx::DATA_5_SCL_SET:
676 case StateRx::DATA_4_SCL_SET:
677 case StateRx::DATA_3_SCL_SET:
678 case StateRx::DATA_2_SCL_SET:
679 case StateRx::DATA_1_SCL_SET:
680 case StateRx::DATA_0_SCL_SET:
684 case StateRx::DATA_7_SCL_CLR:
685 case StateRx::DATA_6_SCL_CLR:
686 case StateRx::DATA_5_SCL_CLR:
687 case StateRx::DATA_4_SCL_CLR:
688 case StateRx::DATA_3_SCL_CLR:
689 case StateRx::DATA_2_SCL_CLR:
690 case StateRx::DATA_1_SCL_CLR:
691 case StateRx::DATA_0_SCL_CLR:
692 if (HW::SCL_Pin::get() ==
false)
695 clockStretchActive_ =
true;
698 if (clockStretchActive_)
704 clockStretchActive_ =
false;
708 if (HW::SDA_Pin::get() ==
true)
713 if (stateRx_ == StateRx::DATA_0_SCL_CLR && !nack)
720 case StateRx::ACK_SDA_SCL_SET:
724 case StateRx::ACK_SCL_CLR:
725 if (HW::SCL_Pin::get() ==
false)
728 clockStretchActive_ =
true;
731 if (clockStretchActive_)
737 clockStretchActive_ =
false;
750template <
class HW> __attribute__((optimize(
"-O3")))
753 switch(stateRecovery_)
755 case StateRecovery::SDA_SET:
758 case StateRecovery::DATA_7_SCL_SET:
759 case StateRecovery::DATA_6_SCL_SET:
760 case StateRecovery::DATA_5_SCL_SET:
761 case StateRecovery::DATA_4_SCL_SET:
762 case StateRecovery::DATA_3_SCL_SET:
763 case StateRecovery::DATA_2_SCL_SET:
764 case StateRecovery::DATA_1_SCL_SET:
765 case StateRecovery::DATA_0_SCL_SET:
766 case StateRecovery::ACK_SCL_SET:
769 case StateRecovery::DATA_7_SCL_CLR:
770 case StateRecovery::DATA_6_SCL_CLR:
771 case StateRecovery::DATA_5_SCL_CLR:
772 case StateRecovery::DATA_4_SCL_CLR:
773 case StateRecovery::DATA_3_SCL_CLR:
774 case StateRecovery::DATA_2_SCL_CLR:
775 case StateRecovery::DATA_1_SCL_CLR:
776 case StateRecovery::DATA_0_SCL_CLR:
777 case StateRecovery::ACK_SCL_CLR:
781 if (stateRecovery_ == StateRecovery::LAST)
809 while (sem_.timedwait(0) == 0)
819 state_ = State::START;
820 stateStart_ = StateStart::FIRST;
832 if (sem_.timedwait(wait) == 0)
839 while (sem_.timedwait(0) == 0)
846 state_ = State::RECOVERY;
847 stateRecovery_ = StateRecovery::FIRST;
854 sem_.timedwait(wait);
BitBangI2CStates::StateStart & operator++(BitBangI2CStates::StateStart &x)
Pre-increment operator overload.
See OSMutexLock in os/OS.hxx.
Lightweight locking class for protecting small critical sections.
Consolidate all the state machine enumerations for easy operator overloading.
StateRx
Low level I2C data RX states.
@ FIRST
first data RX sequence state
@ ACK_SDA_SCL_SET
data RX sequence
@ LAST
last data RX sequence state
StateStart
Low level I2C start states.
@ FIRST
first start sequence state
friend StateStart & operator++(StateStart &)
Allow pre-increment definition.
StateRecovery
Low level I2C data RX states.
@ FIRST
first recovery sequence state
@ LAST
last recovery sequence state
StateStop
Low level I2C stop states.
@ FIRST
first stop sequence state
@ LAST
last stop sequence state
BitBangI2CStates()
Default constructor.
State
High level I2C States.
StateTx
Low level I2C data TX states.
@ ACK_SCL_CLR
data TX sequence
@ DATA_4_SCL_CLR
data TX sequence
@ DATA_2_SCL_CLR
data TX sequence
@ DATA_6_SCL_CLR
data TX sequence
@ DATA_7_SCL_CLR
data TX sequence
@ FIRST
first data TX sequence state
@ DATA_5_SCL_SET
data TX sequence
@ DATA_3_SCL_SET
data TX sequence
@ DATA_4_SCL_SET
data TX sequence
@ DATA_3_SCL_CLR
data TX sequence
@ ACK_SDA_SET_SCL_CLR
data TX sequence
@ DATA_5_SCL_CLR
data TX sequence
@ DATA_1_SCL_SET
data TX sequence
@ DATA_1_SCL_CLR
data TX sequence
@ DATA_0_SCL_CLR
data TX sequence
@ DATA_6_SCL_SET
data TX sequence
@ DATA_0_SCL_SET
data TX sequence
@ DATA_2_SCL_SET
data TX sequence
@ LAST
last data TX sequence state
@ ACK_SCL_SET
data TX sequence
@ DATA_7_SCL_SET
data TX sequence
Implement a bit-banged I2C master.
StateTx stateTx_
I2C data TX state machine state.
bool state_start()
Execute state machine for sending start condition.
StateStart stateStart_
I2C start state machine state.
StateStop stateStop_
I2C stop state machine state.
void disable() override
function to disable device
OSSem sem_
semaphore to wakeup task level from ISR
StateRx stateRx_
I2C data RX state machine state.
bool state_recovery()
Execute recovery state machine.
void enable() override
function to enable device
bool clockStretchActive_
true if the slave is clock stretching.
bool state_tx(uint8_t data)
Execute data TX state machine.
bool state_stop()
Execute state machine for sending the stop condition.
bool stop_
if true, issue stop condition at the end of the message
int count_
the count of data bytes transferred, error if < 0
void tick_interrupt()
Called at a periodic tick, when enabled.
State state_
state machine state
bool state_rx(uint8_t *data, bool nack)
Execute data RX state machine.
struct i2c_msg * msg_
I2C message to presently act upon
StateRecovery stateRecovery_
I2C recovery state machine state.
BitBangI2C(const char *name)
Constructor.
int transfer(struct i2c_msg *msg, bool stop) override
Method to transmit/receive the data.
const char * name
device name
Private data for an I2C device.
This class provides a counting semaphore API.
#define MSEC_TO_NSEC(_msec)
Convert a millisecond value to a nanosecond value.