Browse Source

search rom algorithm almost working (but code is in an awful state, and master doesn't recognize the ROM yet, maybe a CRC issue)

timer1
Youen Toupin 10 years ago
parent
commit
74b3f2100e
  1. 305
      OneWireIO.ino

305
OneWireIO.ino

@ -12,10 +12,9 @@
#define PresenceWaitDuration 30 #define PresenceWaitDuration 30
#define PresenceDuration 300 #define PresenceDuration 300
#define BitZeroMinDuration 20 #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 BitZeroMaxDuration 75
#define SendBitDuration 30 #define SendBitDuration 35
const byte InvalidBit = (byte)-1; const byte InvalidBit = (byte)-1;
const byte IncompleteBit = (byte)-2; const byte IncompleteBit = (byte)-2;
@ -30,7 +29,6 @@ enum OwStatus
{ {
OS_WaitReset, OS_WaitReset,
OS_Presence, OS_Presence,
OS_AfterPresence,
OS_WaitCommand, OS_WaitCommand,
OS_SearchRom, OS_SearchRom,
}; };
@ -55,15 +53,7 @@ void owRelease()
owOutTestPin.writeHigh(); owOutTestPin.writeHigh();
} }
void owWrite(bool value) volatile unsigned long resetStart = (unsigned long)-1;
{
if (value)
owRelease();
else
owPullLow();
}
unsigned long resetStart = (unsigned long)-1;
unsigned long lastReset = (unsigned long)-1; unsigned long lastReset = (unsigned long)-1;
unsigned long bitStart = (unsigned long)-1; unsigned long bitStart = (unsigned long)-1;
byte receivingByte = 0; byte receivingByte = 0;
@ -79,7 +69,7 @@ void setup()
led.writeLow(); led.writeLow();
cli(); // disable interrupts cli(); // disable interrupts
attachInterrupt(InterruptNumber,onewireInterrupt,CHANGE); attachInterrupt(InterruptNumber,onewireInterrupt,FALLING);
// set timer0 interrupt at 250KHz (actually depends on compare match register OCR0A) // set timer0 interrupt at 250KHz (actually depends on compare match register OCR0A)
// 4us between each tick // 4us between each tick
@ -99,11 +89,13 @@ void loop()
{ {
//if ((count++) % 1000 == 0) //if ((count++) % 1000 == 0)
// led.write(!led.read()); // led.write(!led.read());
cli();//disable interrupts cli();//disable interrupts
SerialChannel::swap(); SerialChannel::swap();
sei();//enable interrupts sei();//enable interrupts
SerialChannel::flush(); SerialChannel::flush();
owHandleReset();
} }
void(*timerEvent)() = 0; void(*timerEvent)() = 0;
@ -127,200 +119,195 @@ void owError(const char* message)
status = OS_WaitReset; status = OS_WaitReset;
} }
void owResetError() void owClearError()
{ {
led.writeLow(); led.writeLow();
} }
void onewireInterrupt(void) void owHandleReset()
{ {
bool state = owPin.read(); unsigned long localResetStart = resetStart;
unsigned long now = micros(); if (owPin.read())
//led.write(state);
if (!state)
resetStart = now;
// handle reset
if (state)
{ {
unsigned long resetDuration = resetStart == (unsigned long)-1 ? (unsigned long)-1 : now - resetStart;
resetStart = (unsigned long)-1; 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)
{
status = OS_WaitCommand;
receivingByte = 0;
receivingBitPos = 0;
bitStart = (unsigned long)-1;
if (state)
{
// this is the rising edge of end-of-presence ; don't try to interpret it as a bit
return;
}
} }
else if (localResetStart != (unsigned long)-1)
// read bytes
if (status == OS_WaitCommand)
{ {
byte bit = interpretReceivedEdgeAsBit(state, now); unsigned long resetDuration = micros() - localResetStart;
if (bit != IncompleteBit) if (resetDuration >= ResetMinDuration)
{ {
if (bit == InvalidBit) // wait for master to release the pin (or timeout if the pin is pulled low for too long)
return; unsigned long now = micros();
while (!owPin.read())
receivingByte |= (bit << receivingBitPos);
++receivingBitPos;
if (receivingBitPos == 8)
{ {
debug.SC_APPEND_STR_INT("received byte", (long)receivingByte); if (resetStart != localResetStart)
return;
if (status == OS_WaitCommand && receivingByte == 0xF0) now = micros();
if (now - localResetStart > ResetMaxDuration)
{ {
status = OS_SearchRom; owError("Reset too long");
searchROMReadingMasterResponseBit = false;
searchROMSendingInverse = false;
searchROMCurrentByte = 0;
searchROMCurrentBit = 0;
return; 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 bit = readBit();
bool currentBit = bitRead(currentByte, searchROMCurrentBit);
if (searchROMReadingMasterResponseBit) receivingByte |= ((bit ? 1 : 0) << receivingBitPos);
++receivingBitPos;
if (receivingBitPos == 8)
{ {
byte bit = interpretReceivedEdgeAsBit(state, now); byte receivedByte = receivingByte;
if (bit != IncompleteBit) receivingBitPos = 0;
receivingByte = 0;
//debug.SC_APPEND_STR_INT("received byte", (long)receivedByte);
if (status == OS_WaitCommand && receivedByte == 0xF0)
{ {
status = OS_SearchRom;
searchROMReadingMasterResponseBit = false; searchROMReadingMasterResponseBit = false;
if (bit == InvalidBit) searchROMSendingInverse = false;
return; searchROMCurrentByte = 0;
if ((bit == 1) != currentBit) searchROMCurrentBit = 0;
{ attachInterrupt(InterruptNumber, onewireInterruptSearchROM, FALLING);
debug.SC_APPEND_STR_TIME("Master didn't send our bit, leaving ROM search", now); return;
status = OS_WaitReset;
}
} }
} }
else } break;
{
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;
}
if (searchROMCurrentBit == 8) case OS_SearchRom:
{ {
++searchROMCurrentByte;
searchROMCurrentBit = 0;
debug.SC_APPEND_STR_TIME("sent another ROM byte", now);
}
if (searchROMCurrentByte == 8) } break;
{
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);
}
}
} }
} }
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 ignoreNextFallingEdge = false;
//debug.SC_APPEND_STR_TIME("bit start", now); return;
bitStart = now;
return IncompleteBit;
} }
else
if (searchROMReadingMasterResponseBit)
{ {
if (bitStart == (unsigned long)-1) bool bit = readBit();
{
//owError("Invalid read sequence");
//return InvalidBit;
// we missed the falling edge, we emulate one here (this can happen if handling of rising edge interrupt takes too long) byte currentByte = owROM[searchROMCurrentByte];
bitStart = now; bool currentBit = bitRead(currentByte, searchROMCurrentBit);
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 searchROMReadingMasterResponseBit = false;
unsigned long bitLength = now - bitStart; ++searchROMCurrentBit;
bitStart = (unsigned long)-1; if (searchROMCurrentBit == 8)
{
++searchROMCurrentByte;
searchROMCurrentBit = 0;
debug.SC_APPEND_STR("sent another ROM byte");
}
if (bitLength < BitZeroMinDuration) if (searchROMCurrentByte == 8)
{ {
// received bit = 1 searchROMCurrentByte = 0;
//debug.SC_APPEND_STR_TIME("received bit 1", now); status = OS_WaitReset;
return 1; 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 searchROMSendingInverse = false;
//debug.SC_APPEND_STR_TIME("received bit 0", now); searchROMReadingMasterResponseBit = true;
return 0;
} }
else else
{ {
// this is not a valid bit searchROMSendingInverse = true;
owError("Invalid read timing");
return InvalidBit;
} }
} }
} }
bool readBit()
{
delayMicroseconds(ReadBitSamplingTime);
return owPin.read();
}
void sendBit(bool bit) void sendBit(bool bit)
{ {
if (!bit) if (bit)
{
delayMicroseconds(SendBitDuration);
}
else
{ {
owPullLow(); owPullLow();
delayMicroseconds(SendBitDuration); delayMicroseconds(SendBitDuration);
owRelease(); owRelease();
ignoreNextFallingEdge = true;
} }
} }
@ -328,7 +315,6 @@ void beginPresence()
{ {
unsigned long now = micros(); unsigned long now = micros();
owPullLow(); owPullLow();
owOutTestPin.writeLow();
setTimerEvent(PresenceDuration, &endPresence); setTimerEvent(PresenceDuration, &endPresence);
debug.SC_APPEND_STR_TIME("reset", lastReset); debug.SC_APPEND_STR_TIME("reset", lastReset);
debug.SC_APPEND_STR_TIME("beginPresence", now); debug.SC_APPEND_STR_TIME("beginPresence", now);
@ -340,7 +326,10 @@ void endPresence()
owRelease(); owRelease();
debug.SC_APPEND_STR_TIME("endPresence", now); 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 ISR(TIMER1_COMPA_vect) // timer1 interrupt

Loading…
Cancel
Save