mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 19:59:50 +03:00
462 lines
11 KiB
C++
462 lines
11 KiB
C++
/* Copyright © 2017-2018 Andrey Klimov. (anklimov@gmail.com) All rights reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
Homepage: http://lazyhome.ru
|
|
GIT: https://github.com/anklimov/lighthub
|
|
|
|
*/
|
|
|
|
#include "owSwitch.h"
|
|
#include "owTerm.h"
|
|
#include <Arduino.h>
|
|
#include "utils.h"
|
|
|
|
#ifndef debugSerialPort
|
|
#define debugSerialPort Serial
|
|
#endif
|
|
|
|
int owRead2408(uint8_t* addr) {
|
|
uint8_t buf[13];
|
|
// PrintBytes(buf, 13, true);
|
|
if (!net) return -1;
|
|
net->reset();
|
|
net->select(addr);
|
|
|
|
// uint8_t buf[13]; // Put everything in the buffer so we can compute CRC easily.
|
|
buf[0] = 0xF0; // Read PIO Registers
|
|
buf[1] = 0x88; // LSB address
|
|
buf[2] = 0x00; // MSB address
|
|
net->write_bytes(buf, 3,1);
|
|
net->read_bytes(buf+3, 10); // 3 cmd bytes, 6 data bytes, 2 0xFF, 2 CRC16
|
|
net->reset();
|
|
|
|
if (!OneWire::check_crc16(buf, 11, &buf[11])) {
|
|
debugSerialPort.print(F("CRC failure in DS2408 at "));
|
|
PrintBytes(addr, 8, true);
|
|
PrintBytes(buf+3,10);
|
|
return -1;
|
|
}
|
|
return (buf[3]);
|
|
}
|
|
|
|
|
|
/*
|
|
int read1W(int i)
|
|
{
|
|
|
|
debugSerialPort.print("1W requested: ");
|
|
debugSerialPort.println (i);
|
|
|
|
int t=-1;
|
|
switch (term[i][0]){
|
|
case 0x29: // DS2408
|
|
t=owRead2408(term[i]);
|
|
break;
|
|
case 0x28: // Thermomerer
|
|
t=sensors.getTempC(term[i]);
|
|
}
|
|
return t;
|
|
}
|
|
*/
|
|
|
|
|
|
int ow2408out(DeviceAddress addr,uint8_t cur)
|
|
{
|
|
if (!net) return -1;
|
|
uint8_t buf[5];
|
|
net->reset();
|
|
net->select(addr);
|
|
buf[0] = 0x5A; // Write PIO Registers
|
|
buf[1]=cur;
|
|
buf[2] = ~buf[1];
|
|
net->write_bytes(buf, 3);
|
|
net->read_bytes(buf+3, 2);
|
|
//net.reset();
|
|
PrintBytes(buf, 5);
|
|
debugSerialPort.print(F(" Out: "));debugSerialPort.print(buf[1],BIN);
|
|
debugSerialPort.print(F(" In: "));debugSerialPort.println(buf[4],BIN);
|
|
if (buf[3] != 0xAA) {
|
|
debugSerialPort.print(F("Write failure in DS2408 at "));
|
|
PrintBytes(addr, 8, true);
|
|
return -2;
|
|
}
|
|
return buf[4];
|
|
}
|
|
int cntrl2408(uint8_t* addr, int subchan, int val) {
|
|
if (!net) return -1;
|
|
|
|
uint8_t buf;
|
|
int mask,devnum;
|
|
|
|
if ((devnum=owFind(addr))<0) return -1;
|
|
buf=regs[devnum];
|
|
debugSerialPort.print(F("Current: "));debugSerialPort.println(buf,BIN);
|
|
mask=0;
|
|
int r,f;
|
|
switch (subchan) {
|
|
case 0:
|
|
if ((buf & SW_STAT0) != ((val)?SW_STAT0:0))
|
|
{
|
|
if (wstat[devnum] & (SW_PULSE0|SW_PULSE_P0))
|
|
{
|
|
wstat[devnum]|=SW_CHANGED_P0;
|
|
debugSerialPort.println(F("Rollback 0"));
|
|
}
|
|
else {
|
|
wstat[devnum]|=SW_PULSE0;
|
|
regs[devnum] = (ow2408out(addr,(buf | SW_MASK) & ~SW_OUT0) & SW_INMASK) ^ SW_STAT0; ///?
|
|
|
|
}
|
|
}
|
|
return 0;
|
|
case 1:
|
|
if ((buf & SW_STAT1) != ((val)?SW_STAT1:0))
|
|
{
|
|
if (wstat[devnum] & (SW_PULSE1|SW_PULSE_P1))
|
|
{
|
|
wstat[devnum]|=SW_CHANGED_P1;
|
|
debugSerialPort.println(F("Rollback 1"));
|
|
}
|
|
else {
|
|
wstat[devnum]|=SW_PULSE1;
|
|
regs[devnum] =(ow2408out(addr,(buf | SW_MASK) & ~SW_OUT1) & SW_INMASK) ^ SW_STAT1; /// -?
|
|
|
|
}
|
|
}
|
|
return 0;
|
|
/* Assume AUX 0&1 it is INPUTS - no write
|
|
case 2:
|
|
mask=SW_AUX0;
|
|
break;
|
|
case 3:
|
|
mask=SW_AUX1; */
|
|
}
|
|
|
|
/* Assume AUX 0&1 it is INPUTS - no write
|
|
switch (val) {
|
|
case 0: buf=(buf | SW_MASK | SW_OUT0 | SW_OUT1) | mask;
|
|
break;
|
|
default: buf= (buf | SW_MASK | SW_OUT0 | SW_OUT1) & ~mask;
|
|
}
|
|
|
|
|
|
regs[devnum] = ow2408out(addr,buf); */
|
|
return 0;
|
|
}
|
|
|
|
|
|
int cntrl2890(uint8_t* addr, int val) {
|
|
uint8_t buf[13];
|
|
if (!net) return -1;
|
|
// case 0x2C: //Dimmer
|
|
debugSerialPort.print(F("Update dimmer "));PrintBytes(addr, 8, true);debugSerialPort.print(F(" = "));
|
|
debugSerialPort.println(val);
|
|
|
|
net->reset();
|
|
net->select(addr);
|
|
|
|
buf[0] = 0x55;
|
|
buf[1] = 0x4c;
|
|
net->write_bytes(buf, 2);
|
|
net->read_bytes(buf+2, 1); // check if buf[2] == val = ok
|
|
buf[3]=0x96;
|
|
net->write_bytes(buf+3, 1);
|
|
net->read_bytes(buf+4, 1); // 0 = updated ok
|
|
PrintBytes(buf, 5, true);
|
|
|
|
net->select(addr);
|
|
|
|
|
|
if (val==-1)
|
|
{
|
|
buf[0] = 0xF0;
|
|
net->write_bytes(buf, 1);
|
|
net->read_bytes(buf+1, 2); // check if buf[2] == val = ok
|
|
net->reset();
|
|
return buf[2];
|
|
}
|
|
else
|
|
{
|
|
buf[0] = 0x0F;
|
|
buf[1] = val;
|
|
net->write_bytes(buf, 2);
|
|
net->read_bytes(buf+2, 1); // check if buf[2] == val = ok
|
|
buf[3]=0x96;
|
|
net->write_bytes(buf+3, 1);
|
|
net->read_bytes(buf+4, 1); // 0 = updated ok
|
|
net->reset();
|
|
PrintBytes(buf, 5, true);
|
|
return buf[2];
|
|
}
|
|
|
|
|
|
}
|
|
|
|
#define DS2413_FAMILY_ID 0x3A
|
|
#define DS2413_ACCESS_READ 0xF5
|
|
#define DS2413_ACCESS_WRITE 0x5A
|
|
#define DS2413_ACK_SUCCESS 0xAA
|
|
#define DS2413_ACK_ERROR 0xFF
|
|
|
|
#define DS2413_IN_PinA 1
|
|
#define DS2413_IN_LatchA 2
|
|
#define DS2413_IN_PinB 4
|
|
#define DS2413_IN_LatchB 8
|
|
|
|
#define DS2413_OUT_PinA 1
|
|
#define DS2413_OUT_PinB 2
|
|
|
|
|
|
/*
|
|
byte read(void)
|
|
{
|
|
bool ok = false;
|
|
uint8_t results;
|
|
|
|
oneWire.reset();
|
|
oneWire.select(address);
|
|
oneWire.write(DS2413_ACCESS_READ);
|
|
|
|
results = oneWire.read(); / Get the register results /
|
|
ok = (!results & 0x0F) == (results >> 4); / Compare nibbles /
|
|
results &= 0x0F; / Clear inverted values /
|
|
|
|
oneWire.reset();
|
|
|
|
// return ok ? results : -1;
|
|
return results;
|
|
}
|
|
|
|
bool write(uint8_t state)
|
|
{
|
|
uint8_t ack = 0;
|
|
|
|
/ Top six bits must '1' /
|
|
state |= 0xFC;
|
|
|
|
oneWire.reset();
|
|
oneWire.select(address);
|
|
oneWire.write(DS2413_ACCESS_WRITE);
|
|
oneWire.write(state);
|
|
oneWire.write(~state); / Invert data and resend /
|
|
ack = oneWire.read(); / 0xAA=success, 0xFF=failure /
|
|
if (ack == DS2413_ACK_SUCCESS)
|
|
{
|
|
oneWire.read(); / Read the status byte /
|
|
}
|
|
oneWire.reset();
|
|
|
|
return (ack == DS2413_ACK_SUCCESS ? true : false);
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
int cntrl2413(uint8_t* addr, int subchan, int val) {
|
|
|
|
|
|
bool ok = false;
|
|
uint8_t results;
|
|
uint8_t cmd;
|
|
uint8_t set=0;
|
|
uint8_t count =10;
|
|
if (!net) return -1;
|
|
// case 0x85: //Switch
|
|
debugSerialPort.print(F("Update switch "));PrintBytes(addr, 8, false); debugSerialPort.print(F("/"));debugSerialPort.print(subchan);debugSerialPort.print(F(" = "));debugSerialPort.println(val);
|
|
while (count--)
|
|
{
|
|
net->reset();
|
|
net->select(addr);
|
|
net->setStrongPullup();
|
|
|
|
cmd = DS2413_ACCESS_READ;
|
|
net->write(cmd);
|
|
|
|
results = net->read();
|
|
debugSerialPort.print(F("Got: ")); debugSerialPort.println(results,BIN);
|
|
//debugSerialPort.println((~results & 0x0F),BIN); debugSerialPort.println ((results >> 4),BIN);
|
|
|
|
ok = (~results & 0x0F) == (results >> 4); // Compare nibbles
|
|
results &= 0x0F; // Clear inverted values
|
|
|
|
if (ok) {debugSerialPort.println(F("Read ok"));break;} else {debugSerialPort.println(F("read Error"));delay(1);}
|
|
} //while
|
|
|
|
if (ok && (val>=0))
|
|
{
|
|
count=10;
|
|
while (count--)
|
|
{
|
|
net->reset();
|
|
net->select(addr);
|
|
|
|
if (results & DS2413_IN_LatchA) set|=DS2413_OUT_PinA;
|
|
if (results & DS2413_IN_LatchB) set|=DS2413_OUT_PinB;
|
|
|
|
switch (subchan) {
|
|
case 0:
|
|
if (!val) set|=DS2413_OUT_PinA; else set &= ~DS2413_OUT_PinA;
|
|
break;
|
|
case 1:
|
|
if (!val) set|=DS2413_OUT_PinB; else set &= ~DS2413_OUT_PinB;
|
|
};
|
|
set |= 0xFC;
|
|
debugSerialPort.print(F("New: "));debugSerialPort.println(set,BIN);
|
|
cmd = DS2413_ACCESS_WRITE;
|
|
net->write(cmd);
|
|
|
|
net->write(set);
|
|
net->write(~set);
|
|
|
|
uint8_t ack = net->read(); // 0xAA=success, 0xFF=failure
|
|
|
|
if (ack == DS2413_ACK_SUCCESS)
|
|
{
|
|
results=net->read();
|
|
debugSerialPort.print(F("Updated ok: ")); debugSerialPort.println(results,BIN);
|
|
ok = (~results & 0x0F) == (results >> 4); // Compare nibbles
|
|
{
|
|
if (ok)
|
|
{debugSerialPort.println(F("Readback ok"));
|
|
break;}
|
|
else {debugSerialPort.println(F("readback Error"));delay(1);}
|
|
}
|
|
results &= 0x0F; // Clear inverted values
|
|
}
|
|
else debugSerialPort.println (F("Write failed"));;
|
|
|
|
} //while
|
|
} //if
|
|
return ok ? results : -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
int sensors_ext(void)
|
|
{
|
|
|
|
int t;
|
|
switch (term[si][0]){
|
|
case 0x29: // DS2408
|
|
//debugSerialPort.println(wstat[si],BIN);
|
|
|
|
if (wstat[si] & SW_PULSE0) {
|
|
wstat[si]&=~SW_PULSE0;
|
|
wstat[si]|=SW_PULSE_P0;
|
|
debugSerialPort.println(F("Pulse0 in progress"));
|
|
|
|
return 500;
|
|
}
|
|
|
|
if (wstat[si] & SW_PULSE0_R) {
|
|
wstat[si]&=~SW_PULSE0_R;
|
|
wstat[si]|=SW_PULSE_P0;
|
|
regs[si] =(ow2408out(term[si],(regs[si] | SW_MASK) & ~SW_OUT0) & SW_INMASK) ^ SW_STAT0;
|
|
debugSerialPort.println(F("Pulse0 in activated"));
|
|
|
|
return 500;
|
|
}
|
|
|
|
if (wstat[si] & SW_PULSE1) {
|
|
wstat[si]&=~SW_PULSE1;
|
|
wstat[si]|=SW_PULSE_P1;
|
|
debugSerialPort.println(F("Pulse1 in progress"));
|
|
|
|
return 500;
|
|
}
|
|
|
|
if (wstat[si] & SW_PULSE1_R) {
|
|
wstat[si]&=~SW_PULSE1_R;
|
|
wstat[si]|=SW_PULSE_P1;
|
|
regs[si] =(ow2408out(term[si],(regs[si] | SW_MASK) & ~SW_OUT1) & SW_INMASK) ^ SW_STAT1;
|
|
debugSerialPort.println(F("Pulse0 in activated"));
|
|
|
|
return 500;
|
|
}
|
|
|
|
if (wstat[si] & SW_PULSE_P0) {
|
|
wstat[si]&=~SW_PULSE_P0;
|
|
debugSerialPort.println(F("Pulse0 clearing"));
|
|
ow2408out(term[si],regs[si] | SW_MASK | SW_OUT0);
|
|
|
|
if (wstat[si] & SW_CHANGED_P0) {
|
|
wstat[si]&=~SW_CHANGED_P0;
|
|
wstat[si]|=SW_PULSE0_R;
|
|
return 500;
|
|
}
|
|
}
|
|
|
|
if (wstat[si] & SW_PULSE_P1) {
|
|
wstat[si]&=~SW_PULSE_P1;
|
|
debugSerialPort.println(F("Pulse1 clearing"));
|
|
ow2408out(term[si],regs[si] | SW_MASK | SW_OUT1);
|
|
|
|
if (wstat[si] & SW_CHANGED_P1) {
|
|
wstat[si]&=~SW_CHANGED_P1;
|
|
wstat[si]|=SW_PULSE1_R;
|
|
return 500;
|
|
}
|
|
}
|
|
|
|
if (wstat[si])
|
|
{
|
|
t=owRead2408(term[si]) & SW_INMASK;
|
|
|
|
|
|
|
|
if (t!=regs[si]) {
|
|
|
|
debugSerialPort.print(F("DS2408 data = "));
|
|
debugSerialPort.println(t, BIN);
|
|
|
|
if (!(wstat[si] & SW_DOUBLECHECK))
|
|
{
|
|
wstat[si]|=SW_DOUBLECHECK; //suspected
|
|
debugSerialPort.println(F("DOUBLECHECK"));
|
|
return recheck_interval;
|
|
}
|
|
|
|
|
|
debugSerialPort.println(F("Really Changed"));
|
|
if (owChanged) owChanged(si,term[si],t);
|
|
regs[si]=t;
|
|
|
|
|
|
}
|
|
wstat[si]&=~SW_DOUBLECHECK;
|
|
}
|
|
break;
|
|
|
|
|
|
case 0x01:
|
|
case 0x81:
|
|
t=wstat[si];
|
|
if (t!=regs[si])
|
|
{ debugSerialPort.println(F("Changed"));
|
|
if (owChanged) owChanged(si,term[si],t);
|
|
regs[si]=t;
|
|
}
|
|
}
|
|
|
|
|
|
si++;
|
|
return check_circle;
|
|
|
|
}
|
|
|
|
|
|
|