From b236a684ca4449b11daec9a8379c44537f291196 Mon Sep 17 00:00:00 2001 From: Youen Toupin Date: Fri, 24 Apr 2015 11:29:59 +0200 Subject: [PATCH] implemented reading of bytes sent by the 1-wire master --- OneWireIO.ino | 108 +++++++++++++++++++++++- SerialChannel.cpp | 40 ++++++--- SerialChannel.h | 11 +-- SerialMonitor/SerialMonitor/App.xaml.cs | 2 +- 4 files changed, 139 insertions(+), 22 deletions(-) diff --git a/OneWireIO.ino b/OneWireIO.ino index 46f43ce..5540e80 100644 --- a/OneWireIO.ino +++ b/OneWireIO.ino @@ -12,12 +12,24 @@ #define PresenceWaitDuration 30 #define PresenceDuration 300 +#define BitZeroMinDuration 20 +#define BitZeroMaxDuration 75 + SerialChannel debug("debug"); Pin owPin(OWPin); Pin owOutTestPin(3); Pin led(LEDPin); +enum OwStatus +{ + OS_WaitReset, + OS_Presence, + OS_AfterPresence, + OS_WaitCommand, +}; +OwStatus status; + void owPullLow() { owPin.outputMode(); @@ -40,6 +52,10 @@ void owWrite(bool value) } unsigned long resetStart = (unsigned long)-1; +unsigned long lastReset = (unsigned long)-1; +unsigned long bitStart = (unsigned long)-1; +byte receivingByte = 0; +byte receivingBitPos = 0; void setup() { @@ -63,7 +79,7 @@ void setup() TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt sei(); // enable interrupts - Serial.begin(400000); + Serial.begin(9600); } //int count = 0; @@ -92,6 +108,17 @@ void setTimerEvent(short microSecondsDelay, void(*event)()) TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // turn on CTC mode with 64 prescaler } +void owError(const char* message) +{ + debug.append(message); + led.writeHigh(); +} + +void owResetError() +{ + led.writeLow(); +} + void onewireInterrupt(void) { bool state = owPin.read(); @@ -102,32 +129,107 @@ void onewireInterrupt(void) if (!state) resetStart = now; + // handle reset if (state) { 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) + { + status = OS_WaitCommand; + receivingByte = 0; + receivingBitPos = 0; + + if (state) + { + // 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) + { + if (!state) + { + // master just pulled low, this is a bit start + //debug.SC_APPEND_STR_TIME("bit start", now); + bitStart = now; + } + else + { + if (bitStart == (unsigned long)-1) + { + //owError("Invalid read sequence"); + //return; + + // we missed the falling edge, we emulate one here (this can happen if handling of rising edge interrupt takes too long) + bitStart = now; + } + + // 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; + + if (bitLength < BitZeroMinDuration) + { + // received bit = 1 + //debug.SC_APPEND_STR_TIME("received bit 1", now); + receivingByte |= (1 << receivingBitPos); + ++receivingBitPos; + } + else if (bitLength < BitZeroMaxDuration) + { + // received bit = 0 + //debug.SC_APPEND_STR_TIME("received bit 0", now); + ++receivingBitPos; + } + else + { + // this is not a valid bit + owError("Invalid read timing"); + return; + } + + if (receivingBitPos == 8) + { + debug.SC_APPEND_STR_INT("received byte", (long)receivingByte); + receivingBitPos = 0; + receivingByte = 0; + } + } + } } void beginPresence() { - //debug.SC_APPEND_STR("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); } void endPresence() { - //debug.SC_APPEND_STR("endPresence"); + unsigned long now = micros(); owRelease(); + debug.SC_APPEND_STR_TIME("endPresence", now); + + status = OS_AfterPresence; } ISR(TIMER1_COMPA_vect) // timer1 interrupt diff --git a/SerialChannel.cpp b/SerialChannel.cpp index bcf7346..63537b6 100644 --- a/SerialChannel.cpp +++ b/SerialChannel.cpp @@ -6,10 +6,12 @@ SerialChannel* SerialChannel::first = 0; SerialChannel::Message SerialChannel::buffer1[SerialChannel::MaxPendingMessages]; SerialChannel::Message SerialChannel::buffer2[SerialChannel::MaxPendingMessages]; -SerialChannel::Message* SerialChannel::backBuffer; -byte SerialChannel::backBufferPos; +volatile SerialChannel::Message* SerialChannel::backBuffer; +volatile byte SerialChannel::backBufferPos; byte SerialChannel::frontBufferSize; +SerialChannel::Message dummyMessage; + SerialChannel::SerialChannel(const char* name_) : next(0) , id((byte)-1) @@ -66,16 +68,28 @@ SerialChannel::Message& SerialChannel::append(byte* data, short byteCount, unsig if (time == (unsigned long)-1) time = micros(); - Message& msg = backBuffer[backBufferPos++]; if (backBufferPos >= MaxPendingMessages) - backBufferPos = MaxPendingMessages - 1; - msg.id = id; - msg.data = data; - msg.byteCount = byteCount; - msg.time = time; - msg.longArg0 = 0; - - return msg; + { + Message& msg = ((Message*)backBuffer)[MaxPendingMessages-1]; + msg.id = id; + msg.data = (byte*)"OVERFLOW"; + msg.byteCount = 8; + msg.time = time; + msg.longArg0 = 0; + + return dummyMessage; + } + else + { + Message& msg = ((Message*)backBuffer)[backBufferPos++]; + msg.id = id; + msg.data = data; + msg.byteCount = byteCount; + msg.time = time; + msg.longArg0 = 0; + + return msg; + } } void SerialChannel::append(const char* text, unsigned long time) @@ -115,9 +129,9 @@ void SerialChannel::flush() Serial.write(msg->data, msg->byteCount); if (paramsSize > 0) Serial.write(params, paramsSize); - } - Serial.flush(); + Serial.flush(); + } } void SerialChannel::writeShort(short num) diff --git a/SerialChannel.h b/SerialChannel.h index 0231f24..53e1bd3 100644 --- a/SerialChannel.h +++ b/SerialChannel.h @@ -8,9 +8,7 @@ class SerialChannel { -private: - static const byte MaxPendingMessages = 16; - +public: struct Message { unsigned long time; @@ -20,6 +18,9 @@ private: byte id; }; +private: + static const byte MaxPendingMessages = 32; + static SerialChannel* first; SerialChannel* next; @@ -29,8 +30,8 @@ private: static Message buffer1[MaxPendingMessages]; static Message buffer2[MaxPendingMessages]; - static Message* backBuffer; - static byte backBufferPos; + static volatile Message* backBuffer; + static volatile byte backBufferPos; static byte frontBufferSize; public: diff --git a/SerialMonitor/SerialMonitor/App.xaml.cs b/SerialMonitor/SerialMonitor/App.xaml.cs index b0509e2..3fa11b0 100644 --- a/SerialMonitor/SerialMonitor/App.xaml.cs +++ b/SerialMonitor/SerialMonitor/App.xaml.cs @@ -28,7 +28,7 @@ namespace SerialMonitor Serial = new SerialPort(); Serial.PortName = "COM4"; - Serial.BaudRate = 400000; + Serial.BaudRate = 9600; Serial.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(OnDataReceived);