You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
716 lines
15 KiB
716 lines
15 KiB
10 years ago
|
#include "OneWireSlave.h"
|
||
|
|
||
9 years ago
|
// uncomment this line to enable sending messages along with errors (but takes more program memory)
|
||
|
//#define ERROR_MESSAGES
|
||
10 years ago
|
|
||
|
#ifdef ERROR_MESSAGES
|
||
|
#define ERROR(msg) error_(msg)
|
||
|
#else
|
||
|
#define ERROR(msg) error_(0)
|
||
10 years ago
|
#endif
|
||
|
|
||
|
namespace
|
||
10 years ago
|
{
|
||
10 years ago
|
const unsigned long ResetMinDuration = 480;
|
||
|
const unsigned long ResetMaxDuration = 900;
|
||
|
|
||
8 years ago
|
const unsigned long PresenceWaitDuration = 15;
|
||
|
const unsigned long PresenceDuration = 200;
|
||
10 years ago
|
|
||
10 years ago
|
const unsigned long ReadBitSamplingTime = 25;
|
||
10 years ago
|
|
||
|
const unsigned long SendBitDuration = 35;
|
||
|
|
||
10 years ago
|
const byte ReceiveCommand = (byte)-1;
|
||
|
|
||
10 years ago
|
void(*timerEvent)() = 0;
|
||
|
}
|
||
|
|
||
9 years ago
|
OneWireSlave OWSlave;
|
||
10 years ago
|
|
||
|
byte OneWireSlave::rom_[8];
|
||
10 years ago
|
byte OneWireSlave::scratchpad_[8];
|
||
10 years ago
|
Pin OneWireSlave::pin_;
|
||
|
|
||
|
unsigned long OneWireSlave::resetStart_;
|
||
|
unsigned long OneWireSlave::lastReset_;
|
||
|
|
||
|
void(*OneWireSlave::receiveBitCallback_)(bool bit, bool error);
|
||
|
void(*OneWireSlave::bitSentCallback_)(bool error);
|
||
10 years ago
|
void(*OneWireSlave::clientReceiveCallback_)(ReceiveEvent evt, byte data);
|
||
9 years ago
|
void(*OneWireSlave::clientReceiveBitCallback_)(bool bit);
|
||
10 years ago
|
|
||
|
byte OneWireSlave::receivingByte_;
|
||
|
|
||
|
byte OneWireSlave::searchRomBytePos_;
|
||
|
byte OneWireSlave::searchRomBitPos_;
|
||
|
bool OneWireSlave::searchRomInverse_;
|
||
9 years ago
|
bool OneWireSlave::resumeCommandFlag_;
|
||
9 years ago
|
bool OneWireSlave::alarmedFlag_;
|
||
10 years ago
|
|
||
9 years ago
|
const byte* OneWireSlave::sendBuffer_;
|
||
|
byte* OneWireSlave::recvBuffer_;
|
||
10 years ago
|
short OneWireSlave::bufferLength_;
|
||
|
byte OneWireSlave::bufferBitPos_;
|
||
|
short OneWireSlave::bufferPos_;
|
||
10 years ago
|
void(*OneWireSlave::receiveBytesCallback_)(bool error);
|
||
10 years ago
|
void(*OneWireSlave::sendBytesCallback_)(bool error);
|
||
|
|
||
9 years ago
|
volatile bool OneWireSlave::waitingSynchronousWriteToComplete_;
|
||
|
volatile bool OneWireSlave::synchronousWriteError_;
|
||
9 years ago
|
|
||
|
bool OneWireSlave::sendingClientBytes_;
|
||
|
|
||
9 years ago
|
bool OneWireSlave::singleBit_;
|
||
|
bool OneWireSlave::singleBitRepeat_;
|
||
|
void(*OneWireSlave::singleBitSentCallback_)(bool error);
|
||
|
|
||
9 years ago
|
void(*OneWireSlave::logCallback_)(const char* message);
|
||
|
|
||
10 years ago
|
|
||
9 years ago
|
ISR(USERTIMER_COMPA_vect) // timer1 interrupt
|
||
10 years ago
|
{
|
||
9 years ago
|
UserTimer_Stop(); // disable clock
|
||
10 years ago
|
void(*event)() = timerEvent;
|
||
|
timerEvent = 0;
|
||
|
event();
|
||
|
}
|
||
|
|
||
9 years ago
|
void OneWireSlave::begin(const byte* rom, byte pinNumber)
|
||
10 years ago
|
{
|
||
10 years ago
|
pin_ = Pin(pinNumber);
|
||
|
resetStart_ = (unsigned long)-1;
|
||
|
lastReset_ = 0;
|
||
|
|
||
10 years ago
|
memcpy(rom_, rom, 7);
|
||
9 years ago
|
rom_[7] = crc8(rom_, 7);
|
||
10 years ago
|
|
||
9 years ago
|
resumeCommandFlag_ = false;
|
||
9 years ago
|
alarmedFlag_ = false;
|
||
9 years ago
|
|
||
9 years ago
|
clientReceiveBitCallback_ = 0;
|
||
9 years ago
|
sendingClientBytes_ = false;
|
||
9 years ago
|
|
||
9 years ago
|
// log("Enabling 1-wire library")
|
||
10 years ago
|
|
||
|
cli(); // disable interrupts
|
||
|
pin_.inputMode();
|
||
10 years ago
|
pin_.writeLow(); // make sure the internal pull-up resistor is disabled
|
||
|
|
||
10 years ago
|
// prepare hardware timer
|
||
9 years ago
|
UserTimer_Init();
|
||
10 years ago
|
|
||
|
// start 1-wire activity
|
||
10 years ago
|
beginWaitReset_();
|
||
|
sei(); // enable interrupts
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::end()
|
||
10 years ago
|
{
|
||
9 years ago
|
// log("Disabling 1-wire library");
|
||
10 years ago
|
|
||
10 years ago
|
cli();
|
||
|
disableTimer_();
|
||
|
pin_.detachInterrupt();
|
||
|
releaseBus_();
|
||
|
sei();
|
||
10 years ago
|
}
|
||
|
|
||
9 years ago
|
bool OneWireSlave::write(const byte* bytes, short numBytes)
|
||
|
{
|
||
|
// TODO: put the arduino to sleep between interrupts to save power?
|
||
|
waitingSynchronousWriteToComplete_ = true;
|
||
|
beginWrite(bytes, numBytes, &OneWireSlave::onSynchronousWriteComplete_);
|
||
|
while (waitingSynchronousWriteToComplete_)
|
||
|
delay(1);
|
||
9 years ago
|
return !synchronousWriteError_;
|
||
9 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::onSynchronousWriteComplete_(bool error)
|
||
|
{
|
||
|
synchronousWriteError_ = error;
|
||
|
waitingSynchronousWriteToComplete_ = false;
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::beginWrite(const byte* bytes, short numBytes, void(*complete)(bool error))
|
||
10 years ago
|
{
|
||
10 years ago
|
cli();
|
||
9 years ago
|
endWrite_(true);
|
||
9 years ago
|
sendingClientBytes_ = true;
|
||
10 years ago
|
beginWriteBytes_(bytes, numBytes, complete == 0 ? noOpCallback_ : complete);
|
||
|
sei();
|
||
10 years ago
|
}
|
||
10 years ago
|
|
||
9 years ago
|
void OneWireSlave::endWrite_(bool error, bool resetInterrupts)
|
||
9 years ago
|
{
|
||
9 years ago
|
if(resetInterrupts)
|
||
|
beginWaitReset_();
|
||
|
|
||
9 years ago
|
if (sendingClientBytes_)
|
||
|
{
|
||
|
sendingClientBytes_ = false;
|
||
|
if (sendBytesCallback_ != 0)
|
||
|
{
|
||
|
void(*callback)(bool error) = sendBytesCallback_;
|
||
|
sendBytesCallback_ = noOpCallback_;
|
||
|
callback(error);
|
||
|
}
|
||
|
}
|
||
|
else if (singleBitSentCallback_ != 0)
|
||
|
{
|
||
|
void(*callback)(bool) = singleBitSentCallback_;
|
||
|
singleBitSentCallback_ = 0;
|
||
|
callback(error);
|
||
|
}
|
||
|
}
|
||
|
|
||
9 years ago
|
bool OneWireSlave::writeBit(bool value)
|
||
|
{
|
||
|
// TODO: put the arduino to sleep between interrupts to save power?
|
||
|
waitingSynchronousWriteToComplete_ = true;
|
||
|
beginWriteBit(value, false, &OneWireSlave::onSynchronousWriteComplete_);
|
||
|
while (waitingSynchronousWriteToComplete_)
|
||
|
delay(1);
|
||
|
return !synchronousWriteError_;
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::beginWriteBit(bool value, bool repeat, void(*bitSent)(bool))
|
||
9 years ago
|
{
|
||
|
cli();
|
||
9 years ago
|
endWrite_(true);
|
||
9 years ago
|
|
||
9 years ago
|
singleBit_ = value;
|
||
|
singleBitRepeat_ = repeat;
|
||
|
singleBitSentCallback_ = bitSent;
|
||
|
beginSendBit_(value, &OneWireSlave::onSingleBitSent_);
|
||
|
sei();
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::onSingleBitSent_(bool error)
|
||
|
{
|
||
|
if (!error && singleBitRepeat_)
|
||
|
{
|
||
|
beginSendBit_(singleBit_, &OneWireSlave::onSingleBitSent_);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
9 years ago
|
beginReceiveBytes_(scratchpad_, 1, &OneWireSlave::notifyClientByteReceived_);
|
||
9 years ago
|
}
|
||
|
|
||
|
if (singleBitSentCallback_ != 0)
|
||
|
{
|
||
9 years ago
|
void(*callback)(bool) = singleBitSentCallback_;
|
||
|
singleBitSentCallback_ = 0;
|
||
|
callback(error);
|
||
9 years ago
|
}
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::stopWrite()
|
||
|
{
|
||
9 years ago
|
beginWrite(0, 0, 0);
|
||
9 years ago
|
}
|
||
|
|
||
9 years ago
|
void OneWireSlave::alarmed(bool value)
|
||
|
{
|
||
|
alarmedFlag_ = value;
|
||
|
}
|
||
|
|
||
9 years ago
|
byte OneWireSlave::crc8(const byte* data, short numBytes)
|
||
10 years ago
|
{
|
||
|
byte crc = 0;
|
||
|
|
||
|
while (numBytes--) {
|
||
|
byte inbyte = *data++;
|
||
|
for (byte i = 8; i; i--) {
|
||
|
byte mix = (crc ^ inbyte) & 0x01;
|
||
|
crc >>= 1;
|
||
|
if (mix) crc ^= 0x8C;
|
||
|
inbyte >>= 1;
|
||
|
}
|
||
|
}
|
||
|
return crc;
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::setTimerEvent_(short delayMicroSeconds, void(*handler)())
|
||
|
{
|
||
|
delayMicroSeconds -= 10; // remove overhead (tuned on Arduino Uno)
|
||
|
|
||
|
short skipTicks = (delayMicroSeconds - 3) / 4; // round the micro seconds delay to a number of ticks to skip (4us per tick, so 4us must skip 0 tick, 8us must skip 1 tick, etc.)
|
||
|
if (skipTicks < 1) skipTicks = 1;
|
||
|
timerEvent = handler;
|
||
9 years ago
|
UserTimer_Run(skipTicks);
|
||
10 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::disableTimer_()
|
||
|
{
|
||
9 years ago
|
UserTimer_Stop();
|
||
10 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::onEnterInterrupt_()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::onLeaveInterrupt_()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::error_(const char* message)
|
||
|
{
|
||
9 years ago
|
if (logCallback_ != 0)
|
||
|
logCallback_(message);
|
||
9 years ago
|
endWrite_(true);
|
||
9 years ago
|
if (clientReceiveCallback_ != 0)
|
||
|
clientReceiveCallback_(RE_Error, 0);
|
||
10 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::pullLow_()
|
||
|
{
|
||
|
pin_.outputMode();
|
||
|
pin_.writeLow();
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::releaseBus_()
|
||
|
{
|
||
|
pin_.inputMode();
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::beginResetDetection_()
|
||
|
{
|
||
|
setTimerEvent_(ResetMinDuration - 50, &OneWireSlave::resetCheck_);
|
||
|
resetStart_ = micros() - 50;
|
||
|
}
|
||
|
|
||
9 years ago
|
void OneWireSlave::beginResetDetectionSendZero_()
|
||
|
{
|
||
|
setTimerEvent_(ResetMinDuration - SendBitDuration - 50, &OneWireSlave::resetCheck_);
|
||
|
resetStart_ = micros() - SendBitDuration - 50;
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::cancelResetDetection_()
|
||
10 years ago
|
{
|
||
|
disableTimer_();
|
||
10 years ago
|
resetStart_ = (unsigned long)-1;
|
||
10 years ago
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::resetCheck_()
|
||
10 years ago
|
{
|
||
|
onEnterInterrupt_();
|
||
10 years ago
|
if (!pin_.read())
|
||
10 years ago
|
{
|
||
10 years ago
|
pin_.attachInterrupt(&OneWireSlave::waitReset_, CHANGE);
|
||
9 years ago
|
// log("Reset detected during another operation");
|
||
10 years ago
|
}
|
||
|
onLeaveInterrupt_();
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::beginReceiveBit_(void(*completeCallback)(bool bit, bool error))
|
||
|
{
|
||
|
receiveBitCallback_ = completeCallback;
|
||
10 years ago
|
pin_.attachInterrupt(&OneWireSlave::receive_, FALLING);
|
||
10 years ago
|
}
|
||
10 years ago
|
|
||
|
void OneWireSlave::receive_()
|
||
|
{
|
||
|
onEnterInterrupt_();
|
||
|
|
||
10 years ago
|
pin_.detachInterrupt();
|
||
|
setTimerEvent_(ReadBitSamplingTime, &OneWireSlave::readBit_);
|
||
10 years ago
|
|
||
|
onLeaveInterrupt_();
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::readBit_()
|
||
|
{
|
||
|
onEnterInterrupt_();
|
||
|
|
||
|
bool bit = pin_.read();
|
||
|
if (bit)
|
||
|
cancelResetDetection_();
|
||
|
else
|
||
|
beginResetDetection_();
|
||
|
receiveBitCallback_(bit, false);
|
||
|
//dbgOutput.writeLow();
|
||
|
//dbgOutput.writeHigh();
|
||
|
|
||
|
onLeaveInterrupt_();
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::beginSendBit_(bool bit, void(*completeCallback)(bool error))
|
||
|
{
|
||
|
bitSentCallback_ = completeCallback;
|
||
|
if (bit)
|
||
|
{
|
||
10 years ago
|
pin_.attachInterrupt(&OneWireSlave::sendBitOne_, FALLING);
|
||
10 years ago
|
}
|
||
|
else
|
||
|
{
|
||
10 years ago
|
pin_.attachInterrupt(&OneWireSlave::sendBitZero_, FALLING);
|
||
10 years ago
|
}
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::sendBitOne_()
|
||
|
{
|
||
|
onEnterInterrupt_();
|
||
10 years ago
|
|
||
10 years ago
|
beginResetDetection_();
|
||
10 years ago
|
bitSentCallback_(false);
|
||
10 years ago
|
|
||
|
onLeaveInterrupt_();
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::sendBitZero_()
|
||
|
{
|
||
10 years ago
|
pullLow_(); // this must be executed first because the timing is very tight with some master devices
|
||
10 years ago
|
|
||
10 years ago
|
onEnterInterrupt_();
|
||
10 years ago
|
|
||
|
pin_.detachInterrupt();
|
||
10 years ago
|
setTimerEvent_(SendBitDuration, &OneWireSlave::endSendBitZero_);
|
||
10 years ago
|
|
||
10 years ago
|
onLeaveInterrupt_();
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::endSendBitZero_()
|
||
|
{
|
||
|
onEnterInterrupt_();
|
||
|
|
||
|
releaseBus_();
|
||
9 years ago
|
beginResetDetectionSendZero_();
|
||
10 years ago
|
bitSentCallback_(false);
|
||
|
|
||
|
onLeaveInterrupt_();
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::beginWaitReset_()
|
||
|
{
|
||
|
disableTimer_();
|
||
8 years ago
|
pin_.inputMode();
|
||
10 years ago
|
pin_.attachInterrupt(&OneWireSlave::waitReset_, CHANGE);
|
||
|
resetStart_ = (unsigned int)-1;
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::waitReset_()
|
||
10 years ago
|
{
|
||
|
onEnterInterrupt_();
|
||
10 years ago
|
bool state = pin_.read();
|
||
|
unsigned long now = micros();
|
||
|
if (state)
|
||
|
{
|
||
|
if (resetStart_ == (unsigned int)-1)
|
||
|
{
|
||
|
onLeaveInterrupt_();
|
||
|
return;
|
||
|
}
|
||
10 years ago
|
|
||
10 years ago
|
unsigned long resetDuration = now - resetStart_;
|
||
|
resetStart_ = (unsigned int)-1;
|
||
|
if (resetDuration >= ResetMinDuration)
|
||
|
{
|
||
|
if (resetDuration > ResetMaxDuration)
|
||
|
{
|
||
10 years ago
|
ERROR("Reset too long");
|
||
10 years ago
|
onLeaveInterrupt_();
|
||
|
return;
|
||
|
}
|
||
10 years ago
|
|
||
10 years ago
|
lastReset_ = now;
|
||
|
pin_.detachInterrupt();
|
||
8 years ago
|
unsigned long alreadyElapsedTime = micros() - now;
|
||
|
setTimerEvent_(alreadyElapsedTime < PresenceWaitDuration ? PresenceWaitDuration - alreadyElapsedTime : 0, &OneWireSlave::beginPresence_);
|
||
9 years ago
|
endWrite_(true, false);
|
||
10 years ago
|
if (clientReceiveCallback_ != 0)
|
||
|
clientReceiveCallback_(RE_Reset, 0);
|
||
10 years ago
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
resetStart_ = now;
|
||
|
}
|
||
10 years ago
|
onLeaveInterrupt_();
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::beginPresence_()
|
||
|
{
|
||
|
pullLow_();
|
||
|
setTimerEvent_(PresenceDuration, &OneWireSlave::endPresence_);
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::endPresence_()
|
||
|
{
|
||
|
releaseBus_();
|
||
|
|
||
|
beginWaitCommand_();
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::beginWaitCommand_()
|
||
|
{
|
||
10 years ago
|
bufferPos_ = ReceiveCommand;
|
||
10 years ago
|
beginReceive_();
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::beginReceive_()
|
||
|
{
|
||
|
receivingByte_ = 0;
|
||
10 years ago
|
bufferBitPos_ = 0;
|
||
10 years ago
|
beginReceiveBit_(&OneWireSlave::onBitReceived_);
|
||
|
}
|
||
|
|
||
10 years ago
|
void OneWireSlave::onBitReceived_(bool bit, bool error)
|
||
|
{
|
||
|
if (error)
|
||
|
{
|
||
10 years ago
|
ERROR("Invalid bit");
|
||
|
if (bufferPos_ >= 0)
|
||
10 years ago
|
receiveBytesCallback_(true);
|
||
10 years ago
|
return;
|
||
|
}
|
||
|
|
||
10 years ago
|
receivingByte_ |= ((bit ? 1 : 0) << bufferBitPos_);
|
||
|
++bufferBitPos_;
|
||
10 years ago
|
|
||
9 years ago
|
if (clientReceiveBitCallback_ != 0 && bufferPos_ != ReceiveCommand)
|
||
|
clientReceiveBitCallback_(bit);
|
||
|
|
||
10 years ago
|
if (bufferBitPos_ == 8)
|
||
10 years ago
|
{
|
||
9 years ago
|
// log("received byte", (long)receivingByte_);
|
||
|
|
||
10 years ago
|
if (bufferPos_ == ReceiveCommand)
|
||
10 years ago
|
{
|
||
10 years ago
|
bufferPos_ = 0;
|
||
10 years ago
|
switch (receivingByte_)
|
||
10 years ago
|
{
|
||
10 years ago
|
case 0xF0: // SEARCH ROM
|
||
9 years ago
|
resumeCommandFlag_ = false;
|
||
10 years ago
|
beginSearchRom_();
|
||
10 years ago
|
return;
|
||
9 years ago
|
case 0xEC: // CONDITIONAL SEARCH ROM
|
||
|
resumeCommandFlag_ = false;
|
||
|
if (alarmedFlag_)
|
||
|
{
|
||
|
beginSearchRom_();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
beginWaitReset_();
|
||
|
}
|
||
|
return;
|
||
10 years ago
|
case 0x33: // READ ROM
|
||
9 years ago
|
resumeCommandFlag_ = false;
|
||
10 years ago
|
beginWriteBytes_(rom_, 8, &OneWireSlave::noOpCallback_);
|
||
|
return;
|
||
|
case 0x55: // MATCH ROM
|
||
9 years ago
|
resumeCommandFlag_ = false;
|
||
10 years ago
|
beginReceiveBytes_(scratchpad_, 8, &OneWireSlave::matchRomBytesReceived_);
|
||
|
return;
|
||
|
case 0xCC: // SKIP ROM
|
||
9 years ago
|
resumeCommandFlag_ = false;
|
||
|
beginReceiveBytes_(scratchpad_, 1, &OneWireSlave::notifyClientByteReceived_);
|
||
|
return;
|
||
|
case 0xA5: // RESUME
|
||
|
if (resumeCommandFlag_)
|
||
|
{
|
||
|
beginReceiveBytes_(scratchpad_, 1, &OneWireSlave::notifyClientByteReceived_);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
beginWaitReset_();
|
||
|
}
|
||
10 years ago
|
return;
|
||
|
default:
|
||
10 years ago
|
ERROR("Unknown command");
|
||
10 years ago
|
return;
|
||
10 years ago
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
9 years ago
|
recvBuffer_[bufferPos_++] = receivingByte_;
|
||
10 years ago
|
receivingByte_ = 0;
|
||
10 years ago
|
bufferBitPos_ = 0;
|
||
|
if (bufferPos_ == bufferLength_)
|
||
10 years ago
|
{
|
||
|
beginWaitReset_();
|
||
|
receiveBytesCallback_(false);
|
||
|
return;
|
||
|
}
|
||
10 years ago
|
}
|
||
|
}
|
||
10 years ago
|
|
||
10 years ago
|
beginReceiveBit_(&OneWireSlave::onBitReceived_);
|
||
10 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::beginSearchRom_()
|
||
|
{
|
||
10 years ago
|
searchRomBytePos_ = 0;
|
||
|
searchRomBitPos_ = 0;
|
||
|
searchRomInverse_ = false;
|
||
|
|
||
|
beginSearchRomSendBit_();
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::beginSearchRomSendBit_()
|
||
|
{
|
||
|
byte currentByte = rom_[searchRomBytePos_];
|
||
|
bool currentBit = bitRead(currentByte, searchRomBitPos_);
|
||
|
bool bitToSend = searchRomInverse_ ? !currentBit : currentBit;
|
||
|
|
||
10 years ago
|
beginSendBit_(bitToSend, &OneWireSlave::continueSearchRom_);
|
||
10 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::continueSearchRom_(bool error)
|
||
|
{
|
||
|
if (error)
|
||
|
{
|
||
10 years ago
|
ERROR("Failed to send bit");
|
||
10 years ago
|
return;
|
||
|
}
|
||
|
|
||
|
searchRomInverse_ = !searchRomInverse_;
|
||
|
if (searchRomInverse_)
|
||
|
{
|
||
|
beginSearchRomSendBit_();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
10 years ago
|
beginReceiveBit_(&OneWireSlave::searchRomOnBitReceived_);
|
||
10 years ago
|
}
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::searchRomOnBitReceived_(bool bit, bool error)
|
||
|
{
|
||
|
if (error)
|
||
|
{
|
||
10 years ago
|
ERROR("Bit read error during ROM search");
|
||
10 years ago
|
return;
|
||
|
}
|
||
|
|
||
|
byte currentByte = rom_[searchRomBytePos_];
|
||
|
bool currentBit = bitRead(currentByte, searchRomBitPos_);
|
||
|
|
||
|
if (bit == currentBit)
|
||
|
{
|
||
|
++searchRomBitPos_;
|
||
|
if (searchRomBitPos_ == 8)
|
||
|
{
|
||
|
searchRomBitPos_ = 0;
|
||
|
++searchRomBytePos_;
|
||
|
}
|
||
|
|
||
|
if (searchRomBytePos_ == 8)
|
||
|
{
|
||
9 years ago
|
// log("ROM sent entirely");
|
||
|
|
||
10 years ago
|
beginWaitReset_();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
beginSearchRomSendBit_();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
9 years ago
|
// log("Leaving ROM search");
|
||
10 years ago
|
beginWaitReset_();
|
||
|
}
|
||
|
}
|
||
10 years ago
|
|
||
9 years ago
|
void OneWireSlave::beginWriteBytes_(const byte* data, short numBytes, void(*complete)(bool error))
|
||
10 years ago
|
{
|
||
9 years ago
|
sendBuffer_ = data;
|
||
10 years ago
|
bufferLength_ = numBytes;
|
||
|
bufferPos_ = 0;
|
||
|
bufferBitPos_ = 0;
|
||
|
sendBytesCallback_ = complete;
|
||
|
|
||
9 years ago
|
if (sendBuffer_ != 0 && bufferLength_ > 0)
|
||
|
{
|
||
|
bool bit = bitRead(sendBuffer_[0], 0);
|
||
|
beginSendBit_(bit, &OneWireSlave::bitSent_);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
9 years ago
|
endWrite_(true);
|
||
9 years ago
|
beginReceiveBytes_(scratchpad_, 1, &OneWireSlave::notifyClientByteReceived_);
|
||
9 years ago
|
}
|
||
10 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::bitSent_(bool error)
|
||
|
{
|
||
|
if (error)
|
||
|
{
|
||
|
ERROR("error sending a bit");
|
||
|
sendBytesCallback_(true);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
++bufferBitPos_;
|
||
|
if (bufferBitPos_ == 8)
|
||
|
{
|
||
|
bufferBitPos_ = 0;
|
||
|
++bufferPos_;
|
||
|
}
|
||
|
|
||
|
if (bufferPos_ == bufferLength_)
|
||
|
{
|
||
9 years ago
|
endWrite_(false);
|
||
10 years ago
|
sendBytesCallback_(false);
|
||
|
return;
|
||
|
}
|
||
|
|
||
9 years ago
|
bool bit = bitRead(sendBuffer_[bufferPos_], bufferBitPos_);
|
||
10 years ago
|
beginSendBit_(bit, &OneWireSlave::bitSent_);
|
||
10 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::beginReceiveBytes_(byte* buffer, short numBytes, void(*complete)(bool error))
|
||
|
{
|
||
9 years ago
|
recvBuffer_ = buffer;
|
||
10 years ago
|
bufferLength_ = numBytes;
|
||
|
bufferPos_ = 0;
|
||
10 years ago
|
receiveBytesCallback_ = complete;
|
||
|
beginReceive_();
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::noOpCallback_(bool error)
|
||
|
{
|
||
|
if (error)
|
||
10 years ago
|
ERROR("error during an internal 1-wire operation");
|
||
10 years ago
|
}
|
||
|
|
||
|
void OneWireSlave::matchRomBytesReceived_(bool error)
|
||
|
{
|
||
|
if (error)
|
||
|
{
|
||
9 years ago
|
resumeCommandFlag_ = false;
|
||
10 years ago
|
ERROR("error receiving match rom bytes");
|
||
10 years ago
|
return;
|
||
|
}
|
||
|
|
||
|
if (memcmp(rom_, scratchpad_, 8) == 0)
|
||
|
{
|
||
9 years ago
|
// log("ROM matched");
|
||
9 years ago
|
resumeCommandFlag_ = true;
|
||
10 years ago
|
beginReceiveBytes_(scratchpad_, 1, &OneWireSlave::notifyClientByteReceived_);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
9 years ago
|
// log("ROM not matched");
|
||
9 years ago
|
resumeCommandFlag_ = false;
|
||
10 years ago
|
beginWaitReset_();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OneWireSlave::notifyClientByteReceived_(bool error)
|
||
|
{
|
||
|
if (error)
|
||
|
{
|
||
10 years ago
|
if (clientReceiveCallback_ != 0)
|
||
|
clientReceiveCallback_(RE_Error, 0);
|
||
|
ERROR("error receiving custom bytes");
|
||
10 years ago
|
return;
|
||
|
}
|
||
|
|
||
10 years ago
|
beginReceiveBytes_(scratchpad_, 1, &OneWireSlave::notifyClientByteReceived_);
|
||
|
if (clientReceiveCallback_ != 0)
|
||
|
clientReceiveCallback_(RE_Byte, scratchpad_[0]);
|
||
10 years ago
|
}
|