Skip to content

Commit

Permalink
cleanup send / receive / waitForTimeslot to react faster to bus
Browse files Browse the repository at this point in the history
  • Loading branch information
orgua committed Mar 20, 2016
1 parent d62b1a5 commit 38b22ad
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 64 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,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):
- detect a reset after a reset (when there should be a timeslot)
- hub is more robust to odd master-behaviour (lazy timings and subsequent resets)
- prepare new timing-method which will replace the old one in the next couple of weeks (a 6µs millis() call at 8MHz is not suitable for OW)
- cleanup send / receive / waitForTimeslot to react faster to bus (better for µC with less than 16 MHz)
- support for skipROM-cmd if only one slave is present (thanks to Giermann)
- speed up atmel-crc-functions
- tested with DS9490R: ds28b20, ds2401, ds2405, ds2413, more will follow
- rework of error system, switch to enum, slaves can raise errors now & and Serial interferes less with OW-timings
Expand Down
124 changes: 62 additions & 62 deletions src/OneWireHub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,17 +485,27 @@ bool OneWireHub::send(const uint8_t dataByte)
return true;
}

uint16_t OneWireHub::sendAndCRC16(uint8_t dataByte, uint16_t crc16)
{
for (uint8_t counter = 0; counter < 8; ++counter)
{
sendBit((0x01 & dataByte) ? bool(1) : bool(0));

uint8_t mix = ((uint8_t) crc16 ^ dataByte) & static_cast<uint8_t>(0x01);
crc16 >>= 1;
if (mix) crc16 ^= static_cast<uint16_t>(0xA001);
dataByte >>= 1;

if (_error != Error::NO_ERROR) return 0; // CRC is not important if sending fails
}
return crc16;
}

bool OneWireHub::sendBit(const bool value)
{
volatile uint8_t *reg asm("r30") = pin_baseReg;

noInterrupts();
DIRECT_MODE_INPUT(reg, pin_bitMask);
// wait for a low to high transition followed by a high to low within the time-out
if (!awaitTimeSlot())
if (!awaitTimeSlotAndWrite(!value))
{
interrupts();
_error = Error::WRITE_TIMESLOT_TIMEOUT;
return false; // timeslot violation
}
Expand All @@ -504,32 +514,12 @@ bool OneWireHub::sendBit(const bool value)
else
{
// if we wait for release we could detect faulty writing slots --> pedantic Mode not needed for now
noInterrupts();
DIRECT_WRITE_LOW(reg, pin_bitMask);
DIRECT_MODE_OUTPUT(reg, pin_bitMask);
interrupts();
wait(ONEWIRE_TIME_WRITE_ZERO_LOW_STD);
volatile uint8_t *reg asm("r30") = pin_baseReg;
DIRECT_MODE_INPUT(reg, pin_bitMask);
}
interrupts();
return true;
}


uint16_t OneWireHub::sendAndCRC16(uint8_t dataByte, uint16_t crc16)
{
for (uint8_t counter = 0; counter < 8; ++counter)
{
sendBit((0x01 & dataByte) ? bool(1) : bool(0));

uint8_t mix = ((uint8_t) crc16 ^ dataByte) & static_cast<uint8_t>(0x01);
crc16 >>= 1;
if (mix) crc16 ^= static_cast<uint16_t>(0xA001);
dataByte >>= 1;

if (_error != Error::NO_ERROR) return 0; // CRC is not important if sending fails
}
return crc16;
return true;
}


Expand Down Expand Up @@ -557,35 +547,6 @@ uint8_t OneWireHub::recv(void)
return value;
}

bool OneWireHub::recvBit(void)
{
volatile uint8_t *reg asm("r30") = pin_baseReg;

noInterrupts();
DIRECT_MODE_INPUT(reg, pin_bitMask);

// wait for a low to high transition followed by a high to low within the time-out
if (!awaitTimeSlot())
{
interrupts();

if (extend_timeslot_detection==2)
{
_error = Error::FIRST_TIMESLOT_TIMEOUT;
extend_timeslot_detection = 0;
}
else
{
_error = Error::READ_TIMESLOT_TIMEOUT;
}

return 0;
}
interrupts();
waitWhilePinIs( 0, ONEWIRE_TIME_READ_STD); // no pinCheck demanded, but this additional check can cut waitTime
return DIRECT_READ(reg, pin_bitMask);
}

