Browse Source

finished implementation of most important 1-wire functionalities

pull/5/head
Youen Toupin 10 years ago
parent
commit
c0a183c769
  1. 2
      LowLevel.h
  2. 42
      OneWireIO.ino
  3. 134
      OneWireSlave.cpp
  4. 26
      OneWireSlave.h

2
LowLevel.h

@ -71,8 +71,8 @@
class Pin class Pin
{ {
private: private:
IO_REG_TYPE mask_;
volatile IO_REG_TYPE *reg_; volatile IO_REG_TYPE *reg_;
IO_REG_TYPE mask_;
byte interruptNumber_; byte interruptNumber_;
public: public:

42
OneWireIO.ino

@ -12,11 +12,21 @@ Pin led(LEDPin);
byte owROM[7] = { 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; byte owROM[7] = { 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
byte buffer1[8];
byte buffer2[8];
volatile byte* backBuffer = buffer1;
volatile byte bufferPos = 0;
byte sendBuffer[8];
void owReceive(OneWireSlave::ReceiveEvent evt, byte data);
void setup() void setup()
{ {
led.outputMode(); led.outputMode();
led.writeLow(); led.writeLow();
OneWire.setReceiveCallback(&owReceive);
OneWire.begin(owROM, OWPin); OneWire.begin(owROM, OWPin);
Serial.begin(9600); Serial.begin(9600);
@ -34,15 +44,39 @@ void loop()
cli();//disable interrupts cli();//disable interrupts
SerialChannel::swap(); SerialChannel::swap();
byte* frontBuffer = (byte*)backBuffer;
byte frontBufferSize = bufferPos;
backBuffer = backBuffer == buffer1 ? buffer2 : buffer1;
bufferPos = 0;
sei();//enable interrupts sei();//enable interrupts
SerialChannel::flush(); SerialChannel::flush();
byte b; for (int i = 0; i < frontBufferSize; ++i)
if (OneWire.read(b))
{ {
char msg[32]; char msg[16];
sprintf(msg, "Received byte : %d", (int)b); sprintf(msg, "Received byte: %d", (int)frontBuffer[i]);
debug.write(msg); debug.write(msg);
if (frontBuffer[i] == 0x42)
{
sendBuffer[0] = 0xBA;
sendBuffer[1] = 0xAD;
sendBuffer[2] = 0xF0;
sendBuffer[3] = 0x0D;
OneWire.write(sendBuffer, 4, 0);
}
}
}
void owReceive(OneWireSlave::ReceiveEvent evt, byte data)
{
switch (evt)
{
case OneWireSlave::RE_Byte:
backBuffer[bufferPos++] = data;
break;
default:
;
} }
} }

134
OneWireSlave.cpp

@ -1,11 +1,20 @@
#include "OneWireSlave.h" #include "OneWireSlave.h"
#define DEBUG_LOG #define DEBUG_LOG
#define ERROR_MESSAGES
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
#include "SerialChannel.h" #include "SerialChannel.h"
extern SerialChannel debug; extern SerialChannel debug;
Pin dbgOutput(3); Pin dbgOutput(3);
#else
#undef ERROR_MESSAGES
#endif
#ifdef ERROR_MESSAGES
#define ERROR(msg) error_(msg)
#else
#define ERROR(msg) error_(0)
#endif #endif
namespace namespace
@ -37,18 +46,21 @@ unsigned long OneWireSlave::lastReset_;
void(*OneWireSlave::receiveBitCallback_)(bool bit, bool error); void(*OneWireSlave::receiveBitCallback_)(bool bit, bool error);
void(*OneWireSlave::bitSentCallback_)(bool error); void(*OneWireSlave::bitSentCallback_)(bool error);
void(*OneWireSlave::clientReceiveCallback_)(ReceiveEvent evt, byte data);
byte OneWireSlave::receivingByte_; byte OneWireSlave::receivingByte_;
byte OneWireSlave::receivingBitPos_;
byte OneWireSlave::receiveTarget_;
byte OneWireSlave::searchRomBytePos_; byte OneWireSlave::searchRomBytePos_;
byte OneWireSlave::searchRomBitPos_; byte OneWireSlave::searchRomBitPos_;
bool OneWireSlave::searchRomInverse_; bool OneWireSlave::searchRomInverse_;
byte* OneWireSlave::receiveBytesBuffer_; byte* OneWireSlave::buffer_;
short OneWireSlave::receiveBytesLength_; short OneWireSlave::bufferLength_;
byte OneWireSlave::bufferBitPos_;
short OneWireSlave::bufferPos_;
void(*OneWireSlave::receiveBytesCallback_)(bool error); void(*OneWireSlave::receiveBytesCallback_)(bool error);
void(*OneWireSlave::sendBytesCallback_)(bool error);
ISR(TIMER1_COMPA_vect) // timer1 interrupt ISR(TIMER1_COMPA_vect) // timer1 interrupt
{ {
@ -101,19 +113,11 @@ void OneWireSlave::end()
sei(); sei();
} }
bool OneWireSlave::read(byte& b)
{
return false;
}
void OneWireSlave::setReceiveCallback(void(*callback)())
{
}
void OneWireSlave::write(byte* bytes, short numBytes, void(*complete)(bool error)) void OneWireSlave::write(byte* bytes, short numBytes, void(*complete)(bool error))
{ {
cli();
beginWriteBytes_(bytes, numBytes, complete == 0 ? noOpCallback_ : complete);
sei();
} }
byte OneWireSlave::crc8_(byte* data, short numBytes) byte OneWireSlave::crc8_(byte* data, short numBytes)
@ -151,18 +155,25 @@ void OneWireSlave::disableTimer_()
void OneWireSlave::onEnterInterrupt_() void OneWireSlave::onEnterInterrupt_()
{ {
#ifdef DEBUG_LOG
dbgOutput.writeLow(); dbgOutput.writeLow();
#endif
} }
void OneWireSlave::onLeaveInterrupt_() void OneWireSlave::onLeaveInterrupt_()
{ {
#ifdef DEBUG_LOG
dbgOutput.writeHigh(); dbgOutput.writeHigh();
#endif
} }
void OneWireSlave::error_(const char* message) void OneWireSlave::error_(const char* message)
{ {
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
debug.append(message); if (message == 0)
debug.append("unspecified error");
else
debug.append(message);
#endif #endif
beginWaitReset_(); beginWaitReset_();
} }
@ -312,7 +323,7 @@ void OneWireSlave::waitReset_()
{ {
if (resetDuration > ResetMaxDuration) if (resetDuration > ResetMaxDuration)
{ {
error_("Reset too long"); ERROR("Reset too long");
onLeaveInterrupt_(); onLeaveInterrupt_();
return; return;
} }
@ -320,6 +331,8 @@ void OneWireSlave::waitReset_()
lastReset_ = now; lastReset_ = now;
pin_.detachInterrupt(); pin_.detachInterrupt();
setTimerEvent_(PresenceWaitDuration - (micros() - now), &OneWireSlave::beginPresence_); setTimerEvent_(PresenceWaitDuration - (micros() - now), &OneWireSlave::beginPresence_);
if (clientReceiveCallback_ != 0)
clientReceiveCallback_(RE_Reset, 0);
} }
} }
else else
@ -353,14 +366,14 @@ void OneWireSlave::endPresence_()
void OneWireSlave::beginWaitCommand_() void OneWireSlave::beginWaitCommand_()
{ {
receiveTarget_ = ReceiveCommand; bufferPos_ = ReceiveCommand;
beginReceive_(); beginReceive_();
} }
void OneWireSlave::beginReceive_() void OneWireSlave::beginReceive_()
{ {
receivingByte_ = 0; receivingByte_ = 0;
receivingBitPos_ = 0; bufferBitPos_ = 0;
beginReceiveBit_(&OneWireSlave::onBitReceived_); beginReceiveBit_(&OneWireSlave::onBitReceived_);
} }
@ -368,23 +381,23 @@ void OneWireSlave::onBitReceived_(bool bit, bool error)
{ {
if (error) if (error)
{ {
error_("Invalid bit"); ERROR("Invalid bit");
if (receiveTarget_ >= 0) if (bufferPos_ >= 0)
receiveBytesCallback_(true); receiveBytesCallback_(true);
return; return;
} }
receivingByte_ |= ((bit ? 1 : 0) << receivingBitPos_); receivingByte_ |= ((bit ? 1 : 0) << bufferBitPos_);
++receivingBitPos_; ++bufferBitPos_;
if (receivingBitPos_ == 8) if (bufferBitPos_ == 8)
{ {
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
debug.SC_APPEND_STR_INT("received byte", (long)receivingByte_); debug.SC_APPEND_STR_INT("received byte", (long)receivingByte_);
#endif #endif
if (receiveTarget_ == ReceiveCommand) if (bufferPos_ == ReceiveCommand)
{ {
receiveTarget_ = 0; bufferPos_ = 0;
switch (receivingByte_) switch (receivingByte_)
{ {
case 0xF0: // SEARCH ROM case 0xF0: // SEARCH ROM
@ -402,16 +415,16 @@ void OneWireSlave::onBitReceived_(bool bit, bool error)
matchRomBytesReceived_(false); matchRomBytesReceived_(false);
return; return;
default: default:
error_("Unknown command"); ERROR("Unknown command");
return; return;
} }
} }
else else
{ {
receiveBytesBuffer_[receiveTarget_++] = receivingByte_; buffer_[bufferPos_++] = receivingByte_;
receivingByte_ = 0; receivingByte_ = 0;
receivingBitPos_ = 0; bufferBitPos_ = 0;
if (receiveTarget_ == receiveBytesLength_) if (bufferPos_ == bufferLength_)
{ {
beginWaitReset_(); beginWaitReset_();
receiveBytesCallback_(false); receiveBytesCallback_(false);
@ -445,7 +458,7 @@ void OneWireSlave::continueSearchRom_(bool error)
{ {
if (error) if (error)
{ {
error_("Failed to send bit"); ERROR("Failed to send bit");
return; return;
} }
@ -464,7 +477,7 @@ void OneWireSlave::searchRomOnBitReceived_(bool bit, bool error)
{ {
if (error) if (error)
{ {
error_("Bit read error during ROM search"); ERROR("Bit read error during ROM search");
return; return;
} }
@ -503,15 +516,48 @@ void OneWireSlave::searchRomOnBitReceived_(bool bit, bool error)
void OneWireSlave::beginWriteBytes_(byte* data, short numBytes, void(*complete)(bool error)) void OneWireSlave::beginWriteBytes_(byte* data, short numBytes, void(*complete)(bool error))
{ {
// TODO buffer_ = data;
beginWaitReset_(); bufferLength_ = numBytes;
bufferPos_ = 0;
bufferBitPos_ = 0;
sendBytesCallback_ = complete;
bool bit = bitRead(buffer_[0], 0);
beginSendBit_(bit, &OneWireSlave::bitSent_);
}
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_)
{
beginWaitReset_();
sendBytesCallback_(false);
return;
}
bool bit = bitRead(buffer_[bufferPos_], bufferBitPos_);
beginSendBit_(bit, &OneWireSlave::bitSent_);
} }
void OneWireSlave::beginReceiveBytes_(byte* buffer, short numBytes, void(*complete)(bool error)) void OneWireSlave::beginReceiveBytes_(byte* buffer, short numBytes, void(*complete)(bool error))
{ {
receiveBytesBuffer_ = buffer; buffer_ = buffer;
receiveBytesLength_ = numBytes; bufferLength_ = numBytes;
receiveTarget_ = 0; bufferPos_ = 0;
receiveBytesCallback_ = complete; receiveBytesCallback_ = complete;
beginReceive_(); beginReceive_();
} }
@ -519,14 +565,14 @@ void OneWireSlave::beginReceiveBytes_(byte* buffer, short numBytes, void(*comple
void OneWireSlave::noOpCallback_(bool error) void OneWireSlave::noOpCallback_(bool error)
{ {
if (error) if (error)
error_("error during an internal 1-wire operation"); ERROR("error during an internal 1-wire operation");
} }
void OneWireSlave::matchRomBytesReceived_(bool error) void OneWireSlave::matchRomBytesReceived_(bool error)
{ {
if (error) if (error)
{ {
error_("error receiving match rom bytes"); ERROR("error receiving match rom bytes");
return; return;
} }
@ -550,11 +596,13 @@ void OneWireSlave::notifyClientByteReceived_(bool error)
{ {
if (error) if (error)
{ {
error_("error receiving device specific bytes"); if (clientReceiveCallback_ != 0)
clientReceiveCallback_(RE_Error, 0);
ERROR("error receiving custom bytes");
return; return;
} }
beginWaitReset_(); beginReceiveBytes_(scratchpad_, 1, &OneWireSlave::notifyClientByteReceived_);
if (clientReceiveCallback_ != 0)
// TODO clientReceiveCallback_(RE_Byte, scratchpad_[0]);
} }

26
OneWireSlave.h

@ -7,17 +7,21 @@
class OneWireSlave class OneWireSlave
{ {
public: public:
enum ReceiveEvent
{
RE_Reset, //!< The master has sent a general reset
RE_Byte, //!< The master just sent a byte of data
RE_Error //!< A communication error happened (such as a timeout) ; the library will stop all 1-wire activities until the next reset
};
//! Starts listening for the 1-wire master, on the specified pin, as a virtual slave device identified by the specified ROM (7 bytes, starting from the family code, CRC will be computed internally). Reset, Presence, SearchRom and MatchRom are handled automatically. The library will use the external interrupt on the specified pin (note that this is usually not possible with all pins, depending on the board), as well as one hardware timer. Blocking interrupts (either by disabling them explicitely with sei/cli, or by spending time in another interrupt) can lead to malfunction of the library, due to tight timing for some 1-wire operations. //! Starts listening for the 1-wire master, on the specified pin, as a virtual slave device identified by the specified ROM (7 bytes, starting from the family code, CRC will be computed internally). Reset, Presence, SearchRom and MatchRom are handled automatically. The library will use the external interrupt on the specified pin (note that this is usually not possible with all pins, depending on the board), as well as one hardware timer. Blocking interrupts (either by disabling them explicitely with sei/cli, or by spending time in another interrupt) can lead to malfunction of the library, due to tight timing for some 1-wire operations.
void begin(byte* rom, byte pinNumber); void begin(byte* rom, byte pinNumber);
//! Stops all 1-wire activities, which frees hardware resources for other purposes. //! Stops all 1-wire activities, which frees hardware resources for other purposes.
void end(); void end();
//! Pops one byte from the receive buffer, or returns false if no byte has been received. //! Sets (or replaces) a function to be called when something is received. The callback is executed from interrupts and should be as short as possible. Failure to return quickly can prevent the library from correctly reading the next byte.
bool read(byte& b); void setReceiveCallback(void(*callback)(ReceiveEvent evt, byte data)) { clientReceiveCallback_ = callback; }
//! Sets (or replaces) a function to be called when at least one byte has been received. Callbacks are executed from interrupts and should be as short as possible.
void setReceiveCallback(void(*callback)());
//! Enqueues the specified bytes in the send buffer. They will be sent in the background. The optional callback is used to notify when the bytes are sent, or if an error occured. Callbacks are executed from interrupts and should be as short as possible. //! Enqueues the specified bytes in the send buffer. They will be sent in the background. The optional callback is used to notify when the bytes are sent, or if an error occured. Callbacks are executed from interrupts and should be as short as possible.
void write(byte* bytes, short numBytes, void(*complete)(bool error)); void write(byte* bytes, short numBytes, void(*complete)(bool error));
@ -58,6 +62,7 @@ private:
static void noOpCallback_(bool error); static void noOpCallback_(bool error);
static void matchRomBytesReceived_(bool error); static void matchRomBytesReceived_(bool error);
static void notifyClientByteReceived_(bool error); static void notifyClientByteReceived_(bool error);
static void bitSent_(bool error);
// interrupt handlers // interrupt handlers
static void waitReset_(); static void waitReset_();
@ -83,16 +88,19 @@ private:
static void(*bitSentCallback_)(bool error); static void(*bitSentCallback_)(bool error);
static byte receivingByte_; static byte receivingByte_;
static byte receivingBitPos_;
static byte receiveTarget_;
static byte searchRomBytePos_; static byte searchRomBytePos_;
static byte searchRomBitPos_; static byte searchRomBitPos_;
static bool searchRomInverse_; static bool searchRomInverse_;
static byte* receiveBytesBuffer_; static byte* buffer_;
static short receiveBytesLength_; static short bufferLength_;
static short bufferPos_;
static byte bufferBitPos_;
static void(*receiveBytesCallback_)(bool error); static void(*receiveBytesCallback_)(bool error);
static void(*sendBytesCallback_)(bool error);
static void(*clientReceiveCallback_)(ReceiveEvent evt, byte data);
}; };
extern OneWireSlave OneWire; extern OneWireSlave OneWire;

Loading…
Cancel
Save