i2c.cpp (2465B)
1 #include "i2c.h" 2 3 #include <cassert> 4 5 #include "dsp56kEmu/logging.h" 6 7 namespace hwLib 8 { 9 void I2c::masterWrite(const bool _sda, const bool _scl) 10 { 11 if(_sda != m_sda && _scl != m_scl) 12 { 13 assert(false && "only one pin should flip"); 14 return; 15 } 16 17 if(_sda != m_sda) 18 { 19 m_sda = _sda; 20 sdaFlip(_sda); 21 } 22 else if(_scl != m_scl) 23 { 24 m_scl = _scl; 25 sclFlip(_scl); 26 } 27 } 28 29 std::optional<bool> I2c::masterRead(const bool _scl) 30 { 31 if(_scl == m_scl) 32 return {}; 33 34 if(m_state != State::Start) 35 return {}; 36 37 m_scl = _scl; 38 39 if(_scl) 40 { 41 if(m_nextBit == BitAck) 42 { 43 m_nextBit = Bit7; 44 return m_ackBit; // this was returned already in onAck() 45 } 46 47 if(m_nextBit >= Bit0 && m_nextBit <= Bit7) 48 { 49 if(m_nextBit == Bit7) 50 m_byte = onReadByte(); 51 52 auto res = m_byte & (1<<m_nextBit); 53 --m_nextBit; 54 return res; 55 } 56 } 57 58 return {}; 59 } 60 61 std::optional<bool> I2c::setSdaWrite(const bool _write) 62 { 63 if(m_sdaWrite == _write) 64 return {}; 65 66 m_sdaWrite = _write; 67 68 if(m_state != State::Start) 69 return {}; 70 71 if(!m_sdaWrite) 72 { 73 if(m_nextBit == BitAck) 74 { 75 const auto ackBit = onAck(); 76 if(ackBit) 77 { 78 m_ackBit = *ackBit; 79 } 80 return ackBit; 81 } 82 } 83 return {}; 84 } 85 86 void I2c::onStateChanged(const State _state) 87 { 88 LOG("state: " << (_state == State::Start ? "start" : "stop")); 89 90 switch (_state) 91 { 92 case State::Stop: 93 m_nextBit = BitInvalid; 94 break; 95 case State::Start: 96 m_nextBit = Bit7; 97 m_byte = 0; 98 break; 99 } 100 } 101 102 void I2c::onStartCondition() 103 { 104 setState(State::Start); 105 } 106 107 void I2c::onStopCondition() 108 { 109 setState(State::Stop); 110 } 111 112 void I2c::onByteWritten() 113 { 114 LOG("Got byte " << HEXN(byte(), 2)); 115 } 116 117 void I2c::sdaFlip(const bool _sda) 118 { 119 if(m_scl) 120 { 121 if(!_sda) 122 onStartCondition(); 123 else 124 onStopCondition(); 125 } 126 } 127 128 void I2c::sclFlip(const bool _scl) 129 { 130 if(_scl && m_state == State::Start) 131 { 132 if(m_nextBit >= Bit0 && m_nextBit <= Bit7) 133 { 134 LOG("next bit " << static_cast<int>(m_nextBit) << " = " << m_sda); 135 136 if(m_nextBit == Bit7) 137 m_byte = 0; 138 139 // data input 140 if(m_sda) 141 m_byte |= (1<<m_nextBit); 142 143 --m_nextBit; 144 145 if(m_nextBit < 0) 146 { 147 onByteWritten(); 148 } 149 } 150 else if(m_nextBit == BitAck) 151 { 152 LOG("ACK by master=" << m_sda); 153 m_nextBit = 7; 154 } 155 } 156 } 157 158 void I2c::setState(const State _state) 159 { 160 /* if(m_state == _state) 161 return; 162 */ m_state = _state; 163 onStateChanged(_state); 164 } 165 }