// TODO: not happy with the interface - call by ref is slow here. maybe use a crc in class and expand with crc-reset and get?
uint8_t OneWireHub::recvAndCRC16(uint16_t &crc16)
{
Expand All @@ -610,6 +571,32 @@ uint8_t OneWireHub::recvAndCRC16(uint16_t &crc16)
return value;
}

bool OneWireHub::recvBit(void)
{

// wait for a low to high transition followed by a high to low within the time-out
if (!awaitTimeSlotAndWrite())
{
if (extend_timeslot_detection==2)
{
_error = Error::FIRST_TIMESLOT_TIMEOUT;
extend_timeslot_detection = 0;
}
else
{
_error = Error::READ_TIMESLOT_TIMEOUT;
}

return 0;
}

waitWhilePinIs( 0, ONEWIRE_TIME_READ_STD); // no pinCheck demanded, but this additional check can cut waitTime
volatile uint8_t *reg asm("r30") = pin_baseReg;
DIRECT_MODE_INPUT(reg, pin_bitMask);

return DIRECT_READ(reg, pin_bitMask);
}

#define USE_DELAY 1

void OneWireHub::wait(const uint16_t timeout_us)
Expand Down Expand Up @@ -648,11 +635,11 @@ bool OneWireHub::waitWhilePinIs(const bool value, const uint16_t timeout_us)
}


#define NEW_WAIT 0 // TODO: NewWait does not work as expected
#define NEW_WAIT 0 // TODO: NewWait does not work as expected (and is deprecated)
#if (NEW_WAIT > 0)

// wait for a low to high transition followed by a high to low within the time-out
bool OneWireHub::awaitTimeSlot(void)
bool OneWireHub::awaitTimeSlotAndWrite(void)
{
noInterrupts();
volatile uint8_t *reg asm("r30") = pin_baseReg;
Expand Down Expand Up @@ -690,9 +677,12 @@ bool OneWireHub::awaitTimeSlot(void)
#else

#define TIMESLOT_WAIT_RETRY_COUNT static_cast<uint16_t>(microsecondsToClockCycles(135)/8) /// :11 is a specif value for 8bit-atmega, still to determine
bool OneWireHub::awaitTimeSlot(void)
bool OneWireHub::awaitTimeSlotAndWrite(const bool writeZero)
{
volatile uint8_t *reg asm("r30") = pin_baseReg;
noInterrupts();
DIRECT_WRITE_LOW(reg, pin_bitMask);
DIRECT_MODE_INPUT(reg, pin_bitMask);

//While bus is low, retry until HIGH
uint16_t retries = TIMESLOT_WAIT_RETRY_COUNT;
Expand All @@ -709,19 +699,21 @@ bool OneWireHub::awaitTimeSlot(void)
{
_error = Error::READ_TIMESLOT_TIMEOUT_LOW;
}
interrupts();
return false;
}
}

// extend the wait-time after reset and presence-detection
if (extend_timeslot_detection == 1)
{
retries = 60000;
retries = 65535;
extend_timeslot_detection = 2; // prepare to detect missing timeslot or second reset
}
else
{
retries = TIMESLOT_WAIT_RETRY_COUNT;
//retries = TIMESLOT_WAIT_RETRY_COUNT;
retries = 65535; // TODO: workaround for better compatibility (will be solved later)
}

//Wait for bus to fall form 1 to 0
Expand All @@ -730,10 +722,18 @@ bool OneWireHub::awaitTimeSlot(void)
if (--retries == 0)
{
_error = Error::READ_TIMESLOT_TIMEOUT_HIGH;
interrupts();
return false;
}
}

if (writeZero)
{
// Low is allready set
DIRECT_MODE_OUTPUT(reg, pin_bitMask);
}

interrupts();
return true;
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/OneWireHub.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class OneWireHub
void wait(const uint16_t timeout_us);

__attribute__((always_inline))
bool awaitTimeSlot();
bool awaitTimeSlotAndWrite(const bool writeZero = 0);

__attribute__((always_inline))
bool waitWhilePinIs(const bool value, const uint16_t timeout_us);
Expand Down

0 comments on commit 38b22ad

Please sign in to comment.