diff --git a/OneWireSlave.cpp b/OneWireSlave.cpp index 6e406bc..417231e 100644 --- a/OneWireSlave.cpp +++ b/OneWireSlave.cpp @@ -224,6 +224,7 @@ void OneWireSlave::endPresence_() debug.SC_APPEND_STR_TIME("endPresence", now); #endif + ignoreNextEdge_ = true; beginWaitCommand_(); } @@ -235,10 +236,15 @@ void OneWireSlave::beginWaitCommand_() void OneWireSlave::beginReceive_() { - ignoreNextEdge_ = true; - pin_.attachInterrupt(&OneWireSlave::receiveHandler_, FALLING); receivingByte_ = 0; receivingBitPos_ = 0; + beginReceiveBit_(&OneWireSlave::onBitReceivedHandler_); +} + +void OneWireSlave::beginReceiveBit_(void(*completeCallback)(bool bit, bool error)) +{ + receiveBitCallback_ = completeCallback; + pin_.attachInterrupt(&OneWireSlave::receiveHandler_, FALLING); } void OneWireSlave::receive_() @@ -246,21 +252,90 @@ void OneWireSlave::receive_() onEnterInterrupt_(); if (!ignoreNextEdge_) - setTimerEvent_(ReadBitSamplingTime, &OneWireSlave::receiveBitHandler_); + { + pin_.detachInterrupt(); + setTimerEvent_(ReadBitSamplingTime, &OneWireSlave::readBitHandler_); + } + + ignoreNextEdge_ = false; + + onLeaveInterrupt_(); +} + +void OneWireSlave::beginSendBit_(bool bit, void(*completeCallback)(bool error)) +{ + bitSentCallback_ = completeCallback; + if (bit) + { + pin_.attachInterrupt(&OneWireSlave::sendBitOneHandler_, FALLING); + } + else + { + pin_.attachInterrupt(&OneWireSlave::sendBitZeroHandler_, FALLING); + } +} + +void OneWireSlave::sendBitOne_() +{ + onEnterInterrupt_(); + bool ignoreEdge = ignoreNextEdge_; ignoreNextEdge_ = false; + if (!ignoreEdge) + bitSentCallback_(false); + + onLeaveInterrupt_(); +} + +void OneWireSlave::sendBitZero_() +{ + onEnterInterrupt_(); + + if (ignoreNextEdge_) + { + ignoreNextEdge_ = false; + return; + } + + pullLow_(); + pin_.detachInterrupt(); + setTimerEvent_(SendBitDuration, &OneWireSlave::endSendBitZeroHandler_); + onLeaveInterrupt_(); } -void OneWireSlave::receiveBit_() +void OneWireSlave::endSendBitZero_() +{ + onEnterInterrupt_(); + + releaseBus_(); + bitSentCallback_(false); + + onLeaveInterrupt_(); +} + +void OneWireSlave::readBit_() { onEnterInterrupt_(); bool bit = pin_.read(); + receiveBitCallback_(bit, false); //dbgOutput.writeLow(); //dbgOutput.writeHigh(); + onLeaveInterrupt_(); +} + +void OneWireSlave::onBitReceived_(bool bit, bool error) +{ + if (error) + { + error_("Invalid bit"); + beginWaitReset_(); + return; + } + receivingByte_ |= ((bit ? 1 : 0) << receivingBitPos_); ++receivingBitPos_; @@ -274,24 +349,102 @@ void OneWireSlave::receiveBit_() if (receivingByte_ == 0xF0) { beginSearchRom_(); + return; } else { // TODO: send command to client code beginWaitReset_(); + return; } } else { // TODO: add byte in receive buffer beginWaitReset_(); + return; } } - - onLeaveInterrupt_(); + + beginReceiveBit_(&OneWireSlave::onBitReceivedHandler_); } void OneWireSlave::beginSearchRom_() { - pin_.detachInterrupt(); -} \ No newline at end of file + searchRomBytePos_ = 0; + searchRomBitPos_ = 0; + searchRomInverse_ = false; + + beginSearchRomSendBit_(); +} + +void OneWireSlave::beginSearchRomSendBit_() +{ + byte currentByte = rom_[searchRomBytePos_]; + bool currentBit = bitRead(currentByte, searchRomBitPos_); + bool bitToSend = searchRomInverse_ ? !currentBit : currentBit; + + beginSendBit_(bitToSend, &OneWireSlave::continueSearchRomHandler_); +} + +void OneWireSlave::continueSearchRom_(bool error) +{ + if (error) + { + error_("Failed to send bit"); + beginWaitReset_(); + return; + } + + searchRomInverse_ = !searchRomInverse_; + if (searchRomInverse_) + { + beginSearchRomSendBit_(); + } + else + { + beginReceiveBit_(&OneWireSlave::searchRomOnBitReceivedHandler_); + } +} + +void OneWireSlave::searchRomOnBitReceived_(bool bit, bool error) +{ + if (error) + { + error_("Bit read error during ROM search"); + beginWaitReset_(); + return; + } + + byte currentByte = rom_[searchRomBytePos_]; + bool currentBit = bitRead(currentByte, searchRomBitPos_); + + if (bit == currentBit) + { + ++searchRomBitPos_; + if (searchRomBitPos_ == 8) + { + searchRomBitPos_ = 0; + ++searchRomBytePos_; + } + + if (searchRomBytePos_ == 8) + { + #ifdef DEBUG_LOG + debug.SC_APPEND_STR("ROM sent entirely"); + #endif + beginWaitReset_(); + } + else + { + beginSearchRomSendBit_(); + } + } + else + { + #ifdef DEBUG_LOG + debug.SC_APPEND_STR("Leaving ROM search"); + #endif + beginWaitReset_(); + } +} diff --git a/OneWireSlave.h b/OneWireSlave.h index 390693f..0b999ca 100644 --- a/OneWireSlave.h +++ b/OneWireSlave.h @@ -42,7 +42,16 @@ private: void beginWaitReset_(); void beginWaitCommand_(); void beginReceive_(); + + void beginReceiveBit_(void(*completeCallback)(bool bit, bool error)); + void beginSendBit_(bool bit, void(*completeCallback)(bool error)); + void beginSearchRom_(); + void beginSearchRomSendBit_(); + inline static void continueSearchRomHandler_(bool error) { inst_->continueSearchRom_(error); } + void continueSearchRom_(bool error); + inline static void searchRomOnBitReceivedHandler_(bool bit, bool error) { inst_->searchRomOnBitReceived_(bit, error); } + void searchRomOnBitReceived_(bool bit, bool error); // interrupt handlers inline static void waitResetHandler_() { inst_->waitReset_(); } @@ -53,8 +62,16 @@ private: void endPresence_(); inline static void receiveHandler_() { inst_->receive_(); } void receive_(); - inline static void receiveBitHandler_() { inst_->receiveBit_(); } - void receiveBit_(); + inline static void readBitHandler_() { inst_->readBit_(); } + void readBit_(); + inline static void onBitReceivedHandler_(bool bit, bool error) { inst_->onBitReceived_(bit, error); } + void onBitReceived_(bool bit, bool error); + inline static void sendBitOneHandler_() { inst_->sendBitOne_(); } + void sendBitOne_(); + inline static void sendBitZeroHandler_() { inst_->sendBitZero_(); } + void sendBitZero_(); + inline static void endSendBitZeroHandler_() { inst_->endSendBitZero_(); } + void endSendBitZero_(); private: static OneWireSlave* inst_; @@ -65,11 +82,18 @@ private: unsigned long resetStart_; unsigned long lastReset_; + void(*receiveBitCallback_)(bool bit, bool error); + void(*bitSentCallback_)(bool error); + byte receivingByte_; byte receivingBitPos_; byte receiveTarget_; bool ignoreNextEdge_; + + byte searchRomBytePos_; + byte searchRomBitPos_; + bool searchRomInverse_; }; #endif