From 0df8717b3c2fe2a03397f4660ea9e1a8d20b2500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingmar=20In=CA=92o=20Splitt?= Date: Sat, 8 Oct 2022 23:48:22 +0200 Subject: [PATCH 1/3] Update OneWireHub.cpp --- src/OneWireHub.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OneWireHub.cpp b/src/OneWireHub.cpp index 999b5c2..761ca08 100644 --- a/src/OneWireHub.cpp +++ b/src/OneWireHub.cpp @@ -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 From a199ee65a12204f04ff64b5fc51009e6fd00dc7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingmar=20In=CA=92o=20Splitt?= Date: Sun, 9 Oct 2022 01:38:35 +0200 Subject: [PATCH 2/3] improve documentation --- CODE_OF_CONDUCT.md | 6 ++++++ README.md | 23 ++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 6767741..7738134 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -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 diff --git a/README.md b/README.md index 385c1e5..56c50dd 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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 @@ -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 @@ -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)) @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 From f79cd7aadd9d9bb0b56df0d591abe9238fdeb02a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingmar=20In=CA=92o=20Splitt?= Date: Sun, 9 Oct 2022 01:40:51 +0200 Subject: [PATCH 3/3] DS2430 - fully implement datasheet --- examples/DS2430_EEPROM/DS2430_EEPROM.ino | 37 ++++++++ src/DS2430.cpp | 104 +++++++++++++++-------- src/DS2430.h | 23 +++-- 3 files changed, 119 insertions(+), 45 deletions(-) create mode 100644 examples/DS2430_EEPROM/DS2430_EEPROM.ino diff --git a/examples/DS2430_EEPROM/DS2430_EEPROM.ino b/examples/DS2430_EEPROM/DS2430_EEPROM.ino new file mode 100644 index 0000000..b477ccc --- /dev/null +++ b/examples/DS2430_EEPROM/DS2430_EEPROM.ino @@ -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(memory),sizeof(memory),0x00); + ds2430.syncScratchpad(); + + Serial.println("config done"); +} + +void loop() +{ + // following function must be called periodically + hub.poll(); +} \ No newline at end of file diff --git a/src/DS2430.cpp b/src/DS2430.cpp index 60ecad7..0a24beb 100644 --- a/src/DS2430.cpp +++ b/src/DS2430.cpp @@ -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(®_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(®_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(®_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(®_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(®_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(®_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(®_a)) return; + if (data != 0x00u) break; // verification + hub->send(&status_register, 1u); break; - case 0xF0: // READ MEMORY COMMAND - if (hub->recv(reinterpret_cast(®_TA),1)) return; + case 0xC3: // READ APPLICATION REGISTER COMMAND + if (hub->recv(®_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: @@ -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; } @@ -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; +} + diff --git a/src/DS2430.h b/src/DS2430.h index 51b09e1..4317dbf 100644 --- a/src/DS2430.h +++ b/src/DS2430.h @@ -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 @@ -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); @@ -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