diff --git a/README.md b/README.md index 0925158..be75bcf 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The main goal is to use modern sensors (mainly [I2C](https://github.com/orgua/iL - **DS2890 Single channel digital potentiometer - extended to 1-4 CH** ### Features: -- supports up to 32 slaves (8 is standard setting), adjust ONEWIRESLAVE_LIMIT in OneWireHub.h to safe some RAM +- supports up to 32 slaves (8 is standard setting), adjust ONEWIRESLAVE_LIMIT in OneWireHub.h to safe RAM & program space - hot-plug slaves as needed - cleaner, faster code with c++11 features (requires arduino sw 1.6.x or higher) - use of constexpr instead of #define for better compiler-messages @@ -31,10 +31,10 @@ The main goal is to use modern sensors (mainly [I2C](https://github.com/orgua/iL - good documentation, numerous examples, easy interface for hub and sensors ### Recent development (latest at the top): -- rework of error system, slaves can raise errors now +- rework of error system, switch to enum, slaves can raise errors now & there is only one Block using Serial - rework of the whole timings, if needed you can configure overdrive speed (arduino uno would probably be to slow) - bug fix: non conformal behaviour as a onewire-slave (hopefully) -- raise the maximal slave limit from 8 to 32, takes ~100b extra program-space +- raise the maximal slave limit from 8 to 32, code adapts via variable dataTypes - open up for a lot more platforms with "platform.h" (taken from onewire-lib) - fix bug: open-drain violation on slave side - per-bit-CRC16 with sendAndCRC16() and sendAndCRC16() for load-balancing, 900ns/bit instead of 7µs/byte on Atmega328@16MHz diff --git a/src/OneWireHub.cpp b/src/OneWireHub.cpp index 83da91e..79d2853 100644 --- a/src/OneWireHub.cpp +++ b/src/OneWireHub.cpp @@ -43,6 +43,9 @@ uint8_t OneWireHub::attach(OneWireItem &sensor) } } + if (position == 255) + return 255; + slave_list[position] = &sensor; slave_count++; buildIDTree(); @@ -81,9 +84,9 @@ bool OneWireHub::detach(const uint8_t slave_number) // just look through each bit of each ID and build a tree, so there are n=slaveCount decision-points // trade-off: more online calculation, but @4Slave 16byte storage instead of 3*256 byte -uint8_t OneWireHub::getNrOfFirstBitSet(const uint32_t mask) +uint8_t OneWireHub::getNrOfFirstBitSet(const mask_t mask) { - uint32_t _mask = mask; + mask_t _mask = mask; for (uint8_t i = 0; i < ONEWIRESLAVE_LIMIT; ++i) { if (_mask & 1) return i; @@ -95,7 +98,7 @@ uint8_t OneWireHub::getNrOfFirstBitSet(const uint32_t mask) // gone through the address, store this result uint8_t OneWireHub::getNrOfFirstFreeIDTreeElement(void) { - for (uint8_t i = 0; i < ONEWIRETREE_SIZE; ++i) + for (uint8_t i = 0; i < ONEWIRE_TREE_SIZE; ++i) if (idTree[i].id_position == 255) return i; return 0; @@ -104,8 +107,8 @@ uint8_t OneWireHub::getNrOfFirstFreeIDTreeElement(void) // initial FN to build the ID-Tree uint8_t OneWireHub::buildIDTree(void) { - uint32_t mask_slaves = 0; - uint32_t bit_mask = 0x01; + mask_t mask_slaves = 0; + mask_t bit_mask = 0x01; // build mask for (uint8_t i = 0; i< ONEWIRESLAVE_LIMIT; ++i) @@ -114,7 +117,7 @@ uint8_t OneWireHub::buildIDTree(void) bit_mask <<= 1; } - for (uint8_t i = 0; i< ONEWIRETREE_SIZE; ++i) + for (uint8_t i = 0; i< ONEWIRE_TREE_SIZE; ++i) idTree[i].id_position = 255; // begin with root-element @@ -124,17 +127,17 @@ uint8_t OneWireHub::buildIDTree(void) } // returns the branch that this iteration has worked on -uint8_t OneWireHub::buildIDTree(uint8_t position_IDBit, const uint32_t mask_slaves) +uint8_t OneWireHub::buildIDTree(uint8_t position_IDBit, const mask_t mask_slaves) { if (!mask_slaves) return (255); while (position_IDBit < 64) { - uint32_t mask_pos = 0; - uint32_t mask_neg = 0; + mask_t mask_pos = 0; + mask_t mask_neg = 0; const uint8_t pos_byte = (position_IDBit >> 3); const uint8_t mask_bit = (static_cast(1) << (position_IDBit & (7))); - uint32_t mask_id = 1; + mask_t mask_id = 1; // search through all active slaves for (uint8_t id = 0; id < ONEWIRESLAVE_LIMIT; ++id) @@ -312,7 +315,7 @@ bool OneWireHub::search(void) { sendBit(false); sendBit(false); - uint8_t bit_recv = recvBit(); + const bool bit_recv = recvBit(); if (_error != Error::NO_ERROR) return false; // switch to next junction @@ -331,7 +334,7 @@ bool OneWireHub::search(void) { const uint8_t pos_byte = (position_IDBit >> 3); const uint8_t mask_bit = (static_cast(1) << (position_IDBit & (7))); - uint8_t bit_send, bit_recv; + bool bit_send; if (slave_list[active_slave]->ID[pos_byte] & mask_bit) { @@ -346,7 +349,7 @@ bool OneWireHub::search(void) sendBit(true); } - bit_recv = recvBit(); + const bool bit_recv = recvBit(); if (_error != Error::NO_ERROR) return false; if (bit_send != bit_recv) diff --git a/src/OneWireHub.h b/src/OneWireHub.h index 0b518e9..8663667 100644 --- a/src/OneWireHub.h +++ b/src/OneWireHub.h @@ -8,12 +8,23 @@ #define USE_SERIAL_DEBUG 0 // give debug messages when printError() is called // INFO: had to go with a define because some compilers use constexpr as simple const --> massive problems +#define HUB_SLAVE_LIMIT 8 // set the limit of the hub HERE + + +#ifndef HUB_SLAVE_LIMIT +#error "Slavelimit not defined (why?)" +#elif (HUB_SLAVE_LIMIT > 32) +#error "Slavelimit is set to high (32)" +#elif (HUB_SLAVE_LIMIT > 16) +using mask_t = uint32_t; +#elif (HUB_SLAVE_LIMIT > 8) +using mask_t = uint16_t; +#elif (HUB_SLAVE_LIMIT > 0) +using mask_t = uint8_t; +#else +#error "Slavelimit is set to zero (why?)" +#endif -// TODO: rework this whole system -// - cleaner timing-system throughout the lib (raw tick-counter of micros()?) -// - offer strict and relaxed timing option (if master is also emulated) -// - offer interruptable read / write OPs -// - safe timestamp of last HIGH, LOW state? enum class Error : uint8_t { NO_ERROR = 0, @@ -38,8 +49,8 @@ class OneWireHub { private: - static constexpr uint8_t ONEWIRESLAVE_LIMIT = 8; // 32 is max at the moment - static constexpr uint8_t ONEWIRETREE_SIZE = 2*ONEWIRESLAVE_LIMIT - 1; + static constexpr uint8_t ONEWIRESLAVE_LIMIT = HUB_SLAVE_LIMIT; + static constexpr uint8_t ONEWIRE_TREE_SIZE = 2*ONEWIRESLAVE_LIMIT - 1; /// the following TIME-values are in us and are taken from the ds2408 datasheet @@ -89,12 +100,12 @@ class OneWireHub uint8_t id_position; // where does the algorithm has to look for a junction uint8_t got_zero; // if 0 switch to which tree branch uint8_t got_one; // if 1 switch to which tree branch - } idTree[ONEWIRETREE_SIZE]; + } idTree[ONEWIRE_TREE_SIZE]; uint8_t buildIDTree(void); - uint8_t buildIDTree(uint8_t position_IDBit, const uint32_t slave_mask); + uint8_t buildIDTree(uint8_t position_IDBit, const mask_t slave_mask); - uint8_t getNrOfFirstBitSet(const uint32_t mask); + uint8_t getNrOfFirstBitSet(const mask_t mask); uint8_t getNrOfFirstFreeIDTreeElement(void); bool checkReset(uint16_t timeout_us);