Skip to content

Commit

Permalink
clean up and document ds2408
Browse files Browse the repository at this point in the history
  • Loading branch information
orgua committed Oct 24, 2016
1 parent a80313e commit f4f9e42
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 37 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The main goal is to use modern sensors (mainly [I2C](https://github.com/orgua/iL
- **DS1990 (0x01) iButton** (DS2401 with same family code)
- **DS2401 (0x01) Serial Number**
- **DS2405 (0x05) Single address switch**
- DS2408 (0x29) 8-Channel Addressable Switch, GPIO Port-expander
- **DS2408 (0x29) 8-Channel Addressable Switch**, GPIO Port-expander
- **DS2411 (0x01) Serial Number** (use DS2401 with same family code)
- **DS2413 (0x3A) Dual channel addressable switch with input-sensing**
- DS2423 (0x1D) 4kbit 1-Wire RAM with Counter
Expand Down Expand Up @@ -41,6 +41,7 @@ Note: **Bold printed devices are feature-complete and were mostly tested with a
- documentation, numerous examples, easy interface for hub and sensors

### Recent development (latest at the top):
- basic support for ds2408, thanks to vytautassurvila
- teensy3.2 tested: cleaned warnings, fixed port access, cleaned examples
- sensors with emulated memory use memset and static_asserts to secure implementation
- fix and clean pin access, fix a portability issue (time_t)
Expand Down
13 changes: 12 additions & 1 deletion examples/DS2408_switch/DS2408_switch.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
*
* Tested with:
* - https://github.com/PaulStoffregen/OneWire on the other side as Master
* - DS9490R-Master, atmega328@16MHz as Slave
* - BeagleBoneBlack running Linux 4.4.19. 1wire slave was accessed via original drivers:
*
* #set all pins to 1 (xFF)
* echo -e '\xFF' |dd of=/sys/bus/w1/devices/29-010000000000/output bs=1 count=1
*
* #get values for all pins
* dd if=/sys/bus/w1/devices/29-010000000000/state bs=1 count=1 | hexdump
*
*/

#include "OneWireHub.h"
Expand All @@ -16,7 +25,7 @@ auto ds2408 = DS2408( 0x29, 0x0D, 0x02, 0x04, 0x00, 0x08, 0x0A );

bool blinking()
{
const uint32_t interval = 500; // interval at which to blink (milliseconds)
const uint32_t interval = 1000; // interval at which to blink (milliseconds)
static uint32_t nextMillis = millis(); // will store next time LED will updated

if (millis() > nextMillis)
Expand Down Expand Up @@ -66,5 +75,7 @@ void loop()
{
// this could be used to report up to eight states to 1wire master
//ds2408.setPinState(0, digitalRead(10));
Serial.print("0x");
Serial.println(ds2408.getPinStates(),BIN);
}
}
102 changes: 75 additions & 27 deletions src/DS2408.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

DS2408::DS2408(uint8_t ID1, uint8_t ID2, uint8_t ID3, uint8_t ID4, uint8_t ID5, uint8_t ID6, uint8_t ID7) : OneWireItem(ID1, ID2, ID3, ID4, ID5, ID6, ID7)
{
memory.registers[DS2408_PIO_LOGIC_REG] = 0x41;
memory.registers[DS2408_PIO_OUTPUT_REG] = 0xFF;
memory.registers[DS2408_PIO_ACTIVITY_REG] = 0xFF;
memory.registers[DS2408_SEARCH_MASK_REG] = 0;
memory.registers[DS2408_SEARCH_SELECT_REG] = 0;
memory.registers[DS2408_CONTROL_STATUS_REG] = 0x88;
memory.registers[DS2408_RD_ABOVE_ALWAYS_FF_8E] = 0xFF;
memory.registers[DS2408_RD_ABOVE_ALWAYS_FF_8F] = 0xFF;
memory[DS2408_PIO_LOGIC_REG] = 0xFF;
memory[DS2408_PIO_OUTPUT_REG] = 0xFF;
memory[DS2408_PIO_ACTIVITY_REG] = 0xFF;
memory[DS2408_SEARCH_MASK_REG] = 0;
memory[DS2408_SEARCH_SELECT_REG] = 0;
memory[DS2408_CONTROL_STATUS_REG] = 0x88;
memory[DS2408_RD_ABOVE_ALWAYS_FF_8E] = 0xFF;
memory[DS2408_RD_ABOVE_ALWAYS_FF_8F] = 0xFF;
};

bool DS2408::duty(OneWireHub *hub)
{
uint8_t targetAddress;
uint16_t crc = 0;
uint16_t crc = 0, crc2;
uint8_t cmd = hub->recvAndCRC16(crc);
uint8_t data;
if (hub->getError()) return false;
Expand All @@ -25,31 +25,70 @@ bool DS2408::duty(OneWireHub *hub)
case 0xF0: // Read PIO Registers
targetAddress = hub->recvAndCRC16(crc);
if (hub->getError()) return false;
if(targetAddress < 0x88 || targetAddress > 0x8F) return false;
hub->recvAndCRC16(crc);
if((targetAddress < DS2408_OFFSET) || (targetAddress >= DS2408_OFFSET + DS2408_MEMSIZE)) return false;
if (hub->recvAndCRC16(crc) != 0) return false;
if (hub->getError()) return false;

for (uint8_t count = targetAddress - 0x88; count < 8; ++count)
for (uint8_t count = (targetAddress - DS2408_OFFSET); count < DS2408_MEMSIZE; ++count)
{
crc = hub->sendAndCRC16(memory.registers[count], crc);
crc = hub->sendAndCRC16(memory[count], crc);
if (hub->getError()) return false;
}
crc = ~crc; // most important step, easy to miss....
hub->send(reinterpret_cast<uint8_t *>(&crc)[0]);
if (hub->getError()) return false;
hub->send(reinterpret_cast<uint8_t *>(&crc)[1]);
if (hub->getError()) return false;
// after memory readout this chip sends logic 1s, which is the same as staying passive
break;

case 0x5A: // Channel-Access Write
data = hub->recv();
if (hub->getError()) return false;
hub->recv(); //inverted data
if (hub->getError()) return false;
memory.registers[DS2408_PIO_OUTPUT_REG] = data;
memory.registers[DS2408_PIO_LOGIC_REG] = memory.registers[DS2408_PIO_OUTPUT_REG];
hub->send(0xAA);
if (hub->getError()) return false;
hub->send(memory.registers[DS2408_PIO_OUTPUT_REG]);
while(1)
{
data = hub->recv();
if (hub->getError()) return false;
//if (hub->recv() != ~data) return false; //inverted data, not working properly
hub->recv();
if (hub->getError()) return false;
memory[DS2408_PIO_ACTIVITY_REG] |= data ^ memory[DS2408_PIO_LOGIC_REG];
memory[DS2408_PIO_OUTPUT_REG] = data;
memory[DS2408_PIO_LOGIC_REG] = data;
hub->send(0xAA);
if (hub->getError()) return false;
for (uint8_t count = 0; count < 4; ++count) // TODO: i think this is right, datasheet says: DS2408 samples the status of the PIO pins, as shown in Figure 9, and sends it to the master
{
hub->send(memory[count]);
if (hub->getError()) return false;
}
}

case 0xF5: // Channel-Access Read
crc2 = crc;
while (1)
{
crc = crc2;
for (uint8_t count = 0; count < 4; ++count)
{
crc = hub->sendAndCRC16(memory[count], crc);
if (hub->getError()) return false;
}
crc = ~crc; // most important step, easy to miss....
hub->send(reinterpret_cast<uint8_t *>(&crc)[0]);
if (hub->getError()) return false;
hub->send(reinterpret_cast<uint8_t *>(&crc)[1]);
if (hub->getError()) return false;
};

case 0xC3: // reset activity latches
memory[DS2408_PIO_ACTIVITY_REG] = 0x00;
while(1)
{
hub->send(0xAA);
if (hub->getError()) return false;
};

case 0xCC: // write conditional search register
// TODO: page 18 datasheet
break;

default:
Expand All @@ -61,13 +100,22 @@ bool DS2408::duty(OneWireHub *hub)

bool DS2408::getPinState(uint8_t pinNumber)
{
return memory.registers[DS2408_PIO_LOGIC_REG] & 1 << pinNumber;
return static_cast<bool>(memory[DS2408_PIO_LOGIC_REG] & ( 1 << pinNumber ));
};

uint8_t DS2408::getPinStates(void)
{
return memory[DS2408_PIO_LOGIC_REG];
};

void DS2408::setPinState(uint8_t pinNumber, bool value)
{
if(value)
memory.registers[DS2408_PIO_LOGIC_REG] |= 1 << pinNumber;
else
memory.registers[DS2408_PIO_LOGIC_REG] &= ~(1 << pinNumber);
uint8_t pio_state = memory[DS2408_PIO_LOGIC_REG];
if(value) pio_state |= 1 << pinNumber;
else pio_state &= ~(1 << pinNumber);

// look for changes in the activity latches
memory[DS2408_PIO_ACTIVITY_REG] |= pio_state ^ memory[DS2408_PIO_LOGIC_REG];
memory[DS2408_PIO_LOGIC_REG] = pio_state;
memory[DS2408_PIO_OUTPUT_REG] = pio_state;
};
14 changes: 6 additions & 8 deletions src/DS2408.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
// 0x29 8-Channel Addressable Switch @@@
// Not finished
// basic operation works

#ifndef ONEWIRE_DS2408_H
#define ONEWIRE_DS2408_H

#include "OneWireItem.h"


typedef union {
uint8_t registers[8];
} mDS2408; // overlay with memory_array


class DS2408 : public OneWireItem
{
private:

// Register Indexes
static constexpr uint8_t DS2408_OFFSET = 0x88;
static constexpr uint8_t DS2408_MEMSIZE = 8;

static constexpr uint8_t DS2408_PIO_LOGIC_REG = 0; // 0x88 - Current state
static constexpr uint8_t DS2408_PIO_OUTPUT_REG = 1; // 0x89 - Last write, latch state register
static constexpr uint8_t DS2408_PIO_ACTIVITY_REG = 2; // 0x8A - State Change Activity
Expand All @@ -26,7 +23,7 @@ class DS2408 : public OneWireItem
static constexpr uint8_t DS2408_RD_ABOVE_ALWAYS_FF_8E = 6; // 0x8E - these bytes give always 0xFF
static constexpr uint8_t DS2408_RD_ABOVE_ALWAYS_FF_8F = 7; // 0x8F - these bytes give always 0xFF

mDS2408 memory;
uint8_t memory[DS2408_MEMSIZE];

public:
static constexpr uint8_t family_code = 0x29;
Expand All @@ -36,6 +33,7 @@ class DS2408 : public OneWireItem
bool duty(OneWireHub *hub);

bool getPinState(uint8_t pinNumber);
uint8_t getPinStates(void);
void setPinState(uint8_t pinNumber, bool value);
};

Expand Down

0 comments on commit f4f9e42

Please # to comment.