diff --git a/CMakeLists.txt b/CMakeLists.txt index 25846d4..7e60036 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ project(OneWireHub) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -add_subdirectory(src) -include_directories(./src) +#add_subdirectory(src) +#include_directories(./src) set(SOURCE_FILES main.cpp diff --git a/main.cpp b/main.cpp index 527cf57..61ed416 100644 --- a/main.cpp +++ b/main.cpp @@ -5,21 +5,23 @@ using namespace std; -#include "OneWireHub.h" +#include "src/OneWireHub.h" // include all libs to find errors -#include "DS2401.h" // Serial Number -#include "DS18B20.h" // Digital Thermometer -#include "DS2405.h" // Single adress switch -#include "DS2408.h" // 8-Channel Addressable Switch -#include "DS2413.h" // Dual channel addressable switch -#include "DS2423.h" // 4kb 1-Wire RAM with Counter -#include "DS2431.h" // 1kb 1-Wire EEPROM -#include "DS2433.h" // 4Kb 1-Wire EEPROM -#include "DS2438.h" // Smart Battery Monitor -#include "DS2450.h" // 4 channel A/D -#include "DS2502.h" // 1kb EEPROM -#include "DS2890.h" // Single channel digital potentiometer +#include "src/BAE910.h" +#include "src/DS18B20.h" // Digital Thermometer +#include "src/DS2401.h" // Serial Number +#include "src/DS2405.h" // Single adress switch +#include "src/DS2408.h" // 8-Channel Addressable Switch +#include "src/DS2413.h" // Dual channel addressable switch +#include "src/DS2423.h" // 4kb 1-Wire RAM with Counter +#include "src/DS2431.h" // 1kb 1-Wire EEPROM +#include "src/DS2433.h" // 4Kb 1-Wire EEPROM +#include "src/DS2438.h" // Smart Battery Monitor +#include "src/DS2450.h" // 4 channel A/D +#include "src/DS2502.h" // 1kb EEPROM +#include "src/DS2506.h" // 64kb EEPROM +#include "src/DS2890.h" // Single channel digital potentiometer @@ -27,47 +29,78 @@ using namespace std; const uint8_t OneWire_PIN = 8; -auto hub = OneWireHub(OneWire_PIN); +auto hubA = OneWireHub(OneWire_PIN); +auto hubB = OneWireHub(OneWire_PIN); +auto hubC = OneWireHub(OneWire_PIN); + auto ds1822 = DS18B20(0x22, 0x0D, 0x01, 0x08, 0x02, 0x00, 0x00); auto ds18B20 = DS18B20(0x28, 0x0D, 0x01, 0x08, 0x0B, 0x02, 0x00); // Work - Digital Thermometer auto ds18S20 = DS18B20(0x10, 0x0D, 0x01, 0x08, 0x0F, 0x02, 0x00); auto ds2401a = DS2401( 0x01, 0x00, 0x0D, 0x24, 0x01, 0x00, 0x0A ); // Work - Serial Number auto ds2401b = DS2401( 0x01, 0x00, 0x0D, 0x24, 0x01, 0x00, 0x0B ); // Work - Serial Number -// auto ds2405 = DS2405( 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); // - Single address switch -// auto ds2408 = DS2408( 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); // - 8-Channel Addressable Switch +auto ds2405 = DS2405( 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); // - Single address switch +auto ds2408 = DS2408( 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); // - 8-Channel Addressable Switch auto ds2413 = DS2413( 0x3A, 0x0D, 0x02, 0x04, 0x01, 0x03, 0x00 ); // Work - Dual channel addressable switch -// auto ds2423 = DS2423( 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); // - 4kb 1-Wire RAM with Counter + +auto ds2423 = DS2423( 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); // - 4kb 1-Wire RAM with Counter auto ds2431 = DS2431( 0x2D, 0xE8, 0x9F, 0x90, 0x0E, 0x00, 0x00 ); // Work - 1kb 1-Wire EEPROM -// auto ds2433 = DS2433( 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); // - 4Kb 1-Wire EEPROM +auto ds2433 = DS2433( 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); // - 4Kb 1-Wire EEPROM auto ds2438 = DS2438( 0x26, 0x0D, 0x02, 0x04, 0x03, 0x08, 0x00 ); // - Smart Battery Monitor -auto ds2450 = DS2450( 0x20, 0x0D, 0x0A, 0x02, 0x04, 0x05, 0x00 ); // - 4 channel A/D +auto ds2450 = DS2450( DS2450::family_code, 0x00, 0x00, 0x50, 0x24, 0xDA, 0x00 ); // - 4 channel A/D +auto ds2502 = DS2502( DS2502::family_code, 0x00, 0xA0, 0x02, 0x25, 0xDA, 0x00 ); +auto ds2501a = DS2502( 0x91, 0x00, 0xA0, 0x01, 0x25, 0xDA, 0x00 ); +auto ds2501b = DS2502( 0x11, 0x00, 0xB0, 0x02, 0x25, 0xDA, 0x00 ); + +auto ds2503 = DS2506( 0x13, 0x00, 0x00, 0x03, 0x25, 0xDA, 0x00 ); +auto ds2505 = DS2506( 0x0B, 0x00, 0x00, 0x05, 0x25, 0xDA, 0x00 ); +auto ds2506 = DS2506( 0x0F, 0x00, 0x00, 0x06, 0x25, 0xDA, 0x00 ); auto ds2890A = DS2890( 0x2C, 0x0D, 0x02, 0x08, 0x09, 0x00, 0x0A ); // Work - Single channel digital potentiometer auto ds2890B = DS2890( 0x2C, 0x0D, 0x02, 0x08, 0x09, 0x00, 0x0B ); auto ds2890C = DS2890( 0x2C, 0x0D, 0x02, 0x08, 0x09, 0x00, 0x0C ); +auto bae910 = BAE910(BAE910::family_code, 0x00, 0x00, 0x10, 0xE9, 0xBA, 0x00); int main() { cout << "Hello, World!" << endl; // Setup OneWire - ds1822.setTemp(static_cast(21)); - ds18S20.setTemp(static_cast(10)); - hub.attach(ds1822); - hub.attach(ds18B20); - hub.attach(ds18S20); - hub.attach(ds2401a); - hub.attach(ds2401b); - hub.attach(ds2413); - hub.attach(ds2431); - hub.attach(ds2438); - //hub.attach(ds2450); - hub.attach(ds2890A); - hub.attach(ds2890B); - hub.attach(ds2890C); - - hub.poll(); - - if (hub.getError()) hub.printError(); + hubA.attach(ds1822); + hubA.attach(ds18B20); + hubA.attach(ds18S20); + hubA.attach(ds2401a); + hubA.attach(ds2401b); + hubA.attach(ds2405); + hubA.attach(ds2408); + hubA.attach(ds2413); + + hubB.attach(ds2423); + hubB.attach(ds2431); + hubB.attach(ds2433); + hubB.attach(ds2438); + hubB.attach(ds2450); + hubB.attach(ds2502); + hubB.attach(ds2501a); + hubB.attach(ds2501b); + + hubC.attach(ds2503); + hubC.attach(ds2505); + hubC.attach(ds2506); + hubC.attach(ds2890A); + hubC.attach(ds2890B); + hubC.attach(ds2890C); + hubC.attach(bae910); + + + ds1822.setTemperature(static_cast(21)); + ds18S20.setTemperature(static_cast(10)); + + hubA.poll(); + hubB.poll(); + hubC.poll(); + + if (hubA.hasError()) hubA.printError(); + if (hubB.hasError()) hubB.printError(); + if (hubC.hasError()) hubC.printError(); return 0; }; \ No newline at end of file diff --git a/src/BAE910.h b/src/BAE910.h index 2ed35b0..588b3ed 100644 --- a/src/BAE910.h +++ b/src/BAE910.h @@ -1,6 +1,6 @@ // Multifunction 1-wire slave device @@@ // works, basic functionality -// native features: unknown +// native bus-features: unknown #ifndef ONEWIRE_BAE910_H #define ONEWIRE_BAE910_H diff --git a/src/DS18B20.h b/src/DS18B20.h index f1c2879..888cc86 100644 --- a/src/DS18B20.h +++ b/src/DS18B20.h @@ -3,7 +3,7 @@ // DS18B20: 9-12bit, -55 - +85 degC // DS18S20: 9 bit, -55 - +85 degC // DS1822: 9-12bit, -55 - +125 degC -// native features: alarm search +// native bus-features: alarm search #ifndef ONEWIRE_DS18B20_H #define ONEWIRE_DS18B20_H diff --git a/src/DS2401.h b/src/DS2401.h index 475948d..70f843a 100644 --- a/src/DS2401.h +++ b/src/DS2401.h @@ -1,6 +1,6 @@ // Serial Number // Works -// native features: none +// native bus-features: none #ifndef ONEWIRE_DS2401_H #define ONEWIRE_DS2401_H diff --git a/src/DS2405.h b/src/DS2405.h index 4687d87..4a4a458 100644 --- a/src/DS2405.h +++ b/src/DS2405.h @@ -1,7 +1,7 @@ // Single address switch @@@ // works, but reading back the value is not supported, because alarm search is not implemented yet // this IC is not using standard protocol - it sends data after searchRom and alarmSearch -// native features: alarm search +// native bus-features: alarm search #ifndef ONEWIRE_DS2405_H #define ONEWIRE_DS2405_H diff --git a/src/DS2408.h b/src/DS2408.h index 7055b62..d22da92 100644 --- a/src/DS2408.h +++ b/src/DS2408.h @@ -1,6 +1,6 @@ // 8-Channel Addressable Switch @@@ // works, but no alarm search and higher logic / output / control register-action -// native features: Overdrive capable, alarm search +// native bus-features: Overdrive capable, alarm search #ifndef ONEWIRE_DS2408_H #define ONEWIRE_DS2408_H diff --git a/src/DS2413.h b/src/DS2413.h index 17d059d..e7e2a85 100644 --- a/src/DS2413.h +++ b/src/DS2413.h @@ -1,6 +1,6 @@ // Dual channel addressable switch // Works, master can latch the pin and pull it thereby down -// native features: Overdrive capable +// native bus-features: Overdrive capable #ifndef ONEWIRE_DS2413_H #define ONEWIRE_DS2413_H diff --git a/src/DS2423.h b/src/DS2423.h index 34610ed..98f336b 100644 --- a/src/DS2423.h +++ b/src/DS2423.h @@ -1,6 +1,6 @@ // 4kb 1-Wire RAM with Counter // works -// native features: Overdrive capable +// native bus-features: Overdrive capable #ifndef ONEWIRE_DS2423_H #define ONEWIRE_DS2423_H diff --git a/src/DS2431.h b/src/DS2431.h index 4e56d31..9ea3390 100644 --- a/src/DS2431.h +++ b/src/DS2431.h @@ -1,7 +1,7 @@ // 1Kb 1-Wire EEPROM // works, // note: datasheet is fuzzy, but device is similar to ds2433 -// native features: Overdrive capable +// native bus-features: Overdrive capable #ifndef ONEWIRE_DS2431_H #define ONEWIRE_DS2431_H diff --git a/src/DS2433.h b/src/DS2433.h index 0199106..3940c7f 100644 --- a/src/DS2433.h +++ b/src/DS2433.h @@ -1,6 +1,6 @@ // 4Kb 1-Wire EEPROM // works -// native features: Overdrive capable +// native bus-features: Overdrive capable #ifndef ONEWIRE_DS2433_H #define ONEWIRE_DS2433_H diff --git a/src/DS2438.h b/src/DS2438.h index f818f71..191e701 100644 --- a/src/DS2438.h +++ b/src/DS2438.h @@ -1,6 +1,6 @@ // Smart Battery Monitor // works, but without real EPROM copy/recall functionallity, Timer, -// native features: none +// native bus-features: none #ifndef ONEWIRE_DS2438_H #define ONEWIRE_DS2438_H diff --git a/src/DS2450.cpp b/src/DS2450.cpp index 0ef5100..45d705a 100644 --- a/src/DS2450.cpp +++ b/src/DS2450.cpp @@ -3,49 +3,46 @@ DS2450::DS2450(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) { - static_assert((PAGE_COUNT*PAGE_SIZE) < 256, "Implementation does not cover the whole address-space"); + static_assert(sizeof(memory) < 256, "Implementation does not cover the whole address-space"); clearMemory(); }; void DS2450::duty(OneWireHub * const hub) { uint16_t reg_TA, crc = 0; // target address - uint8_t data, cmd, length; + uint8_t cmd; if (hub->recv(&cmd,1,crc)) return; + if (hub->recv(reinterpret_cast(®_TA),2,crc)) return; switch (cmd) { case 0xAA: // READ MEMORY - if (hub->recv(reinterpret_cast(®_TA),2,crc)) return; - while(reg_TA < MEM_SIZE) { - length = PAGE_SIZE - (reinterpret_cast(®_TA)[0] & PAGE_MASK); + const uint8_t length = PAGE_SIZE - (uint8_t(reg_TA) & PAGE_MASK); if (hub->send(&memory[reg_TA], length, crc)) return; crc = ~crc; // normally crc16 is sent ~inverted if (hub->send(reinterpret_cast(&crc), 2)) return; // prepare next page-readout - reg_TA = (reg_TA & ~PAGE_MASK) + PAGE_SIZE; + reg_TA += length; crc = 0; }; break; case 0x55: // write memory (only page 1&2 allowed) - if (hub->recv(reinterpret_cast(®_TA),2,crc)) break; - if (reg_TA < PAGE_SIZE) break; // page 0 is off limits - while(reg_TA < MEM_SIZE) { + uint8_t data; if (hub->recv(&data, 1, crc)) break; crc = ~crc; // normally crc16 is sent ~inverted if (hub->send(reinterpret_cast(&crc), 2)) break; if (hub->send(&data, 1)) break; - memory[reg_TA] = data; // write data + if (reg_TA >= PAGE_SIZE) memory[reg_TA] = data; // write data, page 0 is off limits crc = ++reg_TA; // prepare next address-readout: load new TA into crc }; @@ -53,14 +50,10 @@ void DS2450::duty(OneWireHub * const hub) break; case 0x3C: // convert, starts adc - if (hub->recv(reinterpret_cast(&cmd),1,crc)) return; // input select mask, not important - if (hub->recv(reinterpret_cast(&data),1,crc)) return; // read out control byte - + // received reg_TA contains: input select mask (not important) and read out control byte // in reality master can now set registers of potentiometers to 0x0000 or 0xFFFF to track changes - crc = ~crc; // normally crc16 is sent ~inverted if (hub->send(reinterpret_cast(&crc),2)) return; - // takes max 5.3 ms for 16 bit ( 4 CH * 16 bit * 80 us + 160 us per request = 5.3 ms ) if (hub->sendBit(false)) return; // still converting.... break; // finished conversion: send 1, is passive ... @@ -78,10 +71,10 @@ void DS2450::clearMemory(void) for (uint8_t adc = 0; adc < POTI_COUNT; ++adc) { // CONTROL/STATUS DATA - memory[(1*PAGE_SIZE) + (adc*2) + 0] = 0x08; - memory[(1*PAGE_SIZE) + (adc*2) + 1] = 0x8C; + memory[(1*PAGE_SIZE) + (adc*2) + 0] = 0x00; // 16bit + memory[(1*PAGE_SIZE) + (adc*2) + 1] = 0x8C; // enable POR, Alarm enable high / low // alarm settings - memory[(2*PAGE_SIZE) + (adc*2) + 1] = 0xFF; + memory[(2*PAGE_SIZE) + (adc*2) + 1] = 0xFF; // high threshold max }; }; @@ -121,7 +114,7 @@ bool DS2450::setPotentiometer(const uint8_t channel, const uint16_t value) memory[(2*channel) ] = LByte; memory[(2*channel)+1] = HByte; correctMemory(); - return true; + return true; // TODO: check with alarm settings p2, and raise alarm, also check when data is written }; uint16_t DS2450::getPotentiometer(const uint8_t channel) const diff --git a/src/DS2450.h b/src/DS2450.h index 352c02d..60cebd6 100644 --- a/src/DS2450.h +++ b/src/DS2450.h @@ -1,6 +1,6 @@ // 4 channel A/D -// works, but without -// native features: Overdrive capable, alarm search +// works, but without alarm features and other controllable functions beside ADC-Reading +// native bus-features: Overdrive capable, alarm search #ifndef ONEWIRE_DS2450_H #define ONEWIRE_DS2450_H @@ -19,12 +19,11 @@ class DS2450 : public OneWireItem static constexpr uint8_t MEM_SIZE = PAGE_COUNT*PAGE_SIZE; uint8_t memory[MEM_SIZE]; - // Page1 : conversion results: 16bit for Channel A, B, C & D, power on default: 0x00 + // Page1 : conversion results: 16 bit for Channel A, B, C & D, power on default: 0x00 // Page2 : control / status: 16 bit per channel // Page3 : alarm settings: 16 bit per channel // Page3 : factory calibration - void correctMemory(void); public: diff --git a/src/DS2502.h b/src/DS2502.h index 8d484e1..e93a5da 100644 --- a/src/DS2502.h +++ b/src/DS2502.h @@ -1,8 +1,6 @@ // 1Kbit 1-Wire EEPROM, Add Only Memory // works, writing could not be tested (DS9490 does not support hi-voltage mode and complains) -// Copyright by Kondi (initial version), https://forum.pjrc.com/threads/33640-Teensy-2-OneWire-Slave -// DS2501: 0x11, autoset to 512bits -// dell powersupply: 0x28 +// native bus-features: none #ifndef ONEWIRE_DS2502_H #define ONEWIRE_DS2502_H diff --git a/src/DS2506.h b/src/DS2506.h index 0dff42c..9d0d62f 100644 --- a/src/DS2506.h +++ b/src/DS2506.h @@ -1,4 +1,7 @@ // 64kbit EEPROM, Add Only Memory +// works, writing could not be tested (DS9490 does not support hi-voltage mode and complains) +// note: not available memory will be redirected or faked +// native bus-features: Overdrive capable #ifndef ONEWIRE_DS2506_H #define ONEWIRE_DS2506_H diff --git a/src/DS2890.cpp b/src/DS2890.cpp index faf24c4..cf368d4 100644 --- a/src/DS2890.cpp +++ b/src/DS2890.cpp @@ -3,7 +3,7 @@ DS2890::DS2890(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) { register_feat = REG_MASK_POTI_CHAR | REG_MASK_WIPER_SET | REG_MASK_POTI_NUMB | REG_MASK_WIPER_POS | REG_MASK_POTI_RESI; - memset(register_poti, 0, 4); + memset(register_poti, uint8_t(0), 4); register_ctrl = 0b00001100; }; @@ -31,12 +31,15 @@ void DS2890::duty(OneWireHub * const hub) if (hub->send(&data)) break; if (hub->recv(&cmd)) break; - if (data&0x01) data &= ~0x04; - else data |= 0x04; - if (data&0x02) data &= ~0x08; - else data |= 0x08; + if (cmd == RELEASE_CODE) + { + if (data&0x01) data &= ~0x04; + else data |= 0x04; + if (data&0x02) data &= ~0x08; + else data |= 0x08; - if (cmd == RELEASE_CODE) register_ctrl = data; + register_ctrl = data; + }; break; // respond with 1s ... passive case 0xAA: // READ CONTROL REGISTER diff --git a/src/DS2890.h b/src/DS2890.h index 955a581..1b1d8d6 100644 --- a/src/DS2890.h +++ b/src/DS2890.h @@ -1,5 +1,6 @@ // Single channel digital potentiometer -// Works - 100% +// Works, is prepared for four channels +// native bus-features: Overdrive capable #ifndef ONEWIRE_DS2890_H #define ONEWIRE_DS2890_H diff --git a/src/OneWireHub_config.h b/src/OneWireHub_config.h index 5c9e829..d5c02c1 100644 --- a/src/OneWireHub_config.h +++ b/src/OneWireHub_config.h @@ -10,7 +10,7 @@ #define OVERDRIVE_ENABLE 0 // support overdrive for the slaves constexpr bool USE_SERIAL_DEBUG { 0 }; // give debug messages when printError() is called (be aware! it may produce heisenbugs, timing is critical) -constexpr bool USE_GPIO_DEBUG { 0 }; // is a better alternative to serial debug (see readme.md for info) +constexpr bool USE_GPIO_DEBUG { 1 }; // is a better alternative to serial debug (see readme.md for info) constexpr uint8_t GPIO_DEBUG_PIN { 7 }; // digital pin constexpr uint32_t REPETITIONS { 5000 }; // for measuring the loop-delay --> 10000L takes ~110ms on atmega328p@16Mhz diff --git a/src/platform.h b/src/platform.h index d7c289a..e9c1d3e 100644 --- a/src/platform.h +++ b/src/platform.h @@ -197,7 +197,7 @@ void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) #define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT) #warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture." using io_reg_t = uint32_t; // define special datatype for register-access -constexpr uint8_t VALUE_IPL {0}; // instructions per loop, uncalibrated so far - see ./examples/debug/calibrate_by_bus_timing for an explanation +constexpr uint8_t VALUE_IPL {1}; // instructions per loop, uncalibrated so far - see ./examples/debug/calibrate_by_bus_timing for an explanation /////////////////////////////////////////// EXTRA PART ///////////////////////////////////////// // this part is loaded if no proper arduino-environment is found (good for external testing) @@ -224,7 +224,7 @@ uint8_t digitalPinToPort(uint8_t x) {return 0;}; uint8_t *portInputRegister(uint8_t x) {return 0;}; uint8_t digitalPinToBitMask(uint8_t x) {return 0;}; -uint32_t microsecondsToClockCycles(uint32_t x) {return 0;}; +constexpr uint32_t microsecondsToClockCycles(uint32_t x) {return 100;}; // mockup, emulate 100 MHz CPU void delayMicroseconds(...) {}; uint32_t micros(void) {return 0;}; // takes about 3 µs to process @ 16 MHz @@ -268,7 +268,7 @@ void memset(T1 address[], T1 initValue, T2 size) }; template -void memcpy(T1 destination[], T1 source, T2 bytes) +void memcpy(T1 destination[], const T1 source[], T2 bytes) { for (T2 counter = 0; counter < bytes; ++counter) {