From 74b3f2100e67f38dd9e314f2e90219677d162d5a Mon Sep 17 00:00:00 2001 From: Youen Toupin Date: Fri, 24 Apr 2015 20:17:29 +0200 Subject: [PATCH] search rom algorithm almost working (but code is in an awful state, and master doesn't recognize the ROM yet, maybe a CRC issue) --- OneWireIO.ino | 309 ++++++++++++++++++++++++-------------------------- 1 file changed, 149 insertions(+), 160 deletions(-) diff --git a/OneWireIO.ino b/OneWireIO.ino index 4a54161..ffe1143 100644 --- a/OneWireIO.ino +++ b/OneWireIO.ino @@ -12,10 +12,9 @@ #define PresenceWaitDuration 30 #define PresenceDuration 300 -#define BitZeroMinDuration 20 -#define BitZeroMaxDuration 75 +#define ReadBitSamplingTime 13 // the theorical time is about 30us, but given various overhead, this is the empirical delay I've found works best (on Arduino Uno) -#define SendBitDuration 30 +#define SendBitDuration 35 const byte InvalidBit = (byte)-1; const byte IncompleteBit = (byte)-2; @@ -30,7 +29,6 @@ enum OwStatus { OS_WaitReset, OS_Presence, - OS_AfterPresence, OS_WaitCommand, OS_SearchRom, }; @@ -55,15 +53,7 @@ void owRelease() owOutTestPin.writeHigh(); } -void owWrite(bool value) -{ - if (value) - owRelease(); - else - owPullLow(); -} - -unsigned long resetStart = (unsigned long)-1; +volatile unsigned long resetStart = (unsigned long)-1; unsigned long lastReset = (unsigned long)-1; unsigned long bitStart = (unsigned long)-1; byte receivingByte = 0; @@ -79,7 +69,7 @@ void setup() led.writeLow(); cli(); // disable interrupts - attachInterrupt(InterruptNumber,onewireInterrupt,CHANGE); + attachInterrupt(InterruptNumber,onewireInterrupt,FALLING); // set timer0 interrupt at 250KHz (actually depends on compare match register OCR0A) // 4us between each tick @@ -99,11 +89,13 @@ void loop() { //if ((count++) % 1000 == 0) // led.write(!led.read()); - cli();//disable interrupts + cli();//disable interrupts SerialChannel::swap(); - sei();//enable interrupts - + sei();//enable interrupts + SerialChannel::flush(); + + owHandleReset(); } void(*timerEvent)() = 0; @@ -127,200 +119,195 @@ void owError(const char* message) status = OS_WaitReset; } -void owResetError() +void owClearError() { led.writeLow(); } -void onewireInterrupt(void) +void owHandleReset() { - bool state = owPin.read(); - unsigned long now = micros(); - - //led.write(state); - - if (!state) - resetStart = now; - - // handle reset - if (state) + unsigned long localResetStart = resetStart; + if (owPin.read()) { - unsigned long resetDuration = resetStart == (unsigned long)-1 ? (unsigned long)-1 : now - resetStart; resetStart = (unsigned long)-1; - lastReset = now; - - if (resetDuration >= ResetMinDuration && resetDuration <= ResetMaxDuration) - { - //debug.SC_APPEND_STR_TIME("reset", now); - owResetError(); - status = OS_Presence; - setTimerEvent(PresenceWaitDuration - (micros() - now), &beginPresence); - return; - } } - - if (status == OS_AfterPresence) + else if (localResetStart != (unsigned long)-1) { - status = OS_WaitCommand; - receivingByte = 0; - receivingBitPos = 0; - bitStart = (unsigned long)-1; - - if (state) + unsigned long resetDuration = micros() - localResetStart; + if (resetDuration >= ResetMinDuration) { - // this is the rising edge of end-of-presence ; don't try to interpret it as a bit - return; - } - } - - // read bytes - if (status == OS_WaitCommand) - { - byte bit = interpretReceivedEdgeAsBit(state, now); - if (bit != IncompleteBit) - { - if (bit == InvalidBit) - return; - - receivingByte |= (bit << receivingBitPos); - ++receivingBitPos; - - if (receivingBitPos == 8) + // wait for master to release the pin (or timeout if the pin is pulled low for too long) + unsigned long now = micros(); + while (!owPin.read()) { - debug.SC_APPEND_STR_INT("received byte", (long)receivingByte); - - if (status == OS_WaitCommand && receivingByte == 0xF0) + if (resetStart != localResetStart) + return; + now = micros(); + if (now - localResetStart > ResetMaxDuration) { - status = OS_SearchRom; - searchROMReadingMasterResponseBit = false; - searchROMSendingInverse = false; - searchROMCurrentByte = 0; - searchROMCurrentBit = 0; + owError("Reset too long"); return; } - - receivingBitPos = 0; - receivingByte = 0; } + + cli(); + owClearError(); + lastReset = now; + status = OS_Presence; + setTimerEvent(PresenceWaitDuration - (micros() - now), &beginPresence); + sei(); } } +} - if (status == OS_SearchRom) +void onewireInterrupt() +{ + //owOutTestPin.writeLow(); + onewireInterruptImpl(); + //owOutTestPin.writeHigh(); +} + +//bool debugState = false; +volatile unsigned long lastInterrupt = 0; +void onewireInterruptImpl(void) +{ + unsigned long now = micros(); + if (now < lastInterrupt + 20) + return; // don't react to our own actions + lastInterrupt = now; + + //debugState = !debugState; + //owOutTestPin.write(debugState); + + //led.write(state); + + resetStart = now; + + // read bytes + switch (status) { + case OS_WaitCommand: { - byte currentByte = owROM[searchROMCurrentByte]; - bool currentBit = bitRead(currentByte, searchROMCurrentBit); + bool bit = readBit(); - if (searchROMReadingMasterResponseBit) + receivingByte |= ((bit ? 1 : 0) << receivingBitPos); + ++receivingBitPos; + + if (receivingBitPos == 8) { - byte bit = interpretReceivedEdgeAsBit(state, now); - if (bit != IncompleteBit) + byte receivedByte = receivingByte; + receivingBitPos = 0; + receivingByte = 0; + //debug.SC_APPEND_STR_INT("received byte", (long)receivedByte); + + if (status == OS_WaitCommand && receivedByte == 0xF0) { + status = OS_SearchRom; searchROMReadingMasterResponseBit = false; - if (bit == InvalidBit) - return; - if ((bit == 1) != currentBit) - { - debug.SC_APPEND_STR_TIME("Master didn't send our bit, leaving ROM search", now); - status = OS_WaitReset; - } + searchROMSendingInverse = false; + searchROMCurrentByte = 0; + searchROMCurrentBit = 0; + attachInterrupt(InterruptNumber, onewireInterruptSearchROM, FALLING); + return; } } - else - { - if (!state) - { - // master is pulling low, we must send our bit - bool bitToSend = searchROMSendingInverse ? !currentBit : currentBit; - sendBit(bitToSend); - if (bitToSend) - debug.SC_APPEND_STR_TIME("Sent ROM search bit : 1", now); - else - debug.SC_APPEND_STR_TIME("Sent ROM search bit : 0", now); - - if (searchROMSendingInverse) - { - searchROMSendingInverse = false; - searchROMReadingMasterResponseBit = true; - } - else - { - searchROMSendingInverse = true; - } + } break; - if (searchROMCurrentBit == 8) - { - ++searchROMCurrentByte; - searchROMCurrentBit = 0; - debug.SC_APPEND_STR_TIME("sent another ROM byte", now); - } - - if (searchROMCurrentByte == 8) - { - searchROMCurrentByte = 0; - status = OS_WaitReset; - debug.SC_APPEND_STR_TIME("ROM sent entirely", now); - } - } - else - { - debug.SC_APPEND_STR_TIME("Search ROM : seen rising edge", now); - } - } + case OS_SearchRom: + { + + } break; } } -byte interpretReceivedEdgeAsBit(bool wireState, unsigned long now) +bool ignoreNextFallingEdge = false; +void onewireInterruptSearchROM() { - if (!wireState) + /*unsigned long now = micros(); + if (now < lastInterrupt + 20) + return; // don't react to our own actions + lastInterrupt = now;*/ + if (ignoreNextFallingEdge) { - // master just pulled low, this is a bit start - //debug.SC_APPEND_STR_TIME("bit start", now); - bitStart = now; - return IncompleteBit; + ignoreNextFallingEdge = false; + return; } - else + + if (searchROMReadingMasterResponseBit) { - if (bitStart == (unsigned long)-1) - { - //owError("Invalid read sequence"); - //return InvalidBit; + bool bit = readBit(); + + byte currentByte = owROM[searchROMCurrentByte]; + bool currentBit = bitRead(currentByte, searchROMCurrentBit); - // we missed the falling edge, we emulate one here (this can happen if handling of rising edge interrupt takes too long) - bitStart = now; + if (bit != currentBit) + { + debug.SC_APPEND_STR("Master didn't send our bit, leaving ROM search"); + status = OS_WaitReset; + attachInterrupt(InterruptNumber, onewireInterrupt, FALLING); + return; } - // master released the line, we interpret it as a bit 1 or 0 depending on timing - unsigned long bitLength = now - bitStart; - bitStart = (unsigned long)-1; + searchROMReadingMasterResponseBit = false; + ++searchROMCurrentBit; + if (searchROMCurrentBit == 8) + { + ++searchROMCurrentByte; + searchROMCurrentBit = 0; + debug.SC_APPEND_STR("sent another ROM byte"); + } - if (bitLength < BitZeroMinDuration) + if (searchROMCurrentByte == 8) { - // received bit = 1 - //debug.SC_APPEND_STR_TIME("received bit 1", now); - return 1; + searchROMCurrentByte = 0; + status = OS_WaitReset; + debug.SC_APPEND_STR("ROM sent entirely"); + attachInterrupt(InterruptNumber, onewireInterrupt, FALLING); + return; } - else if (bitLength < BitZeroMaxDuration) + } + else + { + byte currentByte = owROM[searchROMCurrentByte]; + bool currentBit = bitRead(currentByte, searchROMCurrentBit); + //bool currentBit = 0; + + bool bitToSend = searchROMSendingInverse ? !currentBit : currentBit; + sendBit(bitToSend); + /*if (bitToSend) + debug.SC_APPEND_STR("sent ROM search bit : 1"); + else + debug.SC_APPEND_STR("sent ROM search bit : 0");*/ + + if (searchROMSendingInverse) { - // received bit = 0 - //debug.SC_APPEND_STR_TIME("received bit 0", now); - return 0; + searchROMSendingInverse = false; + searchROMReadingMasterResponseBit = true; } else { - // this is not a valid bit - owError("Invalid read timing"); - return InvalidBit; + searchROMSendingInverse = true; } } } +bool readBit() +{ + delayMicroseconds(ReadBitSamplingTime); + return owPin.read(); +} + void sendBit(bool bit) { - if (!bit) + if (bit) + { + delayMicroseconds(SendBitDuration); + } + else { owPullLow(); delayMicroseconds(SendBitDuration); owRelease(); + ignoreNextFallingEdge = true; } } @@ -328,7 +315,6 @@ void beginPresence() { unsigned long now = micros(); owPullLow(); - owOutTestPin.writeLow(); setTimerEvent(PresenceDuration, &endPresence); debug.SC_APPEND_STR_TIME("reset", lastReset); debug.SC_APPEND_STR_TIME("beginPresence", now); @@ -340,7 +326,10 @@ void endPresence() owRelease(); debug.SC_APPEND_STR_TIME("endPresence", now); - status = OS_AfterPresence; + status = OS_WaitCommand; + receivingByte = 0; + receivingBitPos = 0; + bitStart = (unsigned long)-1; } ISR(TIMER1_COMPA_vect) // timer1 interrupt