Skip to content

Commit

Permalink
Merge pull request #112 from orgua/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
orgua authored Oct 8, 2022
2 parents 1cf9a46 + f79cd7a commit 834d4d1
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 54 deletions.
6 changes: 6 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,9 @@ https://www.contributor-covenant.org/translations.
- secondary / periphery
- MISO -> POCI (periphery out, controller in)
- MOSI -> PICO (periphery in, controller out)

## Example Onewire - naming scheme to use (WIP)

- primary: controller, host
- secondary: hub-device, periphery
- microcontroller running the hub: device-emulator
23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ The main goal is to use modern sensors (mainly [I2C](https://github.com/orgua/iL

[![Build Status](https://travis-ci.org/orgua/OneWireHub.svg?branch=master)](https://travis-ci.org/orgua/OneWireHub)

### Implemented Slaves:
### Implemented Slaves

- **BAE0910 (0xFC) multi purpose device (ADC, Clock, GPIO, PWM, EEPROM)**
- **DS1822 (0x22) Digital Thermometer, 12bit** -> use DS18B20 with different family code
- **DS18B20 (0x28) Digital Thermometer, 12bit** (also known as DS1820)
Expand All @@ -19,10 +20,11 @@ The main goal is to use modern sensors (mainly [I2C](https://github.com/orgua/iL
- **DS2411 (0x01) Serial Number** -> use DS2401 with same family code
- **DS2413 (0x3A) Dual channel addressable switch with input-sensing**
- **DS2423 (0x1D) 4kbit RAM with Counter**
- **DS2430A (0x14) 256bit EEPROM & 64bit OTP** (also known as DS1971)
- **DS2431 (0x2D) 1kbit protected EEPROM** (also known as DS1972 or DS28E07, same FC)
- DS2432 (0x33) 1kbit protected EEPROM (basically a ds2431 with extra sha-engine)
- **DS2433 (0x23) 4Kbit EEPROM** (also known as DS1973)
- **DS2434 (0x1B ???) BatteryManagement** used in some IBM Notebook-Batteries (similar to DS2436 (x1B), with one less cmd)
- DS2434 (0x1B ???) BatteryManagement used in some IBM Notebook-Batteries (similar to DS2436 (x1B), with one less cmd)
- **DS2438 (0x26) Smart Battery Monitor, measures temperature, 2x voltage and current, 10bit**
- **DS2450 (0x20) 4 channel A/D**
- **DS2501 (0x11, 0x91) 512bit EEPROM** -> use DS2502 with different family code
Expand All @@ -35,7 +37,8 @@ The main goal is to use modern sensors (mainly [I2C](https://github.com/orgua/iL

Note: **Bold printed devices are feature-complete and were mostly tested with a DS9490 (look into the regarding example-file for more information) and a loxone system (when supported).**

### Features:
### Features

- supports up to 32 slaves simultaneously (8 is standard setting), adjust HUB_SLAVE_LIMIT in src/OneWireHub_config.h to safe RAM & program space
- implementation-overhead for the hub is minimal and even saves resources for >1 emulated device
- hot-plug: add and remove slaves as needed during operation
Expand All @@ -61,6 +64,7 @@ Note: **Bold printed devices are feature-complete and were mostly tested with a
- provide documentation, numerous examples, easy interface for hub and sensors

### Supported and tested Hardware

- embedded real life test
- setup: run test-example, use ds9490-master, arduino 1.8.3, Windows 10 and the board-library named in the brackets
- Arduino Uno ([Arduino AVR Boards](https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr))
Expand Down Expand Up @@ -89,6 +93,7 @@ Note: **Bold printed devices are feature-complete and were mostly tested with a
- Arduino 101 ([Intel Curie Boards](https://github.com/01org/corelibs-arduino101))

### How does the Hub work

- this layered description gives you a basic idea of how the functions inside the hub work together
- this will not tell you how the [onewire protocol](https://en.wikipedia.org/wiki/1-Wire) works - read a device datasheet or the link for that
- Low Level - hardware access
Expand All @@ -108,6 +113,7 @@ Note: **Bold printed devices are feature-complete and were mostly tested with a
- for further details try reading the header-files or check the examples

### HELP - What to do if things don't work as expected?

- check if your arduino software up to date (>v1.8.0)
- update this lib to the latest release (v2.2.2)
- if you use an uncalibrated architecture the compilation-process will fail with an error, look at ./examples/debug/calibrate_by_bus_timing for an explanation
Expand All @@ -125,7 +131,8 @@ Note: **Bold printed devices are feature-complete and were mostly tested with a
- if you checked all these points feel free to open an issue at [Github](https://github.com/orgua/OneWireHub) and describe your troubleshooting process
- please provide the following basic info: which µC and master do you use, software versions, what device do you try to emulate, what works, what doesn't

### Recent development (latest at the top):
### Recent development (latest at the top)

- travis CI and unittests
- more explicit coding, a lot of bugfixes with the help of unit tests (mainly esp8266, bea910, ds18b20)
- interface of hub and slave-devices has changed, check header-file or examples for more info
Expand Down Expand Up @@ -156,7 +163,8 @@ Note: **Bold printed devices are feature-complete and were mostly tested with a
- faster CRC16 (ds2450 and ds2408 and ds2423), takes 5-7µs/byte instead of 10µs
- replace searchIDTree() algorithm, safes a lot of ram (debug-codeSize-4slaves.ino needs 3986 & 155 byte instead of 3928 & 891 byte) and allows >4 devices

### Plans for the future:
### Plans for the future

- alarm / conditional search
- switch to delay() for fast enough controllers (instead of tick-counting)
- debug tool to determine timings of exotic masters
Expand All @@ -166,7 +174,7 @@ Note: **Bold printed devices are feature-complete and were mostly tested with a
- [List of all Family-Codes](http://owfs.sourceforge.net/family.html)
- [List of Maxim Sensors](https://www.maximintegrated.com/en/app-notes/index.mvp/id/3989) (at the bottom)

### Connecting the HUB with the Network:
### Connecting the HUB with the Network

![Onewire-Schematic](http://wiki.lvl1.org/images/1/15/Onewire.gif)

Expand All @@ -180,7 +188,8 @@ Note: **Bold printed devices are feature-complete and were mostly tested with a

[read more](http://electronics.stackexchange.com/questions/193300/digital-ic-that-draws-power-from-data-pins)

### Ancestors of this Lib:
### Ancestors of this Lib

- original pieces seem to be adopted from [OneWireSlave](http://robocraft.ru/blog/arduino/302.html)
- further development was done in [OneWireSlave](https://github.com/MarkusLange/OneWireSlave) from MarkusLange and [OneWire](https://github.com/PaulStoffregen/OneWire)
- first implementation of the [OneWireHub](https://github.com/Shagrat2/OneWireHub) by Shagrat2
Expand Down
37 changes: 37 additions & 0 deletions examples/DS2430_EEPROM/DS2430_EEPROM.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Example-Code that emulates a DS2430 1024 bits EEPROM
*
* Tested with
* - DS9490R-Controller, atmega328@16MHz as device-emulator
*/

#include "OneWireHub.h"
#include "DS2430.h"

constexpr uint8_t pin_onewire { 2 };

auto hub = OneWireHub(pin_onewire);
auto ds2430 = DS2430(DS2430::family_code, 0x00, 0x00, 0x31, 0x24, 0xDA, 0x00);

void setup()
{
Serial.begin(115200);
Serial.println("OneWire-Hub DS2430");

// Setup OneWire
hub.attach(ds2430);

// Test-Cases: the following code is just to show basic functions, can be removed any time
Serial.println("Test Write Text Data to page 0");
constexpr char memory[] = "abcdefg-test-data full ASCII:-?+";
ds2430.writeMemory(reinterpret_cast<const uint8_t *>(memory),sizeof(memory),0x00);
ds2430.syncScratchpad();

Serial.println("config done");
}

void loop()
{
// following function must be called periodically
hub.poll();
}
104 changes: 67 additions & 37 deletions src/DS2430.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,65 +7,88 @@ DS2430::DS2430(uint8_t ID1, uint8_t ID2, uint8_t ID3, uint8_t ID4, uint8_t ID5,

clearMemory();
clearScratchpad();
status_register = 0xFFu;
}

void DS2430::duty(OneWireHub * const hub)
{
static uint8_t reg_TA { 0 }; // contains TA1, TA2
static uint8_t reg_ES { 0 }; // E/S register
static uint8_t reg_a { 0u };

uint8_t cmd, data;
if (hub->recv(&cmd,1)) return;
if (hub->recv(&cmd,1u)) return;
switch (cmd)
{
case 0x0F: // WRITE SCRATCHPAD COMMAND

if (hub->recv(reinterpret_cast<uint8_t *>(&reg_TA),1)) return;
reg_ES = uint8_t(reg_TA) & SCRATCHPAD_MASK;
scratchpad_start_address = reg_ES;

// receive up to 32 bytes of data
for (; reg_ES < SCRATCHPAD_SIZE; ++reg_ES)
if (hub->recv(&reg_a,1u)) return;
reg_a &= SCRATCHPAD1_MASK;
while (!hub->recv(&scratchpad[reg_a], 1u))
{
if (hub->recv(&scratchpad[reg_ES], 1))
{
if (hub->getError() == Error::AWAIT_TIMESLOT_TIMEOUT_HIGH) reg_ES |= REG_ES_PF_MASK;
break;
}
reg_a = (reg_a + 1u) & SCRATCHPAD1_MASK;
// wrap around if at x1F (writes in loop until reset issued)
}
reg_ES--;
scratchpad_size = scratchpad_start_address;
reg_ES &= SCRATCHPAD_MASK;

break;

case 0xAA: // READ SCRATCHPAD COMMAND

if (hub->send(reinterpret_cast<uint8_t *>(&reg_TA), 1)) return;

{ // send Scratchpad content
const uint8_t start = uint8_t(reg_TA) & SCRATCHPAD_MASK;
const uint8_t length = SCRATCHPAD_MASK - start;
if (hub->send(&scratchpad[start],length)) return;
if (hub->recv(&reg_a,1u)) return;
reg_a &= SCRATCHPAD1_MASK;
while (!hub->send(&scratchpad[reg_a], 1u))
{
reg_a = (reg_a + 1u) & SCRATCHPAD1_MASK;
// wrap around if at x1F (reads in loop until reset issued)
}

break; // send 1s when read is complete, is passive, so do nothing
break;

case 0x55: // COPY SCRATCHPAD COMMAND
if (hub->recv(&data)) return;
if (data != 0xA5u) break; // verification
writeMemory(scratchpad, SCRATCHPAD1_SIZE, 0u);
break;

if (hub->recv(&data)) return;
if (data != 0xA5) break;
case 0xF0: // READ MEMORY COMMAND
if (hub->recv(&reg_a,1u)) return;
reg_a &= SCRATCHPAD1_MASK;
while (!hub->send(&memory[reg_a], 1u))
{
reg_a = (reg_a + 1u) & SCRATCHPAD1_MASK;
// wrap around if at x1F (reads in loop until reset issued)
}
break;

writeMemory(scratchpad, scratchpad_size, scratchpad_start_address);
case 0x99: // WRITE APPLICATION REGISTER
if (hub->recv(&reg_a,1u)) return;
reg_a = (reg_a & SCRATCHPAD2_MASK) + SCRATCHPAD2_ADDR;
if (!(status_register & 0b11)) return;
while (!hub->recv(&scratchpad[reg_a], 1u))
{
reg_a = ((reg_a + 1u) & SCRATCHPAD2_MASK) + SCRATCHPAD2_ADDR;
// wrap around if at x07 (writes in loop until reset issued)
}
break;

case 0x66: // READ STATUS REGISTER
if (hub->recv(&reg_a)) return;
if (data != 0x00u) break; // verification
hub->send(&status_register, 1u);
break;

case 0xF0: // READ MEMORY COMMAND
if (hub->recv(reinterpret_cast<uint8_t *>(&reg_TA),1)) return;
case 0xC3: // READ APPLICATION REGISTER COMMAND
if (hub->recv(&reg_a,1u)) return;
reg_a = (reg_a & SCRATCHPAD2_MASK) + SCRATCHPAD2_ADDR;
// original IC distinguishes between MEM and scratchpad here, but content is the same
while (!hub->send(&scratchpad[reg_a], 1u))
{
reg_a = ((reg_a + 1u) & SCRATCHPAD2_MASK) + SCRATCHPAD2_ADDR;
// wrap around if at x07 (writes in loop until reset issued)
}
break;

if (reg_TA >= MEM_SIZE) return;
if (hub->send(&memory[reg_TA],MEM_SIZE - uint8_t(reg_TA))) return;
break; // send 1s when read is complete, is passive, so do nothing here
case 0x5A: // COPY & LOCK APPLICATION REGISTER
if (hub->recv(&data)) return;
if (data != 0xA5u) break; // verification
if (!(status_register & 0b11)) return;
writeMemory(&scratchpad[SCRATCHPAD2_ADDR], SCRATCHPAD2_SIZE, SCRATCHPAD2_ADDR);
status_register &= ~0b11u; // lock the OTP
break;

default:

Expand All @@ -89,7 +112,6 @@ bool DS2430::writeMemory(const uint8_t* const source, const uint8_t length, cons
if ((position + i) >= sizeof(memory)) break;
memory[position + i] = source[position + i];
}

return true;
}

Expand All @@ -100,3 +122,11 @@ bool DS2430::readMemory(uint8_t* const destination, const uint16_t length, const
memcpy(destination,&memory[position],_length);
return (_length==length);
}

bool DS2430::syncScratchpad()
{
uint8_t length = (MEM_SIZE > SCRATCHPAD_SIZE) ? SCRATCHPAD_SIZE : MEM_SIZE;
memcpy(scratchpad,memory,length);
return true;
}

23 changes: 15 additions & 8 deletions src/DS2430.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// 1Kb 1-Wire EEPROM
// usercontribution, based on ds2431 (but without some features)
// 256bit 1-Wire EEPROM & 64bit OTP
// works

#ifndef ONEWIRE_DS2430_H
#define ONEWIRE_DS2430_H
Expand All @@ -10,19 +10,22 @@ class DS2430 : public OneWireItem
{
private:

static constexpr uint8_t MEM_SIZE { 32 };
static constexpr uint8_t MEM_SIZE { 32 + 8 };

static constexpr uint8_t SCRATCHPAD_SIZE { 32 };
static constexpr uint8_t SCRATCHPAD_MASK { 0b00011111 };
static constexpr uint8_t SCRATCHPAD_SIZE { 32 + 8 };

static constexpr uint8_t REG_ES_PF_MASK { 0b00100000 }; // partial byte flag
static constexpr uint8_t SCRATCHPAD1_MASK { 0b00011111 };
static constexpr uint8_t SCRATCHPAD1_SIZE { 32 };

static constexpr uint8_t SCRATCHPAD2_ADDR { 32 };
static constexpr uint8_t SCRATCHPAD2_SIZE { 8 };
static constexpr uint8_t SCRATCHPAD2_MASK { 0b00000111 };

uint8_t memory[MEM_SIZE];

uint8_t scratchpad[SCRATCHPAD_SIZE];

uint8_t scratchpad_start_address;
uint8_t scratchpad_size;
uint8_t status_register;

void clearScratchpad(void);

Expand All @@ -38,6 +41,10 @@ class DS2430 : public OneWireItem

bool writeMemory(const uint8_t* source, uint8_t length, uint8_t position = 0);
bool readMemory(uint8_t* destination, uint16_t length, uint16_t position = 0) const;

bool syncScratchpad(void);
// this FN copies content of memory to scratchpad
// needed because programming interface only allows access to memory
};

#endif
4 changes: 2 additions & 2 deletions src/OneWireHub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,13 @@ bool OneWireHub::poll(void)
// this additional check prevents an infinite loop when calling this FN without sensors attached
if (slave_count == 0) return true;

//Once reset is done, go to next step
// Once reset is done, go to next step
if (checkReset()) return false;

// Reset is complete, tell the master we are present
if (showPresence()) return false;

//Now that the master should know we are here, we will get a command from the master
// Now that the master should know we are here, we will get a command from the master
if (recvAndProcessCmd()) return false;

// on total success we want to start again, because the next reset could only be ~125 us away
Expand Down

0 comments on commit 834d4d1

Please sign in to comment.